Moved critical section implementation to ntdll.
This commit is contained in:
parent
15bfcd0398
commit
baa15566a0
|
@ -201,7 +201,7 @@ import ntdll.dll
|
|||
182 stdcall DefineDosDeviceA(long str str) DefineDosDeviceA
|
||||
183 stub DefineDosDeviceW
|
||||
184 stdcall DeleteAtom(long) DeleteAtom
|
||||
185 stdcall DeleteCriticalSection(ptr) DeleteCriticalSection
|
||||
185 forward DeleteCriticalSection ntdll.RtlDeleteCriticalSection
|
||||
186 stdcall DeleteFileA(str) DeleteFileA
|
||||
187 stdcall DeleteFileW(wstr) DeleteFileW
|
||||
188 stdcall DeviceIoControl(long long ptr long ptr long ptr ptr) DeviceIoControl
|
||||
|
@ -211,7 +211,7 @@ import ntdll.dll
|
|||
192 stdcall DuplicateHandle(long long long ptr long long long) DuplicateHandle
|
||||
193 stub EndUpdateResourceA
|
||||
194 stub EndUpdateResourceW
|
||||
195 stdcall EnterCriticalSection(ptr) EnterCriticalSection
|
||||
195 forward EnterCriticalSection ntdll.RtlEnterCriticalSection
|
||||
196 stdcall EnumCalendarInfoA(ptr long long long) EnumCalendarInfoA
|
||||
197 stub EnumCalendarInfoW
|
||||
198 stdcall EnumDateFormatsA(ptr long long) EnumDateFormatsA
|
||||
|
@ -510,7 +510,7 @@ import ntdll.dll
|
|||
491 register K32Thk1632Prolog() K32Thk1632Prolog
|
||||
492 stdcall LCMapStringA(long long str long ptr long) LCMapStringA
|
||||
493 stdcall LCMapStringW(long long wstr long ptr long) LCMapStringW
|
||||
494 stdcall LeaveCriticalSection(ptr) LeaveCriticalSection
|
||||
494 forward LeaveCriticalSection ntdll.RtlLeaveCriticalSection
|
||||
495 stdcall LoadLibraryA(str) LoadLibraryA
|
||||
496 stdcall LoadLibraryExA( str long long) LoadLibraryExA
|
||||
497 stdcall LoadLibraryExW(wstr long long) LoadLibraryExW
|
||||
|
@ -914,7 +914,7 @@ import ntdll.dll
|
|||
895 stub SignalObjectAndWait
|
||||
896 stub SwitchToFiber
|
||||
897 stub SwitchToThread
|
||||
898 stdcall TryEnterCriticalSection(ptr) TryEnterCriticalSection
|
||||
898 forward TryEnterCriticalSection ntdll.RtlTryEnterCriticalSection
|
||||
899 stdcall VirtualAllocEx(long ptr long long long) VirtualAllocEx
|
||||
900 stub VirtualFreeEx
|
||||
901 stub WriteFileGather
|
||||
|
|
|
@ -8,6 +8,7 @@ MODULE = ntdll
|
|||
SPEC_SRCS = ntdll.spec
|
||||
|
||||
C_SRCS = \
|
||||
critsection.c \
|
||||
exception.c \
|
||||
error.c \
|
||||
file.c \
|
||||
|
@ -29,5 +30,7 @@ all: $(MODULE).o
|
|||
|
||||
@MAKE_RULES@
|
||||
|
||||
### Dependencies:
|
||||
$(MODULE).o: $(OBJS) Makefile.in $(TOPSRCDIR)/Make.rules.in
|
||||
$(LDCOMBINE) $(OBJS) -o $@
|
||||
|
||||
### Dependencies:
|
||||
|
|
|
@ -0,0 +1,272 @@
|
|||
/*
|
||||
* Win32 critical sections
|
||||
*
|
||||
* Copyright 1998 Alexandre Julliard
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include "winerror.h"
|
||||
#include "ntddk.h"
|
||||
#include "debugtools.h"
|
||||
|
||||
DEFAULT_DEBUG_CHANNEL(ntdll);
|
||||
DECLARE_DEBUG_CHANNEL(relay);
|
||||
|
||||
/* Define the atomic exchange/inc/dec functions.
|
||||
* These are available in kernel32.dll already,
|
||||
* but we don't want to import kernel32 from ntdll.
|
||||
*/
|
||||
|
||||
#ifdef __i386__
|
||||
|
||||
# ifdef __GNUC__
|
||||
|
||||
inline static PVOID interlocked_cmpxchg( PVOID *dest, PVOID xchg, PVOID compare )
|
||||
{
|
||||
PVOID ret;
|
||||
__asm__ __volatile__( "lock; cmpxchgl %2,(%1)"
|
||||
: "=a" (ret) : "r" (dest), "r" (xchg), "0" (compare) : "memory" );
|
||||
return ret;
|
||||
}
|
||||
inline static LONG interlocked_inc( PLONG dest )
|
||||
{
|
||||
LONG ret;
|
||||
__asm__ __volatile__( "lock; xaddl %0,(%1)"
|
||||
: "=r" (ret) : "r" (dest), "0" (1) : "memory" );
|
||||
return ret + 1;
|
||||
}
|
||||
inline static LONG interlocked_dec( PLONG dest )
|
||||
{
|
||||
LONG ret;
|
||||
__asm__ __volatile__( "lock; xaddl %0,(%1)"
|
||||
: "=r" (ret) : "r" (dest), "0" (-1) : "memory" );
|
||||
return ret - 1;
|
||||
}
|
||||
|
||||
# else /* __GNUC__ */
|
||||
|
||||
PVOID WINAPI interlocked_cmpxchg( PVOID *dest, PVOID xchg, PVOID compare );
|
||||
__ASM_GLOBAL_FUNC(interlocked_cmpxchg,
|
||||
"movl 12(%esp),%eax\n\t"
|
||||
"movl 8(%esp),%ecx\n\t"
|
||||
"movl 4(%esp),%edx\n\t"
|
||||
"lock; cmpxchgl %ecx,(%edx)\n\t"
|
||||
"ret $12");
|
||||
LONG WINAPI interlocked_inc( PLONG dest );
|
||||
__ASM_GLOBAL_FUNC(interlocked_inc,
|
||||
"movl 4(%esp),%edx\n\t"
|
||||
"movl $1,%eax\n\t"
|
||||
"lock; xaddl %eax,(%edx)\n\t"
|
||||
"incl %eax\n\t"
|
||||
"ret $4");
|
||||
LONG WINAPI interlocked_dec( PLONG dest );
|
||||
__ASM_GLOBAL_FUNC(interlocked_dec,
|
||||
"movl 4(%esp),%edx\n\t"
|
||||
"movl $-1,%eax\n\t"
|
||||
"lock; xaddl %eax,(%edx)\n\t"
|
||||
"decl %eax\n\t"
|
||||
"ret $4");
|
||||
# endif /* __GNUC__ */
|
||||
|
||||
#elif defined(__sparc__) && defined(__sun__)
|
||||
/*
|
||||
* As the earlier Sparc processors lack necessary atomic instructions,
|
||||
* I'm simply falling back to the library-provided _lwp_mutex routines
|
||||
* to ensure mutual exclusion in a way appropriate for the current
|
||||
* architecture.
|
||||
*
|
||||
* FIXME: If we have the compare-and-swap instruction (Sparc v9 and above)
|
||||
* we could use this to speed up the Interlocked operations ...
|
||||
*/
|
||||
#include <synch.h>
|
||||
static lwp_mutex_t interlocked_mutex = DEFAULTMUTEX;
|
||||
|
||||
static PVOID interlocked_cmpxchg( PVOID *dest, PVOID xchg, PVOID compare )
|
||||
{
|
||||
_lwp_mutex_lock( &interlocked_mutex );
|
||||
if ( *dest == compare )
|
||||
*dest = xchg;
|
||||
else
|
||||
compare = *dest;
|
||||
_lwp_mutex_unlock( &interlocked_mutex );
|
||||
return compare;
|
||||
}
|
||||
|
||||
static LONG interlocked_inc( PLONG dest )
|
||||
{
|
||||
LONG retv;
|
||||
_lwp_mutex_lock( &interlocked_mutex );
|
||||
retv = ++*dest;
|
||||
_lwp_mutex_unlock( &interlocked_mutex );
|
||||
return retv;
|
||||
}
|
||||
|
||||
static LONG interlocked_dec( PLONG dest )
|
||||
{
|
||||
LONG retv;
|
||||
_lwp_mutex_lock( &interlocked_mutex );
|
||||
retv = --*dest;
|
||||
_lwp_mutex_unlock( &interlocked_mutex );
|
||||
return retv;
|
||||
}
|
||||
#else
|
||||
# error You must implement the interlocked* functions for your CPU
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* get_semaphore
|
||||
*/
|
||||
static inline HANDLE get_semaphore( RTL_CRITICAL_SECTION *crit )
|
||||
{
|
||||
HANDLE ret = crit->LockSemaphore;
|
||||
if (!ret)
|
||||
{
|
||||
HANDLE sem;
|
||||
if (NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 )) return 0;
|
||||
if (!(ret = (HANDLE)InterlockedCompareExchange( (PVOID *)&crit->LockSemaphore,
|
||||
(PVOID)sem, 0 )))
|
||||
ret = sem;
|
||||
else
|
||||
NtClose(sem); /* somebody beat us to it */
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RtlInitializeCriticalSection (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI RtlInitializeCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
{
|
||||
crit->LockCount = -1;
|
||||
crit->RecursionCount = 0;
|
||||
crit->OwningThread = 0;
|
||||
crit->LockSemaphore = 0;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RtlDeleteCriticalSection (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
{
|
||||
crit->LockCount = -1;
|
||||
crit->RecursionCount = 0;
|
||||
crit->OwningThread = 0;
|
||||
if (crit->LockSemaphore) NtClose( crit->LockSemaphore );
|
||||
crit->LockSemaphore = 0;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RtlpWaitForCriticalSection (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
EXCEPTION_RECORD rec;
|
||||
HANDLE sem = get_semaphore( crit );
|
||||
|
||||
DWORD res = WaitForSingleObject( sem, 5000L );
|
||||
if ( res == WAIT_TIMEOUT )
|
||||
{
|
||||
ERR("Critical section %p wait timed out, retrying (60 sec)\n", crit );
|
||||
res = WaitForSingleObject( sem, 60000L );
|
||||
if ( res == WAIT_TIMEOUT && TRACE_ON(relay) )
|
||||
{
|
||||
ERR("Critical section %p wait timed out, retrying (5 min)\n", crit );
|
||||
res = WaitForSingleObject( sem, 300000L );
|
||||
}
|
||||
}
|
||||
if (res == STATUS_WAIT_0) return STATUS_SUCCESS;
|
||||
|
||||
rec.ExceptionCode = EXCEPTION_CRITICAL_SECTION_WAIT;
|
||||
rec.ExceptionFlags = 0;
|
||||
rec.ExceptionRecord = NULL;
|
||||
rec.ExceptionAddress = RtlRaiseException; /* sic */
|
||||
rec.NumberParameters = 1;
|
||||
rec.ExceptionInformation[0] = (DWORD)crit;
|
||||
RtlRaiseException( &rec );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RtlpUnWaitCriticalSection (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
{
|
||||
HANDLE sem = get_semaphore( crit );
|
||||
NTSTATUS res = NtReleaseSemaphore( sem, 1, NULL );
|
||||
if (res) RtlRaiseStatus( res );
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RtlEnterCriticalSection (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI RtlEnterCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
{
|
||||
if (interlocked_inc( &crit->LockCount ))
|
||||
{
|
||||
if (crit->OwningThread == GetCurrentThreadId())
|
||||
{
|
||||
crit->RecursionCount++;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Now wait for it */
|
||||
RtlpWaitForCriticalSection( crit );
|
||||
}
|
||||
crit->OwningThread = GetCurrentThreadId();
|
||||
crit->RecursionCount = 1;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RtlTryEnterCriticalSection (NTDLL.@)
|
||||
*/
|
||||
BOOL WINAPI RtlTryEnterCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
if (interlocked_cmpxchg( (PVOID *)&crit->LockCount, (PVOID)0L, (PVOID)-1L ) == (PVOID)-1L)
|
||||
{
|
||||
crit->OwningThread = GetCurrentThreadId();
|
||||
crit->RecursionCount = 1;
|
||||
ret = TRUE;
|
||||
}
|
||||
else if (crit->OwningThread == GetCurrentThreadId())
|
||||
{
|
||||
interlocked_inc( &crit->LockCount );
|
||||
crit->RecursionCount++;
|
||||
ret = TRUE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RtlLeaveCriticalSection (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI RtlLeaveCriticalSection( RTL_CRITICAL_SECTION *crit )
|
||||
{
|
||||
if (--crit->RecursionCount) interlocked_dec( &crit->LockCount );
|
||||
else
|
||||
{
|
||||
crit->OwningThread = 0;
|
||||
if (interlocked_dec( &crit->LockCount ) >= 0)
|
||||
{
|
||||
/* someone is waiting */
|
||||
RtlpUnWaitCriticalSection( crit );
|
||||
}
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
|
@ -331,7 +331,7 @@ type win32
|
|||
@ stub RtlDecompressFragment
|
||||
@ stub RtlDelete
|
||||
@ stub RtlDeleteAce
|
||||
@ stdcall RtlDeleteCriticalSection(ptr) DeleteCriticalSection
|
||||
@ stdcall RtlDeleteCriticalSection(ptr) RtlDeleteCriticalSection
|
||||
@ stub RtlDeleteElementGenericTable
|
||||
@ stub RtlDeleteRegistryValue
|
||||
@ stdcall RtlDeleteResource(ptr) RtlDeleteResource
|
||||
|
@ -348,7 +348,7 @@ type win32
|
|||
@ stub RtlEnlargedIntegerMultiply
|
||||
@ stub RtlEnlargedUnsignedDivide
|
||||
@ stub RtlEnlargedUnsignedMultiply
|
||||
@ stdcall RtlEnterCriticalSection(ptr) EnterCriticalSection
|
||||
@ stdcall RtlEnterCriticalSection(ptr) RtlEnterCriticalSection
|
||||
@ stub RtlEnumProcessHeaps
|
||||
@ stub RtlEnumerateGenericTable
|
||||
@ stub RtlEnumerateGenericTableWithoutSplaying
|
||||
|
@ -410,7 +410,7 @@ type win32
|
|||
@ stdcall RtlInitUnicodeString(ptr wstr) RtlInitUnicodeString
|
||||
@ stdcall RtlInitializeBitMap(long long long) RtlInitializeBitMap
|
||||
@ stub RtlInitializeContext
|
||||
@ stdcall RtlInitializeCriticalSection(ptr) InitializeCriticalSection
|
||||
@ stdcall RtlInitializeCriticalSection(ptr) RtlInitializeCriticalSection
|
||||
@ stdcall RtlInitializeGenericTable() RtlInitializeGenericTable
|
||||
@ stub RtlInitializeRXact
|
||||
@ stdcall RtlInitializeResource(ptr) RtlInitializeResource
|
||||
|
@ -430,7 +430,7 @@ type win32
|
|||
@ stub RtlLargeIntegerShiftRight
|
||||
@ stub RtlLargeIntegerSubtract
|
||||
@ stub RtlLargeIntegerToChar
|
||||
@ stdcall RtlLeaveCriticalSection(ptr) LeaveCriticalSection
|
||||
@ stdcall RtlLeaveCriticalSection(ptr) RtlLeaveCriticalSection
|
||||
@ stdcall RtlLengthRequiredSid(long) RtlLengthRequiredSid
|
||||
@ stdcall RtlLengthSecurityDescriptor(ptr) RtlLengthSecurityDescriptor
|
||||
@ stdcall RtlLengthSid(ptr) RtlLengthSid
|
||||
|
@ -973,7 +973,7 @@ type win32
|
|||
@ stub RtlIsValidHandle
|
||||
@ stub RtlLookupAtomInAtomTable
|
||||
@ stub RtlQueryAtomInAtomTable
|
||||
@ stdcall RtlTryEnterCriticalSection(ptr) TryEnterCriticalSection
|
||||
@ stdcall RtlTryEnterCriticalSection(ptr) RtlTryEnterCriticalSection
|
||||
@ stub RtlEnumerateProperties
|
||||
@ stub RtlSetPropertyClassId
|
||||
@ stub RtlSetPropertyNames
|
||||
|
|
|
@ -918,6 +918,13 @@ NTSTATUS WINAPI NtReleaseSemaphore( IN HANDLE SemaphoreHandle,
|
|||
IN ULONG ReleaseCount,
|
||||
IN PULONG PreviousCount);
|
||||
|
||||
NTSTATUS WINAPI RtlInitializeCriticalSection( RTL_CRITICAL_SECTION *crit );
|
||||
NTSTATUS WINAPI RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit );
|
||||
NTSTATUS WINAPI RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit );
|
||||
NTSTATUS WINAPI RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit );
|
||||
NTSTATUS WINAPI RtlEnterCriticalSection( RTL_CRITICAL_SECTION *crit );
|
||||
BOOL WINAPI RtlTryEnterCriticalSection( RTL_CRITICAL_SECTION *crit );
|
||||
NTSTATUS WINAPI RtlLeaveCriticalSection( RTL_CRITICAL_SECTION *crit );
|
||||
|
||||
/* string functions */
|
||||
extern LPSTR _strlwr( LPSTR str );
|
||||
|
|
|
@ -1206,13 +1206,25 @@ BOOL WINAPI GetVersionExW(OSVERSIONINFOW*);
|
|||
|
||||
/*int WinMain(HINSTANCE, HINSTANCE prev, char *cmd, int show);*/
|
||||
|
||||
LONG WINAPI RtlEnterCriticalSection( CRITICAL_SECTION *crit );
|
||||
LONG WINAPI RtlLeaveCriticalSection( CRITICAL_SECTION *crit );
|
||||
LONG WINAPI RtlDeleteCriticalSection( CRITICAL_SECTION *crit );
|
||||
BOOL WINAPI RtlTryEnterCriticalSection( CRITICAL_SECTION *crit );
|
||||
/* FIXME: need to use defines because we don't have proper imports yet */
|
||||
#define EnterCriticalSection(crit) RtlEnterCriticalSection(crit)
|
||||
#define LeaveCriticalSection(crit) RtlLeaveCriticalSection(crit)
|
||||
#define DeleteCriticalSection(crit) RtlDeleteCriticalSection(crit)
|
||||
#define TryEnterCriticalSection(crit) RtlTryEnterCriticalSection(crit)
|
||||
#if 0
|
||||
void WINAPI DeleteCriticalSection(CRITICAL_SECTION *lpCrit);
|
||||
void WINAPI EnterCriticalSection(CRITICAL_SECTION *lpCrit);
|
||||
BOOL WINAPI TryEnterCriticalSection(CRITICAL_SECTION *lpCrit);
|
||||
void WINAPI InitializeCriticalSection(CRITICAL_SECTION *lpCrit);
|
||||
void WINAPI LeaveCriticalSection(CRITICAL_SECTION *lpCrit);
|
||||
#endif
|
||||
|
||||
void WINAPI InitializeCriticalSection(CRITICAL_SECTION *lpCrit);
|
||||
void WINAPI MakeCriticalSectionGlobal(CRITICAL_SECTION *lpCrit);
|
||||
BOOL WINAPI GetProcessWorkingSetSize(HANDLE,LPDWORD,LPDWORD);
|
||||
BOOL WINAPI GetProcessWorkingSetSize(HANDLE,LPDWORD,LPDWORD);
|
||||
DWORD WINAPI QueueUserAPC(PAPCFUNC,HANDLE,ULONG_PTR);
|
||||
void WINAPI RaiseException(DWORD,DWORD,DWORD,const LPDWORD);
|
||||
BOOL WINAPI SetProcessWorkingSetSize(HANDLE,DWORD,DWORD);
|
||||
|
|
|
@ -19,166 +19,23 @@ DEFAULT_DEBUG_CHANNEL(win32);
|
|||
DECLARE_DEBUG_CHANNEL(relay);
|
||||
|
||||
/***********************************************************************
|
||||
* get_semaphore
|
||||
*/
|
||||
static inline HANDLE get_semaphore( CRITICAL_SECTION *crit )
|
||||
{
|
||||
HANDLE ret = crit->LockSemaphore;
|
||||
if (!ret)
|
||||
{
|
||||
HANDLE sem = CreateSemaphoreA( NULL, 0, 1, NULL );
|
||||
if (!(ret = (HANDLE)InterlockedCompareExchange( (PVOID *)&crit->LockSemaphore,
|
||||
(PVOID)sem, 0 )))
|
||||
ret = sem;
|
||||
else
|
||||
CloseHandle(sem); /* somebody beat us to it */
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* InitializeCriticalSection (KERNEL32.472) (NTDLL.406)
|
||||
* InitializeCriticalSection (KERNEL32.472)
|
||||
*/
|
||||
void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit )
|
||||
{
|
||||
crit->LockCount = -1;
|
||||
crit->RecursionCount = 0;
|
||||
crit->OwningThread = 0;
|
||||
crit->LockSemaphore = 0;
|
||||
NTSTATUS ret = RtlInitializeCriticalSection( crit );
|
||||
if (ret) RtlRaiseStatus( ret );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DeleteCriticalSection (KERNEL32.185) (NTDLL.327)
|
||||
*/
|
||||
void WINAPI DeleteCriticalSection( CRITICAL_SECTION *crit )
|
||||
{
|
||||
if (crit->RecursionCount && crit->OwningThread != GetCurrentThreadId())
|
||||
ERR("Deleting owned critical section (%p)\n", crit );
|
||||
|
||||
crit->LockCount = -1;
|
||||
crit->RecursionCount = 0;
|
||||
crit->OwningThread = 0;
|
||||
if (crit->LockSemaphore) CloseHandle( crit->LockSemaphore );
|
||||
crit->LockSemaphore = 0;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RtlpWaitForCriticalSection (NTDLL.@)
|
||||
*/
|
||||
void WINAPI RtlpWaitForCriticalSection( CRITICAL_SECTION *crit )
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
EXCEPTION_RECORD rec;
|
||||
HANDLE sem = get_semaphore( crit );
|
||||
|
||||
DWORD res = WaitForSingleObject( sem, 5000L );
|
||||
if ( res == WAIT_TIMEOUT )
|
||||
{
|
||||
ERR("Critical section %p wait timed out, retrying (60 sec)\n", crit );
|
||||
res = WaitForSingleObject( sem, 60000L );
|
||||
if ( res == WAIT_TIMEOUT && TRACE_ON(relay) )
|
||||
{
|
||||
ERR("Critical section %p wait timed out, retrying (5 min)\n", crit );
|
||||
res = WaitForSingleObject( sem, 300000L );
|
||||
}
|
||||
}
|
||||
if (res == STATUS_WAIT_0) break;
|
||||
|
||||
rec.ExceptionCode = EXCEPTION_CRITICAL_SECTION_WAIT;
|
||||
rec.ExceptionFlags = 0;
|
||||
rec.ExceptionRecord = NULL;
|
||||
rec.ExceptionAddress = RtlRaiseException; /* sic */
|
||||
rec.NumberParameters = 1;
|
||||
rec.ExceptionInformation[0] = (DWORD)crit;
|
||||
RtlRaiseException( &rec );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RtlpUnWaitCriticalSection (NTDLL.@)
|
||||
*/
|
||||
void WINAPI RtlpUnWaitCriticalSection( CRITICAL_SECTION *crit )
|
||||
{
|
||||
HANDLE sem = get_semaphore( crit );
|
||||
ReleaseSemaphore( sem, 1, NULL );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* EnterCriticalSection (KERNEL32.195) (NTDLL.344)
|
||||
*/
|
||||
void WINAPI EnterCriticalSection( CRITICAL_SECTION *crit )
|
||||
{
|
||||
if (InterlockedIncrement( &crit->LockCount ))
|
||||
{
|
||||
if (crit->OwningThread == GetCurrentThreadId())
|
||||
{
|
||||
crit->RecursionCount++;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now wait for it */
|
||||
RtlpWaitForCriticalSection( crit );
|
||||
}
|
||||
crit->OwningThread = GetCurrentThreadId();
|
||||
crit->RecursionCount = 1;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* TryEnterCriticalSection (KERNEL32.898) (NTDLL.969)
|
||||
*/
|
||||
BOOL WINAPI TryEnterCriticalSection( CRITICAL_SECTION *crit )
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
if (InterlockedCompareExchange( (PVOID *)&crit->LockCount,
|
||||
(PVOID)0L, (PVOID)-1L ) == (PVOID)-1L)
|
||||
{
|
||||
crit->OwningThread = GetCurrentThreadId();
|
||||
crit->RecursionCount = 1;
|
||||
ret = TRUE;
|
||||
}
|
||||
else if (crit->OwningThread == GetCurrentThreadId())
|
||||
{
|
||||
InterlockedIncrement( &crit->LockCount );
|
||||
crit->RecursionCount++;
|
||||
ret = TRUE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LeaveCriticalSection (KERNEL32.494) (NTDLL.426)
|
||||
*/
|
||||
void WINAPI LeaveCriticalSection( CRITICAL_SECTION *crit )
|
||||
{
|
||||
if (crit->OwningThread != GetCurrentThreadId()) return;
|
||||
|
||||
if (--crit->RecursionCount)
|
||||
{
|
||||
InterlockedDecrement( &crit->LockCount );
|
||||
return;
|
||||
}
|
||||
crit->OwningThread = 0;
|
||||
if (InterlockedDecrement( &crit->LockCount ) >= 0)
|
||||
{
|
||||
/* Someone is waiting */
|
||||
RtlpUnWaitCriticalSection( crit );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MakeCriticalSectionGlobal (KERNEL32.515)
|
||||
*/
|
||||
void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
|
||||
{
|
||||
crit->LockSemaphore = ConvertToGlobalHandle( get_semaphore( crit ) );
|
||||
/* let's assume that only one thread at a time will try to do this */
|
||||
HANDLE sem = crit->LockSemaphore;
|
||||
if (!sem) sem = CreateSemaphoreA( NULL, 0, 1, NULL );
|
||||
crit->LockSemaphore = ConvertToGlobalHandle( sem );
|
||||
}
|
||||
|
||||
|
||||
|
@ -188,7 +45,7 @@ void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
|
|||
void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
|
||||
{
|
||||
if ( !crit->LockSemaphore )
|
||||
InitializeCriticalSection( crit );
|
||||
RtlInitializeCriticalSection( crit );
|
||||
}
|
||||
|
||||
|
||||
|
@ -197,7 +54,7 @@ void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
|
|||
*/
|
||||
void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit )
|
||||
{
|
||||
DeleteCriticalSection( crit );
|
||||
RtlDeleteCriticalSection( crit );
|
||||
}
|
||||
|
||||
#ifdef __i386__
|
||||
|
|
Loading…
Reference in New Issue