Make sparks into weak pointers (#2185)
authorSimon Marlow <marlowsd@gmail.com>
Tue, 25 May 2010 15:04:35 +0000 (15:04 +0000)
committerSimon Marlow <marlowsd@gmail.com>
Tue, 25 May 2010 15:04:35 +0000 (15:04 +0000)
The new strategies library (parallel-2.0+, preferably 2.2+) is now
required for parallel programming, otherwise parallelism will be lost.

rts/Capability.c
rts/Capability.h
rts/Sparks.c
rts/Sparks.h
rts/sm/GC.c

index f5e77a9..2fcd72c 100644 (file)
@@ -819,7 +819,7 @@ freeCapabilities (void)
 
 void
 markSomeCapabilities (evac_fn evac, void *user, nat i0, nat delta, 
-                      rtsBool prune_sparks USED_IF_THREADS)
+                      rtsBool no_mark_sparks USED_IF_THREADS)
 {
     nat i;
     Capability *cap;
@@ -843,9 +843,7 @@ markSomeCapabilities (evac_fn evac, void *user, nat i0, nat delta,
        }
 
 #if defined(THREADED_RTS)
-        if (prune_sparks) {
-            pruneSparkQueue (evac, user, cap);
-        } else {
+        if (!no_mark_sparks) {
             traverseSparkQueue (evac, user, cap);
         }
 #endif
index 4b85a13..59da4a8 100644 (file)
@@ -276,7 +276,7 @@ void freeCapabilities (void);
 
 // For the GC:
 void markSomeCapabilities (evac_fn evac, void *user, nat i0, nat delta, 
-                           rtsBool prune_sparks);
+                           rtsBool no_mark_sparks);
 void markCapabilities (evac_fn evac, void *user);
 void traverseSparkQueues (evac_fn evac, void *user);
 
index 3911ae9..93f6417 100644 (file)
@@ -112,7 +112,7 @@ tryStealSpark (Capability *cap)
  * -------------------------------------------------------------------------- */
 
 void
-pruneSparkQueue (evac_fn evac, void *user, Capability *cap)
+pruneSparkQueue (Capability *cap)
 { 
     SparkPool *pool;
     StgClosurePtr spark, tmp, *elements;
@@ -208,17 +208,21 @@ pruneSparkQueue (evac_fn evac, void *user, Capability *cap)
               pruned_sparks++; // discard spark
               cap->sparks_pruned++;
           }
-      } else {
-          if (!(closure_flags[INFO_PTR_TO_STRUCT(info)->type] & _NS)) {
+      } else if (HEAP_ALLOCED(spark) && 
+                 (Bdescr(spark)->flags & BF_EVACUATED)) {
+          if (closure_SHOULD_SPARK(spark)) {
               elements[botInd] = spark; // keep entry (new address)
-              evac (user, &elements[botInd]);
               botInd++;
               n++;
           } else {
               pruned_sparks++; // discard spark
               cap->sparks_pruned++;
           }
+      } else {
+          pruned_sparks++; // discard spark
+          cap->sparks_pruned++;
       }
+
       currInd++;
 
       // in the loop, we may reach the bounds, and instantly wrap around
index 33aa818..71fac6c 100644 (file)
@@ -34,7 +34,7 @@ StgClosure * tryStealSpark     (Capability *cap);
 void         freeSparkPool     (SparkPool *pool);
 void         createSparkThread (Capability *cap);
 void         traverseSparkQueue(evac_fn evac, void *user, Capability *cap);
-void         pruneSparkQueue   (evac_fn evac, void *user, Capability *cap);
+void         pruneSparkQueue   (Capability *cap);
 
 INLINE_HEADER void discardSparks  (SparkPool *pool);
 INLINE_HEADER long sparkPoolSize  (SparkPool *pool);
index 4d63724..e7166a2 100644 (file)
@@ -411,6 +411,16 @@ SET_GCT(gc_threads[0]);
   // Now see which stable names are still alive.
   gcStablePtrTable();
 
+#ifdef THREADED_RTS
+  if (n_gc_threads == 1) {
+      for (n = 0; n < n_capabilities; n++) {
+          pruneSparkQueue(&capabilities[n]);
+      }
+  } else {
+      pruneSparkQueue(&capabilities[gct->thread_index]);
+  }
+#endif
+
 #ifdef PROFILING
   // We call processHeapClosureForDead() on every closure destroyed during
   // the current garbage collection, so we invoke LdvCensusForDead().
@@ -1072,6 +1082,16 @@ gcWorkerThread (Capability *cap)
 
     scavenge_until_all_done();
     
+#ifdef THREADED_RTS
+    // Now that the whole heap is marked, we discard any sparks that
+    // were found to be unreachable.  The main GC thread is currently
+    // marking heap reachable via weak pointers, so it is
+    // non-deterministic whether a spark will be retained if it is
+    // only reachable via weak pointers.  To fix this problem would
+    // require another GC barrier, which is too high a price.
+    pruneSparkQueue(cap);
+#endif
+
 #ifdef USE_PAPI
     // count events in this thread towards the GC totals
     papi_thread_stop_gc1_count(gct->papi_events);