Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Win32 critical sections |
| 3 | * |
| 4 | * Copyright 1998 Alexandre Julliard |
| 5 | */ |
| 6 | |
Francois Gouget | e5ddd26 | 2001-10-14 16:18:52 +0000 | [diff] [blame] | 7 | #include "config.h" |
| 8 | |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 9 | #include <assert.h> |
| 10 | #include <errno.h> |
| 11 | #include <stdio.h> |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 12 | #include <sys/types.h> |
Dimitrie O. Paun | 0b7a7bb | 2000-11-25 01:31:17 +0000 | [diff] [blame] | 13 | |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 14 | #include "winerror.h" |
| 15 | #include "winbase.h" |
Alexandre Julliard | 6f1b642 | 1999-11-24 01:14:04 +0000 | [diff] [blame] | 16 | #include "ntddk.h" |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 17 | #include "debugtools.h" |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 18 | #include "thread.h" |
| 19 | |
Alexandre Julliard | 416a00d | 2000-04-08 20:50:06 +0000 | [diff] [blame] | 20 | DEFAULT_DEBUG_CHANNEL(win32); |
| 21 | DECLARE_DEBUG_CHANNEL(relay); |
Patrik Stridvall | b4b9fae | 1999-04-19 14:56:29 +0000 | [diff] [blame] | 22 | |
Alexandre Julliard | 416a00d | 2000-04-08 20:50:06 +0000 | [diff] [blame] | 23 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 24 | * InitializeCriticalSection (KERNEL32.@) |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 25 | */ |
| 26 | void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit ) |
| 27 | { |
Alexandre Julliard | baa1556 | 2000-09-29 00:31:23 +0000 | [diff] [blame] | 28 | NTSTATUS ret = RtlInitializeCriticalSection( crit ); |
| 29 | if (ret) RtlRaiseStatus( ret ); |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 30 | } |
| 31 | |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 32 | /*********************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 33 | * InitializeCriticalSectionAndSpinCount (KERNEL32.@) |
David Elliott | 44f84b5 | 2000-10-29 01:24:54 +0000 | [diff] [blame] | 34 | */ |
| 35 | BOOL WINAPI InitializeCriticalSectionAndSpinCount( CRITICAL_SECTION *crit, DWORD spincount ) |
| 36 | { |
| 37 | NTSTATUS ret = RtlInitializeCriticalSectionAndSpinCount( crit, spincount ); |
| 38 | if (ret) RtlRaiseStatus( ret ); |
| 39 | return !ret; |
| 40 | } |
| 41 | |
| 42 | /*********************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 43 | * SetCriticalSectionSpinCount (KERNEL32.@) |
David Elliott | 44f84b5 | 2000-10-29 01:24:54 +0000 | [diff] [blame] | 44 | * This function is available on NT4SP3 or later, but not Win98 |
| 45 | * It is SMP related |
| 46 | */ |
| 47 | DWORD WINAPI SetCriticalSectionSpinCount( CRITICAL_SECTION *crit, DWORD spincount ) |
| 48 | { |
| 49 | ULONG_PTR oldspincount = crit->SpinCount; |
| 50 | if(spincount) FIXME("critsection=%p: spincount=%ld not supported\n", crit, spincount); |
| 51 | crit->SpinCount = spincount; |
| 52 | return oldspincount; |
| 53 | } |
| 54 | |
| 55 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 56 | * MakeCriticalSectionGlobal (KERNEL32.@) |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 57 | */ |
| 58 | void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit ) |
| 59 | { |
Alexandre Julliard | baa1556 | 2000-09-29 00:31:23 +0000 | [diff] [blame] | 60 | /* let's assume that only one thread at a time will try to do this */ |
| 61 | HANDLE sem = crit->LockSemaphore; |
Alexandre Julliard | afb49ea | 2000-09-29 20:48:04 +0000 | [diff] [blame] | 62 | if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 ); |
Alexandre Julliard | baa1556 | 2000-09-29 00:31:23 +0000 | [diff] [blame] | 63 | crit->LockSemaphore = ConvertToGlobalHandle( sem ); |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 64 | } |
| 65 | |
| 66 | |
| 67 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 68 | * ReinitializeCriticalSection (KERNEL32.@) |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 69 | */ |
| 70 | void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit ) |
| 71 | { |
Ulrich Weigand | a988074 | 1999-04-25 11:03:59 +0000 | [diff] [blame] | 72 | if ( !crit->LockSemaphore ) |
Alexandre Julliard | baa1556 | 2000-09-29 00:31:23 +0000 | [diff] [blame] | 73 | RtlInitializeCriticalSection( crit ); |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 74 | } |
Bertho Stultiens | 77f08f3 | 1999-04-15 16:42:50 +0000 | [diff] [blame] | 75 | |
| 76 | |
| 77 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 78 | * UninitializeCriticalSection (KERNEL32.@) |
Bertho Stultiens | 77f08f3 | 1999-04-15 16:42:50 +0000 | [diff] [blame] | 79 | */ |
| 80 | void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit ) |
| 81 | { |
Alexandre Julliard | baa1556 | 2000-09-29 00:31:23 +0000 | [diff] [blame] | 82 | RtlDeleteCriticalSection( crit ); |
Bertho Stultiens | 77f08f3 | 1999-04-15 16:42:50 +0000 | [diff] [blame] | 83 | } |
Ulrich Weigand | a988074 | 1999-04-25 11:03:59 +0000 | [diff] [blame] | 84 | |
Alexandre Julliard | ca3c9ba | 2000-03-07 13:14:27 +0000 | [diff] [blame] | 85 | #ifdef __i386__ |
| 86 | |
Patrik Stridvall | 7980a50 | 2000-06-07 02:15:39 +0000 | [diff] [blame] | 87 | /*********************************************************************** |
Patrik Stridvall | db92305 | 2001-07-24 00:58:52 +0000 | [diff] [blame] | 88 | * InterlockedCompareExchange (KERNEL32.@) |
Patrik Stridvall | 7980a50 | 2000-06-07 02:15:39 +0000 | [diff] [blame] | 89 | */ |
Alexandre Julliard | e08a1b5 | 2001-08-17 00:08:20 +0000 | [diff] [blame] | 90 | /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */ |
Alexandre Julliard | ca3c9ba | 2000-03-07 13:14:27 +0000 | [diff] [blame] | 91 | __ASM_GLOBAL_FUNC(InterlockedCompareExchange, |
| 92 | "movl 12(%esp),%eax\n\t" |
| 93 | "movl 8(%esp),%ecx\n\t" |
| 94 | "movl 4(%esp),%edx\n\t" |
| 95 | "lock; cmpxchgl %ecx,(%edx)\n\t" |
| 96 | "ret $12"); |
| 97 | |
Patrik Stridvall | 7980a50 | 2000-06-07 02:15:39 +0000 | [diff] [blame] | 98 | /*********************************************************************** |
| 99 | * InterlockedExchange (KERNEL32.@) |
| 100 | */ |
Patrik Stridvall | db92305 | 2001-07-24 00:58:52 +0000 | [diff] [blame] | 101 | /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */ |
Alexandre Julliard | ca3c9ba | 2000-03-07 13:14:27 +0000 | [diff] [blame] | 102 | __ASM_GLOBAL_FUNC(InterlockedExchange, |
| 103 | "movl 8(%esp),%eax\n\t" |
| 104 | "movl 4(%esp),%edx\n\t" |
| 105 | "lock; xchgl %eax,(%edx)\n\t" |
| 106 | "ret $8"); |
| 107 | |
Patrik Stridvall | 7980a50 | 2000-06-07 02:15:39 +0000 | [diff] [blame] | 108 | /*********************************************************************** |
| 109 | * InterlockedExchangeAdd (KERNEL32.@) |
| 110 | */ |
Patrik Stridvall | db92305 | 2001-07-24 00:58:52 +0000 | [diff] [blame] | 111 | /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */ |
Alexandre Julliard | ca3c9ba | 2000-03-07 13:14:27 +0000 | [diff] [blame] | 112 | __ASM_GLOBAL_FUNC(InterlockedExchangeAdd, |
| 113 | "movl 8(%esp),%eax\n\t" |
| 114 | "movl 4(%esp),%edx\n\t" |
| 115 | "lock; xaddl %eax,(%edx)\n\t" |
| 116 | "ret $8"); |
| 117 | |
Patrik Stridvall | 7980a50 | 2000-06-07 02:15:39 +0000 | [diff] [blame] | 118 | /*********************************************************************** |
| 119 | * InterlockedIncrement (KERNEL32.@) |
| 120 | */ |
Patrik Stridvall | db92305 | 2001-07-24 00:58:52 +0000 | [diff] [blame] | 121 | /* LONG WINAPI InterlockedIncrement( PLONG dest ); */ |
Alexandre Julliard | ca3c9ba | 2000-03-07 13:14:27 +0000 | [diff] [blame] | 122 | __ASM_GLOBAL_FUNC(InterlockedIncrement, |
| 123 | "movl 4(%esp),%edx\n\t" |
| 124 | "movl $1,%eax\n\t" |
| 125 | "lock; xaddl %eax,(%edx)\n\t" |
| 126 | "incl %eax\n\t" |
| 127 | "ret $4"); |
| 128 | |
Patrik Stridvall | 7980a50 | 2000-06-07 02:15:39 +0000 | [diff] [blame] | 129 | /*********************************************************************** |
Patrik Stridvall | db92305 | 2001-07-24 00:58:52 +0000 | [diff] [blame] | 130 | * InterlockedDecrement (KERNEL32.@) |
Patrik Stridvall | 7980a50 | 2000-06-07 02:15:39 +0000 | [diff] [blame] | 131 | */ |
Alexandre Julliard | ca3c9ba | 2000-03-07 13:14:27 +0000 | [diff] [blame] | 132 | __ASM_GLOBAL_FUNC(InterlockedDecrement, |
| 133 | "movl 4(%esp),%edx\n\t" |
| 134 | "movl $-1,%eax\n\t" |
| 135 | "lock; xaddl %eax,(%edx)\n\t" |
| 136 | "decl %eax\n\t" |
| 137 | "ret $4"); |
| 138 | |
Ulrich Weigand | afd6a4b | 2000-06-04 01:48:05 +0000 | [diff] [blame] | 139 | #elif defined(__sparc__) && defined(__sun__) |
| 140 | |
| 141 | /* |
| 142 | * As the earlier Sparc processors lack necessary atomic instructions, |
| 143 | * I'm simply falling back to the library-provided _lwp_mutex routines |
| 144 | * to ensure mutual exclusion in a way appropriate for the current |
| 145 | * architecture. |
| 146 | * |
| 147 | * FIXME: If we have the compare-and-swap instruction (Sparc v9 and above) |
| 148 | * we could use this to speed up the Interlocked operations ... |
| 149 | */ |
| 150 | |
| 151 | #include <synch.h> |
| 152 | static lwp_mutex_t interlocked_mutex = DEFAULTMUTEX; |
| 153 | |
Patrik Stridvall | 7980a50 | 2000-06-07 02:15:39 +0000 | [diff] [blame] | 154 | /*********************************************************************** |
| 155 | * InterlockedCompareExchange (KERNEL32.@) |
| 156 | */ |
Alexandre Julliard | e994d50 | 2001-08-09 21:21:13 +0000 | [diff] [blame] | 157 | LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ) |
Ulrich Weigand | afd6a4b | 2000-06-04 01:48:05 +0000 | [diff] [blame] | 158 | { |
| 159 | _lwp_mutex_lock( &interlocked_mutex ); |
| 160 | |
| 161 | if ( *dest == compare ) |
| 162 | *dest = xchg; |
| 163 | else |
| 164 | compare = *dest; |
| 165 | |
| 166 | _lwp_mutex_unlock( &interlocked_mutex ); |
| 167 | return compare; |
| 168 | } |
| 169 | |
Patrik Stridvall | 7980a50 | 2000-06-07 02:15:39 +0000 | [diff] [blame] | 170 | /*********************************************************************** |
| 171 | * InterlockedExchange (KERNEL32.@) |
| 172 | */ |
Ulrich Weigand | afd6a4b | 2000-06-04 01:48:05 +0000 | [diff] [blame] | 173 | LONG WINAPI InterlockedExchange( PLONG dest, LONG val ) |
| 174 | { |
| 175 | LONG retv; |
| 176 | _lwp_mutex_lock( &interlocked_mutex ); |
| 177 | |
| 178 | retv = *dest; |
| 179 | *dest = val; |
| 180 | |
| 181 | _lwp_mutex_unlock( &interlocked_mutex ); |
| 182 | return retv; |
| 183 | } |
| 184 | |
Patrik Stridvall | 7980a50 | 2000-06-07 02:15:39 +0000 | [diff] [blame] | 185 | /*********************************************************************** |
| 186 | * InterlockedExchangeAdd (KERNEL32.@) |
| 187 | */ |
Ulrich Weigand | afd6a4b | 2000-06-04 01:48:05 +0000 | [diff] [blame] | 188 | LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ) |
| 189 | { |
| 190 | LONG retv; |
| 191 | _lwp_mutex_lock( &interlocked_mutex ); |
| 192 | |
| 193 | retv = *dest; |
| 194 | *dest += incr; |
| 195 | |
| 196 | _lwp_mutex_unlock( &interlocked_mutex ); |
| 197 | return retv; |
| 198 | } |
| 199 | |
Patrik Stridvall | 7980a50 | 2000-06-07 02:15:39 +0000 | [diff] [blame] | 200 | /*********************************************************************** |
| 201 | * InterlockedIncrement (KERNEL32.@) |
| 202 | */ |
Ulrich Weigand | afd6a4b | 2000-06-04 01:48:05 +0000 | [diff] [blame] | 203 | LONG WINAPI InterlockedIncrement( PLONG dest ) |
| 204 | { |
| 205 | LONG retv; |
| 206 | _lwp_mutex_lock( &interlocked_mutex ); |
| 207 | |
| 208 | retv = ++*dest; |
| 209 | |
| 210 | _lwp_mutex_unlock( &interlocked_mutex ); |
| 211 | return retv; |
| 212 | } |
| 213 | |
Patrik Stridvall | 7980a50 | 2000-06-07 02:15:39 +0000 | [diff] [blame] | 214 | /*********************************************************************** |
| 215 | * InterlockedDecrement (KERNEL32.@) |
| 216 | */ |
Ulrich Weigand | afd6a4b | 2000-06-04 01:48:05 +0000 | [diff] [blame] | 217 | LONG WINAPI InterlockedDecrement( PLONG dest ) |
| 218 | { |
| 219 | LONG retv; |
| 220 | _lwp_mutex_lock( &interlocked_mutex ); |
| 221 | |
| 222 | retv = --*dest; |
| 223 | |
| 224 | _lwp_mutex_unlock( &interlocked_mutex ); |
| 225 | return retv; |
| 226 | } |
| 227 | |
| 228 | #else |
Alexandre Julliard | ca3c9ba | 2000-03-07 13:14:27 +0000 | [diff] [blame] | 229 | #error You must implement the Interlocked* functions for your CPU |
Ulrich Weigand | afd6a4b | 2000-06-04 01:48:05 +0000 | [diff] [blame] | 230 | #endif |