summaryrefslogtreecommitdiff
path: root/include/private/gc_locks.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/private/gc_locks.h')
-rw-r--r--include/private/gc_locks.h102
1 files changed, 82 insertions, 20 deletions
diff --git a/include/private/gc_locks.h b/include/private/gc_locks.h
index a1aa561b..6133343a 100644
--- a/include/private/gc_locks.h
+++ b/include/private/gc_locks.h
@@ -145,15 +145,15 @@
# if defined(POWERPC)
inline static int GC_test_and_set(volatile unsigned int *addr) {
int oldval;
- int temp = 1; // locked value
+ int temp = 1; /* locked value */
__asm__ __volatile__(
- "1:\tlwarx %0,0,%3\n" // load and reserve
- "\tcmpwi %0, 0\n" // if load is
- "\tbne 2f\n" // non-zero, return already set
- "\tstwcx. %2,0,%1\n" // else store conditional
- "\tbne- 1b\n" // retry if lost reservation
- "2:\t\n" // oldval is zero if we set
+ "1:\tlwarx %0,0,%3\n" /* load and reserve */
+ "\tcmpwi %0, 0\n" /* if load is */
+ "\tbne 2f\n" /* non-zero, return already set */
+ "\tstwcx. %2,0,%1\n" /* else store conditional */
+ "\tbne- 1b\n" /* retry if lost reservation */
+ "2:\t\n" /* oldval is zero if we set */
: "=&r"(oldval), "=p"(addr)
: "r"(temp), "1"(addr)
: "memory");
@@ -191,8 +191,11 @@
return oldvalue;
}
# define GC_TEST_AND_SET_DEFINED
- /* Should probably also define GC_clear, since it needs */
- /* a memory barrier ?? */
+ inline static void GC_clear(volatile unsigned int *addr) {
+ __asm__ __volatile__("mb" : : : "memory");
+ *(addr) = 0;
+ }
+# define GC_CLEAR_DEFINED
# endif /* ALPHA */
# ifdef ARM32
inline static int GC_test_and_set(volatile unsigned int *addr) {
@@ -211,15 +214,27 @@
# endif /* ARM32 */
# endif /* __GNUC__ */
# if (defined(ALPHA) && !defined(__GNUC__))
-# define GC_test_and_set(addr) __cxx_test_and_set_atomic(addr, 1)
+# ifndef OSF1
+ --> We currently assume that if gcc is not used, we are
+ --> running under Tru64.
+# endif
+# include <machine/builtins.h>
+# include <c_asm.h>
+# define GC_test_and_set(addr) __ATOMIC_EXCH_LONG(addr, 1)
# define GC_TEST_AND_SET_DEFINED
+# define GC_clear(addr) { asm("mb"); *(volatile unsigned *)addr = 0; }
+# define GC_CLEAR_DEFINED
# endif
# if defined(MSWIN32)
# define GC_test_and_set(addr) InterlockedExchange((LPLONG)addr,1)
# define GC_TEST_AND_SET_DEFINED
# endif
# ifdef MIPS
-# if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) \
+# ifdef LINUX
+# include <sys/tas.h>
+# define GC_test_and_set(addr) _test_and_set((int *) addr,1)
+# define GC_TEST_AND_SET_DEFINED
+# elif __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) \
|| !defined(_COMPILER_VERSION) || _COMPILER_VERSION < 700
# ifdef __GNUC__
# define GC_test_and_set(addr) _test_and_set(addr,1)
@@ -266,7 +281,7 @@
# endif
# if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
- && !defined(GC_IRIX_THREADS)
+ && !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS)
# define NO_THREAD (pthread_t)(-1)
# include <pthread.h>
# if defined(PARALLEL_MARK)
@@ -302,7 +317,7 @@
return (GC_bool) result;
}
# endif /* !GENERIC_COMPARE_AND_SWAP */
- inline static void GC_memory_write_barrier()
+ inline static void GC_memory_barrier()
{
/* We believe the processor ensures at least processor */
/* consistent ordering. Thus a compiler barrier */
@@ -324,12 +339,52 @@
# endif /* !GENERIC_COMPARE_AND_SWAP */
# if 0
/* Shouldn't be needed; we use volatile stores instead. */
- inline static void GC_memory_write_barrier()
+ inline static void GC_memory_barrier()
{
__asm__ __volatile__("mf" : : : "memory");
}
# endif /* 0 */
# endif /* IA64 */
+# if defined(ALPHA)
+# if !defined(GENERIC_COMPARE_AND_SWAP)
+# if defined(__GNUC__)
+ inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr,
+ GC_word old, GC_word new_val)
+ {
+ unsigned long was_equal;
+ unsigned long temp;
+
+ __asm__ __volatile__(
+ "1: ldq_l %0,%1\n"
+ " cmpeq %0,%4,%2\n"
+ " mov %3,%0\n"
+ " beq %2,2f\n"
+ " stq_c %0,%1\n"
+ " beq %0,1b\n"
+ "2:\n"
+ " mb\n"
+ :"=&r" (temp), "=m" (*addr), "=&r" (was_equal)
+ : "r" (new_val), "Ir" (old)
+ :"memory");
+ return was_equal;
+ }
+# else /* !__GNUC__ */
+ inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr,
+ GC_word old, GC_word new_val)
+ {
+ return __CMP_STORE_QUAD(addr, old, new_val, addr);
+ }
+# endif /* !__GNUC__ */
+# endif /* !GENERIC_COMPARE_AND_SWAP */
+# ifdef __GNUC__
+ inline static void GC_memory_barrier()
+ {
+ __asm__ __volatile__("mb" : : : "memory");
+ }
+# else
+# define GC_memory_barrier() asm("mb")
+# endif /* !__GNUC__ */
+# endif /* ALPHA */
# if !defined(GENERIC_COMPARE_AND_SWAP)
/* Returns the original value of *addr. */
inline static GC_word GC_atomic_add(volatile GC_word *addr,
@@ -435,7 +490,7 @@
# define NO_THREAD (pthread_t)(-1)
# define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD
# define I_HOLD_LOCK() (pthread_equal(GC_lock_holder, pthread_self()))
-# define LOCK() { if (GC_test_and_set(&GC_allocate_lock, 1)) GC_lock(); }
+# define LOCK() { if (GC_test_and_set(&GC_allocate_lock)) GC_lock(); }
# define UNLOCK() GC_clear(&GC_allocate_lock);
extern VOLATILE GC_bool GC_collecting;
# define ENTER_GC() \
@@ -444,11 +499,18 @@
}
# define EXIT_GC() GC_collecting = 0;
# endif /* GC_IRIX_THREADS */
-# ifdef GC_WIN32_THREADS
-# include <windows.h>
- GC_API CRITICAL_SECTION GC_allocate_ml;
-# define LOCK() EnterCriticalSection(&GC_allocate_ml);
-# define UNLOCK() LeaveCriticalSection(&GC_allocate_ml);
+# if defined(GC_WIN32_THREADS)
+# if defined(GC_PTHREADS)
+# include <pthread.h>
+ extern pthread_mutex_t GC_allocate_ml;
+# define LOCK() pthread_mutex_lock(&GC_allocate_ml)
+# define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml)
+# else
+# include <windows.h>
+ GC_API CRITICAL_SECTION GC_allocate_ml;
+# define LOCK() EnterCriticalSection(&GC_allocate_ml);
+# define UNLOCK() LeaveCriticalSection(&GC_allocate_ml);
+# endif
# endif
# ifndef SET_LOCK_HOLDER
# define SET_LOCK_HOLDER()