Don't pin a register for gc_thread on SPARC.
[ghc-hetmet.git] / rts / sm / GCThread.h
index 338cca7..1d0a05c 100644 (file)
@@ -105,7 +105,7 @@ typedef struct step_workspace_ {
    GC thread object
 
    Every GC thread has one of these. It contains all the step specific
    GC thread object
 
    Every GC thread has one of these. It contains all the step specific
-   workspaces and other GC thread loacl information. At some later
+   workspaces and other GC thread local information. At some later
    point it maybe useful to move this other into the TLS store of the
    GC threads
    ------------------------------------------------------------------------- */
    point it maybe useful to move this other into the TLS store of the
    GC threads
    ------------------------------------------------------------------------- */
@@ -113,10 +113,9 @@ typedef struct step_workspace_ {
 typedef struct gc_thread_ {
 #ifdef THREADED_RTS
     OSThreadId id;                 // The OS thread that this struct belongs to
 typedef struct gc_thread_ {
 #ifdef THREADED_RTS
     OSThreadId id;                 // The OS thread that this struct belongs to
-    Mutex      wake_mutex;
-    Condition  wake_cond;          // So we can go to sleep between GCs
-    rtsBool    wakeup;
-    rtsBool    exit;
+    SpinLock   gc_spin;
+    SpinLock   mut_spin;
+    volatile rtsBool wakeup;
 #endif
     nat thread_index;              // a zero based index identifying the thread
 
 #endif
     nat thread_index;              // a zero based index identifying the thread
 
@@ -181,8 +180,50 @@ typedef struct gc_thread_ {
 extern nat n_gc_threads;
 
 extern gc_thread **gc_threads;
 extern nat n_gc_threads;
 
 extern gc_thread **gc_threads;
-register gc_thread *gct __asm__("%rbx");
-// extern gc_thread *gct;  // this thread's gct TODO: make thread-local
+
+/* -----------------------------------------------------------------------------
+   The gct variable is thread-local and points to the current thread's
+   gc_thread structure.  It is heavily accessed, so we try to put gct
+   into a global register variable if possible; if we don't have a
+   register then use gcc's __thread extension to create a thread-local
+   variable.
+
+   Even on x86 where registers are scarce, it is worthwhile using a
+   register variable here: I measured about a 2-5% slowdown with the
+   __thread version.
+   -------------------------------------------------------------------------- */
+
+#define GLOBAL_REG_DECL(type,name,reg) register type name REG(reg);
+
+#if defined(sparc_HOST_ARCH)
+// Don't use REG_base or R1 for gct on SPARC because they're getting clobbered 
+//     by something else. Not sure what yet. -- BL 2009/01/03
+
+extern __thread gc_thread* gct;
+#define DECLARE_GCT __thread gc_thread* gct;
+
+#elif defined(REG_Base) && !defined(i386_HOST_ARCH)
+// on i386, REG_Base is %ebx which is also used for PIC, so we don't
+// want to steal it
+
+GLOBAL_REG_DECL(gc_thread*, gct, REG_Base)
+#define DECLARE_GCT /* nothing */
+
+#elif defined(REG_R1)
+
+GLOBAL_REG_DECL(gc_thread*, gct, REG_R1)
+#define DECLARE_GCT /* nothing */
+
+#elif defined(__GNUC__)
+
+extern __thread gc_thread* gct;
+#define DECLARE_GCT __thread gc_thread* gct;
+
+#else
+
+#error Cannot find a way to declare the thread-local gct
+
+#endif
 
 #endif // GCTHREAD_H
 
 
 #endif // GCTHREAD_H