2 * Win32 critical sections
4 * Copyright 1998 Alexandre Julliard
10 #include <sys/types.h>
16 #include "debugtools.h"
19 DEFAULT_DEBUG_CHANNEL(win32);
20 DECLARE_DEBUG_CHANNEL(relay);
22 /***********************************************************************
23 * InitializeCriticalSection (KERNEL32.@)
25 void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit )
27 NTSTATUS ret = RtlInitializeCriticalSection( crit );
28 if (ret) RtlRaiseStatus( ret );
31 /***********************************************************************
32 * InitializeCriticalSectionAndSpinCount (KERNEL32.@)
34 BOOL WINAPI InitializeCriticalSectionAndSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
36 NTSTATUS ret = RtlInitializeCriticalSectionAndSpinCount( crit, spincount );
37 if (ret) RtlRaiseStatus( ret );
41 /***********************************************************************
42 * SetCriticalSectionSpinCount (KERNEL32.@)
43 * This function is available on NT4SP3 or later, but not Win98
46 DWORD WINAPI SetCriticalSectionSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
48 ULONG_PTR oldspincount = crit->SpinCount;
49 if(spincount) FIXME("critsection=%p: spincount=%ld not supported\n", crit, spincount);
50 crit->SpinCount = spincount;
54 /***********************************************************************
55 * MakeCriticalSectionGlobal (KERNEL32.@)
57 void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
59 /* let's assume that only one thread at a time will try to do this */
60 HANDLE sem = crit->LockSemaphore;
61 if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 );
62 crit->LockSemaphore = ConvertToGlobalHandle( sem );
66 /***********************************************************************
67 * ReinitializeCriticalSection (KERNEL32.@)
69 void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
71 if ( !crit->LockSemaphore )
72 RtlInitializeCriticalSection( crit );
76 /***********************************************************************
77 * UninitializeCriticalSection (KERNEL32.@)
79 void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit )
81 RtlDeleteCriticalSection( crit );
86 /***********************************************************************
87 * InterlockedCompareExchange (KERNEL32.@)
89 /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */
90 __ASM_GLOBAL_FUNC(InterlockedCompareExchange,
91 "movl 12(%esp),%eax\n\t"
92 "movl 8(%esp),%ecx\n\t"
93 "movl 4(%esp),%edx\n\t"
94 "lock; cmpxchgl %ecx,(%edx)\n\t"
97 /***********************************************************************
98 * InterlockedExchange (KERNEL32.@)
100 /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */
101 __ASM_GLOBAL_FUNC(InterlockedExchange,
102 "movl 8(%esp),%eax\n\t"
103 "movl 4(%esp),%edx\n\t"
104 "lock; xchgl %eax,(%edx)\n\t"
107 /***********************************************************************
108 * InterlockedExchangeAdd (KERNEL32.@)
110 /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */
111 __ASM_GLOBAL_FUNC(InterlockedExchangeAdd,
112 "movl 8(%esp),%eax\n\t"
113 "movl 4(%esp),%edx\n\t"
114 "lock; xaddl %eax,(%edx)\n\t"
117 /***********************************************************************
118 * InterlockedIncrement (KERNEL32.@)
120 /* LONG WINAPI InterlockedIncrement( PLONG dest ); */
121 __ASM_GLOBAL_FUNC(InterlockedIncrement,
122 "movl 4(%esp),%edx\n\t"
124 "lock; xaddl %eax,(%edx)\n\t"
128 /***********************************************************************
129 * InterlockedDecrement (KERNEL32.@)
131 __ASM_GLOBAL_FUNC(InterlockedDecrement,
132 "movl 4(%esp),%edx\n\t"
134 "lock; xaddl %eax,(%edx)\n\t"
138 #elif defined(__sparc__) && defined(__sun__)
141 * As the earlier Sparc processors lack necessary atomic instructions,
142 * I'm simply falling back to the library-provided _lwp_mutex routines
143 * to ensure mutual exclusion in a way appropriate for the current
146 * FIXME: If we have the compare-and-swap instruction (Sparc v9 and above)
147 * we could use this to speed up the Interlocked operations ...
151 static lwp_mutex_t interlocked_mutex = DEFAULTMUTEX;
153 /***********************************************************************
154 * InterlockedCompareExchange (KERNEL32.@)
156 LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare )
158 _lwp_mutex_lock( &interlocked_mutex );
160 if ( *dest == compare )
165 _lwp_mutex_unlock( &interlocked_mutex );
169 /***********************************************************************
170 * InterlockedExchange (KERNEL32.@)
172 LONG WINAPI InterlockedExchange( PLONG dest, LONG val )
175 _lwp_mutex_lock( &interlocked_mutex );
180 _lwp_mutex_unlock( &interlocked_mutex );
184 /***********************************************************************
185 * InterlockedExchangeAdd (KERNEL32.@)
187 LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr )
190 _lwp_mutex_lock( &interlocked_mutex );
195 _lwp_mutex_unlock( &interlocked_mutex );
199 /***********************************************************************
200 * InterlockedIncrement (KERNEL32.@)
202 LONG WINAPI InterlockedIncrement( PLONG dest )
205 _lwp_mutex_lock( &interlocked_mutex );
209 _lwp_mutex_unlock( &interlocked_mutex );
213 /***********************************************************************
214 * InterlockedDecrement (KERNEL32.@)
216 LONG WINAPI InterlockedDecrement( PLONG dest )
219 _lwp_mutex_lock( &interlocked_mutex );
223 _lwp_mutex_unlock( &interlocked_mutex );
228 #error You must implement the Interlocked* functions for your CPU