Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries * FILE: lib/rtl/critical.c * PURPOSE: Critical sections * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) * Gunnar Dalsnes */
/* INCLUDES *****************************************************************/
#include <rtl.h>
#define NDEBUG#include <debug.h>
#define MAX_STATIC_CS_DEBUG_OBJECTS 64
static RTL_CRITICAL_SECTION RtlCriticalSectionLock;static LIST_ENTRY RtlCriticalSectionList = {&RtlCriticalSectionList, &RtlCriticalSectionList};static BOOLEAN RtlpCritSectInitialized = FALSE;static RTL_CRITICAL_SECTION_DEBUG RtlpStaticDebugInfo[MAX_STATIC_CS_DEBUG_OBJECTS];static BOOLEAN RtlpDebugInfoFreeList[MAX_STATIC_CS_DEBUG_OBJECTS];
LARGE_INTEGER RtlpTimeout;BOOLEAN RtlpTimeoutDisable;
extern BOOLEAN LdrpShutdownInProgress;extern HANDLE LdrpShutdownThreadId;
/* FUNCTIONS *****************************************************************/
#define CRITSECT_HAS_DEBUG_INFO(CriticalSection) \ (((CriticalSection)->DebugInfo != NULL) && \ ((CriticalSection)->DebugInfo != LongToPtr(-1)))
/*++ * RtlpCreateCriticalSectionSem * * Checks if an Event has been created for the critical section. * * Params: * None * * Returns: * None. Raises an exception if the system call failed. * * Remarks: * None * *--*/_At_(CriticalSection->LockSemaphore, _Post_notnull_)VOIDNTAPIRtlpCreateCriticalSectionSem(PRTL_CRITICAL_SECTION CriticalSection){ HANDLE hEvent = CriticalSection->LockSemaphore; HANDLE hNewEvent; NTSTATUS Status;
/* Check if we have an event */ if (!hEvent) { /* No, so create it */ Status = NtCreateEvent(&hNewEvent, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to Create Event!\n");
/* * Use INVALID_HANDLE_VALUE (-1) to signal that * the global keyed event must be used. */ hNewEvent = INVALID_HANDLE_VALUE; }
DPRINT("Created Event: %p\n", hNewEvent);
/* Exchange the LockSemaphore field with the new handle, if it is still 0 */ if (InterlockedCompareExchangePointer((PVOID*)&CriticalSection->LockSemaphore, (PVOID)hNewEvent, NULL) != NULL) { /* Someone else just created an event */ if (hNewEvent != INVALID_HANDLE_VALUE) { DPRINT("Closing already created event: %p\n", hNewEvent); NtClose(hNewEvent); } } }
return;}
/*++ * RtlpWaitForCriticalSection * * Slow path of RtlEnterCriticalSection. Waits on an Event Object. * * Params: * CriticalSection - Critical section to acquire. * * Returns: * STATUS_SUCCESS, or raises an exception if a deadlock is occuring. * * Remarks: * None * *--*/NTSTATUSNTAPIRtlpWaitForCriticalSection(PRTL_CRITICAL_SECTION CriticalSection){ NTSTATUS Status; EXCEPTION_RECORD ExceptionRecord; BOOLEAN LastChance = FALSE;
/* Increase the Debug Entry count */ DPRINT("Waiting on Critical Section Event: %p %p\n", CriticalSection, CriticalSection->LockSemaphore);
if (CRITSECT_HAS_DEBUG_INFO(CriticalSection)) CriticalSection->DebugInfo->EntryCount++;
/* * If we're shutting down the process, we're allowed to acquire any * critical sections by force (the loader lock in particular) */ if (LdrpShutdownInProgress && LdrpShutdownThreadId == NtCurrentTeb()->RealClientId.UniqueThread) { DPRINT("Forcing ownership of critical section %p\n", CriticalSection); return STATUS_SUCCESS; }
/* Do we have an Event yet? */ if (!CriticalSection->LockSemaphore) { RtlpCreateCriticalSectionSem(CriticalSection); }
for (;;) { /* Increase the number of times we've had contention */ if (CRITSECT_HAS_DEBUG_INFO(CriticalSection)) CriticalSection->DebugInfo->ContentionCount++;
/* Check if allocating the event failed */ if (CriticalSection->LockSemaphore == INVALID_HANDLE_VALUE) { /* Use the global keyed event (NULL as keyed event handle) */ Status = NtWaitForKeyedEvent(NULL, CriticalSection, FALSE, (RtlpTimeoutDisable ? NULL : &RtlpTimeout)); } else { /* Wait on the Event */ Status = NtWaitForSingleObject(CriticalSection->LockSemaphore, FALSE, (RtlpTimeoutDisable ? NULL : &RtlpTimeout)); }
/* We have Timed out */ if (Status == STATUS_TIMEOUT) { /* Is this the 2nd time we've timed out? */ if (LastChance) { ERROR_DBGBREAK("Deadlock: 0x%p\n", CriticalSection);
/* Yes it is, we are raising an exception */ ExceptionRecord.ExceptionCode = STATUS_POSSIBLE_DEADLOCK; ExceptionRecord.ExceptionFlags = 0; ExceptionRecord.ExceptionRecord = NULL; ExceptionRecord.ExceptionAddress = RtlRaiseException; ExceptionRecord.NumberParameters = 1; ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR)CriticalSection; RtlRaiseException(&ExceptionRecord); }
/* One more try */ LastChance = TRUE; } else { /* If we are here, everything went fine */ return STATUS_SUCCESS; } }}
/*++ * RtlpUnWaitCriticalSection * * Slow path of RtlLeaveCriticalSection. Fires an Event Object. * * Params: * CriticalSection - Critical section to release. * * Returns: * None. Raises an exception if the system call failed. * * Remarks: * None * *--*/VOIDNTAPIRtlpUnWaitCriticalSection(PRTL_CRITICAL_SECTION CriticalSection){ NTSTATUS Status;
/* Do we have an Event yet? */ if (!CriticalSection->LockSemaphore) { RtlpCreateCriticalSectionSem(CriticalSection); }
/* Signal the Event */ DPRINT("Signaling Critical Section Event: %p, %p\n", CriticalSection, CriticalSection->LockSemaphore);
/* Check if this critical section needs to use the keyed event */ if (CriticalSection->LockSemaphore == INVALID_HANDLE_VALUE) { /* Release keyed event */ Status = NtReleaseKeyedEvent(NULL, CriticalSection, FALSE, &RtlpTimeout); } else { /* Set the event */ Status = NtSetEvent(CriticalSection->LockSemaphore, NULL); }
if (!NT_SUCCESS(Status)) { /* We've failed */ DPRINT1("Signaling Failed for: %p, %p, 0x%08lx\n", CriticalSection, CriticalSection->LockSemaphore, Status); RtlRaiseStatus(Status); }}
/*++ * RtlpInitDeferredCriticalSection * * Initializes the Critical Section implementation. * * Params: * None * * Returns: * None. * * Remarks: * After this call, the Process Critical Section list is protected. * *--*/VOIDNTAPIRtlpInitDeferredCriticalSection(VOID){ /* Initialize the CS Protecting the List */ RtlInitializeCriticalSection(&RtlCriticalSectionLock);
/* It's now safe to enter it */ RtlpCritSectInitialized = TRUE;}
/*++ * RtlpAllocateDebugInfo * * Finds or allocates memory for a Critical Section Debug Object * * Params: * None * * Returns: * A pointer to an empty Critical Section Debug Object. * * Remarks: * For optimization purposes, the first 64 entries can be cached. From * then on, future Critical Sections will allocate memory from the heap. * *--*/PRTL_CRITICAL_SECTION_DEBUGNTAPIRtlpAllocateDebugInfo(VOID){ ULONG i;
/* Try to allocate from our buffer first */ for (i = 0; i < MAX_STATIC_CS_DEBUG_OBJECTS; i++) { /* Check if Entry is free */ if (!RtlpDebugInfoFreeList[i]) { /* Mark entry in use */ DPRINT("Using entry: %lu. Buffer: %p\n", i, &RtlpStaticDebugInfo[i]); RtlpDebugInfoFreeList[i] = TRUE;
/* Use free entry found */ return &RtlpStaticDebugInfo[i]; } }
/* We are out of static buffer, allocate dynamic */ return RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(RTL_CRITICAL_SECTION_DEBUG));}
/*++ * RtlpFreeDebugInfo * * Frees the memory for a Critical Section Debug Object * * Params: * DebugInfo - Pointer to Critical Section Debug Object to free. * * Returns: * None. * * Remarks: * If the pointer is part of the static buffer, then the entry is made * free again. If not, the object is de-allocated from the heap. * *--*/VOIDNTAPIRtlpFreeDebugInfo(PRTL_CRITICAL_SECTION_DEBUG DebugInfo){ SIZE_T EntryId;
/* Is it part of our cached entries? */ if ((DebugInfo >= RtlpStaticDebugInfo) && (DebugInfo <= &RtlpStaticDebugInfo[MAX_STATIC_CS_DEBUG_OBJECTS-1])) { /* Yes. zero it out */ RtlZeroMemory(DebugInfo, sizeof(RTL_CRITICAL_SECTION_DEBUG));
/* Mark as free */ EntryId = (DebugInfo - RtlpStaticDebugInfo); DPRINT("Freeing from Buffer: %p. Entry: %Iu inside Process: %p\n", DebugInfo, EntryId, NtCurrentTeb()->ClientId.UniqueProcess); RtlpDebugInfoFreeList[EntryId] = FALSE;
} else if (!DebugInfo->Flags) { /* It's a dynamic one, so free from the heap */ DPRINT("Freeing from Heap: %p inside Process: %p\n", DebugInfo, NtCurrentTeb()->ClientId.UniqueProcess); RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, DebugInfo); } else { /* HACK for Wine: stores a section name pointer in the Flags member */ DPRINT("Assuming static: %p inside Process: %p\n", DebugInfo, NtCurrentTeb()->ClientId.UniqueProcess); }}
/*++ * RtlDeleteCriticalSection * @implemented NT4 * * Deletes a Critical Section * * Params: * CriticalSection - Critical section to delete. * * Returns: * STATUS_SUCCESS, or error value returned by NtClose. * * Remarks: * The critical section members should not be read after this call. * *--*/NTSTATUSNTAPIRtlDeleteCriticalSection(PRTL_CRITICAL_SECTION CriticalSection){ NTSTATUS Status = STATUS_SUCCESS;
DPRINT("Deleting Critical Section: %p\n", CriticalSection);
/* Close the Event Object Handle if it exists */ if (CriticalSection->LockSemaphore) { /* In case NtClose fails, return the status */ Status = NtClose(CriticalSection->LockSemaphore); }
/* Protect List */ RtlEnterCriticalSection(&RtlCriticalSectionLock);
if (CRITSECT_HAS_DEBUG_INFO(CriticalSection)) { /* Remove it from the list */ RemoveEntryList(&CriticalSection->DebugInfo->ProcessLocksList);#if 0 /* HACK for Wine: We need to preserve Flags for RtlpFreeDebugInfo */ RtlZeroMemory(CriticalSection->DebugInfo, sizeof(RTL_CRITICAL_SECTION_DEBUG));#endif }
/* Unprotect */ RtlLeaveCriticalSection(&RtlCriticalSectionLock);
if (CRITSECT_HAS_DEBUG_INFO(CriticalSection)) { /* Free it */ RtlpFreeDebugInfo(CriticalSection->DebugInfo); }
/* Wipe it out */ RtlZeroMemory(CriticalSection, sizeof(RTL_CRITICAL_SECTION));
/* Return */ return Status;}
/*++ * RtlSetCriticalSectionSpinCount * @implemented NT4 * * Sets the spin count for a critical section. * * Params: * CriticalSection - Critical section to set the spin count for. * * SpinCount - Spin count for the critical section. * * Returns: * STATUS_SUCCESS. * * Remarks: * SpinCount is ignored on single-processor systems. * *--*/ULONGNTAPIRtlSetCriticalSectionSpinCount(PRTL_CRITICAL_SECTION CriticalSection, ULONG SpinCount){ ULONG OldCount = (ULONG)CriticalSection->SpinCount;
/* Set to parameter if MP, or to 0 if this is Uniprocessor */ CriticalSection->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? SpinCount : 0; return OldCount;}
/*++ * RtlEnterCriticalSection * @implemented NT4 * * Waits to gain ownership of the critical section. * * Params: * CriticalSection - Critical section to wait for. * * Returns: * STATUS_SUCCESS. * * Remarks: * Uses a fast-path unless contention happens. * *--*/NTSTATUSNTAPIRtlEnterCriticalSection(PRTL_CRITICAL_SECTION CriticalSection){ HANDLE Thread = (HANDLE)NtCurrentTeb()->ClientId.UniqueThread;
/* Try to lock it */ if (InterlockedIncrement(&CriticalSection->LockCount) != 0) { /* We've failed to lock it! Does this thread actually own it? */ if (Thread == CriticalSection->OwningThread) { /* * You own it, so you'll get it when you're done with it! No need to * use the interlocked functions as only the thread who already owns * the lock can modify this data. */ CriticalSection->RecursionCount++; return STATUS_SUCCESS; }
/* NOTE - CriticalSection->OwningThread can be NULL here because changing this information is not serialized. This happens when thread a acquires the lock (LockCount == 0) and thread b tries to acquire it as well (LockCount == 1) but thread a hasn't had a chance to set the OwningThread! So it's not an error when OwningThread is NULL here! */
/* We don't own it, so we must wait for it */ RtlpWaitForCriticalSection(CriticalSection); }
/* * Lock successful. Changing this information has not to be serialized * because only one thread at a time can actually change it (the one who * acquired the lock)! */ CriticalSection->OwningThread = Thread; CriticalSection->RecursionCount = 1; NtCurrentTeb()->CountOfOwnedCriticalSections++; return STATUS_SUCCESS;}
/*++ * RtlInitializeCriticalSection * @implemented NT4 * * Initialises a new critical section. * * Params: * CriticalSection - Critical section to initialise * * Returns: * STATUS_SUCCESS. * * Remarks: * Simply calls RtlInitializeCriticalSectionAndSpinCount * *--*/NTSTATUSNTAPIRtlInitializeCriticalSection(PRTL_CRITICAL_SECTION CriticalSection){ /* Call the Main Function */ return RtlInitializeCriticalSectionAndSpinCount(CriticalSection, 0);}
/*++ * RtlInitializeCriticalSectionEx * @implemented NT6.0 * * Initialises a new critical section. * * Params: * CriticalSection - Critical section to initialise * * SpinCount - Spin count for the critical section. * * Flags - Flags for initialization. * * Returns: * STATUS_SUCCESS. * * Remarks: * SpinCount is ignored on single-processor systems. * *--*/NTSTATUSNTAPIRtlInitializeCriticalSectionEx( _Out_ PRTL_CRITICAL_SECTION CriticalSection, _In_ ULONG SpinCount, _In_ ULONG Flags){ PRTL_CRITICAL_SECTION_DEBUG CritcalSectionDebugData; ULONG AllowedFlags; ULONG OsVersion;
/* Remove lower bits from flags */ Flags &= RTL_CRITICAL_SECTION_ALL_FLAG_BITS;
/* These flags generally allowed */ AllowedFlags = RTL_CRITICAL_SECTION_FLAG_NO_DEBUG_INFO | RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN | RTL_CRITICAL_SECTION_FLAG_STATIC_INIT;
/* Flags for Windows 7+ (CHECKME) */ OsVersion = NtCurrentPeb()->OSMajorVersion << 8 | NtCurrentPeb()->OSMinorVersion; if (OsVersion >= _WIN32_WINNT_WIN7) { AllowedFlags |= RTL_CRITICAL_SECTION_FLAG_RESOURCE_TYPE | RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO; }
if (Flags & ~AllowedFlags) { return STATUS_INVALID_PARAMETER_3; }
if (SpinCount & RTL_CRITICAL_SECTION_ALL_FLAG_BITS) { return STATUS_INVALID_PARAMETER_2; }
/* First things first, set up the Object */ DPRINT("Initializing Critical Section: %p\n", CriticalSection); CriticalSection->LockCount = -1; CriticalSection->RecursionCount = 0; CriticalSection->OwningThread = 0; CriticalSection->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? SpinCount : 0; CriticalSection->LockSemaphore = 0;
if (Flags & RTL_CRITICAL_SECTION_FLAG_NO_DEBUG_INFO) { CriticalSection->DebugInfo = LongToPtr(-1); } else { /* Allocate the Debug Data */ CritcalSectionDebugData = RtlpAllocateDebugInfo(); DPRINT("Allocated Debug Data: %p inside Process: %p\n", CritcalSectionDebugData, NtCurrentTeb()->ClientId.UniqueProcess);
if (!CritcalSectionDebugData) { /* This is bad! */ DPRINT1("Couldn't allocate Debug Data for: %p\n", CriticalSection); return STATUS_NO_MEMORY; }
/* Set it up */ CritcalSectionDebugData->Type = RTL_CRITSECT_TYPE; CritcalSectionDebugData->ContentionCount = 0; CritcalSectionDebugData->EntryCount = 0; CritcalSectionDebugData->CriticalSection = CriticalSection; CritcalSectionDebugData->Flags = 0; CriticalSection->DebugInfo = CritcalSectionDebugData;
/* * Add it to the List of Critical Sections owned by the process. * If we've initialized the Lock, then use it. If not, then probably * this is the lock initialization itself, so insert it directly. */ if ((CriticalSection != &RtlCriticalSectionLock) && (RtlpCritSectInitialized)) { DPRINT("Securely Inserting into ProcessLocks: %p, %p, %p\n", &CritcalSectionDebugData->ProcessLocksList, CriticalSection, &RtlCriticalSectionList);
/* Protect List */ RtlEnterCriticalSection(&RtlCriticalSectionLock);
/* Add this one */ InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList);
/* Unprotect */ RtlLeaveCriticalSection(&RtlCriticalSectionLock); } else { DPRINT("Inserting into ProcessLocks: %p, %p, %p\n", &CritcalSectionDebugData->ProcessLocksList, CriticalSection, &RtlCriticalSectionList);
/* Add it directly */ InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList); } }
return STATUS_SUCCESS;}
/*++ * RtlInitializeCriticalSectionAndSpinCount * @implemented NT4 * * Initialises a new critical section. * * Params: * CriticalSection - Critical section to initialise * * SpinCount - Spin count for the critical section. * * Returns: * STATUS_SUCCESS. * * Remarks: * SpinCount is ignored on single-processor systems. * *--*/NTSTATUSNTAPIRtlInitializeCriticalSectionAndSpinCount( _Out_ PRTL_CRITICAL_SECTION CriticalSection, _In_ ULONG SpinCount){ SpinCount &= ~RTL_CRITICAL_SECTION_ALL_FLAG_BITS; return RtlInitializeCriticalSectionEx(CriticalSection, SpinCount, 0);}
/*++ * RtlGetCriticalSectionRecursionCount * @implemented NT5.2 SP1 * * Retrieves the recursion count of a given critical section. * * Params: * CriticalSection - Critical section to retrieve its recursion count. * * Returns: * The recursion count. * * Remarks: * We return the recursion count of the critical section if it is owned * by the current thread, and otherwise we return zero. * *--*/LONGNTAPIRtlGetCriticalSectionRecursionCount(PRTL_CRITICAL_SECTION CriticalSection){ if (CriticalSection->OwningThread == NtCurrentTeb()->ClientId.UniqueThread) { /* * The critical section is owned by the current thread, * therefore retrieve its actual recursion count. */ return CriticalSection->RecursionCount; } else { /* * It is not owned by the current thread, so * for this thread there is no recursion. */ return 0; }}
/*++ * RtlLeaveCriticalSection * @implemented NT4 * * Releases a critical section and makes if available for new owners. * * Params: * CriticalSection - Critical section to release. * * Returns: * STATUS_SUCCESS. * * Remarks: * If another thread was waiting, the slow path is entered. * *--*/NTSTATUSNTAPIRtlLeaveCriticalSection(PRTL_CRITICAL_SECTION CriticalSection){#if DBG HANDLE Thread = (HANDLE)NtCurrentTeb()->ClientId.UniqueThread;
/* * In win this case isn't checked. However it's a valid check so it should * only be performed in debug builds! */ if (Thread != CriticalSection->OwningThread) { DPRINT1("Releasing critical section not owned!\n"); return STATUS_INVALID_PARAMETER; }#endif
/* * Decrease the Recursion Count. No need to do this atomically because only * the thread who holds the lock can call this function (unless the program * is totally screwed... */ if (--CriticalSection->RecursionCount) { if (CriticalSection->RecursionCount < 0) { DPRINT1("CRITICAL SECTION MESS: Section %p is not acquired!\n", CriticalSection); return STATUS_UNSUCCESSFUL; } /* Someone still owns us, but we are free. This needs to be done atomically. */ InterlockedDecrement(&CriticalSection->LockCount); } else { /* * Nobody owns us anymore. No need to do this atomically. * See comment above. */ CriticalSection->OwningThread = 0; NtCurrentTeb()->CountOfOwnedCriticalSections--;
/* Was someone wanting us? This needs to be done atomically. */ if (-1 != InterlockedDecrement(&CriticalSection->LockCount)) { /* Let him have us */ RtlpUnWaitCriticalSection(CriticalSection); } }
/* Sucessful! */ return STATUS_SUCCESS;}
/*++ * RtlTryEnterCriticalSection * @implemented NT4 * * Attempts to gain ownership of the critical section without waiting. * * Params: * CriticalSection - Critical section to attempt acquiring. * * Returns: * TRUE if the critical section has been acquired, FALSE otherwise. * * Remarks: * None * *--*/LOGICALNTAPIRtlTryEnterCriticalSection(PRTL_CRITICAL_SECTION CriticalSection){ /* Try to take control */ if (InterlockedCompareExchange(&CriticalSection->LockCount, 0, -1) == -1) { /* It's ours */ CriticalSection->OwningThread = NtCurrentTeb()->ClientId.UniqueThread; CriticalSection->RecursionCount = 1; NtCurrentTeb()->CountOfOwnedCriticalSections++; return TRUE; } else if (CriticalSection->OwningThread == NtCurrentTeb()->ClientId.UniqueThread) { /* It's already ours */ InterlockedIncrement(&CriticalSection->LockCount); CriticalSection->RecursionCount++; return TRUE; }
/* It's not ours */ return FALSE;}
VOIDNTAPIRtlCheckForOrphanedCriticalSections(HANDLE ThreadHandle){ UNIMPLEMENTED;}
LOGICALNTAPIRtlIsCriticalSectionLocked(PRTL_CRITICAL_SECTION CriticalSection){ return CriticalSection->RecursionCount != 0;}
LOGICALNTAPIRtlIsCriticalSectionLockedByThread(PRTL_CRITICAL_SECTION CriticalSection){ return CriticalSection->OwningThread == NtCurrentTeb()->ClientId.UniqueThread && CriticalSection->RecursionCount != 0;}
VOIDNTAPIRtlpNotOwnerCriticalSection(PRTL_CRITICAL_SECTION CriticalSection){ RtlRaiseStatus(STATUS_RESOURCE_NOT_OWNED);}
/* EOF */