Modified: trunk/reactos/include/funcs.h
Modified: trunk/reactos/include/ntdll/rtl.h
Modified: trunk/reactos/lib/advapi32/reg/reg.c
Modified: trunk/reactos/lib/kernel32/include/kernel32.h
Modified: trunk/reactos/lib/kernel32/misc/console.c
Modified: trunk/reactos/lib/kernel32/misc/dllmain.c
Modified: trunk/reactos/lib/kernel32/misc/lcformat.c
Modified: trunk/reactos/lib/kernel32/misc/nls.c
Modified: trunk/reactos/lib/kernel32/misc/profile.c
Modified: trunk/reactos/lib/kernel32/synch/critical.c
Modified: trunk/reactos/lib/ntdll/ldr/startup.c
Modified: trunk/reactos/lib/ntdll/rtl/critical.c
Modified: trunk/reactos/subsys/csrss/api/process.c
Modified: trunk/reactos/subsys/csrss/include/api.h
Modified: trunk/reactos/subsys/csrss/win32csr/conio.c
Modified: trunk/reactos/subsys/csrss/win32csr/dllmain.c
Modified: trunk/reactos/subsys/csrss/win32csr/guiconsole.c
--- trunk/reactos/include/funcs.h 2005-01-03 22:53:21 UTC (rev 12765)
+++ trunk/reactos/include/funcs.h 2005-01-03 23:02:15 UTC (rev 12766)
@@ -2082,8 +2082,6 @@
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);
--- trunk/reactos/include/ntdll/rtl.h 2005-01-03 22:53:21 UTC (rev 12765)
+++ trunk/reactos/include/ntdll/rtl.h 2005-01-03 23:02:15 UTC (rev 12766)
@@ -99,8 +99,8 @@
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 @@
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,7 +170,30 @@
#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,
IN ULONG Revision,
@@ -191,19 +218,19 @@
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 @@
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 (
--- trunk/reactos/lib/advapi32/reg/reg.c 2005-01-03 22:53:21 UTC (rev 12765)
+++ trunk/reactos/lib/advapi32/reg/reg.c 2005-01-03 23:02:15 UTC (rev 12766)
@@ -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;
--- trunk/reactos/lib/kernel32/include/kernel32.h 2005-01-03 22:53:21 UTC (rev 12765)
+++ trunk/reactos/lib/kernel32/include/kernel32.h 2005-01-03 23:02:15 UTC (rev 12766)
@@ -39,7 +39,7 @@
extern HANDLE hBaseDir;
extern HMODULE hCurrentModule;
-extern CRITICAL_SECTION DllLock;
+extern RTL_CRITICAL_SECTION DllLock;
extern UNICODE_STRING DllDirectory;
--- trunk/reactos/lib/kernel32/misc/console.c 2005-01-03 22:53:21 UTC (rev 12765)
+++ trunk/reactos/lib/kernel32/misc/console.c 2005-01-03 23:02:15 UTC (rev 12766)
@@ -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);
--- trunk/reactos/lib/kernel32/misc/dllmain.c 2005-01-03 22:53:21 UTC (rev 12765)
+++ trunk/reactos/lib/kernel32/misc/dllmain.c 2005-01-03 23:02:15 UTC (rev 12766)
@@ -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 @@
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);
--- trunk/reactos/lib/kernel32/misc/lcformat.c 2005-01-03 22:53:21 UTC (rev 12765)
+++ trunk/reactos/lib/kernel32/misc/lcformat.c 2005-01-03 23:02:15 UTC (rev 12766)
@@ -82,15 +82,15 @@
#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 <internal>
--- trunk/reactos/lib/kernel32/misc/nls.c 2005-01-03 22:53:21 UTC (rev 12765)
+++ trunk/reactos/lib/kernel32/misc/nls.c 2005-01-03 23:02:15 UTC (rev 12766)
@@ -58,7 +58,7 @@
static LIST_ENTRY CodePageListHead;
static CODEPAGE_ENTRY AnsiCodePage;
static CODEPAGE_ENTRY OemCodePage;
-static CRITICAL_SECTION CodePageListLock;
+static RTL_CRITICAL_SECTION CodePageListLock;
/* FORWARD DECLARATIONS *******************************************************/
--- trunk/reactos/lib/kernel32/misc/profile.c 2005-01-03 22:53:21 UTC (rev 12765)
+++ trunk/reactos/lib/kernel32/misc/profile.c 2005-01-03 23:02:15 UTC (rev 12766)
@@ -72,14 +72,14 @@
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";
--- trunk/reactos/lib/kernel32/synch/critical.c 2005-01-03 22:53:21 UTC (rev 12765)
+++ trunk/reactos/lib/kernel32/synch/critical.c 2005-01-03 23:02:15 UTC (rev 12766)
@@ -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 @@
{
NTSTATUS Status;
- Status = RtlInitializeCriticalSection(lpCriticalSection);
+ Status = RtlInitializeCriticalSection((PRTL_CRITICAL_SECTION)lpCriticalSection);
if (!NT_SUCCESS(Status))
{
RtlRaiseStatus(Status);
@@ -45,7 +45,7 @@
{
NTSTATUS Status;
- Status = RtlInitializeCriticalSectionAndSpinCount(lpCriticalSection, dwSpinCount);
+ Status = RtlInitializeCriticalSectionAndSpinCount((PRTL_CRITICAL_SECTION)lpCriticalSection, dwSpinCount);
if (Status)
{
RtlRaiseStatus(Status);
--- trunk/reactos/lib/ntdll/ldr/startup.c 2005-01-03 22:53:21 UTC (rev 12765)
+++ trunk/reactos/lib/ntdll/ldr/startup.c 2005-01-03 23:02:15 UTC (rev 12766)
@@ -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 @@
/* 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 @@
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 @@
DPRINT1("Failed to create process heap\n");
ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL);
}
-
+
/* initalize peb lock support */
RtlInitializeCriticalSection (&PebLock);
Peb->FastPebLock = &PebLock;
@@ -311,7 +315,7 @@
RtlAllocateHeap(RtlGetProcessHeap(),
0,
sizeof(PVOID) * (USER32_CALLBACK_MAXIMUM + 1));
-
+
/* initalize loader lock */
RtlInitializeCriticalSection (&LoaderLock);
Peb->LoaderLock = &LoaderLock;
--- trunk/reactos/lib/ntdll/rtl/critical.c 2005-01-03 22:53:21 UTC (rev 12765)
+++ trunk/reactos/lib/ntdll/rtl/critical.c 2005-01-03 23:02:15 UTC (rev 12766)
@@ -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()
-{
- return (HANDLE)NtCurrentTeb()->Cid.UniqueThread;
-}
+static RTL_CRITICAL_SECTION RtlCriticalSectionLock;
+static LIST_ENTRY RtlCriticalSectionList;
+static BOOLEAN RtlpCritSectInitialized = FALSE;
-inline static void small_pause(void)
+/*++
+ * 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)
{
-#ifdef __i386__
- __asm__ __volatile__( "rep;nop" : : : "memory" );
-#else
- __asm__ __volatile__( "" : : : "memory" );
-#endif
+ 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;
}
-/***********************************************************************
- * get_semaphore
- */
-static inline HANDLE get_semaphore( PCRITICAL_SECTION crit )
-{
- 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;
+/*++
+ * 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;
}
-/***********************************************************************
- * RtlInitializeCriticalSection (NTDLL.@)
+/*++
+ * RtlEnterCriticalSection
+ * @implemented NT4
*
- * Initialises a new critical section.
+ * Waits to gain ownership of the critical section.
*
- * PARAMS
- * crit [O] Critical section to initialise
+ * Params:
+ * CriticalSection - Critical section to wait for.
*
- * RETURNS
- * STATUS_SUCCESS.
+ * Returns:
+ * STATUS_SUCCESS.
*
- * SEE
- * RtlInitializeCriticalSectionAndSpinCount(), RtlDeleteCriticalSection(),
- * RtlEnterCriticalSection(), RtlLeaveCriticalSection(),
- * RtlTryEnterCriticalSection(), RtlSetCriticalSectionSpinCount()
- */
-NTSTATUS STDCALL RtlInitializeCriticalSection( PCRITICAL_SECTION crit )
+ * Remarks:
+ * Uses a fast-path unless contention happens.
+ *
+ *--*/
+NTSTATUS
+STDCALL
+RtlEnterCriticalSection(
+ PRTL_CRITICAL_SECTION CriticalSection)
{
- return RtlInitializeCriticalSectionAndSpinCount( crit, 0 );
+ 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;
}
-/***********************************************************************
- * RtlInitializeCriticalSectionAndSpinCount (NTDLL.@)
+/*++
+ * RtlInitializeCriticalSection
+ * @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.
+ * Returns:
+ * STATUS_SUCCESS.
*
- * SEE
- * RtlInitializeCriticalSection(), RtlDeleteCriticalSection(),
- * RtlEnterCriticalSection(), RtlLeaveCriticalSection(),
- * RtlTryEnterCriticalSection(), RtlSetCriticalSectionSpinCount()
- */
-NTSTATUS STDCALL RtlInitializeCriticalSectionAndSpinCount( PCRITICAL_SECTION crit, ULONG 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;
+ * Remarks:
+ * Simply calls RtlInitializeCriticalSectionAndSpinCount
+ *
+ *--*/
+NTSTATUS
+STDCALL
+RtlInitializeCriticalSection(
+ PRTL_CRITICAL_SECTION CriticalSection)
+{
+ /* Call the Main Function */
+ return RtlInitializeCriticalSectionAndSpinCount(CriticalSection, 0);
}
-/***********************************************************************
- * RtlSetCriticalSectionSpinCount (NTDLL.@)
+/*++
+ * RtlInitializeCriticalSectionAndSpinCount
+ * @implemented NT4
*
- * Sets the spin count of a critical section.
+ * Initialises a new critical section.
*
- * PARAMS
- * crit [I/O] Critical section
- * spincount [I] Spin count for crit
+ * Params:
+ * CriticalSection - Critical section to initialise
*
- * RETURNS
- * The previous spin count.
+ * SpinCount - Spin count for the critical section.
*
- * NOTES
- * If the system is not SMP, spincount is ignored and set to 0.
+ * Returns:
+ * STATUS_SUCCESS.
*
- * SEE
- * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(),
- * RtlDeleteCriticalSection(), RtlEnterCriticalSection(),
- * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection()
- */
-ULONG STDCALL RtlSetCriticalSectionSpinCount( PCRITICAL_SECTION crit, ULONG spincount )
+ * Remarks:
+ * SpinCount is ignored on single-processor systems.
+ *
+ *--*/
+NTSTATUS
+STDCALL
+RtlInitializeCriticalSectionAndSpinCount (
+ PRTL_CRITICAL_SECTION CriticalSection,
+ DWORD SpinCount)
{
- ULONG oldspincount = crit->SpinCount;
- crit->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? spincount : 0;
- return oldspincount;
+ 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;
}
-/***********************************************************************
- * RtlDeleteCriticalSection (NTDLL.@)
+/*++
+ * RtlLeaveCriticalSection
+ * @implemented NT4
*
- * Frees the resources used by a critical section.
+ * Releases a critical section and makes if available for new owners.
*
- * PARAMS
- * crit [I/O] Critical section to free
+ * Params:
+ * CriticalSection - Critical section to release.
*
- * RETURNS
- * STATUS_SUCCESS.
+ * Returns:
+ * STATUS_SUCCESS.
*
- * 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:
+ * If another thread was waiting, the slow path is entered.
+ *
+ *--*/
+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;
}
-
-/***********************************************************************
- * RtlpWaitForCriticalSection (NTDLL.@)
+/*++
+ * RtlTryEnterCriticalSection
+ * @implemented NT4
*
- * Waits for a busy critical section to become free.
- *
- * PARAMS
- * crit [I/O] Critical section to wait for
+ * Attemps to gain ownership of the critical section without waiting.
*
- * RETURNS
- * STATUS_SUCCESS.
+ * Params:
+ * CriticalSection - Critical section to attempt acquiring.
*
- * NOTES
- * Use RtlEnterCriticalSection() instead of this function as it is often much
- * faster.
+ * Returns:
+ * TRUE if the critical section has been acquired, FALSE otherwise.
*
- * SEE
- * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(),
- * RtlDeleteCriticalSection(), RtlEnterCriticalSection(),
- * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection()
- */
-NTSTATUS STDCALL RtlpWaitForCriticalSection( PCRITICAL_SECTION crit )
-{
- for (;;)
- {
- EXCEPTION_RECORD rec;
- HANDLE sem = get_semaphore( crit );
- LARGE_INTEGER time;
- NTSTATUS status;
+ * Remarks:
+ * None
+ *
+ *--*/
+BOOLEAN
+STDCALL
+RtlTryEnterCriticalSection(
+ PRTL_CRITICAL_SECTION CriticalSection)
+{
+ /* Try to take control */
+ if (InterlockedCompareExchange(&CriticalSection->LockCount,
+ 0,
+ -1) == -1) {
- 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 );
- }
+ /* 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;
}
-
-/***********************************************************************
- * RtlpUnWaitCriticalSection (NTDLL.@)
+/*++
+ * RtlpWaitForCriticalSection
*
- * Notifies other threads waiting on the busy critical section that it has
- * become free.
- *
- * PARAMS
- * crit [I/O] Critical section
+ * Slow path of RtlEnterCriticalSection. Waits on an Event Object.
*
- * RETURNS
- * Success: STATUS_SUCCESS.
- * Failure: Any error returned by NtReleaseSemaphore()
+ * Params:
+ * CriticalSection - Critical section to acquire.
*
- * NOTES
- * Use RtlLeaveCriticalSection() 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 RtlpUnWaitCriticalSection( PCRITICAL_SECTION crit )
+ * Remarks:
+ * None
+ *
+ *--*/
+NTSTATUS
+STDCALL
+RtlpWaitForCriticalSection(
+ 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;
+ 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;
+ }
+ }
}
-
-/***********************************************************************
- * RtlEnterCriticalSection (NTDLL.@)
+/*++
+ * RtlpUnWaitCriticalSection
*
- * Enters a critical section, waiting for it to become available if necessary.
+ * Slow path of RtlLeaveCriticalSection. Fires an Event Object.
*
- * PARAMS
- * crit [I/O] Critical section to enter
+ * Params:
+ * CriticalSection - Critical section to release.
*
- * 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
+RtlpUnWaitCriticalSection(
+ 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())
[truncated at 1000 lines; 302 more skipped]