2 * atomic.h: Atomic operations
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002 Ximian, Inc.
10 #ifndef _WAPI_ATOMIC_H_
11 #define _WAPI_ATOMIC_H_
15 #include "mono/io-layer/wapi.h"
18 #define WAPI_ATOMIC_ASM
21 * NB: The *Pointer() functions here assume that
22 * sizeof(pointer)==sizeof(gint32)
24 * NB2: These asm functions assume 486+ (some of the opcodes dont
25 * exist on 386). If this becomes an issue, we can get configure to
26 * fall back to the non-atomic C versions of these calls.
29 static inline gint32 InterlockedCompareExchange(volatile gint32 *dest,
30 gint32 exch, gint32 comp)
34 __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
35 : "=m" (*dest), "=a" (old)
36 : "r" (exch), "m" (*dest), "a" (comp));
40 static inline gpointer InterlockedCompareExchangePointer(volatile gpointer *dest, gpointer exch, gpointer comp)
44 __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
45 : "=m" (*dest), "=a" (old)
46 : "r" (exch), "m" (*dest), "a" (comp));
50 static inline gint32 InterlockedIncrement(volatile gint32 *val)
54 __asm__ __volatile__ ("lock; xaddl %0, %1"
55 : "=r" (tmp), "=m" (*val)
56 : "0" (1), "m" (*val));
61 static inline gint32 InterlockedDecrement(volatile gint32 *val)
65 __asm__ __volatile__ ("lock; xaddl %0, %1"
66 : "=r" (tmp), "=m" (*val)
67 : "0" (-1), "m" (*val));
74 * http://msdn.microsoft.com/library/en-us/dnmag00/html/win320700.asp?frame=true
75 * for the reasons for using cmpxchg and a loop here.
77 * That url is no longer valid, but it's still in the google cache at the
78 * moment: http://www.google.com/search?q=cache:http://msdn.microsoft.com/library/en-us/dnmag00/html/win320700.asp?frame=true
80 static inline gint32 InterlockedExchange(volatile gint32 *val, gint32 new_val)
84 __asm__ __volatile__ ("1:; lock; cmpxchgl %2, %0; jne 1b"
85 : "=m" (*val), "=a" (ret)
86 : "r" (new_val), "m" (*val), "a" (*val));
91 static inline gpointer InterlockedExchangePointer(volatile gpointer *val,
96 __asm__ __volatile__ ("1:; lock; cmpxchgl %2, %0; jne 1b"
97 : "=m" (*val), "=a" (ret)
98 : "r" (new_val), "m" (*val), "a" (*val));
103 static inline gint32 InterlockedExchangeAdd(volatile gint32 *val, gint32 add)
107 __asm__ __volatile__ ("lock; xaddl %0, %1"
108 : "=r" (ret), "=m" (*val)
109 : "0" (add), "m" (*val));
114 #elif defined(sparc) || defined (__sparc__)
115 #define WAPI_ATOMIC_ASM
117 #define BEGIN_SPIN(tmp,lock) \
118 __asm__ __volatile__("1: ldstub [%1],%0\n\t" \
126 #define END_SPIN(lock) \
127 __asm__ __volatile__("stb %%g0, [%0]" \
133 static inline gint32 InterlockedCompareExchange(volatile gint32 *dest, gint32 exch, gint32 comp)
135 static unsigned char lock;
151 static inline gpointer InterlockedCompareExchangePointer(volatile gpointer *dest, gpointer exch, gpointer comp)
153 static unsigned char lock;
169 static inline gint32 InterlockedIncrement(volatile gint32 *dest)
171 static unsigned char lock;
185 static inline gint32 InterlockedDecrement(volatile gint32 *dest)
187 static unsigned char lock;
201 static inline gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch)
203 static unsigned char lock;
217 static inline gpointer InterlockedExchangePointer(volatile gpointer *dest, gpointer exch)
219 static unsigned char lock;
233 static inline gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add)
235 static unsigned char lock;
251 #define WAPI_ATOMIC_ASM
254 InterlockedCompareExchange(volatile gint32 *dest,
255 gint32 exch, gint32 comp)
259 __asm__ __volatile__ ("\tL\t%1,%0\n"
261 : "=m" (*dest), "=r" (old)
262 : "r" (exch), "r" (comp)
267 #define InterlockedCompareExchangePointer InterlockedCompareExchange
270 InterlockedIncrement(volatile gint32 *val)
274 __asm__ __volatile__ ("0:\tL\t%0,%1\n"
279 : "=r" (tmp), "+m" (*val)
286 InterlockedDecrement(volatile gint32 *val)
290 __asm__ __volatile__ ("0:\tL\t%0,%1\n"
295 : "=r" (tmp), "+m" (*val)
303 InterlockedExchange(volatile gint32 *val, gint32 new_val)
307 __asm__ __volatile__ ("0:\tL\t%1,%0\n"
310 : "+m" (*val), "=r" (ret)
317 #define InterlockedExchangePointer InterlockedExchange
320 InterlockedExchangeAdd(volatile gint32 *val, gint32 add)
324 __asm__ __volatile__ ("0:\tL\t%0,%1\n"
329 : "=r" (ret), "+m" (*val)
338 extern gint32 InterlockedCompareExchange(volatile gint32 *dest, gint32 exch, gint32 comp);
339 extern gpointer InterlockedCompareExchangePointer(volatile gpointer *dest, gpointer exch, gpointer comp);
340 extern gint32 InterlockedIncrement(volatile gint32 *dest);
341 extern gint32 InterlockedDecrement(volatile gint32 *dest);
342 extern gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch);
343 extern gpointer InterlockedExchangePointer(volatile gpointer *dest, gpointer exch);
344 extern gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add);
347 #endif /* _WAPI_ATOMIC_H_ */