100
100
# define GC_TEST_AND_SET_DEFINED
102
102
# if defined(IA64)
103
# if defined(__INTEL_COMPILER)
104
# include <ia64intrin.h>
103
106
inline static int GC_test_and_set(volatile unsigned int *addr) {
104
107
long oldval, n = 1;
108
# ifndef __INTEL_COMPILER
105
109
__asm__ __volatile__("xchg4 %0=%1,%2"
106
110
: "=r"(oldval), "=m"(*addr)
107
111
: "r"(n), "1"(*addr) : "memory");
113
oldval = _InterlockedExchange(addr, n);
110
117
# define GC_TEST_AND_SET_DEFINED
111
118
/* Should this handle post-increment addressing?? */
112
119
inline static void GC_clear(volatile unsigned int *addr) {
120
# ifndef __INTEL_COMPILER
113
121
__asm__ __volatile__("st4.rel %0=r0" : "=m" (*addr) : : "memory");
123
// there is no st4 but I can use xchg I hope
124
_InterlockedExchange(addr, 0);
115
127
# define GC_CLEAR_DEFINED
145
157
# if defined(POWERPC)
146
158
inline static int GC_test_and_set(volatile unsigned int *addr) {
148
int temp = 1; // locked value
160
int temp = 1; /* locked value */
150
162
__asm__ __volatile__(
151
"1:\tlwarx %0,0,%3\n" // load and reserve
152
"\tcmpwi %0, 0\n" // if load is
153
"\tbne 2f\n" // non-zero, return already set
154
"\tstwcx. %2,0,%1\n" // else store conditional
155
"\tbne- 1b\n" // retry if lost reservation
156
"2:\t\n" // oldval is zero if we set
163
"1:\tlwarx %0,0,%3\n" /* load and reserve */
164
"\tcmpwi %0, 0\n" /* if load is */
165
"\tbne 2f\n" /* non-zero, return already set */
166
"\tstwcx. %2,0,%1\n" /* else store conditional */
167
"\tbne- 1b\n" /* retry if lost reservation */
168
"\tsync\n" /* import barrier */
169
"2:\t\n" /* oldval is zero if we set */
157
170
: "=&r"(oldval), "=p"(addr)
158
171
: "r"(temp), "1"(addr)
162
175
# define GC_TEST_AND_SET_DEFINED
163
176
inline static void GC_clear(volatile unsigned int *addr) {
164
__asm__ __volatile__("eieio" : : : "memory");
177
__asm__ __volatile__("lwsync" : : : "memory");
167
180
# define GC_CLEAR_DEFINED
210
232
# define GC_TEST_AND_SET_DEFINED
211
233
# endif /* ARM32 */
235
inline static int GC_test_and_set(volatile unsigned int *addr) {
236
/* Ripped from linuxthreads/sysdeps/cris/pt-machine.h. */
237
/* Included with Hans-Peter Nilsson's permission. */
238
register unsigned long int ret;
240
/* Note the use of a dummy output of *addr to expose the write.
241
* The memory barrier is to stop *other* writes being moved past
244
__asm__ __volatile__("clearf\n"
251
: "=&r" (ret), "=m" (*addr)
252
: "r" (addr), "r" ((int) 1), "m" (*addr)
256
# define GC_TEST_AND_SET_DEFINED
259
inline static int GC_test_and_set(volatile unsigned int *addr) {
261
__asm__ __volatile__ (
263
"0: cs %0,%1,0(%2)\n"
266
: "d" (1), "a" (addr)
212
271
# endif /* __GNUC__ */
213
272
# if (defined(ALPHA) && !defined(__GNUC__))
214
# define GC_test_and_set(addr) __cxx_test_and_set_atomic(addr, 1)
274
--> We currently assume that if gcc is not used, we are
275
--> running under Tru64.
277
# include <machine/builtins.h>
279
# define GC_test_and_set(addr) __ATOMIC_EXCH_LONG(addr, 1)
215
280
# define GC_TEST_AND_SET_DEFINED
281
# define GC_clear(addr) { asm("mb"); *(volatile unsigned *)addr = 0; }
282
# define GC_CLEAR_DEFINED
217
284
# if defined(MSWIN32)
218
285
# define GC_test_and_set(addr) InterlockedExchange((LPLONG)addr,1)
219
286
# define GC_TEST_AND_SET_DEFINED
222
# if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) \
290
# include <sys/tas.h>
291
# define GC_test_and_set(addr) _test_and_set((int *) addr,1)
292
# define GC_TEST_AND_SET_DEFINED
293
# elif __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) \
223
294
|| !defined(_COMPILER_VERSION) || _COMPILER_VERSION < 700
225
# define GC_test_and_set(addr) _test_and_set(addr,1)
296
# define GC_test_and_set(addr) _test_and_set((void *)addr,1)
227
# define GC_test_and_set(addr) test_and_set(addr,1)
298
# define GC_test_and_set(addr) test_and_set((void *)addr,1)
230
# define GC_test_and_set(addr) __test_and_set(addr,1)
301
# define GC_test_and_set(addr) __test_and_set32((void *)addr,1)
231
302
# define GC_clear(addr) __lock_release(addr);
232
303
# define GC_CLEAR_DEFINED
234
305
# define GC_TEST_AND_SET_DEFINED
235
306
# endif /* MIPS */
308
# include <sys/atomic_op.h>
309
# if (defined(_POWER) || defined(_POWERPC))
310
# if defined(__GNUC__)
311
inline static void GC_memsync() {
312
__asm__ __volatile__ ("sync" : : : "memory");
316
# define inline __inline
318
# pragma mc_func GC_memsync { \
319
"7c0004ac" /* sync (same opcode used for dcs)*/ \
323
# error dont know how to memsync
325
inline static int GC_test_and_set(volatile unsigned int * addr) {
327
if (compare_and_swap((void *)addr, &oldvalue, 1)) {
332
# define GC_TEST_AND_SET_DEFINED
333
inline static void GC_clear(volatile unsigned int *addr) {
337
# define GC_CLEAR_DEFINED
236
340
# if 0 /* defined(HP_PA) */
237
341
/* The official recommendation seems to be to not use ldcw from */
238
342
/* user mode. Since multithreaded incremental collection doesn't */
299
403
__asm__ __volatile__("lock; cmpxchgl %2, %0; setz %1"
300
: "=m"(*(addr)), "=r"(result)
301
: "r" (new_val), "0"(*(addr)), "a"(old) : "memory");
404
: "+m"(*(addr)), "=r"(result)
405
: "r" (new_val), "a"(old) : "memory");
302
406
return (GC_bool) result;
304
408
# endif /* !GENERIC_COMPARE_AND_SWAP */
305
inline static void GC_memory_write_barrier()
409
inline static void GC_memory_barrier()
307
411
/* We believe the processor ensures at least processor */
308
412
/* consistent ordering. Thus a compiler barrier */
310
414
__asm__ __volatile__("" : : : "memory");
312
416
# endif /* I386 */
418
# if defined(POWERPC)
419
# if !defined(GENERIC_COMPARE_AND_SWAP)
420
/* Returns TRUE if the comparison succeeded. */
421
inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr,
422
GC_word old, GC_word new_val)
425
__asm__ __volatile__(
426
"1:\tlwarx %0,0,%5\n"
436
: "=&r" (dummy), "=r" (result), "=p" (addr)
437
: "r" (new_val), "r" (old), "2"(addr)
439
return (GC_bool) result;
441
# endif /* !GENERIC_COMPARE_AND_SWAP */
442
inline static void GC_memory_barrier()
444
__asm__ __volatile__("sync" : : : "memory");
446
# endif /* POWERPC */
313
448
# if defined(IA64)
314
449
# if !defined(GENERIC_COMPARE_AND_SWAP)
315
450
inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr,
324
459
# endif /* !GENERIC_COMPARE_AND_SWAP */
326
461
/* Shouldn't be needed; we use volatile stores instead. */
327
inline static void GC_memory_write_barrier()
462
inline static void GC_memory_barrier()
329
464
__asm__ __volatile__("mf" : : : "memory");
332
467
# endif /* IA64 */
469
# if !defined(GENERIC_COMPARE_AND_SWAP)
470
# if defined(__GNUC__)
471
inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr,
472
GC_word old, GC_word new_val)
474
unsigned long was_equal;
477
__asm__ __volatile__(
486
:"=&r" (temp), "=m" (*addr), "=&r" (was_equal)
487
: "r" (new_val), "Ir" (old)
491
# else /* !__GNUC__ */
492
inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr,
493
GC_word old, GC_word new_val)
495
return __CMP_STORE_QUAD(addr, old, new_val, addr);
497
# endif /* !__GNUC__ */
498
# endif /* !GENERIC_COMPARE_AND_SWAP */
500
inline static void GC_memory_barrier()
502
__asm__ __volatile__("mb" : : : "memory");
505
# define GC_memory_barrier() asm("mb")
506
# endif /* !__GNUC__ */
509
# if !defined(GENERIC_COMPARE_AND_SWAP)
510
inline static GC_bool GC_compare_and_exchange(volatile C_word *addr,
511
GC_word old, GC_word new_val)
514
__asm__ __volatile__ (
522
: "=&d" (retval), "+d" (old)
523
: "d" (new_val), "a" (addr)
333
529
# if !defined(GENERIC_COMPARE_AND_SWAP)
334
530
/* Returns the original value of *addr. */
335
531
inline static GC_word GC_atomic_add(volatile GC_word *addr,
400
596
{ GC_ASSERT(I_HOLD_LOCK()); UNSET_LOCK_HOLDER(); \
401
597
pthread_mutex_unlock(&GC_allocate_ml); }
402
598
# else /* !GC_ASSERTIONS */
599
# if defined(NO_PTHREAD_TRYLOCK)
600
# define LOCK() GC_lock();
601
# else /* !defined(NO_PTHREAD_TRYLOCK) */
403
602
# define LOCK() \
404
603
{ if (0 != pthread_mutex_trylock(&GC_allocate_ml)) GC_lock(); }
405
605
# define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml)
406
606
# endif /* !GC_ASSERTIONS */
407
607
# endif /* USE_PTHREAD_LOCKS */
445
645
# define EXIT_GC() GC_collecting = 0;
446
646
# endif /* GC_IRIX_THREADS */
447
# ifdef GC_WIN32_THREADS
448
# include <windows.h>
449
GC_API CRITICAL_SECTION GC_allocate_ml;
450
# define LOCK() EnterCriticalSection(&GC_allocate_ml);
451
# define UNLOCK() LeaveCriticalSection(&GC_allocate_ml);
647
# if defined(GC_WIN32_THREADS)
648
# if defined(GC_PTHREADS)
649
# include <pthread.h>
650
extern pthread_mutex_t GC_allocate_ml;
651
# define LOCK() pthread_mutex_lock(&GC_allocate_ml)
652
# define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml)
654
# include <windows.h>
655
GC_API CRITICAL_SECTION GC_allocate_ml;
656
# define LOCK() EnterCriticalSection(&GC_allocate_ml);
657
# define UNLOCK() LeaveCriticalSection(&GC_allocate_ml);
453
660
# ifndef SET_LOCK_HOLDER
454
661
# define SET_LOCK_HOLDER()