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