replace sparc-specific Int64 code with calls to platform-independent macros
[ghc-hetmet.git] / rts / sm / GC.c
index 501a9e5..88b11aa 100644 (file)
@@ -116,7 +116,10 @@ nat mutlist_MUTVARS,
 /* Thread-local data for each GC thread
  */
 gc_thread **gc_threads = NULL;
-// gc_thread *gct = NULL;  // this thread's gct TODO: make thread-local
+
+#if !defined(THREADED_RTS)
+StgWord8 the_gc_thread[sizeof(gc_thread) + 64 * sizeof(step_workspace)];
+#endif
 
 // Number of threads running in *this* GC.  Affects how many
 // step->todos[] lists we have to look in to find work.
@@ -144,8 +147,8 @@ static void resize_generations      (void);
 static void resize_nursery          (void);
 static void start_gc_threads        (void);
 static void scavenge_until_all_done (void);
-static nat  inc_running             (void);
-static nat  dec_running             (void);
+static StgWord inc_running          (void);
+static StgWord dec_running          (void);
 static void wakeup_gc_threads       (nat n_threads, nat me);
 static void shutdown_gc_threads     (nat n_threads, nat me);
 
@@ -212,6 +215,9 @@ GarbageCollect (rtsBool force_major_gc,
   // tell the STM to discard any cached closures it's hoping to re-use
   stmPreGCHook();
 
+  // lock the StablePtr table
+  stablePtrPreGC();
+
 #ifdef DEBUG
   mutlist_MUTVARS = 0;
   mutlist_MUTARRS = 0;
@@ -264,7 +270,7 @@ GarbageCollect (rtsBool force_major_gc,
   n_gc_threads = 1;
 #endif
 
-  trace(TRACE_gc|DEBUG_gc, "GC (gen %d): %d KB to collect, %ld MB in use, using %d thread(s)",
+  debugTrace(DEBUG_gc, "GC (gen %d): %d KB to collect, %ld MB in use, using %d thread(s)",
         N, n * (BLOCK_SIZE / 1024), mblocks_allocated, n_gc_threads);
 
 #ifdef RTS_GTK_FRONTPANEL
@@ -314,12 +320,12 @@ GarbageCollect (rtsBool force_major_gc,
   // this is the main thread
 #ifdef THREADED_RTS
   if (n_gc_threads == 1) {
-      gct = gc_threads[0];
+      SET_GCT(gc_threads[0]);
   } else {
-      gct = gc_threads[cap->no];
+      SET_GCT(gc_threads[cap->no]);
   }
 #else
-  gct = gc_threads[0];
+SET_GCT(gc_threads[0]);
 #endif
 
   /* -----------------------------------------------------------------------
@@ -534,12 +540,12 @@ GarbageCollect (rtsBool force_major_gc,
       nat i;
       for (i=0; i < n_gc_threads; i++) {
           if (n_gc_threads > 1) {
-              trace(TRACE_gc,"thread %d:", i);
-              trace(TRACE_gc,"   copied           %ld", gc_threads[i]->copied * sizeof(W_));
-              trace(TRACE_gc,"   scanned          %ld", gc_threads[i]->scanned * sizeof(W_));
-              trace(TRACE_gc,"   any_work         %ld", gc_threads[i]->any_work);
-              trace(TRACE_gc,"   no_work          %ld", gc_threads[i]->no_work);
-              trace(TRACE_gc,"   scav_find_work %ld",   gc_threads[i]->scav_find_work);
+              debugTrace(DEBUG_gc,"thread %d:", i);
+              debugTrace(DEBUG_gc,"   copied           %ld", gc_threads[i]->copied * sizeof(W_));
+              debugTrace(DEBUG_gc,"   scanned          %ld", gc_threads[i]->scanned * sizeof(W_));
+              debugTrace(DEBUG_gc,"   any_work         %ld", gc_threads[i]->any_work);
+              debugTrace(DEBUG_gc,"   no_work          %ld", gc_threads[i]->no_work);
+              debugTrace(DEBUG_gc,"   scav_find_work %ld",   gc_threads[i]->scav_find_work);
           }
           copied += gc_threads[i]->copied;
           max_copied = stg_max(gc_threads[i]->copied, max_copied);
@@ -764,7 +770,7 @@ GarbageCollect (rtsBool force_major_gc,
   IF_DEBUG(sanity, checkSanity());
 
   // extra GC trace info 
-  if (traceClass(TRACE_gc|DEBUG_gc)) statDescribeGens();
+  IF_DEBUG(gc, statDescribeGens());
 
 #ifdef DEBUG
   // symbol-table based profiling 
@@ -791,6 +797,9 @@ GarbageCollect (rtsBool force_major_gc,
   slop = calcLiveBlocks() * BLOCK_SIZE_W - live;
   stat_endGC(allocated, live, copied, N, max_copied, avg_copied, slop);
 
+  // unlock the StablePtr table
+  stablePtrPostGC();
+
   // Guess which generation we'll collect *next* time
   initialise_N(force_major_gc);
 
@@ -803,7 +812,7 @@ GarbageCollect (rtsBool force_major_gc,
 
   RELEASE_SM_LOCK;
 
-  gct = saved_gct;
+  SET_GCT(saved_gct);
 }
 
 /* -----------------------------------------------------------------------------
@@ -857,15 +866,11 @@ initialise_N (rtsBool force_major_gc)
 #define GC_THREAD_RUNNING              2
 #define GC_THREAD_WAITING_TO_CONTINUE  3
 
-static gc_thread *
-alloc_gc_thread (int n)
+static void
+new_gc_thread (nat n, gc_thread *t)
 {
     nat s;
     step_workspace *ws;
-    gc_thread *t;
-
-    t = stgMallocBytes(sizeof(gc_thread) + total_steps * sizeof(step_workspace),
-                       "alloc_gc_thread");
 
 #ifdef THREADED_RTS
     t->id = 0;
@@ -891,7 +896,7 @@ alloc_gc_thread (int n)
         ws = &t->steps[s];
         ws->step = &all_steps[s];
         ASSERT(s == ws->step->abs_no);
-        ws->gct = t;
+        ws->my_gct = t;
         
         ws->todo_bd = NULL;
         ws->todo_q = newWSDeque(128);
@@ -904,8 +909,6 @@ alloc_gc_thread (int n)
         ws->scavd_list = NULL;
         ws->n_scavd_blocks = 0;
     }
-
-    return t;
 }
 
 
@@ -920,14 +923,34 @@ initGcThreads (void)
                                     "alloc_gc_threads");
 
        for (i = 0; i < RtsFlags.ParFlags.nNodes; i++) {
-           gc_threads[i] = alloc_gc_thread(i);
+            gc_threads[i] = 
+                stgMallocBytes(sizeof(gc_thread) + total_steps * sizeof(step_workspace),
+                               "alloc_gc_threads");
+
+            new_gc_thread(i, gc_threads[i]);
        }
 #else
-       gc_threads = stgMallocBytes (sizeof(gc_thread*), 
-                                    "alloc_gc_threads");
+        gc_threads = stgMallocBytes (sizeof(gc_thread*),"alloc_gc_threads");
+       gc_threads[0] = gct;
+        new_gc_thread(0,gc_threads[0]);
+#endif
+    }
+}
 
-       gc_threads[0] = alloc_gc_thread(0);
+void
+freeGcThreads (void)
+{
+    if (gc_threads != NULL) {
+#if defined(THREADED_RTS)
+        nat i;
+       for (i = 0; i < RtsFlags.ParFlags.nNodes; i++) {
+            stgFree (gc_threads[i]);
+       }
+        stgFree (gc_threads);
+#else
+        stgFree (gc_threads);
 #endif
+        gc_threads = NULL;
     }
 }
 
@@ -935,32 +958,22 @@ initGcThreads (void)
    Start GC threads
    ------------------------------------------------------------------------- */
 
-static nat gc_running_threads;
-
-#if defined(THREADED_RTS)
-static Mutex gc_running_mutex;
-#endif
+static volatile StgWord gc_running_threads;
 
-static nat
+static StgWord
 inc_running (void)
 {
-    nat n_running;
-    ACQUIRE_LOCK(&gc_running_mutex);
-    n_running = ++gc_running_threads;
-    RELEASE_LOCK(&gc_running_mutex);
-    ASSERT(n_running <= n_gc_threads);
-    return n_running;
+    StgWord new;
+    new = atomic_inc(&gc_running_threads);
+    ASSERT(new <= n_gc_threads);
+    return new;
 }
 
-static nat
+static StgWord
 dec_running (void)
 {
-    nat n_running;
-    ACQUIRE_LOCK(&gc_running_mutex);
-    ASSERT(n_gc_threads != 0);
-    n_running = --gc_running_threads;
-    RELEASE_LOCK(&gc_running_mutex);
-    return n_running;
+    ASSERT(gc_running_threads != 0);
+    return atomic_dec(&gc_running_threads);
 }
 
 static rtsBool
@@ -1136,7 +1149,6 @@ start_gc_threads (void)
 {
 #if defined(THREADED_RTS)
     gc_running_threads = 0;
-    initMutex(&gc_running_mutex);
 #endif
 }
 
@@ -1435,7 +1447,7 @@ init_gc_thread (gc_thread *t)
    -------------------------------------------------------------------------- */
 
 static void
-mark_root(void *user, StgClosure **root)
+mark_root(void *user USED_IF_THREADS, StgClosure **root)
 {
     // we stole a register for gct, but this function is called from
     // *outside* the GC where the register variable is not in effect,
@@ -1444,11 +1456,11 @@ mark_root(void *user, StgClosure **root)
     // incorrect.
     gc_thread *saved_gct;
     saved_gct = gct;
-    gct = user;
+    SET_GCT(user);
     
     evacuate(root);
     
-    gct = saved_gct;
+    SET_GCT(saved_gct);
 }
 
 /* -----------------------------------------------------------------------------