Rewrite ROS Critical Section implementation, which was slow and broken (because it always created an event, which is the slow path). Note that coincidentally, Gunnar also fixed this code and committed a patch this morning, taken from WINE. This code is also based on WINE, but adds more features which WINE does not support/need yet (regarding Debug CS). Hence, this code was a re-write of the original ROS code, not of Gunnar's, and we've both discussed the accidental conflict.

svn path=/trunk/; revision=12766
This commit is contained in:
Alex Ionescu 2005-01-03 23:02:15 +00:00
parent a3e3b56cca
commit 352d524633
17 changed files with 542 additions and 370 deletions

View file

@ -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);

View file

@ -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 (

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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 <internal>

View file

@ -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 *******************************************************/

View file

@ -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";

View file

@ -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);

View file

@ -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;

View file

@ -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 */

View file

@ -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 *****************************************************************/

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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