| /* | |
| * 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 <assert.h> | |
| #include <errno.h> | |
| #include <stdio.h> | |
| #include <sys/types.h> | |
| #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__ */ |