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;
/* FUNCTIONS *****************************************************************/
* None
*
*--*/
+_At_(CriticalSection->LockSemaphore, _Post_notnull_)
VOID
NTAPI
RtlpCreateCriticalSectionSem(PRTL_CRITICAL_SECTION CriticalSection)
HANDLE hNewEvent;
NTSTATUS Status;
- /* Chevk if we have an event */
- if (!hEvent) {
+ /* Check if we have an event */
+ if (!hEvent)
+ {
/* No, so create it */
- if (!NT_SUCCESS(Status = NtCreateEvent(&hNewEvent,
- EVENT_ALL_ACCESS,
- NULL,
- SynchronizationEvent,
- FALSE))) {
-
- /* We failed, this is bad... */
+ Status = NtCreateEvent(&hNewEvent,
+ EVENT_ALL_ACCESS,
+ NULL,
+ SynchronizationEvent,
+ FALSE);
+ if (!NT_SUCCESS(Status))
+ {
DPRINT1("Failed to Create Event!\n");
- InterlockedDecrement(&CriticalSection->LockCount);
- RtlRaiseStatus(Status);
- return;
+
+ /* 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,
- 0)) {
-
- /* Some just created an event */
- DPRINT("Closing already created event: %p\n", hNewEvent);
- NtClose(hNewEvent);
+ NULL) != NULL)
+ {
+ /* Someone else just created an event */
+ if (hEvent != INVALID_HANDLE_VALUE)
+ {
+ DPRINT("Closing already created event: %p\n", hNewEvent);
+ NtClose(hNewEvent);
+ }
}
}
NTSTATUS Status;
EXCEPTION_RECORD ExceptionRecord;
BOOLEAN LastChance = FALSE;
- LARGE_INTEGER Timeout;
-
- /* Wait 2.5 minutes */
- Timeout.QuadPart = 150000L * (ULONGLONG)10000;
- Timeout.QuadPart = -Timeout.QuadPart;
- /* ^^ HACK HACK HACK. Good way:
- Timeout = &NtCurrentPeb()->CriticalSectionTimeout */
/* Do we have an Event yet? */
if (!CriticalSection->LockSemaphore) {
if (CriticalSection->DebugInfo)
CriticalSection->DebugInfo->ContentionCount++;
- /* Wait on the Event */
- Status = NtWaitForSingleObject(CriticalSection->LockSemaphore,
- FALSE,
- &Timeout);
+ /* 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,
+ &RtlpTimeout);
+ }
+ else
+ {
+ /* Wait on the Event */
+ Status = NtWaitForSingleObject(CriticalSection->LockSemaphore,
+ FALSE,
+ &RtlpTimeout);
+ }
/* We have Timed out */
if (Status == STATUS_TIMEOUT) {
DPRINT("Signaling Critical Section Event: %p, %p\n",
CriticalSection,
CriticalSection->LockSemaphore);
- Status = NtSetEvent(CriticalSection->LockSemaphore, NULL);
+
+ /* 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 are out of static buffer, allocate dynamic */
- return RtlAllocateHeap(NtCurrentPeb()->ProcessHeap,
+ return RtlAllocateHeap(RtlGetProcessHeap(),
0,
sizeof(RTL_CRITICAL_SECTION_DEBUG));
}
* SpinCount is ignored on single-processor systems.
*
*--*/
-DWORD
+ULONG
NTAPI
RtlSetCriticalSectionSpinCount(PRTL_CRITICAL_SECTION CriticalSection,
ULONG SpinCount)
return STATUS_SUCCESS;
}
+/*++
+ * 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.
+ *
+ *--*/
+LONG
+NTAPI
+RtlGetCriticalSectionRecursionCount(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
NTAPI
RtlLeaveCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)
{
-#ifndef NDEBUG
+#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
return FALSE;
}
+VOID
+NTAPI
+RtlCheckForOrphanedCriticalSections(
+ HANDLE ThreadHandle)
+{
+ UNIMPLEMENTED;
+}
+
/* EOF */