check return value of write (quiets gcc)
[ghc-hetmet.git] / rts / sm / GCThread.h
index 42d20bb..aacef82 100644 (file)
@@ -15,6 +15,7 @@
 #define GCTHREAD_H
 
 #include "OSThreads.h"
+#include "WSDeque.h"
 
 /* -----------------------------------------------------------------------------
    General scheme
@@ -81,13 +82,14 @@ typedef struct step_workspace_ {
     StgPtr       todo_free;            // free ptr for todo_bd
     StgPtr       todo_lim;             // lim for todo_bd
 
-    bdescr *     buffer_todo_bd;     // buffer to reduce contention
-                                     // on the step's todos list
+    WSDeque *    todo_q;
+    bdescr *     todo_overflow;
+    nat          n_todo_overflow;
 
     // where large objects to be scavenged go
     bdescr *     todo_large_objects;
 
-    // Objects that have already been, scavenged.
+    // Objects that have already been scavenged.
     bdescr *     scavd_list;
     nat          n_scavd_blocks;     // count of blocks in this list
 
@@ -95,7 +97,7 @@ typedef struct step_workspace_ {
     bdescr *     part_list;
     unsigned int n_part_blocks;      // count of above
 
-    StgWord pad[5];
+    StgWord pad[3];
 
 } step_workspace ATTRIBUTE_ALIGNED(64);
 // align so that computing gct->steps[n] is a shift, not a multiply
@@ -105,7 +107,7 @@ typedef struct step_workspace_ {
    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
    ------------------------------------------------------------------------- */
@@ -113,10 +115,9 @@ typedef struct step_workspace_ {
 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
 
@@ -132,6 +133,14 @@ typedef struct gc_thread_ {
     // block that is currently being scanned
     bdescr *     scan_bd;
 
+    // Remembered sets on this CPU.  Each GC thread has its own
+    // private per-generation remembered sets, so it can add an item
+    // to the remembered set without taking a lock.  The mut_lists
+    // array on a gc_thread is the same as the one on the
+    // corresponding Capability; we stash it here too for easy access
+    // during GC; see recordMutableGen_GC().
+    bdescr **    mut_lists;
+
     // --------------------
     // evacuate flags
 
@@ -185,12 +194,27 @@ extern gc_thread **gc_threads;
 /* -----------------------------------------------------------------------------
    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.
+   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(REG_Base)
+#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 */