diff --git a/dlls/kernel/kernel32.spec b/dlls/kernel/kernel32.spec index 8803a348780..e722884197a 100644 --- a/dlls/kernel/kernel32.spec +++ b/dlls/kernel/kernel32.spec @@ -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 diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index 5e91d270c01..e5e24816609 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -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: diff --git a/dlls/ntdll/critsection.c b/dlls/ntdll/critsection.c new file mode 100644 index 00000000000..b40fa10eb4b --- /dev/null +++ b/dlls/ntdll/critsection.c @@ -0,0 +1,272 @@ +/* + * Win32 critical sections + * + * Copyright 1998 Alexandre Julliard + */ + +#include +#include +#include +#include +#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 +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; +} diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 8db2817025e..53dcdeb9889 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -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 diff --git a/include/ntddk.h b/include/ntddk.h index 73fadfce187..7d7a66d9761 100644 --- a/include/ntddk.h +++ b/include/ntddk.h @@ -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 ); diff --git a/include/winbase.h b/include/winbase.h index 7098724d306..48fd25521e0 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -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); diff --git a/scheduler/critsection.c b/scheduler/critsection.c index 8c2c4bfd4e5..9c223a7fc42 100644 --- a/scheduler/critsection.c +++ b/scheduler/critsection.c @@ -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__