-/* $Id$
- *
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS system libraries
- * FILE: lib/ntdll/rtl/critical.c
- * PURPOSE: Critical sections
- * UPDATE HISTORY:
- * Created 30/09/98
- * Rewritten ROS version, based on WINE code plus
- * some fixes useful only for ROS right now - 03/01/05
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <ntdll.h>
-#define NDEBUG
-#include <debug.h>
-
-/* FUNCTIONS *****************************************************************/
-
-#define MAX_STATIC_CS_DEBUG_OBJECTS 64
-
-static RTL_CRITICAL_SECTION RtlCriticalSectionLock;
-static LIST_ENTRY RtlCriticalSectionList;
-static BOOLEAN RtlpCritSectInitialized = FALSE;
-static RTL_CRITICAL_SECTION_DEBUG RtlpStaticDebugInfo[MAX_STATIC_CS_DEBUG_OBJECTS];
-static BOOLEAN RtlpDebugInfoFreeList[MAX_STATIC_CS_DEBUG_OBJECTS];
-
-/*++
- * 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.
- *
- *--*/
-NTSTATUS
-STDCALL
-RtlDeleteCriticalSection(
- PRTL_CRITICAL_SECTION CriticalSection)
-{
- NTSTATUS Status = STATUS_SUCCESS;
-
- DPRINT("Deleting Critical Section: %x\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);
-
- /* Remove it from the list */
- RemoveEntryList(&CriticalSection->DebugInfo->ProcessLocksList);
-
- /* Unprotect */
- RtlLeaveCriticalSection(&RtlCriticalSectionLock);
-
- /* 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.
- *
- *--*/
-DWORD
-STDCALL
-RtlSetCriticalSectionSpinCount(
- PRTL_CRITICAL_SECTION CriticalSection,
- ULONG SpinCount
- )
-{
- ULONG OldCount = 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.
- *
- *--*/
-NTSTATUS
-STDCALL
-RtlEnterCriticalSection(
- PRTL_CRITICAL_SECTION CriticalSection)
-{
- HANDLE Thread = (HANDLE)NtCurrentTeb()->Cid.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;
- return STATUS_SUCCESS;
-}
-
-/*++
- * RtlInitializeCriticalSection
- * @implemented NT4
- *
- * Initialises a new critical section.
- *
- * Params:
- * CriticalSection - Critical section to initialise
- *
- * Returns:
- * STATUS_SUCCESS.
- *
- * Remarks:
- * Simply calls RtlInitializeCriticalSectionAndSpinCount
- *
- *--*/
-NTSTATUS
-STDCALL
-RtlInitializeCriticalSection(
- PRTL_CRITICAL_SECTION CriticalSection)
-{
- /* Call the Main Function */
- return RtlInitializeCriticalSectionAndSpinCount(CriticalSection, 0);
-}
-
-/*++
- * 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.
- *
- *--*/
-NTSTATUS
-STDCALL
-RtlInitializeCriticalSectionAndSpinCount (
- PRTL_CRITICAL_SECTION CriticalSection,
- ULONG SpinCount)
-{
- PRTL_CRITICAL_SECTION_DEBUG CritcalSectionDebugData;
-
- /* First things first, set up the Object */
- DPRINT("Initializing Critical Section: %x\n", CriticalSection);
- CriticalSection->LockCount = -1;
- CriticalSection->RecursionCount = 0;
- CriticalSection->OwningThread = 0;
- CriticalSection->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? SpinCount : 0;
- CriticalSection->LockSemaphore = 0;
-
- /* Allocate the Debug Data */
- CritcalSectionDebugData = RtlpAllocateDebugInfo();
- DPRINT("Allocated Debug Data: %x inside Process: %x\n",
- CritcalSectionDebugData,
- NtCurrentTeb()->Cid.UniqueProcess);
-
- if (!CritcalSectionDebugData) {
-
- /* This is bad! */
- DPRINT1("Couldn't allocate Debug Data for: %x\n", CriticalSection);
- return STATUS_NO_MEMORY;
- }
-
- /* Set it up */
- CritcalSectionDebugData->Type = RTL_CRITSECT_TYPE;
- CritcalSectionDebugData->ContentionCount = 0;
- CritcalSectionDebugData->EntryCount = 0;
- CritcalSectionDebugData->CriticalSection = CriticalSection;
- 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: %x, %x, %x\n",
- &CritcalSectionDebugData->ProcessLocksList,
- CriticalSection,
- &RtlCriticalSectionList);
-
- /* Protect List */
- RtlEnterCriticalSection(&RtlCriticalSectionLock);
-
- /* Add this one */
- InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList);
-
- /* Unprotect */
- RtlLeaveCriticalSection(&RtlCriticalSectionLock);
-
- } else {
-
- DPRINT("Inserting into ProcessLocks: %x, %x, %x\n",
- &CritcalSectionDebugData->ProcessLocksList,
- CriticalSection,
- &RtlCriticalSectionList);
-
- /* Add it directly */
- InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList);
- }
-
- return STATUS_SUCCESS;
-}
-
-/*++
- * 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.
- *
- *--*/
-NTSTATUS
-STDCALL
-RtlLeaveCriticalSection(
- PRTL_CRITICAL_SECTION CriticalSection)
-{
-#ifndef NDEBUG
- HANDLE Thread = (HANDLE)NtCurrentTeb()->Cid.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) {
-
- /* 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;
-
- /* 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
- *
- * Attemps 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
- *
- *--*/
-BOOLEAN
-STDCALL
-RtlTryEnterCriticalSection(
- PRTL_CRITICAL_SECTION CriticalSection)
-{
- /* Try to take control */
- if (InterlockedCompareExchange(&CriticalSection->LockCount,
- 0,
- -1) == -1) {
-
- /* It's ours */
- CriticalSection->OwningThread = NtCurrentTeb()->Cid.UniqueThread;
- CriticalSection->RecursionCount = 1;
- return TRUE;
-
- } else if (CriticalSection->OwningThread == NtCurrentTeb()->Cid.UniqueThread) {
-
- /* It's already ours */
- InterlockedIncrement(&CriticalSection->LockCount);
- CriticalSection->RecursionCount++;
- return TRUE;
- }
-
- /* It's not ours */
- return FALSE;
-}
-
-/*++
- * 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
- *
- *--*/
-NTSTATUS
-STDCALL
-RtlpWaitForCriticalSection(
- PRTL_CRITICAL_SECTION CriticalSection)
-{
- 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) {
- RtlpCreateCriticalSectionSem(CriticalSection);
- }
-
- /* Increase the Debug Entry count */
- DPRINT("Waiting on Critical Section Event: %x %x\n",
- CriticalSection,
- CriticalSection->LockSemaphore);
- CriticalSection->DebugInfo->EntryCount++;
-
- for (;;) {
-
- /* Increase the number of times we've had contention */
- CriticalSection->DebugInfo->ContentionCount++;
-
- /* Wait on the Event */
- Status = NtWaitForSingleObject(CriticalSection->LockSemaphore,
- FALSE,
- &Timeout);
-
- /* We have Timed out */
- if (Status == STATUS_TIMEOUT) {
-
- /* Is this the 2nd time we've timed out? */
- if (LastChance) {
-
- DPRINT1("Deadlock: %x\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
- *
- *--*/
-VOID
-STDCALL
-RtlpUnWaitCriticalSection(
- 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: %x, %x\n",
- CriticalSection,
- CriticalSection->LockSemaphore);
- Status = NtSetEvent(CriticalSection->LockSemaphore, NULL);
-
- if (!NT_SUCCESS(Status)) {
-
- /* We've failed */
- DPRINT1("Signaling Failed for: %x, %x, %x\n",
- CriticalSection,
- CriticalSection->LockSemaphore,
- Status);
- RtlRaiseStatus(Status);
- }
-}
-
-/*++
- * 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
- *
- *--*/
-VOID
-STDCALL
-RtlpCreateCriticalSectionSem(
- PRTL_CRITICAL_SECTION CriticalSection)
-{
- HANDLE hEvent = CriticalSection->LockSemaphore;
- HANDLE hNewEvent;
- NTSTATUS Status;
-
- /* Chevk 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... */
- DPRINT1("Failed to Create Event!\n");
- InterlockedDecrement(&CriticalSection->LockCount);
- RtlRaiseStatus(Status);
- return;
- }
- DPRINT("Created Event: %x \n", hNewEvent);
-
- if ((hEvent = InterlockedCompareExchangePointer((PVOID*)&CriticalSection->LockSemaphore,
- (PVOID)hNewEvent,
- 0))) {
-
- /* Some just created an event */
- DPRINT("Closing already created event: %x\n", hNewEvent);
- NtClose(hNewEvent);
- }
- }
-
- return;
-}
-
-/*++
- * RtlpInitDeferedCriticalSection
- *
- * Initializes the Critical Section implementation.
- *
- * Params:
- * None
- *
- * Returns:
- * None.
- *
- * Remarks:
- * After this call, the Process Critical Section list is protected.
- *
- *--*/
-VOID
-STDCALL
-RtlpInitDeferedCriticalSection(
- VOID)
-{
-
- /* Initialize the Process Critical Section List */
- InitializeListHead(&RtlCriticalSectionList);
-
- /* 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_DEBUG
-STDCALL
-RtlpAllocateDebugInfo(
- 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: %d. Buffer: %x\n", i, &RtlpStaticDebugInfo[i]);
- RtlpDebugInfoFreeList[i] = TRUE;
-
- /* Use free entry found */
- return &RtlpStaticDebugInfo[i];
- }
-
- }
-
- /* We are out of static buffer, allocate dynamic */
- return RtlAllocateHeap(NtCurrentPeb()->ProcessHeap,
- 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.
- *
- *--*/
-VOID
-STDCALL
-RtlpFreeDebugInfo(
- PRTL_CRITICAL_SECTION_DEBUG DebugInfo)
-{
- ULONG 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: %x. Entry: %d inside Process: %x\n",
- DebugInfo,
- EntryId,
- NtCurrentTeb()->Cid.UniqueProcess);
- RtlpDebugInfoFreeList[EntryId] = FALSE;
-
- } else {
-
- /* It's a dynamic one, so free from the heap */
- DPRINT("Freeing from Heap: %x inside Process: %x\n",
- DebugInfo,
- NtCurrentTeb()->Cid.UniqueProcess);
- RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, DebugInfo);
-
- }
-}
-
-/* EOF */
+/*\r
+ * COPYRIGHT: See COPYING in the top level directory\r
+ * PROJECT: ReactOS system libraries\r
+ * FILE: lib/rtl/critical.c\r
+ * PURPOSE: Critical sections\r
+ * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)\r
+ * Gunnar Dalsnes\r
+ */\r
+\r
+/* INCLUDES *****************************************************************/\r
+\r
+#include <rtl.h>\r
+\r
+#define NDEBUG\r
+#include <debug.h>\r
+\r
+#define MAX_STATIC_CS_DEBUG_OBJECTS 64\r
+\r
+static RTL_CRITICAL_SECTION RtlCriticalSectionLock;\r
+static LIST_ENTRY RtlCriticalSectionList;\r
+static BOOLEAN RtlpCritSectInitialized = FALSE;\r
+static RTL_CRITICAL_SECTION_DEBUG RtlpStaticDebugInfo[MAX_STATIC_CS_DEBUG_OBJECTS];\r
+static BOOLEAN RtlpDebugInfoFreeList[MAX_STATIC_CS_DEBUG_OBJECTS];\r
+\r
+/* FUNCTIONS *****************************************************************/\r
+\r
+/*++\r
+ * RtlpCreateCriticalSectionSem\r
+ *\r
+ * Checks if an Event has been created for the critical section.\r
+ *\r
+ * Params:\r
+ * None\r
+ *\r
+ * Returns:\r
+ * None. Raises an exception if the system call failed.\r
+ *\r
+ * Remarks:\r
+ * None\r
+ *\r
+ *--*/\r
+VOID\r
+STDCALL\r
+RtlpCreateCriticalSectionSem(PRTL_CRITICAL_SECTION CriticalSection)\r
+{\r
+ HANDLE hEvent = CriticalSection->LockSemaphore;\r
+ HANDLE hNewEvent;\r
+ NTSTATUS Status;\r
+\r
+ /* Chevk if we have an event */\r
+ if (!hEvent) {\r
+\r
+ /* No, so create it */\r
+ if (!NT_SUCCESS(Status = NtCreateEvent(&hNewEvent,\r
+ EVENT_ALL_ACCESS,\r
+ NULL,\r
+ SynchronizationEvent,\r
+ FALSE))) {\r
+\r
+ /* We failed, this is bad... */\r
+ DPRINT1("Failed to Create Event!\n");\r
+ InterlockedDecrement(&CriticalSection->LockCount);\r
+ RtlRaiseStatus(Status);\r
+ return;\r
+ }\r
+ DPRINT("Created Event: %x \n", hNewEvent);\r
+\r
+ if ((hEvent = InterlockedCompareExchangePointer((PVOID*)&CriticalSection->LockSemaphore,\r
+ (PVOID)hNewEvent,\r
+ 0))) {\r
+\r
+ /* Some just created an event */\r
+ DPRINT("Closing already created event: %x\n", hNewEvent);\r
+ NtClose(hNewEvent);\r
+ }\r
+ }\r
+\r
+ return;\r
+}\r
+\r
+/*++\r
+ * RtlpWaitForCriticalSection\r
+ *\r
+ * Slow path of RtlEnterCriticalSection. Waits on an Event Object.\r
+ *\r
+ * Params:\r
+ * CriticalSection - Critical section to acquire.\r
+ *\r
+ * Returns:\r
+ * STATUS_SUCCESS, or raises an exception if a deadlock is occuring.\r
+ *\r
+ * Remarks:\r
+ * None\r
+ *\r
+ *--*/\r
+NTSTATUS\r
+STDCALL\r
+RtlpWaitForCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)\r
+{\r
+ NTSTATUS Status;\r
+ EXCEPTION_RECORD ExceptionRecord;\r
+ BOOLEAN LastChance = FALSE;\r
+ LARGE_INTEGER Timeout;\r
+\r
+ /* Wait 2.5 minutes */\r
+ Timeout.QuadPart = 150000L * (ULONGLONG)10000;\r
+ Timeout.QuadPart = -Timeout.QuadPart;\r
+ /* ^^ HACK HACK HACK. Good way:\r
+ Timeout = &NtCurrentPeb()->CriticalSectionTimeout */\r
+\r
+ /* Do we have an Event yet? */\r
+ if (!CriticalSection->LockSemaphore) {\r
+ RtlpCreateCriticalSectionSem(CriticalSection);\r
+ }\r
+\r
+ /* Increase the Debug Entry count */\r
+ DPRINT("Waiting on Critical Section Event: %x %x\n",\r
+ CriticalSection,\r
+ CriticalSection->LockSemaphore);\r
+ CriticalSection->DebugInfo->EntryCount++;\r
+\r
+ for (;;) {\r
+\r
+ /* Increase the number of times we've had contention */\r
+ CriticalSection->DebugInfo->ContentionCount++;\r
+\r
+ /* Wait on the Event */\r
+ Status = NtWaitForSingleObject(CriticalSection->LockSemaphore,\r
+ FALSE,\r
+ &Timeout);\r
+\r
+ /* We have Timed out */\r
+ if (Status == STATUS_TIMEOUT) {\r
+\r
+ /* Is this the 2nd time we've timed out? */\r
+ if (LastChance) {\r
+\r
+ DPRINT1("Deadlock: %x\n", CriticalSection);\r
+\r
+ /* Yes it is, we are raising an exception */\r
+ ExceptionRecord.ExceptionCode = STATUS_POSSIBLE_DEADLOCK;\r
+ ExceptionRecord.ExceptionFlags = 0;\r
+ ExceptionRecord.ExceptionRecord = NULL;\r
+ ExceptionRecord.ExceptionAddress = RtlRaiseException;\r
+ ExceptionRecord.NumberParameters = 1;\r
+ ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR)CriticalSection;\r
+ RtlRaiseException(&ExceptionRecord);\r
+\r
+ }\r
+\r
+ /* One more try */\r
+ LastChance = TRUE;\r
+\r
+ } else {\r
+\r
+ /* If we are here, everything went fine */\r
+ return STATUS_SUCCESS;\r
+ }\r
+ }\r
+}\r
+\r
+/*++\r
+ * RtlpUnWaitCriticalSection\r
+ *\r
+ * Slow path of RtlLeaveCriticalSection. Fires an Event Object.\r
+ *\r
+ * Params:\r
+ * CriticalSection - Critical section to release.\r
+ *\r
+ * Returns:\r
+ * None. Raises an exception if the system call failed.\r
+ *\r
+ * Remarks:\r
+ * None\r
+ *\r
+ *--*/\r
+VOID\r
+STDCALL\r
+RtlpUnWaitCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)\r
+{\r
+ NTSTATUS Status;\r
+\r
+ /* Do we have an Event yet? */\r
+ if (!CriticalSection->LockSemaphore) {\r
+ RtlpCreateCriticalSectionSem(CriticalSection);\r
+ }\r
+\r
+ /* Signal the Event */\r
+ DPRINT("Signaling Critical Section Event: %x, %x\n",\r
+ CriticalSection,\r
+ CriticalSection->LockSemaphore);\r
+ Status = NtSetEvent(CriticalSection->LockSemaphore, NULL);\r
+\r
+ if (!NT_SUCCESS(Status)) {\r
+\r
+ /* We've failed */\r
+ DPRINT1("Signaling Failed for: %x, %x, %x\n",\r
+ CriticalSection,\r
+ CriticalSection->LockSemaphore,\r
+ Status);\r
+ RtlRaiseStatus(Status);\r
+ }\r
+}\r
+\r
+/*++\r
+ * RtlpInitDeferedCriticalSection\r
+ *\r
+ * Initializes the Critical Section implementation.\r
+ *\r
+ * Params:\r
+ * None\r
+ *\r
+ * Returns:\r
+ * None.\r
+ *\r
+ * Remarks:\r
+ * After this call, the Process Critical Section list is protected.\r
+ *\r
+ *--*/\r
+VOID\r
+STDCALL\r
+RtlpInitDeferedCriticalSection(VOID)\r
+{\r
+\r
+ /* Initialize the Process Critical Section List */\r
+ InitializeListHead(&RtlCriticalSectionList);\r
+\r
+ /* Initialize the CS Protecting the List */\r
+ RtlInitializeCriticalSection(&RtlCriticalSectionLock);\r
+\r
+ /* It's now safe to enter it */\r
+ RtlpCritSectInitialized = TRUE;\r
+}\r
+\r
+/*++\r
+ * RtlpAllocateDebugInfo\r
+ *\r
+ * Finds or allocates memory for a Critical Section Debug Object\r
+ *\r
+ * Params:\r
+ * None\r
+ *\r
+ * Returns:\r
+ * A pointer to an empty Critical Section Debug Object.\r
+ *\r
+ * Remarks:\r
+ * For optimization purposes, the first 64 entries can be cached. From\r
+ * then on, future Critical Sections will allocate memory from the heap.\r
+ *\r
+ *--*/\r
+PRTL_CRITICAL_SECTION_DEBUG\r
+STDCALL\r
+RtlpAllocateDebugInfo(VOID)\r
+{\r
+ ULONG i;\r
+\r
+ /* Try to allocate from our buffer first */\r
+ for (i = 0; i < MAX_STATIC_CS_DEBUG_OBJECTS; i++) {\r
+\r
+ /* Check if Entry is free */\r
+ if (!RtlpDebugInfoFreeList[i]) {\r
+\r
+ /* Mark entry in use */\r
+ DPRINT("Using entry: %d. Buffer: %x\n", i, &RtlpStaticDebugInfo[i]);\r
+ RtlpDebugInfoFreeList[i] = TRUE;\r
+\r
+ /* Use free entry found */\r
+ return &RtlpStaticDebugInfo[i];\r
+ }\r
+\r
+ }\r
+\r
+ /* We are out of static buffer, allocate dynamic */\r
+ return RtlAllocateHeap(NtCurrentPeb()->ProcessHeap,\r
+ 0,\r
+ sizeof(RTL_CRITICAL_SECTION_DEBUG));\r
+}\r
+\r
+/*++\r
+ * RtlpFreeDebugInfo\r
+ *\r
+ * Frees the memory for a Critical Section Debug Object\r
+ *\r
+ * Params:\r
+ * DebugInfo - Pointer to Critical Section Debug Object to free.\r
+ *\r
+ * Returns:\r
+ * None.\r
+ *\r
+ * Remarks:\r
+ * If the pointer is part of the static buffer, then the entry is made\r
+ * free again. If not, the object is de-allocated from the heap.\r
+ *\r
+ *--*/\r
+VOID\r
+STDCALL\r
+RtlpFreeDebugInfo(PRTL_CRITICAL_SECTION_DEBUG DebugInfo)\r
+{\r
+ ULONG EntryId;\r
+\r
+ /* Is it part of our cached entries? */\r
+ if ((DebugInfo >= RtlpStaticDebugInfo) &&\r
+ (DebugInfo <= &RtlpStaticDebugInfo[MAX_STATIC_CS_DEBUG_OBJECTS-1])) {\r
+\r
+ /* Yes. zero it out */\r
+ RtlZeroMemory(DebugInfo, sizeof(RTL_CRITICAL_SECTION_DEBUG));\r
+\r
+ /* Mark as free */\r
+ EntryId = (DebugInfo - RtlpStaticDebugInfo);\r
+ DPRINT("Freeing from Buffer: %x. Entry: %d inside Process: %x\n",\r
+ DebugInfo,\r
+ EntryId,\r
+ NtCurrentTeb()->Cid.UniqueProcess);\r
+ RtlpDebugInfoFreeList[EntryId] = FALSE;\r
+\r
+ } else {\r
+\r
+ /* It's a dynamic one, so free from the heap */\r
+ DPRINT("Freeing from Heap: %x inside Process: %x\n",\r
+ DebugInfo,\r
+ NtCurrentTeb()->Cid.UniqueProcess);\r
+ RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, DebugInfo);\r
+\r
+ }\r
+}\r
+\r
+/*++\r
+ * RtlDeleteCriticalSection\r
+ * @implemented NT4\r
+ *\r
+ * Deletes a Critical Section\r
+ *\r
+ * Params:\r
+ * CriticalSection - Critical section to delete.\r
+ *\r
+ * Returns:\r
+ * STATUS_SUCCESS, or error value returned by NtClose.\r
+ *\r
+ * Remarks:\r
+ * The critical section members should not be read after this call.\r
+ *\r
+ *--*/\r
+NTSTATUS\r
+STDCALL\r
+RtlDeleteCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)\r
+{\r
+ NTSTATUS Status = STATUS_SUCCESS;\r
+\r
+ DPRINT("Deleting Critical Section: %x\n", CriticalSection);\r
+ /* Close the Event Object Handle if it exists */\r
+ if (CriticalSection->LockSemaphore) {\r
+\r
+ /* In case NtClose fails, return the status */\r
+ Status = NtClose(CriticalSection->LockSemaphore);\r
+\r
+ }\r
+\r
+ /* Protect List */\r
+ RtlEnterCriticalSection(&RtlCriticalSectionLock);\r
+\r
+ /* Remove it from the list */\r
+ RemoveEntryList(&CriticalSection->DebugInfo->ProcessLocksList);\r
+\r
+ /* Unprotect */\r
+ RtlLeaveCriticalSection(&RtlCriticalSectionLock);\r
+\r
+ /* Free it */\r
+ RtlpFreeDebugInfo(CriticalSection->DebugInfo);\r
+\r
+ /* Wipe it out */\r
+ RtlZeroMemory(CriticalSection, sizeof(RTL_CRITICAL_SECTION));\r
+\r
+ /* Return */\r
+ return Status;\r
+}\r
+\r
+/*++\r
+ * RtlSetCriticalSectionSpinCount\r
+ * @implemented NT4\r
+ *\r
+ * Sets the spin count for a critical section.\r
+ *\r
+ * Params:\r
+ * CriticalSection - Critical section to set the spin count for.\r
+ *\r
+ * SpinCount - Spin count for the critical section.\r
+ *\r
+ * Returns:\r
+ * STATUS_SUCCESS.\r
+ *\r
+ * Remarks:\r
+ * SpinCount is ignored on single-processor systems.\r
+ *\r
+ *--*/\r
+DWORD\r
+STDCALL\r
+RtlSetCriticalSectionSpinCount(PRTL_CRITICAL_SECTION CriticalSection,\r
+ ULONG SpinCount)\r
+{\r
+ ULONG OldCount = CriticalSection->SpinCount;\r
+\r
+ /* Set to parameter if MP, or to 0 if this is Uniprocessor */\r
+ CriticalSection->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? SpinCount : 0;\r
+ return OldCount;\r
+}\r
+\r
+/*++\r
+ * RtlEnterCriticalSection\r
+ * @implemented NT4\r
+ *\r
+ * Waits to gain ownership of the critical section.\r
+ *\r
+ * Params:\r
+ * CriticalSection - Critical section to wait for.\r
+ *\r
+ * Returns:\r
+ * STATUS_SUCCESS.\r
+ *\r
+ * Remarks:\r
+ * Uses a fast-path unless contention happens.\r
+ *\r
+ *--*/\r
+NTSTATUS\r
+STDCALL\r
+RtlEnterCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)\r
+{\r
+ HANDLE Thread = (HANDLE)NtCurrentTeb()->Cid.UniqueThread;\r
+\r
+ /* Try to Lock it */\r
+ if (InterlockedIncrement(&CriticalSection->LockCount) != 0) {\r
+\r
+ /*\r
+ * We've failed to lock it! Does this thread\r
+ * actually own it?\r
+ */\r
+ if (Thread == CriticalSection->OwningThread) {\r
+\r
+ /* You own it, so you'll get it when you're done with it! No need to\r
+ use the interlocked functions as only the thread who already owns\r
+ the lock can modify this data. */\r
+ CriticalSection->RecursionCount++;\r
+ return STATUS_SUCCESS;\r
+ }\r
+\r
+ /* NOTE - CriticalSection->OwningThread can be NULL here because changing\r
+ this information is not serialized. This happens when thread a\r
+ acquires the lock (LockCount == 0) and thread b tries to\r
+ acquire it as well (LockCount == 1) but thread a hasn't had a\r
+ chance to set the OwningThread! So it's not an error when\r
+ OwningThread is NULL here! */\r
+\r
+ /* We don't own it, so we must wait for it */\r
+ RtlpWaitForCriticalSection(CriticalSection);\r
+ }\r
+\r
+ /* Lock successful. Changing this information has not to be serialized because\r
+ only one thread at a time can actually change it (the one who acquired\r
+ the lock)! */\r
+ CriticalSection->OwningThread = Thread;\r
+ CriticalSection->RecursionCount = 1;\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+/*++\r
+ * RtlInitializeCriticalSection\r
+ * @implemented NT4\r
+ *\r
+ * Initialises a new critical section.\r
+ *\r
+ * Params:\r
+ * CriticalSection - Critical section to initialise\r
+ *\r
+ * Returns:\r
+ * STATUS_SUCCESS.\r
+ *\r
+ * Remarks:\r
+ * Simply calls RtlInitializeCriticalSectionAndSpinCount\r
+ *\r
+ *--*/\r
+NTSTATUS\r
+STDCALL\r
+RtlInitializeCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)\r
+{\r
+ /* Call the Main Function */\r
+ return RtlInitializeCriticalSectionAndSpinCount(CriticalSection, 0);\r
+}\r
+\r
+/*++\r
+ * RtlInitializeCriticalSectionAndSpinCount\r
+ * @implemented NT4\r
+ *\r
+ * Initialises a new critical section.\r
+ *\r
+ * Params:\r
+ * CriticalSection - Critical section to initialise\r
+ *\r
+ * SpinCount - Spin count for the critical section.\r
+ *\r
+ * Returns:\r
+ * STATUS_SUCCESS.\r
+ *\r
+ * Remarks:\r
+ * SpinCount is ignored on single-processor systems.\r
+ *\r
+ *--*/\r
+NTSTATUS\r
+STDCALL\r
+RtlInitializeCriticalSectionAndSpinCount(PRTL_CRITICAL_SECTION CriticalSection,\r
+ ULONG SpinCount)\r
+{\r
+ PRTL_CRITICAL_SECTION_DEBUG CritcalSectionDebugData;\r
+\r
+ /* First things first, set up the Object */\r
+ DPRINT("Initializing Critical Section: %x\n", CriticalSection);\r
+ CriticalSection->LockCount = -1;\r
+ CriticalSection->RecursionCount = 0;\r
+ CriticalSection->OwningThread = 0;\r
+ CriticalSection->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? SpinCount : 0;\r
+ CriticalSection->LockSemaphore = 0;\r
+\r
+ /* Allocate the Debug Data */\r
+ CritcalSectionDebugData = RtlpAllocateDebugInfo();\r
+ DPRINT("Allocated Debug Data: %x inside Process: %x\n",\r
+ CritcalSectionDebugData,\r
+ NtCurrentTeb()->Cid.UniqueProcess);\r
+\r
+ if (!CritcalSectionDebugData) {\r
+\r
+ /* This is bad! */\r
+ DPRINT1("Couldn't allocate Debug Data for: %x\n", CriticalSection);\r
+ return STATUS_NO_MEMORY;\r
+ }\r
+\r
+ /* Set it up */\r
+ CritcalSectionDebugData->Type = RTL_CRITSECT_TYPE;\r
+ CritcalSectionDebugData->ContentionCount = 0;\r
+ CritcalSectionDebugData->EntryCount = 0;\r
+ CritcalSectionDebugData->CriticalSection = CriticalSection;\r
+ CriticalSection->DebugInfo = CritcalSectionDebugData;\r
+\r
+ /*\r
+ * Add it to the List of Critical Sections owned by the process.\r
+ * If we've initialized the Lock, then use it. If not, then probably\r
+ * this is the lock initialization itself, so insert it directly.\r
+ */\r
+ if ((CriticalSection != &RtlCriticalSectionLock) && (RtlpCritSectInitialized)) {\r
+\r
+ DPRINT("Securely Inserting into ProcessLocks: %x, %x, %x\n",\r
+ &CritcalSectionDebugData->ProcessLocksList,\r
+ CriticalSection,\r
+ &RtlCriticalSectionList);\r
+\r
+ /* Protect List */\r
+ RtlEnterCriticalSection(&RtlCriticalSectionLock);\r
+\r
+ /* Add this one */\r
+ InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList);\r
+\r
+ /* Unprotect */\r
+ RtlLeaveCriticalSection(&RtlCriticalSectionLock);\r
+\r
+ } else {\r
+\r
+ DPRINT("Inserting into ProcessLocks: %x, %x, %x\n",\r
+ &CritcalSectionDebugData->ProcessLocksList,\r
+ CriticalSection,\r
+ &RtlCriticalSectionList);\r
+\r
+ /* Add it directly */\r
+ InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList);\r
+ }\r
+\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+/*++\r
+ * RtlLeaveCriticalSection\r
+ * @implemented NT4\r
+ *\r
+ * Releases a critical section and makes if available for new owners.\r
+ *\r
+ * Params:\r
+ * CriticalSection - Critical section to release.\r
+ *\r
+ * Returns:\r
+ * STATUS_SUCCESS.\r
+ *\r
+ * Remarks:\r
+ * If another thread was waiting, the slow path is entered.\r
+ *\r
+ *--*/\r
+NTSTATUS\r
+STDCALL\r
+RtlLeaveCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)\r
+{\r
+#ifndef NDEBUG\r
+ HANDLE Thread = (HANDLE)NtCurrentTeb()->Cid.UniqueThread;\r
+\r
+ /* In win this case isn't checked. However it's a valid check so it should only\r
+ be performed in debug builds! */\r
+ if (Thread != CriticalSection->OwningThread)\r
+ {\r
+ DPRINT1("Releasing critical section not owned!\n");\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+#endif\r
+\r
+ /* Decrease the Recursion Count. No need to do this atomically because only\r
+ the thread who holds the lock can call this function (unless the program\r
+ is totally screwed... */\r
+ if (--CriticalSection->RecursionCount) {\r
+\r
+ /* Someone still owns us, but we are free. This needs to be done atomically. */\r
+ InterlockedDecrement(&CriticalSection->LockCount);\r
+\r
+ } else {\r
+\r
+ /* Nobody owns us anymore. No need to do this atomically. See comment\r
+ above. */\r
+ CriticalSection->OwningThread = 0;\r
+\r
+ /* Was someone wanting us? This needs to be done atomically. */\r
+ if (-1 != InterlockedDecrement(&CriticalSection->LockCount)) {\r
+\r
+ /* Let him have us */\r
+ RtlpUnWaitCriticalSection(CriticalSection);\r
+ }\r
+ }\r
+\r
+ /* Sucessful! */\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+/*++\r
+ * RtlTryEnterCriticalSection\r
+ * @implemented NT4\r
+ *\r
+ * Attemps to gain ownership of the critical section without waiting.\r
+ *\r
+ * Params:\r
+ * CriticalSection - Critical section to attempt acquiring.\r
+ *\r
+ * Returns:\r
+ * TRUE if the critical section has been acquired, FALSE otherwise.\r
+ *\r
+ * Remarks:\r
+ * None\r
+ *\r
+ *--*/\r
+BOOLEAN\r
+STDCALL\r
+RtlTryEnterCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)\r
+{\r
+ /* Try to take control */\r
+ if (InterlockedCompareExchange(&CriticalSection->LockCount,\r
+ 0,\r
+ -1) == -1) {\r
+\r
+ /* It's ours */\r
+ CriticalSection->OwningThread = NtCurrentTeb()->Cid.UniqueThread;\r
+ CriticalSection->RecursionCount = 1;\r
+ return TRUE;\r
+\r
+ } else if (CriticalSection->OwningThread == NtCurrentTeb()->Cid.UniqueThread) {\r
+\r
+ /* It's already ours */\r
+ InterlockedIncrement(&CriticalSection->LockCount);\r
+ CriticalSection->RecursionCount++;\r
+ return TRUE;\r
+ }\r
+\r
+ /* It's not ours */\r
+ return FALSE;\r
+}\r
+\r
+/* EOF */\r
/* Initialize critical section */
- RtlInitializeCriticalSection( &heap->critSection );
+ RtlInitializeHeapLock( &heap->critSection );
}
/* Commit memory */
return 0;
flags |= heapPtr->flags;
if (!(flags & HEAP_NO_SERIALIZE))
- RtlEnterCriticalSection( &heapPtr->critSection );
+ RtlEnterHeapLock( &heapPtr->critSection );
ret = (((subheap = HEAP_FindSubHeap( heapPtr, ptr )) != NULL) &&
(((char *)ptr >= (char *)subheap + subheap->headerSize
+ sizeof(ARENA_INUSE))));
if (!(flags & HEAP_NO_SERIALIZE))
- RtlLeaveCriticalSection( &heapPtr->critSection );
+ RtlLeaveHeapLock( &heapPtr->critSection );
return ret;
}
flags |= heapPtr->flags;
/* calling HeapLock may result in infinite recursion, so do the critsect directly */
if (!(flags & HEAP_NO_SERIALIZE))
- RtlEnterCriticalSection( &heapPtr->critSection );
+ RtlEnterHeapLock( &heapPtr->critSection );
if (block)
{
ret = HEAP_ValidateInUseArena( subheap, (ARENA_INUSE *)block - 1, quiet );
if (!(flags & HEAP_NO_SERIALIZE))
- RtlLeaveCriticalSection( &heapPtr->critSection );
+ RtlLeaveHeapLock( &heapPtr->critSection );
return ret;
}
}
if (!(flags & HEAP_NO_SERIALIZE))
- RtlLeaveCriticalSection( &heapPtr->critSection );
+ RtlLeaveHeapLock( &heapPtr->critSection );
return ret;
}
if (RtlpGetMode() == UserMode)
{
/* link it into the per-process heap list */
- RtlEnterCriticalSection (&RtlpProcessHeapsListLock);
+ RtlEnterHeapLock (&RtlpProcessHeapsListLock);
heapPtr = subheap->heap;
heapPtr->next = (HEAP*)NtCurrentPeb()->ProcessHeaps;
NtCurrentPeb()->ProcessHeaps = (HANDLE)heapPtr;
NtCurrentPeb()->NumberOfHeaps++;
- RtlLeaveCriticalSection (&RtlpProcessHeapsListLock);
+ RtlLeaveHeapLock (&RtlpProcessHeapsListLock);
}
return (HANDLE)subheap;
return heap; /* cannot delete the main process heap */
/* remove it from the per-process list */
- RtlEnterCriticalSection (&RtlpProcessHeapsListLock);
+ RtlEnterHeapLock (&RtlpProcessHeapsListLock);
pptr = (HEAP**)&NtCurrentPeb()->ProcessHeaps;
while (*pptr && *pptr != heapPtr) pptr = &(*pptr)->next;
if (*pptr) *pptr = (*pptr)->next;
NtCurrentPeb()->NumberOfHeaps--;
- RtlLeaveCriticalSection (&RtlpProcessHeapsListLock);
+ RtlLeaveHeapLock (&RtlpProcessHeapsListLock);
}
- RtlDeleteCriticalSection( &heapPtr->critSection );
+ RtlDeleteHeapLock( &heapPtr->critSection );
subheap = &heapPtr->subheap;
// We must save the flags. The first subheap is located after
// the heap structure. If we release the first subheap,
flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY;
flags |= heapPtr->flags;
if (!(flags & HEAP_NO_SERIALIZE))
- RtlEnterCriticalSection( &heapPtr->critSection );
+ RtlEnterHeapLock( &heapPtr->critSection );
size = (size + 7) & ~7;
if (size < HEAP_MIN_BLOCK_SIZE)
size = HEAP_MIN_BLOCK_SIZE;
DPRINT("(%08x,%08lx,%08lx): returning NULL\n",
heap, flags, size );
if (!(flags & HEAP_NO_SERIALIZE))
- RtlLeaveCriticalSection( &heapPtr->critSection );
+ RtlLeaveHeapLock( &heapPtr->critSection );
if (flags & HEAP_GENERATE_EXCEPTIONS)
RtlRaiseStatus( STATUS_NO_MEMORY );
return NULL;
memset( pInUse + 1, ARENA_INUSE_FILLER, pInUse->size & ARENA_SIZE_MASK );
if (!(flags & HEAP_NO_SERIALIZE))
- RtlLeaveCriticalSection( &heapPtr->critSection );
+ RtlLeaveHeapLock( &heapPtr->critSection );
DPRINT("(%08x,%08lx,%08lx): returning %p\n",
heap, flags, size, (PVOID)(pInUse + 1) );
flags &= HEAP_NO_SERIALIZE;
flags |= heapPtr->flags;
if (!(flags & HEAP_NO_SERIALIZE))
- RtlEnterCriticalSection( &heapPtr->critSection );
+ RtlEnterHeapLock( &heapPtr->critSection );
if (!HEAP_IsRealArena( heap, HEAP_NO_SERIALIZE, ptr, QUIET ))
{
if (!(flags & HEAP_NO_SERIALIZE))
- RtlLeaveCriticalSection( &heapPtr->critSection );
+ RtlLeaveHeapLock( &heapPtr->critSection );
DPRINT("(%08x,%08lx,%p): returning FALSE\n",
heap, flags, ptr );
return FALSE;
HEAP_MakeInUseBlockFree( subheap, pInUse, heapPtr->flags );
if (!(flags & HEAP_NO_SERIALIZE))
- RtlLeaveCriticalSection( &heapPtr->critSection );
+ RtlLeaveHeapLock( &heapPtr->critSection );
DPRINT("(%08x,%08lx,%p): returning TRUE\n",
heap, flags, ptr );
Size = HEAP_MIN_BLOCK_SIZE;
if (!(Flags & HEAP_NO_SERIALIZE))
- RtlEnterCriticalSection( &heapPtr->critSection );
+ RtlEnterHeapLock( &heapPtr->critSection );
if (!HEAP_IsRealArena( Heap, HEAP_NO_SERIALIZE, Ptr, QUIET ))
{
if (!(Flags & HEAP_NO_SERIALIZE))
- RtlLeaveCriticalSection( &heapPtr->critSection );
+ RtlLeaveHeapLock( &heapPtr->critSection );
DPRINT("(%08x,%08lx,%p,%08lx): returning NULL\n",
Heap, Flags, Ptr, Size );
if (Flags & HEAP_GENERATE_EXCEPTIONS)
heapPtr->flags))
{
if (!(Flags & HEAP_NO_SERIALIZE))
- RtlLeaveCriticalSection( &heapPtr->critSection );
+ RtlLeaveHeapLock( &heapPtr->critSection );
if (Flags & HEAP_GENERATE_EXCEPTIONS)
RtlRaiseStatus( STATUS_NO_MEMORY );
return NULL;
!(pNew = HEAP_FindFreeBlock( heapPtr, Size, &newsubheap )))
{
if (!(Flags & HEAP_NO_SERIALIZE))
- RtlLeaveCriticalSection( &heapPtr->critSection );
+ RtlLeaveHeapLock( &heapPtr->critSection );
if (Flags & HEAP_GENERATE_EXCEPTIONS)
RtlRaiseStatus( STATUS_NO_MEMORY );
return NULL;
/* Return the new arena */
if (!(Flags & HEAP_NO_SERIALIZE))
- RtlLeaveCriticalSection( &heapPtr->critSection );
+ RtlLeaveHeapLock( &heapPtr->critSection );
DPRINT("(%08x,%08lx,%p,%08lx): returning %p\n",
Heap, Flags, Ptr, Size, (PVOID)(pArena + 1) );
HEAP *heapPtr = HEAP_GetPtr( Heap );
if (!heapPtr)
return FALSE;
- RtlEnterCriticalSection( &heapPtr->critSection );
+ RtlEnterHeapLock( &heapPtr->critSection );
return TRUE;
}
HEAP *heapPtr = HEAP_GetPtr( Heap );
if (!heapPtr)
return FALSE;
- RtlLeaveCriticalSection( &heapPtr->critSection );
+ RtlLeaveHeapLock( &heapPtr->critSection );
return TRUE;
}
Flags &= HEAP_NO_SERIALIZE;
Flags |= heapPtr->flags;
if (!(Flags & HEAP_NO_SERIALIZE))
- RtlEnterCriticalSection( &heapPtr->critSection );
+ RtlEnterHeapLock( &heapPtr->critSection );
if (!HEAP_IsRealArena( Heap, HEAP_NO_SERIALIZE, Ptr, QUIET ))
{
ret = 0xffffffff;
ret = pArena->size & ARENA_SIZE_MASK;
}
if (!(Flags & HEAP_NO_SERIALIZE))
- RtlLeaveCriticalSection( &heapPtr->critSection );
+ RtlLeaveHeapLock( &heapPtr->critSection );
DPRINT("(%08x,%08lx,%p): returning %08lx\n",
Heap, Flags, Ptr, ret );
}
if (!(heapPtr->flags & HEAP_NO_SERIALIZE))
- RtlEnterCriticalSection( &heapPtr->critSection );
+ RtlEnterHeapLock( &heapPtr->critSection );
/* set ptr to the next arena to be examined */
HW_end:
if (!(heapPtr->flags & HEAP_NO_SERIALIZE))
- RtlLeaveCriticalSection( &heapPtr->critSection );
+ RtlLeaveHeapLock( &heapPtr->critSection );
return ret;
}
Peb->MaximumNumberOfHeaps = -1; /* no limit */
Peb->ProcessHeaps = NULL;
- RtlInitializeCriticalSection(&RtlpProcessHeapsListLock);
+ RtlInitializeHeapLock(&RtlpProcessHeapsListLock);
}
NTSTATUS Status = STATUS_SUCCESS;
HEAP** pptr;
- RtlEnterCriticalSection(&RtlpProcessHeapsListLock);
+ RtlEnterHeapLock(&RtlpProcessHeapsListLock);
for (pptr = (HEAP**)&NtCurrentPeb()->ProcessHeaps; *pptr; pptr = &(*pptr)->next)
{
break;
}
- RtlLeaveCriticalSection(&RtlpProcessHeapsListLock);
+ RtlLeaveHeapLock(&RtlpProcessHeapsListLock);
return Status;
}
ULONG Result = 0;
HEAP ** pptr;
- RtlEnterCriticalSection(&RtlpProcessHeapsListLock);
+ RtlEnterHeapLock(&RtlpProcessHeapsListLock);
Result = NtCurrentPeb()->NumberOfHeaps;
}
}
- RtlLeaveCriticalSection (&RtlpProcessHeapsListLock);
+ RtlLeaveHeapLock (&RtlpProcessHeapsListLock);
return Result;
}
BOOLEAN Result = TRUE;
HEAP ** pptr;
- RtlEnterCriticalSection(&RtlpProcessHeapsListLock);
+ RtlEnterHeapLock(&RtlpProcessHeapsListLock);
for (pptr = (HEAP**)&NtCurrentPeb()->ProcessHeaps; *pptr; pptr = &(*pptr)->next)
{
}
}
- RtlLeaveCriticalSection (&RtlpProcessHeapsListLock);
+ RtlLeaveHeapLock (&RtlpProcessHeapsListLock);
return Result;
}
-/* $Id$
- *
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * PURPOSE: User-mode exception support
- * FILE: lib/ntdll/rtl/exception.c
- * PROGRAMERS: David Welch <welch@cwcom.net>
- * Skywing <skywing@valhallalegends.com>
- * KJK::Hyperion <noog@libero.it>
- * UPDATES: Skywing, 09/11/2003: Implemented RtlRaiseException and
- * KiUserRaiseExceptionDispatcher.
- * KJK::Hyperion, 22/06/2003: Moved common parts to rtl
- */
-
-/* INCLUDES *****************************************************************/
-
-#include <ntdll.h>
-#define NDEBUG
-#include <debug.h>
-
-static RTL_CRITICAL_SECTION RtlpVectoredExceptionLock;
-static LIST_ENTRY RtlpVectoredExceptionHead;
-
-typedef struct _RTL_VECTORED_EXCEPTION_HANDLER
-{
- LIST_ENTRY ListEntry;
- PVECTORED_EXCEPTION_HANDLER VectoredHandler;
-} RTL_VECTORED_EXCEPTION_HANDLER, *PRTL_VECTORED_EXCEPTION_HANDLER;
-
-/* FIXME - stupid ld won't resolve RtlDecodePointer! Since their implementation
- is the same just use RtlEncodePointer for now! */
-#define RtlDecodePointer RtlEncodePointer
-
-/* FUNCTIONS ***************************************************************/
-
-VOID STDCALL
-RtlBaseProcessStart(PTHREAD_START_ROUTINE StartAddress,
- PVOID Parameter);
-
-__declspec(dllexport)
-PRTL_BASE_PROCESS_START_ROUTINE RtlBaseProcessStartRoutine = RtlBaseProcessStart;
-
-ULONG
-RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
- IN PCONTEXT Context);
-
-EXCEPTION_DISPOSITION
-RtlpExecuteVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord,
- IN PCONTEXT Context)
-{
- PLIST_ENTRY CurrentEntry;
- PRTL_VECTORED_EXCEPTION_HANDLER veh;
- PVECTORED_EXCEPTION_HANDLER VectoredHandler;
- EXCEPTION_POINTERS ExceptionInfo;
-
- ExceptionInfo.ExceptionRecord = ExceptionRecord;
- ExceptionInfo.ContextRecord = Context;
-
- if(RtlpVectoredExceptionHead.Flink != &RtlpVectoredExceptionHead)
- {
- RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
- for(CurrentEntry = RtlpVectoredExceptionHead.Flink;
- CurrentEntry != &RtlpVectoredExceptionHead;
- CurrentEntry = CurrentEntry->Flink)
- {
- veh = CONTAINING_RECORD(CurrentEntry,
- RTL_VECTORED_EXCEPTION_HANDLER,
- ListEntry);
- VectoredHandler = RtlDecodePointer(veh->VectoredHandler);
- if(VectoredHandler(&ExceptionInfo) == EXCEPTION_CONTINUE_EXECUTION)
- {
- RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
- return ExceptionContinueSearch;
- }
- }
- RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
- }
-
- return ExceptionContinueExecution;
-}
-
-VOID STDCALL
-KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord,
- PCONTEXT Context)
-{
- EXCEPTION_RECORD NestedExceptionRecord;
- NTSTATUS Status;
-
- if(RtlpExecuteVectoredExceptionHandlers(ExceptionRecord,
- Context) != ExceptionContinueExecution)
- {
- Status = NtContinue(Context, FALSE);
- }
- else
- {
- if(RtlpDispatchException(ExceptionRecord, Context) != ExceptionContinueExecution)
- {
- Status = NtContinue(Context, FALSE);
- }
- else
- {
- Status = NtRaiseException(ExceptionRecord, Context, FALSE);
- }
- }
-
- NestedExceptionRecord.ExceptionCode = Status;
- NestedExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
- NestedExceptionRecord.ExceptionRecord = ExceptionRecord;
- NestedExceptionRecord.NumberParameters = Status;
-
- RtlRaiseException(&NestedExceptionRecord);
-}
-
-
-/*
- * @implemented
- */
-VOID STDCALL
-KiRaiseUserExceptionDispatcher(VOID)
-{
- EXCEPTION_RECORD ExceptionRecord;
-
- ExceptionRecord.ExceptionCode = ((PTEB)NtCurrentTeb())->ExceptionCode;
- ExceptionRecord.ExceptionFlags = 0;
- ExceptionRecord.ExceptionRecord = NULL;
- ExceptionRecord.NumberParameters = 0;
-
- RtlRaiseException(&ExceptionRecord);
-}
-
-VOID STDCALL
-RtlBaseProcessStart(PTHREAD_START_ROUTINE StartAddress,
- PVOID Parameter)
-{
- NTSTATUS ExitStatus = STATUS_SUCCESS;
-
- ExitStatus = (NTSTATUS) (StartAddress)(Parameter);
-
- NtTerminateProcess(NtCurrentProcess(), ExitStatus);
-}
-
-
-VOID
-RtlpInitializeVectoredExceptionHandling(VOID)
-{
- InitializeListHead(&RtlpVectoredExceptionHead);
- RtlInitializeCriticalSection(&RtlpVectoredExceptionLock);
-}
-
-
-/*
- * @implemented
- */
-PVOID STDCALL
-RtlAddVectoredExceptionHandler(IN ULONG FirstHandler,
- IN PVECTORED_EXCEPTION_HANDLER VectoredHandler)
-{
- PRTL_VECTORED_EXCEPTION_HANDLER veh;
-
- veh = RtlAllocateHeap(RtlGetProcessHeap(),
- 0,
- sizeof(RTL_VECTORED_EXCEPTION_HANDLER));
- if(veh != NULL)
- {
- veh->VectoredHandler = RtlEncodePointer(VectoredHandler);
- RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
- if(FirstHandler != 0)
- {
- InsertHeadList(&RtlpVectoredExceptionHead,
- &veh->ListEntry);
- }
- else
- {
- InsertTailList(&RtlpVectoredExceptionHead,
- &veh->ListEntry);
- }
- RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
- }
-
- return veh;
-}
-
-
-/*
- * @implemented
- */
-ULONG STDCALL
-RtlRemoveVectoredExceptionHandler(IN PVOID VectoredHandlerHandle)
-{
- PLIST_ENTRY CurrentEntry;
- PRTL_VECTORED_EXCEPTION_HANDLER veh = NULL;
- ULONG Removed = FALSE;
-
- RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
- for(CurrentEntry = RtlpVectoredExceptionHead.Flink;
- CurrentEntry != &RtlpVectoredExceptionHead;
- CurrentEntry = CurrentEntry->Flink)
- {
- veh = CONTAINING_RECORD(CurrentEntry,
- RTL_VECTORED_EXCEPTION_HANDLER,
- ListEntry);
- if(veh == VectoredHandlerHandle)
- {
- RemoveEntryList(&veh->ListEntry);
- Removed = TRUE;
- break;
- }
- }
- RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
-
- if(Removed)
- {
- RtlFreeHeap(RtlGetProcessHeap(),
- 0,
- veh);
- }
-
- return Removed;
-}
-
-/* EOF */
+/*\r
+ * COPYRIGHT: See COPYING in the top level directory\r
+ * PROJECT: ReactOS sysem libraries\r
+ * PURPOSE: Vectored Exception Handling\r
+ * FILE: lib/rtl/vectoreh.c\r
+ * PROGRAMERS: Thomas Weidenmueller\r
+ */\r
+\r
+/* INCLUDES *****************************************************************/\r
+\r
+#include <rtl.h>\r
+\r
+#define NDEBUG\r
+#include <debug.h>\r
+\r
+static RTL_CRITICAL_SECTION RtlpVectoredExceptionLock;\r
+static LIST_ENTRY RtlpVectoredExceptionHead;\r
+\r
+typedef struct _RTL_VECTORED_EXCEPTION_HANDLER\r
+{\r
+ LIST_ENTRY ListEntry;\r
+ PVECTORED_EXCEPTION_HANDLER VectoredHandler;\r
+} RTL_VECTORED_EXCEPTION_HANDLER, *PRTL_VECTORED_EXCEPTION_HANDLER;\r
+\r
+/* FIXME - stupid ld won't resolve RtlDecodePointer! Since their implementation\r
+ is the same just use RtlEncodePointer for now! */\r
+#define RtlDecodePointer RtlEncodePointer\r
+\r
+/* FUNCTIONS ***************************************************************/\r
+\r
+EXCEPTION_DISPOSITION\r
+RtlpExecuteVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord,\r
+ IN PCONTEXT Context)\r
+{\r
+ PLIST_ENTRY CurrentEntry;\r
+ PRTL_VECTORED_EXCEPTION_HANDLER veh;\r
+ PVECTORED_EXCEPTION_HANDLER VectoredHandler;\r
+ EXCEPTION_POINTERS ExceptionInfo;\r
+\r
+ ExceptionInfo.ExceptionRecord = ExceptionRecord;\r
+ ExceptionInfo.ContextRecord = Context;\r
+\r
+ if(RtlpVectoredExceptionHead.Flink != &RtlpVectoredExceptionHead)\r
+ {\r
+ RtlEnterCriticalSection(&RtlpVectoredExceptionLock);\r
+ for(CurrentEntry = RtlpVectoredExceptionHead.Flink;\r
+ CurrentEntry != &RtlpVectoredExceptionHead;\r
+ CurrentEntry = CurrentEntry->Flink)\r
+ {\r
+ veh = CONTAINING_RECORD(CurrentEntry,\r
+ RTL_VECTORED_EXCEPTION_HANDLER,\r
+ ListEntry);\r
+ VectoredHandler = RtlDecodePointer(veh->VectoredHandler);\r
+ if(VectoredHandler(&ExceptionInfo) == EXCEPTION_CONTINUE_EXECUTION)\r
+ {\r
+ RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);\r
+ return ExceptionContinueSearch;\r
+ }\r
+ }\r
+ RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);\r
+ }\r
+\r
+ return ExceptionContinueExecution;\r
+}\r
+\r
+VOID\r
+RtlpInitializeVectoredExceptionHandling(VOID)\r
+{\r
+ InitializeListHead(&RtlpVectoredExceptionHead);\r
+ RtlInitializeCriticalSection(&RtlpVectoredExceptionLock);\r
+}\r
+\r
+\r
+/*\r
+ * @implemented\r
+ */\r
+PVOID STDCALL\r
+RtlAddVectoredExceptionHandler(IN ULONG FirstHandler,\r
+ IN PVECTORED_EXCEPTION_HANDLER VectoredHandler)\r
+{\r
+ PRTL_VECTORED_EXCEPTION_HANDLER veh;\r
+\r
+ veh = RtlAllocateHeap(RtlGetProcessHeap(),\r
+ 0,\r
+ sizeof(RTL_VECTORED_EXCEPTION_HANDLER));\r
+ if(veh != NULL)\r
+ {\r
+ veh->VectoredHandler = RtlEncodePointer(VectoredHandler);\r
+ RtlEnterCriticalSection(&RtlpVectoredExceptionLock);\r
+ if(FirstHandler != 0)\r
+ {\r
+ InsertHeadList(&RtlpVectoredExceptionHead,\r
+ &veh->ListEntry);\r
+ }\r
+ else\r
+ {\r
+ InsertTailList(&RtlpVectoredExceptionHead,\r
+ &veh->ListEntry);\r
+ }\r
+ RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);\r
+ }\r
+\r
+ return veh;\r
+}\r
+\r
+\r
+/*\r
+ * @implemented\r
+ */\r
+ULONG STDCALL\r
+RtlRemoveVectoredExceptionHandler(IN PVOID VectoredHandlerHandle)\r
+{\r
+ PLIST_ENTRY CurrentEntry;\r
+ PRTL_VECTORED_EXCEPTION_HANDLER veh = NULL;\r
+ ULONG Removed = FALSE;\r
+\r
+ RtlEnterCriticalSection(&RtlpVectoredExceptionLock);\r
+ for(CurrentEntry = RtlpVectoredExceptionHead.Flink;\r
+ CurrentEntry != &RtlpVectoredExceptionHead;\r
+ CurrentEntry = CurrentEntry->Flink)\r
+ {\r
+ veh = CONTAINING_RECORD(CurrentEntry,\r
+ RTL_VECTORED_EXCEPTION_HANDLER,\r
+ ListEntry);\r
+ if(veh == VectoredHandlerHandle)\r
+ {\r
+ RemoveEntryList(&veh->ListEntry);\r
+ Removed = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);\r
+\r
+ if(Removed)\r
+ {\r
+ RtlFreeHeap(RtlGetProcessHeap(),\r
+ 0,\r
+ veh);\r
+ }\r
+\r
+ return Removed;\r
+}\r
+\r
+/* EOF */\r