diff --git a/reactos/include/funcs.h b/reactos/include/funcs.h index 8b7cdbfdce2..573b18eecd6 100644 --- a/reactos/include/funcs.h +++ b/reactos/include/funcs.h @@ -2082,8 +2082,6 @@ VOID STDCALL WEP(); DWORD STDCALL RtlDeleteSecurityObject(DWORD x1); DWORD STDCALL RtlNewSecurityObject(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5,DWORD x6); NTSTATUS STDCALL RtlWalkHeap( HANDLE heap, PVOID entry_ptr ); -NTSTATUS STDCALL RtlpUnWaitCriticalSection(RTL_CRITICAL_SECTION *crit); -NTSTATUS STDCALL RtlpWaitForCriticalSection(RTL_CRITICAL_SECTION *crit); NTSTATUS STDCALL LdrLockLoaderLock(ULONG flags, ULONG *result, ULONG *magic); NTSTATUS STDCALL LdrUnlockLoaderLock(ULONG flags, ULONG magic); diff --git a/reactos/include/ntdll/rtl.h b/reactos/include/ntdll/rtl.h index c400129f009..6cd6ada5f7c 100644 --- a/reactos/include/ntdll/rtl.h +++ b/reactos/include/ntdll/rtl.h @@ -99,8 +99,8 @@ typedef struct _CRITICAL_SECTION_DEBUG LIST_ENTRY ProcessLocksList; ULONG EntryCount; ULONG ContentionCount; - ULONG Depth; - PVOID Spare[ 2 ]; + PVOID OwnerBackTrace[2]; + PVOID Spare[2]; } CRITICAL_SECTION_DEBUG, *PCRITICAL_SECTION_DEBUG; @@ -114,9 +114,13 @@ typedef struct _CRITICAL_SECTION ULONG_PTR SpinCount; } CRITICAL_SECTION, *PCRITICAL_SECTION, *LPCRITICAL_SECTION; +#define RTL_CRITSECT_TYPE 0 + typedef CRITICAL_SECTION RTL_CRITICAL_SECTION; typedef PCRITICAL_SECTION PRTL_CRITICAL_SECTION; typedef LPCRITICAL_SECTION LPRTL_CRITICAL_SECTION; +typedef CRITICAL_SECTION_DEBUG RTL_CRITICAL_SECTION_DEBUG; +typedef PCRITICAL_SECTION_DEBUG PRTL_CRITICAL_SECTION_DEBUG; #endif /* !__USE_W32API */ @@ -166,6 +170,29 @@ typedef struct _RTL_HANDLE_TABLE #define PDI_HEAP_BLOCKS 0x10 /* The heap blocks */ #define PDI_LOCKS 0x20 /* The locks created by the process */ +NTSTATUS +STDCALL +RtlpWaitForCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection +); + +VOID +STDCALL +RtlpUnWaitCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection +); + +VOID +STDCALL +RtlpCreateCriticalSectionSem( + PRTL_CRITICAL_SECTION CriticalSection +); + +VOID +STDCALL +RtlpInitDeferedCriticalSection( + VOID +); NTSTATUS STDCALL RtlAddAccessAllowedAceEx (IN OUT PACL Acl, @@ -191,19 +218,19 @@ RtlAddAuditAccessAceEx(IN OUT PACL Acl, IN BOOLEAN Failure); NTSTATUS STDCALL -RtlDeleteCriticalSection (PCRITICAL_SECTION CriticalSection); +RtlDeleteCriticalSection (PRTL_CRITICAL_SECTION CriticalSection); WCHAR STDCALL RtlDowncaseUnicodeChar(IN WCHAR Source); NTSTATUS STDCALL -RtlEnterCriticalSection (PCRITICAL_SECTION CriticalSection); +RtlEnterCriticalSection (PRTL_CRITICAL_SECTION CriticalSection); NTSTATUS STDCALL -RtlInitializeCriticalSection (PCRITICAL_SECTION CriticalSection); +RtlInitializeCriticalSection (PRTL_CRITICAL_SECTION CriticalSection); NTSTATUS STDCALL -RtlInitializeCriticalSectionAndSpinCount (PCRITICAL_SECTION CriticalSection, +RtlInitializeCriticalSectionAndSpinCount (PRTL_CRITICAL_SECTION CriticalSection, ULONG SpinCount); NTSTATUS STDCALL @@ -212,10 +239,10 @@ RtlInt64ToUnicodeString (IN ULONGLONG Value, PUNICODE_STRING String); NTSTATUS STDCALL -RtlLeaveCriticalSection (PCRITICAL_SECTION CriticalSection); +RtlLeaveCriticalSection (PRTL_CRITICAL_SECTION CriticalSection); BOOLEAN STDCALL -RtlTryEnterCriticalSection (PCRITICAL_SECTION CriticalSection); +RtlTryEnterCriticalSection (PRTL_CRITICAL_SECTION CriticalSection); DWORD STDCALL RtlCompactHeap ( diff --git a/reactos/lib/advapi32/reg/reg.c b/reactos/lib/advapi32/reg/reg.c index f45d64645dd..9c6a668a95b 100644 --- a/reactos/lib/advapi32/reg/reg.c +++ b/reactos/lib/advapi32/reg/reg.c @@ -1,4 +1,4 @@ -/* $Id: reg.c,v 1.67 2004/12/26 23:09:51 gvg Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -24,7 +24,7 @@ /* GLOBALS ******************************************************************/ -static CRITICAL_SECTION HandleTableCS; +static RTL_CRITICAL_SECTION HandleTableCS; static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES]; static HANDLE ProcessHeap; diff --git a/reactos/lib/kernel32/include/kernel32.h b/reactos/lib/kernel32/include/kernel32.h index 26e3784c743..b4515c0ebc3 100755 --- a/reactos/lib/kernel32/include/kernel32.h +++ b/reactos/lib/kernel32/include/kernel32.h @@ -39,7 +39,7 @@ extern HANDLE hProcessHeap; extern HANDLE hBaseDir; extern HMODULE hCurrentModule; -extern CRITICAL_SECTION DllLock; +extern RTL_CRITICAL_SECTION DllLock; extern UNICODE_STRING DllDirectory; diff --git a/reactos/lib/kernel32/misc/console.c b/reactos/lib/kernel32/misc/console.c index bea635dd3de..0eb896d0ed9 100644 --- a/reactos/lib/kernel32/misc/console.c +++ b/reactos/lib/kernel32/misc/console.c @@ -1,4 +1,4 @@ -/* $Id: console.c,v 1.89 2004/12/24 17:45:57 weiden Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -21,7 +21,7 @@ extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event); extern __declspec(noreturn) VOID CALLBACK ConsoleControlDispatcher(DWORD CodeAndFlag); -extern CRITICAL_SECTION ConsoleLock; +extern RTL_CRITICAL_SECTION ConsoleLock; extern BOOL WINAPI IsDebuggerPresent(VOID); diff --git a/reactos/lib/kernel32/misc/dllmain.c b/reactos/lib/kernel32/misc/dllmain.c index 85b08900827..6431ff04873 100644 --- a/reactos/lib/kernel32/misc/dllmain.c +++ b/reactos/lib/kernel32/misc/dllmain.c @@ -1,4 +1,4 @@ -/* $Id: dllmain.c,v 1.38 2004/11/29 00:08:59 gdalsnes Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -33,8 +33,8 @@ DllMain(HANDLE hInst, LPVOID lpReserved); /* Critical section for various kernel32 data structures */ -CRITICAL_SECTION DllLock; -CRITICAL_SECTION ConsoleLock; +RTL_CRITICAL_SECTION DllLock; +RTL_CRITICAL_SECTION ConsoleLock; extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event); diff --git a/reactos/lib/kernel32/misc/lcformat.c b/reactos/lib/kernel32/misc/lcformat.c index 043447a0142..c07b95890d4 100644 --- a/reactos/lib/kernel32/misc/lcformat.c +++ b/reactos/lib/kernel32/misc/lcformat.c @@ -82,15 +82,15 @@ typedef struct _NLS_FORMAT_NODE #define GetShortMonth(fmt,mth) fmt->lppszStrings[30 + mth] /* Write access to the cache is protected by this critical section */ -static CRITICAL_SECTION NLS_FormatsCS; -static CRITICAL_SECTION_DEBUG NLS_FormatsCS_debug = +static RTL_CRITICAL_SECTION NLS_FormatsCS; +static RTL_CRITICAL_SECTION_DEBUG NLS_FormatsCS_debug = { 0, 0, &NLS_FormatsCS, { &NLS_FormatsCS_debug.ProcessLocksList, &NLS_FormatsCS_debug.ProcessLocksList }, 0, 0, { 0, (DWORD)(__FILE__ ": NLS_Formats") } }; -static CRITICAL_SECTION NLS_FormatsCS = { &NLS_FormatsCS_debug, -1, 0, 0, 0, 0 }; +static RTL_CRITICAL_SECTION NLS_FormatsCS = { &NLS_FormatsCS_debug, -1, 0, 0, 0, 0 }; /************************************************************************** * NLS_GetLocaleNumber diff --git a/reactos/lib/kernel32/misc/nls.c b/reactos/lib/kernel32/misc/nls.c index 259d3134231..8ecee401051 100755 --- a/reactos/lib/kernel32/misc/nls.c +++ b/reactos/lib/kernel32/misc/nls.c @@ -58,7 +58,7 @@ static const unsigned char UTF8Mask[6] = {0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01}; static LIST_ENTRY CodePageListHead; static CODEPAGE_ENTRY AnsiCodePage; static CODEPAGE_ENTRY OemCodePage; -static CRITICAL_SECTION CodePageListLock; +static RTL_CRITICAL_SECTION CodePageListLock; /* FORWARD DECLARATIONS *******************************************************/ diff --git a/reactos/lib/kernel32/misc/profile.c b/reactos/lib/kernel32/misc/profile.c index 406b90fd92b..fdb9ac4276f 100644 --- a/reactos/lib/kernel32/misc/profile.c +++ b/reactos/lib/kernel32/misc/profile.c @@ -72,14 +72,14 @@ static PROFILE *MRUProfile[N_CACHED_PROFILES]={NULL}; static const WCHAR emptystringW[] = {0}; -static CRITICAL_SECTION PROFILE_CritSect; -static CRITICAL_SECTION_DEBUG critsect_debug = +static RTL_CRITICAL_SECTION PROFILE_CritSect; +static RTL_CRITICAL_SECTION_DEBUG critsect_debug = { 0, 0, &PROFILE_CritSect, { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, 0, 0, { 0, (DWORD)(__FILE__ ": PROFILE_CritSect") } }; -static CRITICAL_SECTION PROFILE_CritSect = { &critsect_debug, -1, 0, 0, 0, 0 }; +static RTL_CRITICAL_SECTION PROFILE_CritSect = { &critsect_debug, -1, 0, 0, 0, 0 }; static const char hex[16] = "0123456789ABCDEF"; diff --git a/reactos/lib/kernel32/synch/critical.c b/reactos/lib/kernel32/synch/critical.c index 708d8238b62..87810c8e021 100644 --- a/reactos/lib/kernel32/synch/critical.c +++ b/reactos/lib/kernel32/synch/critical.c @@ -1,4 +1,4 @@ -/* $Id: critical.c,v 1.16 2004/01/29 23:41:36 navaraf Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -26,7 +26,7 @@ InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) { NTSTATUS Status; - Status = RtlInitializeCriticalSection(lpCriticalSection); + Status = RtlInitializeCriticalSection((PRTL_CRITICAL_SECTION)lpCriticalSection); if (!NT_SUCCESS(Status)) { RtlRaiseStatus(Status); @@ -45,7 +45,7 @@ InitializeCriticalSectionAndSpinCount( { NTSTATUS Status; - Status = RtlInitializeCriticalSectionAndSpinCount(lpCriticalSection, dwSpinCount); + Status = RtlInitializeCriticalSectionAndSpinCount((PRTL_CRITICAL_SECTION)lpCriticalSection, dwSpinCount); if (Status) { RtlRaiseStatus(Status); diff --git a/reactos/lib/ntdll/ldr/startup.c b/reactos/lib/ntdll/ldr/startup.c index a88701ea3f5..821842bb384 100644 --- a/reactos/lib/ntdll/ldr/startup.c +++ b/reactos/lib/ntdll/ldr/startup.c @@ -1,4 +1,4 @@ -/* $Id: startup.c,v 1.60 2004/12/15 03:00:33 royce Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -259,6 +259,7 @@ __true_LdrInitializeThunk (ULONG Unknown1, /* If MZ header exists */ PEDosHeader = (PIMAGE_DOS_HEADER) ImageBase; DPRINT("PEDosHeader %x\n", PEDosHeader); + if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC || PEDosHeader->e_lfanew == 0L || *(PULONG)((PUCHAR)ImageBase + PEDosHeader->e_lfanew) != IMAGE_PE_MAGIC) @@ -279,6 +280,9 @@ __true_LdrInitializeThunk (ULONG Unknown1, NTHeaders = (PIMAGE_NT_HEADERS)(ImageBase + PEDosHeader->e_lfanew); + /* Initialize Critical Section Data */ + RtlpInitDeferedCriticalSection(); + /* create process heap */ RtlInitializeHeapManager(); Peb->ProcessHeap = RtlCreateHeap(HEAP_GROWABLE, @@ -292,7 +296,7 @@ __true_LdrInitializeThunk (ULONG Unknown1, DPRINT1("Failed to create process heap\n"); ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL); } - + /* initalize peb lock support */ RtlInitializeCriticalSection (&PebLock); Peb->FastPebLock = &PebLock; @@ -311,7 +315,7 @@ __true_LdrInitializeThunk (ULONG Unknown1, RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(PVOID) * (USER32_CALLBACK_MAXIMUM + 1)); - + /* initalize loader lock */ RtlInitializeCriticalSection (&LoaderLock); Peb->LoaderLock = &LoaderLock; diff --git a/reactos/lib/ntdll/rtl/critical.c b/reactos/lib/ntdll/rtl/critical.c index 94a533179b9..2e9002533ec 100644 --- a/reactos/lib/ntdll/rtl/critical.c +++ b/reactos/lib/ntdll/rtl/critical.c @@ -6,6 +6,8 @@ * 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 ******************************************************************/ @@ -19,391 +21,532 @@ /* FUNCTIONS *****************************************************************/ -inline static HANDLE RtlGetCurrentThreadId() +static RTL_CRITICAL_SECTION RtlCriticalSectionLock; +static LIST_ENTRY RtlCriticalSectionList; +static BOOLEAN RtlpCritSectInitialized = FALSE; + +/*++ + * 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) { - return (HANDLE)NtCurrentTeb()->Cid.UniqueThread; + NTSTATUS Status = STATUS_SUCCESS; + + /* Close the Event Object Handle if it exists */ + if (CriticalSection->LockSemaphore) { + Status = NtClose(CriticalSection->LockSemaphore); + } + + /* Protect List */ + RtlEnterCriticalSection(&RtlCriticalSectionLock); + + /* Delete the Debug Data, if it exists */ + if (CriticalSection->DebugInfo) { + + /* Remove it from the list */ + RemoveEntryList(&CriticalSection->DebugInfo->ProcessLocksList); + + /* Free it */ + RtlFreeHeap(RtlGetProcessHeap(), 0, CriticalSection->DebugInfo); + } + + /* Unprotect */ + RtlLeaveCriticalSection(&RtlCriticalSectionLock); + + /* Wipe it out */ + RtlZeroMemory(CriticalSection, sizeof(RTL_CRITICAL_SECTION)); + + /* Return */ + return Status; } -inline static void small_pause(void) -{ -#ifdef __i386__ - __asm__ __volatile__( "rep;nop" : : : "memory" ); -#else - __asm__ __volatile__( "" : : : "memory" ); -#endif +/*++ + * 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, + DWORD SpinCount + ) +{ + DWORD OldCount = CriticalSection->SpinCount; + + /* Set to parameter if MP, or to 0 if this is Uniprocessor */ + CriticalSection->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? SpinCount : 0; + return OldCount; } -/*********************************************************************** - * get_semaphore - */ -static inline HANDLE get_semaphore( PCRITICAL_SECTION crit ) +/*++ + * 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 ret = crit->LockSemaphore; - if (!ret) - { - HANDLE sem; - if (!NT_SUCCESS(NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 ))) return 0; - if (!(ret = (HANDLE)InterlockedCompareExchangePointer( (PVOID *)&crit->LockSemaphore, - (PVOID)sem, 0 ))) - ret = sem; - else - NtClose(sem); /* somebody beat us to it */ - } - return ret; + HANDLE Thread = (HANDLE)NtCurrentTeb()->Cid.UniqueThread; + + /* Try to Lock it */ + if (InterlockedIncrement(&CriticalSection->LockCount)) { + + /* + * 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! */ + CriticalSection->RecursionCount++; + return STATUS_SUCCESS; + } + + /* We don't own it, so we must wait for it */ + RtlpWaitForCriticalSection(CriticalSection); + } + + /* Lock successful */ + CriticalSection->OwningThread = Thread; + CriticalSection->RecursionCount = 1; + return STATUS_SUCCESS; } -/*********************************************************************** - * RtlInitializeCriticalSection (NTDLL.@) +/*++ + * RtlInitializeCriticalSection + * @implemented NT4 * - * Initialises a new critical section. + * Initialises a new critical section. * - * PARAMS - * crit [O] Critical section to initialise + * Params: + * CriticalSection - Critical section to initialise * - * RETURNS - * STATUS_SUCCESS. + * Returns: + * STATUS_SUCCESS. * - * SEE - * RtlInitializeCriticalSectionAndSpinCount(), RtlDeleteCriticalSection(), - * RtlEnterCriticalSection(), RtlLeaveCriticalSection(), - * RtlTryEnterCriticalSection(), RtlSetCriticalSectionSpinCount() - */ -NTSTATUS STDCALL RtlInitializeCriticalSection( PCRITICAL_SECTION crit ) -{ - return RtlInitializeCriticalSectionAndSpinCount( crit, 0 ); + * Remarks: + * Simply calls RtlInitializeCriticalSectionAndSpinCount + * + *--*/ +NTSTATUS +STDCALL +RtlInitializeCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) +{ + /* Call the Main Function */ + return RtlInitializeCriticalSectionAndSpinCount(CriticalSection, 0); } -/*********************************************************************** - * RtlInitializeCriticalSectionAndSpinCount (NTDLL.@) +/*++ + * RtlInitializeCriticalSectionAndSpinCount + * @implemented NT4 * - * Initialises a new critical section with a given spin count. + * Initialises a new critical section. * - * PARAMS - * crit [O] Critical section to initialise - * spincount [I] Spin count for crit - * - * RETURNS - * STATUS_SUCCESS. + * Params: + * CriticalSection - Critical section to initialise * - * NOTES - * Available on NT4 SP3 or later. + * SpinCount - Spin count for the critical section. * - * SEE - * RtlInitializeCriticalSection(), RtlDeleteCriticalSection(), - * RtlEnterCriticalSection(), RtlLeaveCriticalSection(), - * RtlTryEnterCriticalSection(), RtlSetCriticalSectionSpinCount() - */ -NTSTATUS STDCALL RtlInitializeCriticalSectionAndSpinCount( PCRITICAL_SECTION crit, ULONG spincount ) + * Returns: + * STATUS_SUCCESS. + * + * Remarks: + * SpinCount is ignored on single-processor systems. + * + *--*/ +NTSTATUS +STDCALL +RtlInitializeCriticalSectionAndSpinCount ( + PRTL_CRITICAL_SECTION CriticalSection, + DWORD SpinCount) { - /* Does ROS need this, or is this special to Wine? And if ros need it, should - it be enabled in the release build? -Gunnar */ - if (RtlGetProcessHeap()) crit->DebugInfo = NULL; - else - { - crit->DebugInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(CRITICAL_SECTION_DEBUG)); - if (crit->DebugInfo) - { - crit->DebugInfo->Type = 0; - crit->DebugInfo->CreatorBackTraceIndex = 0; - crit->DebugInfo->CriticalSection = crit; - crit->DebugInfo->ProcessLocksList.Blink = &(crit->DebugInfo->ProcessLocksList); - crit->DebugInfo->ProcessLocksList.Flink = &(crit->DebugInfo->ProcessLocksList); - crit->DebugInfo->EntryCount = 0; - crit->DebugInfo->ContentionCount = 0; - crit->DebugInfo->Spare[0] = 0; - crit->DebugInfo->Spare[1] = 0; - } - } - crit->LockCount = -1; - crit->RecursionCount = 0; - crit->OwningThread = 0; - crit->LockSemaphore = 0; - crit->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? spincount : 0; - return STATUS_SUCCESS; + PRTL_CRITICAL_SECTION_DEBUG CritcalSectionDebugData; + PVOID Heap; + + /* First things first, set up the Object */ + CriticalSection->LockCount = -1; + CriticalSection->RecursionCount = 0; + CriticalSection->OwningThread = 0; + CriticalSection->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? SpinCount : 0; + + /* + * Now set up the Debug Data + * Think of a better way to allocate it, because the Heap Manager won't + * have any debug data since the Heap isn't initalized! + */ + if ((Heap = RtlGetProcessHeap())) { + + CritcalSectionDebugData = RtlAllocateHeap(Heap, 0, sizeof(RTL_CRITICAL_SECTION_DEBUG)); + 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)) { + + /* Protect List */ + RtlEnterCriticalSection(&RtlCriticalSectionLock); + + /* Add this one */ + InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList); + + /* Unprotect */ + RtlLeaveCriticalSection(&RtlCriticalSectionLock); + + } else { + + /* Add it directly */ + InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList); + } + + } else { + + /* This shouldn't happen... */ + CritcalSectionDebugData = NULL; + } + + return STATUS_SUCCESS; } -/*********************************************************************** - * RtlSetCriticalSectionSpinCount (NTDLL.@) +/*++ + * RtlLeaveCriticalSection + * @implemented NT4 * - * Sets the spin count of a critical section. + * Releases a critical section and makes if available for new owners. * - * PARAMS - * crit [I/O] Critical section - * spincount [I] Spin count for crit + * Params: + * CriticalSection - Critical section to release. * - * RETURNS - * The previous spin count. + * Returns: + * STATUS_SUCCESS. * - * NOTES - * If the system is not SMP, spincount is ignored and set to 0. + * Remarks: + * If another thread was waiting, the slow path is entered. * - * SEE - * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), - * RtlDeleteCriticalSection(), RtlEnterCriticalSection(), - * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection() - */ -ULONG STDCALL RtlSetCriticalSectionSpinCount( PCRITICAL_SECTION crit, ULONG spincount ) -{ - ULONG oldspincount = crit->SpinCount; - crit->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? spincount : 0; - return oldspincount; + *--*/ +NTSTATUS +STDCALL +RtlLeaveCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) +{ + /* Decrease the Recursion Count */ + if (--CriticalSection->RecursionCount) { + + /* Someone still owns us, but we are free */ + InterlockedDecrement(&CriticalSection->LockCount); + + } else { + + /* Nobody owns us anymore */ + CriticalSection->OwningThread = 0; + + /* Was someone wanting us? */ + if (InterlockedDecrement(&CriticalSection->LockCount) >= 0) { + + /* Let him have us */ + RtlpUnWaitCriticalSection(CriticalSection); + + } + } + + /* Sucessful! */ + return STATUS_SUCCESS; } -/*********************************************************************** - * RtlDeleteCriticalSection (NTDLL.@) +/*++ + * RtlTryEnterCriticalSection + * @implemented NT4 * - * Frees the resources used by a critical section. + * Attemps to gain ownership of the critical section without waiting. * - * PARAMS - * crit [I/O] Critical section to free + * Params: + * CriticalSection - Critical section to attempt acquiring. * - * RETURNS - * STATUS_SUCCESS. + * Returns: + * TRUE if the critical section has been acquired, FALSE otherwise. * - * SEE - * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), - * RtlDeleteCriticalSection(), RtlEnterCriticalSection(), - * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection() - */ -NTSTATUS STDCALL RtlDeleteCriticalSection( PCRITICAL_SECTION crit ) -{ - crit->LockCount = -1; - crit->RecursionCount = 0; - crit->OwningThread = (HANDLE)0; - if (crit->LockSemaphore) - NtClose( crit->LockSemaphore ); - crit->LockSemaphore = 0; - if (crit->DebugInfo) - { - /* only free the ones we made in here */ - if (!crit->DebugInfo->Spare[1]) - { - RtlFreeHeap( RtlGetProcessHeap(), 0, crit->DebugInfo ); - crit->DebugInfo = NULL; - } - } - return STATUS_SUCCESS; + * 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 (NTDLL.@) +/*++ + * RtlpWaitForCriticalSection * - * Waits for a busy critical section to become free. - * - * PARAMS - * crit [I/O] Critical section to wait for + * Slow path of RtlEnterCriticalSection. Waits on an Event Object. * - * RETURNS - * STATUS_SUCCESS. + * Params: + * CriticalSection - Critical section to acquire. * - * NOTES - * Use RtlEnterCriticalSection() instead of this function as it is often much - * faster. + * Returns: + * STATUS_SUCCESS, or raises an exception if a deadlock is occuring. * - * SEE - * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), - * RtlDeleteCriticalSection(), RtlEnterCriticalSection(), - * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection() - */ -NTSTATUS STDCALL RtlpWaitForCriticalSection( PCRITICAL_SECTION crit ) + * Remarks: + * None + * + *--*/ +NTSTATUS +STDCALL +RtlpWaitForCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) { - for (;;) - { - EXCEPTION_RECORD rec; - HANDLE sem = get_semaphore( crit ); - LARGE_INTEGER time; - NTSTATUS status; - - time.QuadPart = -5000 * 10000; /* 5 seconds */ - status = NtWaitForSingleObject( sem, FALSE, &time ); - if ( status == STATUS_TIMEOUT ) - { - const char *name = NULL; - if (crit->DebugInfo) name = (char *)crit->DebugInfo->Spare[1]; - if (!name) name = "?"; - DPRINT1( "section %p %s wait timed out in thread %04lx, blocked by %04lx, retrying (60 sec)\n", - crit, name, RtlGetCurrentThreadId(), (DWORD)crit->OwningThread ); - time.QuadPart = -60000 * 10000; - status = NtWaitForSingleObject( sem, FALSE, &time ); - if ( status == STATUS_TIMEOUT /*&& TRACE_ON(relay)*/ ) - { - DPRINT1( "section %p %s wait timed out in thread %04lx, blocked by %04lx, retrying (5 min)\n", - crit, name, RtlGetCurrentThreadId(), (DWORD) crit->OwningThread ); - time.QuadPart = -300000 * (ULONGLONG)10000; - status = NtWaitForSingleObject( sem, FALSE, &time ); - } - } - if (status == STATUS_WAIT_0) return STATUS_SUCCESS; - - /* Throw exception only for Wine internal locks */ - if ((!crit->DebugInfo) || (!crit->DebugInfo->Spare[1])) continue; - - rec.ExceptionCode = STATUS_POSSIBLE_DEADLOCK; - rec.ExceptionFlags = 0; - rec.ExceptionRecord = NULL; - rec.ExceptionAddress = RtlRaiseException; /* sic */ - rec.NumberParameters = 1; - rec.ExceptionInformation[0] = (DWORD)crit; - RtlRaiseException( &rec ); - } + NTSTATUS Status; + EXCEPTION_RECORD ExceptionRecord; + BOOLEAN LastChance = FALSE; + LARGE_INTEGER Timeout; + + Timeout = RtlConvertLongToLargeInteger(150000); + /* ^^ HACK HACK HACK. Good way: + Timeout = &NtCurrentPeb()->CriticalSectionTimeout */ + + /* Do we have an Event yet? */ + if (!CriticalSection->LockSemaphore) { + RtlpCreateCriticalSectionSem(CriticalSection); + } + + /* Increase the Debug Entry count */ + 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) { + + /* 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 (NTDLL.@) +/*++ + * RtlpUnWaitCriticalSection * - * Notifies other threads waiting on the busy critical section that it has - * become free. - * - * PARAMS - * crit [I/O] Critical section + * Slow path of RtlLeaveCriticalSection. Fires an Event Object. * - * RETURNS - * Success: STATUS_SUCCESS. - * Failure: Any error returned by NtReleaseSemaphore() + * Params: + * CriticalSection - Critical section to release. * - * NOTES - * Use RtlLeaveCriticalSection() instead of this function as it is often much - * faster. + * Returns: + * None. Raises an exception if the system call failed. * - * SEE - * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), - * RtlDeleteCriticalSection(), RtlEnterCriticalSection(), - * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection() - */ -NTSTATUS STDCALL RtlpUnWaitCriticalSection( PCRITICAL_SECTION crit ) + * Remarks: + * None + * + *--*/ +VOID +STDCALL +RtlpUnWaitCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) + { - HANDLE sem = get_semaphore( crit ); - NTSTATUS res = NtReleaseSemaphore( sem, 1, NULL ); - if (!NT_SUCCESS(res)) RtlRaiseStatus( res ); - return res; + NTSTATUS Status; + + /* Do we have an Event yet? */ + if (!CriticalSection->LockSemaphore) { + RtlpCreateCriticalSectionSem(CriticalSection); + } + + /* Signal the Event */ + Status = NtSetEvent(CriticalSection->LockSemaphore, NULL); + + if (!NT_SUCCESS(Status)) { + + /* We've failed */ + RtlRaiseStatus(Status); + } } - -/*********************************************************************** - * RtlEnterCriticalSection (NTDLL.@) +/*++ + * RtlpCreateCriticalSectionSem * - * Enters a critical section, waiting for it to become available if necessary. + * Checks if an Event has been created for the critical section. * - * PARAMS - * crit [I/O] Critical section to enter + * Params: + * None * - * RETURNS - * STATUS_SUCCESS. The critical section is held by the caller. - * - * SEE - * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), - * RtlDeleteCriticalSection(), RtlSetCriticalSectionSpinCount(), - * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection() - */ -NTSTATUS STDCALL RtlEnterCriticalSection( PCRITICAL_SECTION crit ) + * Returns: + * None. Raises an exception if the system call failed. + * + * Remarks: + * None + * + *--*/ +VOID +STDCALL +RtlpCreateCriticalSectionSem( + PRTL_CRITICAL_SECTION CriticalSection) { - if (crit->SpinCount) - { - ULONG count; - - if (RtlTryEnterCriticalSection( crit )) return STATUS_SUCCESS; - for (count = crit->SpinCount; count > 0; count--) - { - if (crit->LockCount > 0) break; /* more than one waiter, don't bother spinning */ - if (crit->LockCount == -1) /* try again */ - { - if (InterlockedCompareExchange(&crit->LockCount, 0,-1 ) == -1) goto done; - } - small_pause(); - } - } - - if (InterlockedIncrement( &crit->LockCount )) - { - if (crit->OwningThread == (HANDLE)RtlGetCurrentThreadId()) - { - crit->RecursionCount++; - return STATUS_SUCCESS; - } - - /* Now wait for it */ - RtlpWaitForCriticalSection( crit ); - } -done: - crit->OwningThread = (HANDLE)RtlGetCurrentThreadId(); - crit->RecursionCount = 1; - return STATUS_SUCCESS; + 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... */ + InterlockedDecrement(&CriticalSection->LockCount); + RtlRaiseStatus(Status); + return; + } + + if (!(hEvent = InterlockedCompareExchangePointer((PVOID*)&CriticalSection->LockSemaphore, + (PVOID)hNewEvent, + 0))) { + + /* We created a new event succesffuly */ + hEvent = hNewEvent; + } else { + + /* Some just created an event */ + NtClose(hNewEvent); + } + + /* Set either the new or the old */ + CriticalSection->LockSemaphore = hEvent; + } + + return; } - -/*********************************************************************** - * RtlTryEnterCriticalSection (NTDLL.@) +/*++ + * RtlpInitDeferedCriticalSection * - * Tries to enter a critical section without waiting. + * Initializes the Critical Section implementation. * - * PARAMS - * crit [I/O] Critical section to enter + * Params: + * None * - * RETURNS - * Success: TRUE. The critical section is held by the caller. - * Failure: FALSE. The critical section is currently held by another thread. + * Returns: + * None. * - * SEE - * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), - * RtlDeleteCriticalSection(), RtlEnterCriticalSection(), - * RtlLeaveCriticalSection(), RtlSetCriticalSectionSpinCount() - */ -BOOLEAN STDCALL RtlTryEnterCriticalSection( PCRITICAL_SECTION crit ) + * Remarks: + * After this call, the Process Critical Section list is protected. + * + *--*/ +VOID +STDCALL +RtlpInitDeferedCriticalSection( + VOID) { - BOOL ret = FALSE; - if (InterlockedCompareExchange(&crit->LockCount, 0L, -1 ) == -1) - { - crit->OwningThread = (HANDLE)RtlGetCurrentThreadId(); - crit->RecursionCount = 1; - ret = TRUE; - } - else if (crit->OwningThread == (HANDLE)RtlGetCurrentThreadId()) - { - InterlockedIncrement( &crit->LockCount ); - crit->RecursionCount++; - ret = TRUE; - } - return ret; + + /* 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; } - -/*********************************************************************** - * RtlLeaveCriticalSection (NTDLL.@) - * - * Leaves a critical section. - * - * PARAMS - * crit [I/O] Critical section to leave. - * - * RETURNS - * STATUS_SUCCESS. - * - * SEE - * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), - * RtlDeleteCriticalSection(), RtlEnterCriticalSection(), - * RtlSetCriticalSectionSpinCount(), RtlTryEnterCriticalSection() - */ -NTSTATUS STDCALL RtlLeaveCriticalSection( PCRITICAL_SECTION crit ) -{ - if (crit->OwningThread != RtlGetCurrentThreadId()) - { - DPRINT1("Freeing critical section not owned\n"); - } - - if (--crit->RecursionCount) InterlockedDecrement( &crit->LockCount ); - else - { - crit->OwningThread = 0; - if (InterlockedDecrement( &crit->LockCount ) >= 0) - { - /* someone is waiting */ - RtlpUnWaitCriticalSection( crit ); - } - } - return STATUS_SUCCESS; -} - - /* EOF */ diff --git a/reactos/subsys/csrss/api/process.c b/reactos/subsys/csrss/api/process.c index e3944eee2d0..e985eeaacf9 100644 --- a/reactos/subsys/csrss/api/process.c +++ b/reactos/subsys/csrss/api/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.39 2004/12/25 22:58:59 gvg Exp $ +/* $Id$ * * reactos/subsys/csrss/api/process.c * @@ -25,7 +25,7 @@ static ULONG NrProcess; static PCSRSS_PROCESS_DATA ProcessData[256]; -CRITICAL_SECTION ProcessDataLock; +RTL_CRITICAL_SECTION ProcessDataLock; /* FUNCTIONS *****************************************************************/ diff --git a/reactos/subsys/csrss/include/api.h b/reactos/subsys/csrss/include/api.h index cfc9749e135..07f6b47e042 100644 --- a/reactos/subsys/csrss/include/api.h +++ b/reactos/subsys/csrss/include/api.h @@ -1,4 +1,4 @@ -/* $Id: api.h,v 1.7 2004/11/14 18:47:10 hbirr Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries diff --git a/reactos/subsys/csrss/win32csr/conio.c b/reactos/subsys/csrss/win32csr/conio.c index 098aba4022c..97ca9e5f4b4 100644 --- a/reactos/subsys/csrss/win32csr/conio.c +++ b/reactos/subsys/csrss/win32csr/conio.c @@ -1,4 +1,4 @@ -/* $Id: conio.c,v 1.19 2004/12/25 11:22:37 navaraf Exp $ +/* $Id$ * * reactos/subsys/csrss/win32csr/conio.c * @@ -139,7 +139,7 @@ CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console, { return STATUS_INSUFFICIENT_RESOURCES; } - RtlInitializeCriticalSection(&Buffer->Header.Lock); + InitializeCriticalSection(&Buffer->Header.Lock); ConioInitScreenBuffer(Console, Buffer); /* initialize buffer to be empty with default attributes */ for (Buffer->CurrentY = 0 ; Buffer->CurrentY < Buffer->MaxY; Buffer->CurrentY++) @@ -193,7 +193,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console) return STATUS_UNSUCCESSFUL; } Console->PrivateData = NULL; - RtlInitializeCriticalSection(&Console->Header.Lock); + InitializeCriticalSection(&Console->Header.Lock); GuiMode = DtbgIsDesktopVisible(); if (! GuiMode) { @@ -210,7 +210,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console) if (! NT_SUCCESS(Status)) { RtlFreeUnicodeString(&Console->Title); - RtlDeleteCriticalSection(&Console->Header.Lock); + DeleteCriticalSection(&Console->Header.Lock); CloseHandle(Console->ActiveEvent); return Status; } @@ -221,7 +221,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console) { ConioCleanupConsole(Console); RtlFreeUnicodeString(&Console->Title); - RtlDeleteCriticalSection(&Console->Header.Lock); + DeleteCriticalSection(&Console->Header.Lock); CloseHandle(Console->ActiveEvent); return STATUS_INSUFFICIENT_RESOURCES; } @@ -230,7 +230,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console) { ConioCleanupConsole(Console); RtlFreeUnicodeString(&Console->Title); - RtlDeleteCriticalSection(&Console->Header.Lock); + DeleteCriticalSection(&Console->Header.Lock); CloseHandle(Console->ActiveEvent); HeapFree(Win32CsrApiHeap, 0, NewBuffer); return Status; @@ -956,7 +956,7 @@ VOID STDCALL ConioDeleteScreenBuffer(Object_t *Object) { PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER) Object; - RtlDeleteCriticalSection(&Buffer->Header.Lock); + DeleteCriticalSection(&Buffer->Header.Lock); HeapFree(Win32CsrApiHeap, 0, Buffer->Buffer); HeapFree(Win32CsrApiHeap, 0, Buffer); } @@ -998,7 +998,7 @@ ConioDeleteConsole(Object_t *Object) ConioCleanupConsole(Console); CloseHandle(Console->ActiveEvent); - RtlDeleteCriticalSection(&Console->Header.Lock); + DeleteCriticalSection(&Console->Header.Lock); RtlFreeUnicodeString(&Console->Title); HeapFree(Win32CsrApiHeap, 0, Console); } diff --git a/reactos/subsys/csrss/win32csr/dllmain.c b/reactos/subsys/csrss/win32csr/dllmain.c index 4d1bed57dc5..7fd2f7b6c12 100644 --- a/reactos/subsys/csrss/win32csr/dllmain.c +++ b/reactos/subsys/csrss/win32csr/dllmain.c @@ -1,4 +1,4 @@ -/* $Id: dllmain.c,v 1.9 2004/12/24 17:45:58 weiden Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries diff --git a/reactos/subsys/csrss/win32csr/guiconsole.c b/reactos/subsys/csrss/win32csr/guiconsole.c index 78b53e77cf7..46d5c4bd340 100644 --- a/reactos/subsys/csrss/win32csr/guiconsole.c +++ b/reactos/subsys/csrss/win32csr/guiconsole.c @@ -1,4 +1,4 @@ -/* $Id: guiconsole.c,v 1.26 2004/12/25 11:22:37 navaraf Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries