/* * Win32 critical sections * * Copyright 1998 Alexandre Julliard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include "wine/port.h" #include #include #include #include "winerror.h" #include "winbase.h" #include "winternl.h" #include "wine/debug.h" #include "thread.h" WINE_DEFAULT_DEBUG_CHANNEL(win32); WINE_DECLARE_DEBUG_CHANNEL(relay); /*********************************************************************** * InitializeCriticalSection (KERNEL32.@) */ void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit ) { NTSTATUS ret = RtlInitializeCriticalSection( crit ); if (ret) RtlRaiseStatus( ret ); } /*********************************************************************** * InitializeCriticalSectionAndSpinCount (KERNEL32.@) */ BOOL WINAPI InitializeCriticalSectionAndSpinCount( CRITICAL_SECTION *crit, DWORD spincount ) { NTSTATUS ret = RtlInitializeCriticalSectionAndSpinCount( crit, spincount ); if (ret) RtlRaiseStatus( ret ); return !ret; } /*********************************************************************** * SetCriticalSectionSpinCount (KERNEL32.@) * This function is available on NT4SP3 or later, but not Win98 * It is SMP related */ DWORD WINAPI SetCriticalSectionSpinCount( CRITICAL_SECTION *crit, DWORD spincount ) { ULONG_PTR oldspincount = crit->SpinCount; if(spincount) FIXME("critsection=%p: spincount=%ld not supported\n", crit, spincount); crit->SpinCount = spincount; return oldspincount; } /*********************************************************************** * MakeCriticalSectionGlobal (KERNEL32.@) */ void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit ) { /* let's assume that only one thread at a time will try to do this */ HANDLE sem = crit->LockSemaphore; if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 ); crit->LockSemaphore = ConvertToGlobalHandle( sem ); } /*********************************************************************** * ReinitializeCriticalSection (KERNEL32.@) */ void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit ) { if ( !crit->LockSemaphore ) RtlInitializeCriticalSection( crit ); } /*********************************************************************** * UninitializeCriticalSection (KERNEL32.@) */ void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit ) { RtlDeleteCriticalSection( crit ); } #ifdef __i386__ /*********************************************************************** * InterlockedCompareExchange (KERNEL32.@) */ /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */ __ASM_GLOBAL_FUNC(InterlockedCompareExchange, "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"); /*********************************************************************** * InterlockedExchange (KERNEL32.@) */ /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */ __ASM_GLOBAL_FUNC(InterlockedExchange, "movl 8(%esp),%eax\n\t" "movl 4(%esp),%edx\n\t" "lock; xchgl %eax,(%edx)\n\t" "ret $8"); /*********************************************************************** * InterlockedExchangeAdd (KERNEL32.@) */ /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */ __ASM_GLOBAL_FUNC(InterlockedExchangeAdd, "movl 8(%esp),%eax\n\t" "movl 4(%esp),%edx\n\t" "lock; xaddl %eax,(%edx)\n\t" "ret $8"); /*********************************************************************** * InterlockedIncrement (KERNEL32.@) */ /* LONG WINAPI InterlockedIncrement( PLONG dest ); */ __ASM_GLOBAL_FUNC(InterlockedIncrement, "movl 4(%esp),%edx\n\t" "movl $1,%eax\n\t" "lock; xaddl %eax,(%edx)\n\t" "incl %eax\n\t" "ret $4"); /*********************************************************************** * InterlockedDecrement (KERNEL32.@) */ __ASM_GLOBAL_FUNC(InterlockedDecrement, "movl 4(%esp),%edx\n\t" "movl $-1,%eax\n\t" "lock; xaddl %eax,(%edx)\n\t" "decl %eax\n\t" "ret $4"); #else /* __i386__ */ /*********************************************************************** * InterlockedCompareExchange (KERNEL32.@) */ LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ) { return interlocked_cmpxchg( dest, xchg, compare ); } /*********************************************************************** * InterlockedExchange (KERNEL32.@) */ LONG WINAPI InterlockedExchange( PLONG dest, LONG val ) { return interlocked_xchg( dest, val ); } /*********************************************************************** * InterlockedExchangeAdd (KERNEL32.@) */ LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ) { return interlocked_xchg_add( dest, incr ); } /*********************************************************************** * InterlockedIncrement (KERNEL32.@) */ LONG WINAPI InterlockedIncrement( PLONG dest ) { return interlocked_xchg_add( dest, 1 ) + 1; } /*********************************************************************** * InterlockedDecrement (KERNEL32.@) */ LONG WINAPI InterlockedDecrement( PLONG dest ) { return interlocked_xchg_add( dest, -1 ) - 1; } #endif /* __i386__ */