Commit baa15566 authored by Alexandre Julliard's avatar Alexandre Julliard

Moved critical section implementation to ntdll.

parent 15bfcd03
...@@ -201,7 +201,7 @@ import ntdll.dll ...@@ -201,7 +201,7 @@ import ntdll.dll
182 stdcall DefineDosDeviceA(long str str) DefineDosDeviceA 182 stdcall DefineDosDeviceA(long str str) DefineDosDeviceA
183 stub DefineDosDeviceW 183 stub DefineDosDeviceW
184 stdcall DeleteAtom(long) DeleteAtom 184 stdcall DeleteAtom(long) DeleteAtom
185 stdcall DeleteCriticalSection(ptr) DeleteCriticalSection 185 forward DeleteCriticalSection ntdll.RtlDeleteCriticalSection
186 stdcall DeleteFileA(str) DeleteFileA 186 stdcall DeleteFileA(str) DeleteFileA
187 stdcall DeleteFileW(wstr) DeleteFileW 187 stdcall DeleteFileW(wstr) DeleteFileW
188 stdcall DeviceIoControl(long long ptr long ptr long ptr ptr) DeviceIoControl 188 stdcall DeviceIoControl(long long ptr long ptr long ptr ptr) DeviceIoControl
...@@ -211,7 +211,7 @@ import ntdll.dll ...@@ -211,7 +211,7 @@ import ntdll.dll
192 stdcall DuplicateHandle(long long long ptr long long long) DuplicateHandle 192 stdcall DuplicateHandle(long long long ptr long long long) DuplicateHandle
193 stub EndUpdateResourceA 193 stub EndUpdateResourceA
194 stub EndUpdateResourceW 194 stub EndUpdateResourceW
195 stdcall EnterCriticalSection(ptr) EnterCriticalSection 195 forward EnterCriticalSection ntdll.RtlEnterCriticalSection
196 stdcall EnumCalendarInfoA(ptr long long long) EnumCalendarInfoA 196 stdcall EnumCalendarInfoA(ptr long long long) EnumCalendarInfoA
197 stub EnumCalendarInfoW 197 stub EnumCalendarInfoW
198 stdcall EnumDateFormatsA(ptr long long) EnumDateFormatsA 198 stdcall EnumDateFormatsA(ptr long long) EnumDateFormatsA
...@@ -510,7 +510,7 @@ import ntdll.dll ...@@ -510,7 +510,7 @@ import ntdll.dll
491 register K32Thk1632Prolog() K32Thk1632Prolog 491 register K32Thk1632Prolog() K32Thk1632Prolog
492 stdcall LCMapStringA(long long str long ptr long) LCMapStringA 492 stdcall LCMapStringA(long long str long ptr long) LCMapStringA
493 stdcall LCMapStringW(long long wstr long ptr long) LCMapStringW 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 495 stdcall LoadLibraryA(str) LoadLibraryA
496 stdcall LoadLibraryExA( str long long) LoadLibraryExA 496 stdcall LoadLibraryExA( str long long) LoadLibraryExA
497 stdcall LoadLibraryExW(wstr long long) LoadLibraryExW 497 stdcall LoadLibraryExW(wstr long long) LoadLibraryExW
...@@ -914,7 +914,7 @@ import ntdll.dll ...@@ -914,7 +914,7 @@ import ntdll.dll
895 stub SignalObjectAndWait 895 stub SignalObjectAndWait
896 stub SwitchToFiber 896 stub SwitchToFiber
897 stub SwitchToThread 897 stub SwitchToThread
898 stdcall TryEnterCriticalSection(ptr) TryEnterCriticalSection 898 forward TryEnterCriticalSection ntdll.RtlTryEnterCriticalSection
899 stdcall VirtualAllocEx(long ptr long long long) VirtualAllocEx 899 stdcall VirtualAllocEx(long ptr long long long) VirtualAllocEx
900 stub VirtualFreeEx 900 stub VirtualFreeEx
901 stub WriteFileGather 901 stub WriteFileGather
......
...@@ -8,6 +8,7 @@ MODULE = ntdll ...@@ -8,6 +8,7 @@ MODULE = ntdll
SPEC_SRCS = ntdll.spec SPEC_SRCS = ntdll.spec
C_SRCS = \ C_SRCS = \
critsection.c \
exception.c \ exception.c \
error.c \ error.c \
file.c \ file.c \
...@@ -29,5 +30,7 @@ all: $(MODULE).o ...@@ -29,5 +30,7 @@ all: $(MODULE).o
@MAKE_RULES@ @MAKE_RULES@
### Dependencies: $(MODULE).o: $(OBJS) Makefile.in $(TOPSRCDIR)/Make.rules.in
$(LDCOMBINE) $(OBJS) -o $@
### Dependencies:
/*
* 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 ...@@ -331,7 +331,7 @@ type win32
@ stub RtlDecompressFragment @ stub RtlDecompressFragment
@ stub RtlDelete @ stub RtlDelete
@ stub RtlDeleteAce @ stub RtlDeleteAce
@ stdcall RtlDeleteCriticalSection(ptr) DeleteCriticalSection @ stdcall RtlDeleteCriticalSection(ptr) RtlDeleteCriticalSection
@ stub RtlDeleteElementGenericTable @ stub RtlDeleteElementGenericTable
@ stub RtlDeleteRegistryValue @ stub RtlDeleteRegistryValue
@ stdcall RtlDeleteResource(ptr) RtlDeleteResource @ stdcall RtlDeleteResource(ptr) RtlDeleteResource
...@@ -348,7 +348,7 @@ type win32 ...@@ -348,7 +348,7 @@ type win32
@ stub RtlEnlargedIntegerMultiply @ stub RtlEnlargedIntegerMultiply
@ stub RtlEnlargedUnsignedDivide @ stub RtlEnlargedUnsignedDivide
@ stub RtlEnlargedUnsignedMultiply @ stub RtlEnlargedUnsignedMultiply
@ stdcall RtlEnterCriticalSection(ptr) EnterCriticalSection @ stdcall RtlEnterCriticalSection(ptr) RtlEnterCriticalSection
@ stub RtlEnumProcessHeaps @ stub RtlEnumProcessHeaps
@ stub RtlEnumerateGenericTable @ stub RtlEnumerateGenericTable
@ stub RtlEnumerateGenericTableWithoutSplaying @ stub RtlEnumerateGenericTableWithoutSplaying
...@@ -410,7 +410,7 @@ type win32 ...@@ -410,7 +410,7 @@ type win32
@ stdcall RtlInitUnicodeString(ptr wstr) RtlInitUnicodeString @ stdcall RtlInitUnicodeString(ptr wstr) RtlInitUnicodeString
@ stdcall RtlInitializeBitMap(long long long) RtlInitializeBitMap @ stdcall RtlInitializeBitMap(long long long) RtlInitializeBitMap
@ stub RtlInitializeContext @ stub RtlInitializeContext
@ stdcall RtlInitializeCriticalSection(ptr) InitializeCriticalSection @ stdcall RtlInitializeCriticalSection(ptr) RtlInitializeCriticalSection
@ stdcall RtlInitializeGenericTable() RtlInitializeGenericTable @ stdcall RtlInitializeGenericTable() RtlInitializeGenericTable
@ stub RtlInitializeRXact @ stub RtlInitializeRXact
@ stdcall RtlInitializeResource(ptr) RtlInitializeResource @ stdcall RtlInitializeResource(ptr) RtlInitializeResource
...@@ -430,7 +430,7 @@ type win32 ...@@ -430,7 +430,7 @@ type win32
@ stub RtlLargeIntegerShiftRight @ stub RtlLargeIntegerShiftRight
@ stub RtlLargeIntegerSubtract @ stub RtlLargeIntegerSubtract
@ stub RtlLargeIntegerToChar @ stub RtlLargeIntegerToChar
@ stdcall RtlLeaveCriticalSection(ptr) LeaveCriticalSection @ stdcall RtlLeaveCriticalSection(ptr) RtlLeaveCriticalSection
@ stdcall RtlLengthRequiredSid(long) RtlLengthRequiredSid @ stdcall RtlLengthRequiredSid(long) RtlLengthRequiredSid
@ stdcall RtlLengthSecurityDescriptor(ptr) RtlLengthSecurityDescriptor @ stdcall RtlLengthSecurityDescriptor(ptr) RtlLengthSecurityDescriptor
@ stdcall RtlLengthSid(ptr) RtlLengthSid @ stdcall RtlLengthSid(ptr) RtlLengthSid
...@@ -973,7 +973,7 @@ type win32 ...@@ -973,7 +973,7 @@ type win32
@ stub RtlIsValidHandle @ stub RtlIsValidHandle
@ stub RtlLookupAtomInAtomTable @ stub RtlLookupAtomInAtomTable
@ stub RtlQueryAtomInAtomTable @ stub RtlQueryAtomInAtomTable
@ stdcall RtlTryEnterCriticalSection(ptr) TryEnterCriticalSection @ stdcall RtlTryEnterCriticalSection(ptr) RtlTryEnterCriticalSection
@ stub RtlEnumerateProperties @ stub RtlEnumerateProperties
@ stub RtlSetPropertyClassId @ stub RtlSetPropertyClassId
@ stub RtlSetPropertyNames @ stub RtlSetPropertyNames
......
...@@ -918,6 +918,13 @@ NTSTATUS WINAPI NtReleaseSemaphore( IN HANDLE SemaphoreHandle, ...@@ -918,6 +918,13 @@ NTSTATUS WINAPI NtReleaseSemaphore( IN HANDLE SemaphoreHandle,
IN ULONG ReleaseCount, IN ULONG ReleaseCount,
IN PULONG PreviousCount); 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 */ /* string functions */
extern LPSTR _strlwr( LPSTR str ); extern LPSTR _strlwr( LPSTR str );
......
...@@ -1206,13 +1206,25 @@ BOOL WINAPI GetVersionExW(OSVERSIONINFOW*); ...@@ -1206,13 +1206,25 @@ BOOL WINAPI GetVersionExW(OSVERSIONINFOW*);
/*int WinMain(HINSTANCE, HINSTANCE prev, char *cmd, int show);*/ /*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 DeleteCriticalSection(CRITICAL_SECTION *lpCrit);
void WINAPI EnterCriticalSection(CRITICAL_SECTION *lpCrit); void WINAPI EnterCriticalSection(CRITICAL_SECTION *lpCrit);
BOOL WINAPI TryEnterCriticalSection(CRITICAL_SECTION *lpCrit); BOOL WINAPI TryEnterCriticalSection(CRITICAL_SECTION *lpCrit);
void WINAPI InitializeCriticalSection(CRITICAL_SECTION *lpCrit);
void WINAPI LeaveCriticalSection(CRITICAL_SECTION *lpCrit); void WINAPI LeaveCriticalSection(CRITICAL_SECTION *lpCrit);
#endif
void WINAPI InitializeCriticalSection(CRITICAL_SECTION *lpCrit);
void WINAPI MakeCriticalSectionGlobal(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); DWORD WINAPI QueueUserAPC(PAPCFUNC,HANDLE,ULONG_PTR);
void WINAPI RaiseException(DWORD,DWORD,DWORD,const LPDWORD); void WINAPI RaiseException(DWORD,DWORD,DWORD,const LPDWORD);
BOOL WINAPI SetProcessWorkingSetSize(HANDLE,DWORD,DWORD); BOOL WINAPI SetProcessWorkingSetSize(HANDLE,DWORD,DWORD);
......
...@@ -19,166 +19,23 @@ DEFAULT_DEBUG_CHANNEL(win32); ...@@ -19,166 +19,23 @@ DEFAULT_DEBUG_CHANNEL(win32);
DECLARE_DEBUG_CHANNEL(relay); DECLARE_DEBUG_CHANNEL(relay);
/*********************************************************************** /***********************************************************************
* get_semaphore * InitializeCriticalSection (KERNEL32.472)
*/
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)
*/ */
void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit ) void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit )
{ {
crit->LockCount = -1; NTSTATUS ret = RtlInitializeCriticalSection( crit );
crit->RecursionCount = 0; if (ret) RtlRaiseStatus( ret );
crit->OwningThread = 0;
crit->LockSemaphore = 0;
}
/***********************************************************************
* 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) * MakeCriticalSectionGlobal (KERNEL32.515)
*/ */
void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit ) 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 ) ...@@ -188,7 +45,7 @@ void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit ) void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
{ {
if ( !crit->LockSemaphore ) if ( !crit->LockSemaphore )
InitializeCriticalSection( crit ); RtlInitializeCriticalSection( crit );
} }
...@@ -197,7 +54,7 @@ void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit ) ...@@ -197,7 +54,7 @@ void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
*/ */
void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit ) void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit )
{ {
DeleteCriticalSection( crit ); RtlDeleteCriticalSection( crit );
} }
#ifdef __i386__ #ifdef __i386__
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment