GC: move static object processinng into thread-local storage
authorSimon Marlow <simonmarhaskell@gmail.com>
Wed, 16 Apr 2008 21:48:25 +0000 (21:48 +0000)
committerSimon Marlow <simonmarhaskell@gmail.com>
Wed, 16 Apr 2008 21:48:25 +0000 (21:48 +0000)
includes/Storage.h
rts/RetainerProfile.c
rts/RetainerProfile.h
rts/Stats.c
rts/sm/Compact.c
rts/sm/Evac.c-inc
rts/sm/GC.c
rts/sm/GC.h
rts/sm/Scav.c
rts/sm/Storage.c

index 28225d7..c51f51b 100644 (file)
@@ -576,7 +576,6 @@ extern void newDynCAF(StgClosure *);
 extern void move_TSO(StgTSO *src, StgTSO *dest);
 extern StgTSO *relocate_stack(StgTSO *dest, ptrdiff_t diff);
 
-extern StgClosure * RTS_VAR(scavenged_static_objects);
 extern StgWeak    * RTS_VAR(old_weak_ptr_list);
 extern StgWeak    * RTS_VAR(weak_ptr_list);
 extern StgClosure * RTS_VAR(caf_list);
index e963567..dec886a 100644 (file)
@@ -1913,7 +1913,7 @@ computeRetainerSet( void )
  *    they are not taken into consideration in computing retainer sets.
  * -------------------------------------------------------------------------- */
 void
-resetStaticObjectForRetainerProfiling( void )
+resetStaticObjectForRetainerProfiling( StgClosure *static_objects )
 {
 #ifdef DEBUG_RETAINER
     nat count;
@@ -1923,7 +1923,7 @@ resetStaticObjectForRetainerProfiling( void )
 #ifdef DEBUG_RETAINER
     count = 0;
 #endif
-    p = scavenged_static_objects;
+    p = static_objects;
     while (p != END_OF_STATIC_LIST) {
 #ifdef DEBUG_RETAINER
        count++;
index 827daa8..f33c079 100644 (file)
@@ -18,7 +18,7 @@ extern void  initRetainerProfiling ( void );
 extern void  endRetainerProfiling  ( void );
 extern void  printRetainer         ( FILE *, retainer );
 extern void  retainerProfile       ( void );
-extern void  resetStaticObjectForRetainerProfiling ( void );
+extern void resetStaticObjectForRetainerProfiling( StgClosure *static_objects );
 
 extern StgWord RTS_VAR(flip);
 
index 7347918..9a9acca 100644 (file)
@@ -644,7 +644,6 @@ stat_exit(int alloc)
             
             statsPrintf("recordMutableGen_sync: %"FMT_Word64"\n", recordMutableGen_sync.spin);
             statsPrintf("gc_alloc_block_sync: %"FMT_Word64"\n", gc_alloc_block_sync.spin);
-            statsPrintf("static_objects_sync: %"FMT_Word64"\n", static_objects_sync.spin);
             statsPrintf("whitehole_spin: %"FMT_Word64"\n", whitehole_spin);
             for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
                 for (s = 0; s < generations[g].n_steps; s++) {
index b8a40d4..44b5242 100644 (file)
@@ -999,7 +999,7 @@ compact(void)
     }
 
     // the static objects
-    thread_static(scavenged_static_objects);
+    thread_static(gct->scavenged_static_objects /* ToDo: ok? */);
 
     // the stable pointer table
     threadStablePtrTable((evac_fn)thread);
index 752fe92..e651418 100644 (file)
@@ -217,26 +217,39 @@ loop:
       switch (info->type) {
 
       case THUNK_STATIC:
-         if (info->srt_bitmap != 0 &&
-             *THUNK_STATIC_LINK((StgClosure *)q) == NULL) {
-             ACQUIRE_SPIN_LOCK(&static_objects_sync);
+         if (info->srt_bitmap != 0) {
              if (*THUNK_STATIC_LINK((StgClosure *)q) == NULL) {
-                 *THUNK_STATIC_LINK((StgClosure *)q) = static_objects;
-                 static_objects = (StgClosure *)q;
+#ifndef THREADED_RTS
+                 *THUNK_STATIC_LINK((StgClosure *)q) = gct->static_objects;
+                 gct->static_objects = (StgClosure *)q;
+#else
+                  StgPtr link;
+                  link = (StgPtr)cas((StgPtr)THUNK_STATIC_LINK((StgClosure *)q),
+                                     (StgWord)NULL,
+                                     (StgWord)gct->static_objects);
+                  if (link == NULL) {
+                      gct->static_objects = (StgClosure *)q;
+                  }
+#endif
              }
-             RELEASE_SPIN_LOCK(&static_objects_sync);
          }
          return;
-         
+
       case FUN_STATIC:
          if (info->srt_bitmap != 0 &&
              *FUN_STATIC_LINK((StgClosure *)q) == NULL) {
-             ACQUIRE_SPIN_LOCK(&static_objects_sync);
-             if (*FUN_STATIC_LINK((StgClosure *)q) == NULL) {
-                 *FUN_STATIC_LINK((StgClosure *)q) = static_objects;
-                 static_objects = (StgClosure *)q;
-             }
-             RELEASE_SPIN_LOCK(&static_objects_sync);
+#ifndef THREADED_RTS
+              *FUN_STATIC_LINK((StgClosure *)q) = gct->static_objects;
+              gct->static_objects = (StgClosure *)q;
+#else
+              StgPtr link;
+              link = (StgPtr)cas((StgPtr)FUN_STATIC_LINK((StgClosure *)q),
+                                 (StgWord)NULL,
+                                 (StgWord)gct->static_objects);
+              if (link == NULL) {
+                  gct->static_objects = (StgClosure *)q;
+              }
+#endif
          }
          return;
          
@@ -246,27 +259,40 @@ loop:
           * scavenge it later).
           */
          if (((StgIndStatic *)q)->saved_info == NULL) {
-             ACQUIRE_SPIN_LOCK(&static_objects_sync);
              if (*IND_STATIC_LINK((StgClosure *)q) == NULL) {
-                 *IND_STATIC_LINK((StgClosure *)q) = static_objects;
-                 static_objects = (StgClosure *)q;
+#ifndef THREADED_RTS
+                 *IND_STATIC_LINK((StgClosure *)q) = gct->static_objects;
+                 gct->static_objects = (StgClosure *)q;
+#else
+                  StgPtr link;
+                  link = (StgPtr)cas((StgPtr)IND_STATIC_LINK((StgClosure *)q),
+                                     (StgWord)NULL,
+                                     (StgWord)gct->static_objects);
+                  if (link == NULL) {
+                      gct->static_objects = (StgClosure *)q;
+                  }
+#endif
              }
-             RELEASE_SPIN_LOCK(&static_objects_sync);
          }
          return;
          
       case CONSTR_STATIC:
          if (*STATIC_LINK(info,(StgClosure *)q) == NULL) {
-             ACQUIRE_SPIN_LOCK(&static_objects_sync);
-             // re-test, after acquiring lock
-             if (*STATIC_LINK(info,(StgClosure *)q) == NULL) {
-                 *STATIC_LINK(info,(StgClosure *)q) = static_objects;
-                 static_objects = (StgClosure *)q;
-             }
-             RELEASE_SPIN_LOCK(&static_objects_sync);
-               /* I am assuming that static_objects pointers are not
-                * written to other objects, and thus, no need to retag. */
-         }
+#ifndef THREADED_RTS
+              *STATIC_LINK(info,(StgClosure *)q) = gct->static_objects;
+              gct->static_objects = (StgClosure *)q;
+#else
+              StgPtr link;
+              link = (StgPtr)cas((StgPtr)STATIC_LINK(info,(StgClosure *)q),
+                                 (StgWord)NULL,
+                                 (StgWord)gct->static_objects);
+              if (link == NULL) {
+                  gct->static_objects = (StgClosure *)q;
+              }
+#endif
+          }
+          /* I am assuming that static_objects pointers are not
+           * written to other objects, and thus, no need to retag. */
           return;
          
       case CONSTR_NOCAF_STATIC:
index 6c19a6a..5b16694 100644 (file)
  * We build up a static object list while collecting generations 0..N,
  * which is then appended to the static object list of generation N+1.
  */
-StgClosure* static_objects;      // live static objects
-StgClosure* scavenged_static_objects;   // static objects scavenged so far
-#ifdef THREADED_RTS
-SpinLock static_objects_sync;
-#endif
 
 /* N is the oldest generation being collected, where the generations
  * are numbered starting at 0.  A major GC (indicated by the major_gc
@@ -269,11 +264,6 @@ GarbageCollect ( rtsBool force_major_gc )
   // check stack sanity *before* GC (ToDo: check all threads) 
   IF_DEBUG(sanity, checkFreeListSanity());
 
-  /* Initialise the static object lists
-   */
-  static_objects = END_OF_STATIC_LIST;
-  scavenged_static_objects = END_OF_STATIC_LIST;
-
   // Initialise all the generations/steps that we're collecting.
   for (g = 0; g <= N; g++) {
       init_collected_gen(g,n_gc_threads);
@@ -629,12 +619,19 @@ GarbageCollect ( rtsBool force_major_gc )
 #ifdef PROFILING
   // resetStaticObjectForRetainerProfiling() must be called before
   // zeroing below.
-  resetStaticObjectForRetainerProfiling();
+  if (n_gc_threads > 1) {
+      barf("profiling is currently broken with multi-threaded GC");
+      // ToDo: fix the gct->scavenged_static_objects below
+  }
+  resetStaticObjectForRetainerProfiling(gct->scavenged_static_objects);
 #endif
 
   // zero the scavenged static object list 
   if (major_gc) {
-    zero_static_object_list(scavenged_static_objects);
+      nat i;
+      for (i = 0; i < n_gc_threads; i++) {
+          zero_static_object_list(gc_threads[i]->scavenged_static_objects);
+      }
   }
 
   // Reset the nursery
@@ -1357,6 +1354,8 @@ init_uncollected_gen (nat g, nat threads)
 static void
 init_gc_thread (gc_thread *t)
 {
+    t->static_objects = END_OF_STATIC_LIST;
+    t->scavenged_static_objects = END_OF_STATIC_LIST;
     t->evac_step = 0;
     t->failed_to_evac = rtsFalse;
     t->eager_promotion = rtsTrue;
@@ -1366,6 +1365,7 @@ init_gc_thread (gc_thread *t)
     t->no_work = 0;
     t->scav_global_work = 0;
     t->scav_local_work = 0;
+
 }
 
 /* -----------------------------------------------------------------------------
index 58aa46f..01c6024 100644 (file)
@@ -120,6 +120,9 @@ typedef struct gc_thread_ {
                                    //  during GC without accessing the block
                                    //   allocators spin lock. 
 
+    StgClosure* static_objects;      // live static objects
+    StgClosure* scavenged_static_objects;   // static objects scavenged so far
+
     lnat gc_count;                 // number of gc's this thread has done
 
     // --------------------
@@ -174,9 +177,6 @@ extern gc_thread **gc_threads;
 register gc_thread *gct __asm__("%rbx");
 // extern gc_thread *gct;  // this thread's gct TODO: make thread-local
 
-extern StgClosure* static_objects;
-extern StgClosure* scavenged_static_objects;
-
 extern bdescr *mark_stack_bdescr;
 extern StgPtr *mark_stack;
 extern StgPtr *mark_sp;
@@ -188,10 +188,6 @@ extern StgPtr  oldgen_scan;
 
 extern long copied;
 
-#ifdef THREADED_RTS
-extern SpinLock static_objects_sync;
-#endif
-
 #ifdef DEBUG
 extern nat mutlist_MUTVARS, mutlist_MUTARRS, mutlist_MVARS, mutlist_OTHERS;
 #endif
index c284dee..fc63a85 100644 (file)
@@ -1078,15 +1078,12 @@ scavenge_static(void)
 
   while (1) {
       
-    ACQUIRE_SPIN_LOCK(&static_objects_sync);
-    
     /* get the next static object from the list.  Remember, there might
      * be more stuff on this list after each evacuation...
      * (static_objects is a global)
      */
-    p = static_objects;
+    p = gct->static_objects;
     if (p == END_OF_STATIC_LIST) {
-         RELEASE_SPIN_LOCK(&static_objects_sync);
          break;
     }
     
@@ -1101,11 +1098,9 @@ scavenge_static(void)
     /* Take this object *off* the static_objects list,
      * and put it on the scavenged_static_objects list.
      */
-    static_objects = *STATIC_LINK(info,p);
-    *STATIC_LINK(info,p) = scavenged_static_objects;
-    scavenged_static_objects = p;
-    
-    RELEASE_SPIN_LOCK(&static_objects_sync);
+    gct->static_objects = *STATIC_LINK(info,p);
+    *STATIC_LINK(info,p) = gct->scavenged_static_objects;
+    gct->scavenged_static_objects = p;
     
     switch (info -> type) {
       
@@ -1528,8 +1523,8 @@ loop:
     work_to_do = rtsFalse;
 
     // scavenge static objects 
-    if (major_gc && static_objects != END_OF_STATIC_LIST) {
-       IF_DEBUG(sanity, checkStaticObjects(static_objects));
+    if (major_gc && gct->static_objects != END_OF_STATIC_LIST) {
+       IF_DEBUG(sanity, checkStaticObjects(gct->static_objects));
        scavenge_static();
     }
     
@@ -1561,11 +1556,6 @@ any_work (void)
 
     write_barrier();
 
-    // scavenge static objects 
-    if (major_gc && static_objects != END_OF_STATIC_LIST) {
-       return rtsTrue;
-    }
-    
     // scavenge objects in compacted generation
     if (mark_stack_overflowed || oldgen_scan_bd != NULL ||
        (mark_stack_bdescr != NULL && !mark_stack_empty())) {
index 7f4c723..6b16cc4 100644 (file)
@@ -259,7 +259,6 @@ initStorage( void )
 
 #ifdef THREADED_RTS
   initSpinLock(&gc_alloc_block_sync);
-  initSpinLock(&static_objects_sync);
   initSpinLock(&recordMutableGen_sync);
   whitehole_spin = 0;
 #endif