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"
 #define GCTHREAD_H
 
 #include "OSThreads.h"
+#include "WSDeque.h"
 
 /* -----------------------------------------------------------------------------
    General scheme
 
 /* -----------------------------------------------------------------------------
    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
 
     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;
 
 
     // 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
 
     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
 
     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
 
 } 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
    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 +115,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
 
@@ -132,6 +133,14 @@ typedef struct gc_thread_ {
     // block that is currently being scanned
     bdescr *     scan_bd;
 
     // 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
 
     // --------------------
     // 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
 /* -----------------------------------------------------------------------------
    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);
 
    -------------------------------------------------------------------------- */
 
 #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 */
 
 GLOBAL_REG_DECL(gc_thread*, gct, REG_Base)
 #define DECLARE_GCT /* nothing */