2
* ptw32_InterlockedCompareExchange.c
5
* This translation unit implements routines which are private to
6
* the implementation and may be used throughout it.
8
* --------------------------------------------------------------------------
10
* Pthreads-win32 - POSIX Threads Library for Win32
11
* Copyright(C) 1998 John E. Bossom
12
* Copyright(C) 1999,2005 Pthreads-win32 contributors
14
* Contact Email: rpj@callisto.canberra.edu.au
16
* The current list of contributors is contained
17
* in the file CONTRIBUTORS included with the source
18
* code distribution. The list can also be seen at the
19
* following World Wide Web location:
20
* http://sources.redhat.com/pthreads-win32/contributors.html
22
* This library is free software; you can redistribute it and/or
23
* modify it under the terms of the GNU Lesser General Public
24
* License as published by the Free Software Foundation; either
25
* version 2 of the License, or (at your option) any later version.
27
* This library is distributed in the hope that it will be useful,
28
* but WITHOUT ANY WARRANTY; without even the implied warranty of
29
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30
* Lesser General Public License for more details.
32
* You should have received a copy of the GNU Lesser General Public
33
* License along with this library in the file COPYING.LIB;
34
* if not, write to the Free Software Foundation, Inc.,
35
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
41
#include "implement.h"
45
* ptw32_InterlockedCompareExchange --
47
* Originally needed because W9x doesn't support InterlockedCompareExchange.
48
* We now use this version wherever possible so we can inline it.
51
PTW32_INTERLOCKED_LONG WINAPI
52
ptw32_InterlockedCompareExchange (PTW32_INTERLOCKED_LPLONG location,
53
PTW32_INTERLOCKED_LONG value,
54
PTW32_INTERLOCKED_LONG comparand)
57
#if defined(__WATCOMC__)
58
/* Don't report that result is not assigned a value before being referenced */
59
#pragma disable_message (200)
62
PTW32_INTERLOCKED_LONG result;
65
* Using the LOCK prefix on uni-processor machines is significantly slower
66
* and it is not necessary. The overhead of the conditional below is
67
* negligible in comparison. Since an optimised DLL will inline this
68
* routine, this will be faster than calling the system supplied
69
* Interlocked routine, which appears to avoid the LOCK prefix on
70
* uniprocessor systems. So one DLL works for all systems.
76
#if defined(_M_IX86) || defined(_X86_)
78
#if defined(_MSC_VER) || defined(__WATCOMC__) || (defined(__BORLANDC__) && defined(HAVE_TASM32))
79
#define HAVE_INLINABLE_INTERLOCKED_CMPXCHG
84
MOV ecx,dword ptr [location]
85
MOV edx,dword ptr [value]
86
MOV eax,dword ptr [comparand]
87
LOCK CMPXCHG dword ptr [ecx],edx
88
MOV dword ptr [result], eax
98
MOV ecx,dword ptr [location]
99
MOV edx,dword ptr [value]
100
MOV eax,dword ptr [comparand]
101
CMPXCHG dword ptr [ecx],edx
102
MOV dword ptr [result], eax
108
#elif defined(__GNUC__)
109
#define HAVE_INLINABLE_INTERLOCKED_CMPXCHG
115
"cmpxchgl %2,%1" /* if (EAX == [location]) */
116
/* [location] = value */
118
/* EAX = [location] */
120
:"m" (*location), "r" (value), "a" (comparand));
126
"cmpxchgl %2,%1" /* if (EAX == [location]) */
127
/* [location] = value */
129
/* EAX = [location] */
131
:"m" (*location), "r" (value), "a" (comparand));
139
* If execution gets to here then we're running on a currently
140
* unsupported processor or compiler.
143
#error Unsupported platform or compiler!
151
#if defined(__WATCOMC__)
152
#pragma enable_message (200)
158
* ptw32_InterlockedExchange --
160
* We now use this version wherever possible so we can inline it.
164
ptw32_InterlockedExchange (LPLONG location,
168
#if defined(__WATCOMC__)
169
/* Don't report that result is not assigned a value before being referenced */
170
#pragma disable_message (200)
176
* The XCHG instruction always locks the bus with or without the
177
* LOCKED prefix. This makes it significantly slower than CMPXCHG on
178
* uni-processor machines. The Windows InterlockedExchange function
179
* is nearly 3 times faster than the XCHG instruction, so this routine
180
* is not yet very useful for speeding up pthreads.
182
if (ptw32_smp_system)
186
#if defined(_M_IX86) || defined(_X86_)
188
#if defined(_MSC_VER) || defined(__WATCOMC__) || (defined(__BORLANDC__) && defined(HAVE_TASM32))
189
#define HAVE_INLINABLE_INTERLOCKED_XCHG
194
MOV ecx,dword ptr [location]
195
MOV eax,dword ptr [value]
196
XCHG dword ptr [ecx],eax
197
MOV dword ptr [result], eax
204
* Faster version of XCHG for uni-processor systems because
205
* it doesn't lock the bus. If an interrupt or context switch
206
* occurs between the MOV and the CMPXCHG then the value in
207
* 'location' may have changed, in which case we will loop
208
* back to do the MOV again.
210
* FIXME! Need memory barriers for the MOV+CMPXCHG combo?
212
* Tests show that this routine has almost identical timing
213
* to Win32's InterlockedExchange(), which is much faster than
214
* using the inlined 'xchg' instruction above, so it's probably
215
* doing something similar to this (on UP systems).
217
* Can we do without the PUSH/POP instructions?
222
MOV ecx,dword ptr [location]
223
MOV edx,dword ptr [value]
224
L1: MOV eax,dword ptr [ecx]
225
CMPXCHG dword ptr [ecx],edx
227
MOV dword ptr [result], eax
233
#elif defined(__GNUC__)
234
#define HAVE_INLINABLE_INTERLOCKED_XCHG
241
:"m" (*location), "0" (value));
246
* Faster version of XCHG for uni-processor systems because
247
* it doesn't lock the bus. If an interrupt or context switch
248
* occurs between the movl and the cmpxchgl then the value in
249
* 'location' may have changed, in which case we will loop
250
* back to do the movl again.
252
* FIXME! Need memory barriers for the MOV+CMPXCHG combo?
254
* Tests show that this routine has almost identical timing
255
* to Win32's InterlockedExchange(), and is much faster than
256
* using an inlined 'xchg' instruction, so Win32 is probably
257
* doing something similar to this (on UP systems).
266
:"m" (*location), "r" (value));
274
* If execution gets to here then we're running on a currently
275
* unsupported processor or compiler.
278
#error Unsupported platform or compiler!
286
#if defined(__WATCOMC__)
287
#pragma enable_message (200)
295
#if defined(PTW32_BUILD_INLINED) && defined(HAVE_INLINABLE_INTERLOCKED_CMPXCHG)
296
#undef PTW32_INTERLOCKED_COMPARE_EXCHANGE
297
#define PTW32_INTERLOCKED_COMPARE_EXCHANGE ptw32_InterlockedCompareExchange
300
#if defined(PTW32_BUILD_INLINED) && defined(HAVE_INLINABLE_INTERLOCKED_XCHG)
301
#undef PTW32_INTERLOCKED_EXCHANGE
302
#define PTW32_INTERLOCKED_EXCHANGE ptw32_InterlockedExchange