~ubuntu-branches/ubuntu/hardy/libgc/hardy-updates

« back to all changes in this revision

Viewing changes to include/private/gc_locks.h

  • Committer: Bazaar Package Importer
  • Author(s): Ryan Murray
  • Date: 2005-02-03 00:50:53 UTC
  • mto: (3.1.1 etch) (1.2.4 upstream)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20050203005053-9c0v9r2qcm2g1cfp
Tags: upstream-6.4
ImportĀ upstreamĀ versionĀ 6.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
100
100
#      define GC_TEST_AND_SET_DEFINED
101
101
#    endif
102
102
#    if defined(IA64)
 
103
#      if defined(__INTEL_COMPILER)
 
104
#        include <ia64intrin.h>
 
105
#      endif
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");
 
112
#       else
 
113
          oldval = _InterlockedExchange(addr, n);
 
114
#       endif
108
115
          return oldval;
109
116
       }
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");
 
122
#       else
 
123
        // there is no st4 but I can use xchg I hope
 
124
         _InterlockedExchange(addr, 0);
 
125
#       endif
114
126
       }
115
127
#      define GC_CLEAR_DEFINED
116
128
#    endif
145
157
#    if defined(POWERPC)
146
158
        inline static int GC_test_and_set(volatile unsigned int *addr) {
147
159
          int oldval;
148
 
          int temp = 1; // locked value
 
160
          int temp = 1; /* locked value */
149
161
 
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)
159
 
              : "memory");
160
 
          return (int)oldval;
 
172
              : "cr0","memory");
 
173
          return oldval;
161
174
        }
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");
165
178
          *(addr) = 0;
166
179
        }
167
180
#       define GC_CLEAR_DEFINED
178
191
                             "       bne %2,2f\n"
179
192
                             "       xor %0,%3,%0\n"
180
193
                             "       stl_c %0,%1\n"
 
194
#       ifdef __ELF__
181
195
                             "       beq %0,3f\n"
 
196
#       else
 
197
                             "       beq %0,1b\n"
 
198
#       endif
182
199
                             "       mb\n"
183
200
                             "2:\n"
 
201
#       ifdef __ELF__
184
202
                             ".section .text2,\"ax\"\n"
185
203
                             "3:     br 1b\n"
186
204
                             ".previous"
 
205
#       endif
187
206
                             :"=&r" (temp), "=m" (*addr), "=&r" (oldvalue)
188
207
                             :"Ir" (1), "m" (*addr)
189
208
                             :"memory");
191
210
          return oldvalue;
192
211
        }
193
212
#       define GC_TEST_AND_SET_DEFINED
194
 
        /* Should probably also define GC_clear, since it needs */
195
 
        /* a memory barrier ??                                  */
 
213
        inline static void GC_clear(volatile unsigned int *addr) {
 
214
          __asm__ __volatile__("mb" : : : "memory");
 
215
          *(addr) = 0;
 
216
        }
 
217
#       define GC_CLEAR_DEFINED
196
218
#    endif /* ALPHA */
197
219
#    ifdef ARM32
198
220
        inline static int GC_test_and_set(volatile unsigned int *addr) {
209
231
        }
210
232
#       define GC_TEST_AND_SET_DEFINED
211
233
#    endif /* ARM32 */
 
234
#    ifdef CRIS
 
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;
 
239
 
 
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
 
242
           * this code.
 
243
           */
 
244
            __asm__ __volatile__("clearf\n"
 
245
                                 "0:\n\t"
 
246
                                 "movu.b [%2],%0\n\t"
 
247
                                 "ax\n\t"
 
248
                                 "move.b %3,[%2]\n\t"
 
249
                                 "bwf 0b\n\t"
 
250
                                 "clearf"
 
251
                                 : "=&r" (ret), "=m" (*addr)
 
252
                                 : "r" (addr), "r" ((int) 1), "m" (*addr)
 
253
                                 : "memory");
 
254
            return ret;
 
255
        }
 
256
#       define GC_TEST_AND_SET_DEFINED
 
257
#    endif /* CRIS */
 
258
#    ifdef S390
 
259
       inline static int GC_test_and_set(volatile unsigned int *addr) {
 
260
         int ret;
 
261
         __asm__ __volatile__ (
 
262
          "     l     %0,0(%2)\n"
 
263
          "0:   cs    %0,%1,0(%2)\n"
 
264
          "     jl    0b"
 
265
          : "=&d" (ret)
 
266
          : "d" (1), "a" (addr)
 
267
          : "cc", "memory");
 
268
         return ret;
 
269
       }
 
270
#    endif
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)
 
273
#    ifndef OSF1
 
274
        --> We currently assume that if gcc is not used, we are
 
275
        --> running under Tru64.
 
276
#    endif
 
277
#    include <machine/builtins.h>
 
278
#    include <c_asm.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
216
283
#  endif
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
220
287
#  endif
221
288
#  ifdef MIPS
222
 
#    if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) \
 
289
#    ifdef LINUX
 
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
224
295
#        ifdef __GNUC__
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)
226
297
#        else
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)
228
299
#        endif
229
300
#    else
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
233
304
#    endif
234
305
#    define GC_TEST_AND_SET_DEFINED
235
306
#  endif /* MIPS */
 
307
#  if defined(_AIX)
 
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");
 
313
         }
 
314
#      else
 
315
#        ifndef inline
 
316
#          define inline __inline
 
317
#        endif
 
318
#        pragma mc_func GC_memsync { \
 
319
           "7c0004ac" /* sync (same opcode used for dcs)*/ \
 
320
         }
 
321
#      endif
 
322
#    else 
 
323
#    error dont know how to memsync
 
324
#    endif
 
325
     inline static int GC_test_and_set(volatile unsigned int * addr) {
 
326
          int oldvalue = 0;
 
327
          if (compare_and_swap((void *)addr, &oldvalue, 1)) {
 
328
            GC_memsync();
 
329
            return 0;
 
330
          } else return 1;
 
331
     }
 
332
#    define GC_TEST_AND_SET_DEFINED
 
333
     inline static void GC_clear(volatile unsigned int *addr) {
 
334
          GC_memsync();
 
335
          *(addr) = 0;
 
336
     }
 
337
#    define GC_CLEAR_DEFINED
 
338
 
 
339
#  endif
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  */
266
370
#  endif
267
371
 
268
372
#  if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
269
 
      && !defined(GC_IRIX_THREADS)
 
373
      && !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS)
270
374
#    define NO_THREAD (pthread_t)(-1)
271
375
#    include <pthread.h>
272
376
#    if defined(PARALLEL_MARK) 
297
401
         {
298
402
           char result;
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;
303
407
         }
304
408
#      endif /* !GENERIC_COMPARE_AND_SWAP */
305
 
       inline static void GC_memory_write_barrier()
 
409
       inline static void GC_memory_barrier()
306
410
       {
307
411
         /* We believe the processor ensures at least processor */
308
412
         /* consistent ordering.  Thus a compiler barrier       */
310
414
         __asm__ __volatile__("" : : : "memory");
311
415
       }
312
416
#     endif /* I386 */
 
417
 
 
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) 
 
423
        {
 
424
            int result, dummy;
 
425
            __asm__ __volatile__(
 
426
                "1:\tlwarx %0,0,%5\n"
 
427
                  "\tcmpw %0,%4\n"
 
428
                  "\tbne  2f\n"
 
429
                  "\tstwcx. %3,0,%2\n"
 
430
                  "\tbne- 1b\n"
 
431
                  "\tsync\n"
 
432
                  "\tli %1, 1\n"
 
433
                  "\tb 3f\n"
 
434
                "2:\tli %1, 0\n"
 
435
                "3:\t\n"
 
436
                :  "=&r" (dummy), "=r" (result), "=p" (addr)
 
437
                :  "r" (new_val), "r" (old), "2"(addr)
 
438
                : "cr0","memory");
 
439
            return (GC_bool) result;
 
440
        }
 
441
#      endif /* !GENERIC_COMPARE_AND_SWAP */
 
442
        inline static void GC_memory_barrier()
 
443
        {
 
444
            __asm__ __volatile__("sync" : : : "memory");
 
445
        }
 
446
#     endif /* POWERPC */
 
447
 
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 */
325
460
#      if 0
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()
328
463
        {
329
464
          __asm__ __volatile__("mf" : : : "memory");
330
465
        }
331
466
#      endif /* 0 */
332
467
#     endif /* IA64 */
 
468
#     if defined(ALPHA)
 
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) 
 
473
           {
 
474
             unsigned long was_equal;
 
475
             unsigned long temp;
 
476
 
 
477
             __asm__ __volatile__(
 
478
                             "1:     ldq_l %0,%1\n"
 
479
                             "       cmpeq %0,%4,%2\n"
 
480
                             "       mov %3,%0\n"
 
481
                             "       beq %2,2f\n"
 
482
                             "       stq_c %0,%1\n"
 
483
                             "       beq %0,1b\n"
 
484
                             "2:\n"
 
485
                             "       mb\n"
 
486
                             :"=&r" (temp), "=m" (*addr), "=&r" (was_equal)
 
487
                             : "r" (new_val), "Ir" (old)
 
488
                             :"memory");
 
489
             return was_equal;
 
490
           }
 
491
#        else /* !__GNUC__ */
 
492
           inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr,
 
493
                                                         GC_word old, GC_word new_val) 
 
494
          {
 
495
            return __CMP_STORE_QUAD(addr, old, new_val, addr);
 
496
          }
 
497
#        endif /* !__GNUC__ */
 
498
#      endif /* !GENERIC_COMPARE_AND_SWAP */
 
499
#      ifdef __GNUC__
 
500
         inline static void GC_memory_barrier()
 
501
         {
 
502
           __asm__ __volatile__("mb" : : : "memory");
 
503
         }
 
504
#      else
 
505
#        define GC_memory_barrier() asm("mb")
 
506
#      endif /* !__GNUC__ */
 
507
#     endif /* ALPHA */
 
508
#     if defined(S390)
 
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)
 
512
         {
 
513
           int retval;
 
514
           __asm__ __volatile__ (
 
515
#            ifndef __s390x__
 
516
               "     cs  %1,%2,0(%3)\n"
 
517
#            else
 
518
               "     csg %1,%2,0(%3)\n"
 
519
#            endif
 
520
             "     ipm %0\n"
 
521
             "     srl %0,28\n"
 
522
             : "=&d" (retval), "+d" (old)
 
523
             : "d" (new_val), "a" (addr)
 
524
             : "cc", "memory");
 
525
           return retval == 0;
 
526
         }
 
527
#      endif
 
528
#     endif
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(); }
 
604
#        endif
405
605
#        define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml)
406
606
#      endif /* !GC_ASSERTIONS */
407
607
#   endif /* USE_PTHREAD_LOCKS */
423
623
     /* on Irix anymore.                                                */
424
624
#    include <mutex.h>
425
625
 
426
 
     extern unsigned long GC_allocate_lock;
 
626
     extern volatile unsigned int GC_allocate_lock;
427
627
        /* This is not a mutex because mutexes that obey the (optional)         */
428
628
        /* POSIX scheduling rules are subject to convoys in high contention     */
429
629
        /* applications.  This is basically a spin lock.                        */
435
635
#    define NO_THREAD (pthread_t)(-1)
436
636
#    define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD
437
637
#    define I_HOLD_LOCK() (pthread_equal(GC_lock_holder, pthread_self()))
438
 
#    define LOCK() { if (GC_test_and_set(&GC_allocate_lock, 1)) GC_lock(); }
 
638
#    define LOCK() { if (GC_test_and_set(&GC_allocate_lock)) GC_lock(); }
439
639
#    define UNLOCK() GC_clear(&GC_allocate_lock);
440
640
     extern VOLATILE GC_bool GC_collecting;
441
641
#    define ENTER_GC() \
444
644
                }
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)
 
653
#    else
 
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);
 
658
#    endif
452
659
#  endif
453
660
#  ifndef SET_LOCK_HOLDER
454
661
#      define SET_LOCK_HOLDER()