Change tryStealSpark so it does not consume fizzled sparks
authorDuncan Coutts <duncan@well-typed.com>
Wed, 1 Jun 2011 17:17:27 +0000 (18:17 +0100)
committerDuncan Coutts <duncan@well-typed.com>
Mon, 18 Jul 2011 15:31:13 +0000 (16:31 +0100)
We want to count fizzled sparks accurately. Now tryStealSpark returns
fizzled sparks, and the callers now update the fizzled spark count.

rts/Capability.c
rts/Schedule.c
rts/Sparks.c
rts/Sparks.h

index fe5dbdc..a9bb743 100644 (file)
@@ -92,7 +92,11 @@ findSpark (Capability *cap)
       //   spark = reclaimSpark(cap->sparks);
       // However, measurements show that this makes at least one benchmark
       // slower (prsa) and doesn't affect the others.
-      spark = tryStealSpark(cap);
+      spark = tryStealSpark(cap->sparks);
+      while (spark != NULL && fizzledSpark(spark)) {
+          cap->sparks_fizzled++;
+          spark = tryStealSpark(cap->sparks);
+      }
       if (spark != NULL) {
           cap->sparks_converted++;
 
@@ -121,7 +125,11 @@ findSpark (Capability *cap)
           if (emptySparkPoolCap(robbed)) // nothing to steal here
               continue;
 
-          spark = tryStealSpark(robbed);
+          spark = tryStealSpark(robbed->sparks);
+          while (spark != NULL && fizzledSpark(spark)) {
+              cap->sparks_fizzled++;
+              spark = tryStealSpark(robbed->sparks);
+          }
           if (spark == NULL && !emptySparkPoolCap(robbed)) {
               // we conflicted with another thread while trying to steal;
               // try again later.
index 50e0663..125f9f0 100644 (file)
@@ -783,6 +783,10 @@ schedulePushWork(Capability *cap USED_IF_THREADS,
                if (emptySparkPoolCap(free_caps[i])) {
                    spark = tryStealSpark(cap->sparks);
                    if (spark != NULL) {
+                        /* TODO: if anyone wants to re-enable this code then
+                         * they must consider the fizzledSpark(spark) case
+                         * and update the per-cap spark statistics.
+                         */
                        debugTrace(DEBUG_sched, "pushing spark %p to capability %d", spark, free_caps[i]->no);
 
             traceEventStealSpark(free_caps[i], t, cap->no);
index 18d9597..5c78055 100644 (file)
@@ -73,32 +73,6 @@ newSpark (StgRegTable *reg, StgClosure *p)
     return 1;
 }
 
-/* -----------------------------------------------------------------------------
- * 
- * tryStealSpark: try to steal a spark from a Capability.
- *
- * Returns a valid spark, or NULL if the pool was empty, and can
- * occasionally return NULL if there was a race with another thread
- * stealing from the same pool.  In this case, try again later.
- *
- -------------------------------------------------------------------------- */
-
-StgClosure *
-tryStealSpark (Capability *cap)
-{
-  SparkPool *pool = cap->sparks;
-  StgClosure *stolen;
-
-  do { 
-      stolen = stealWSDeque_(pool); 
-      // use the no-loopy version, stealWSDeque_(), since if we get a
-      // spurious NULL here the caller may want to try stealing from
-      // other pools before trying again.
-  } while (stolen != NULL && !closure_SHOULD_SPARK(stolen));
-
-  return stolen;
-}
-
 /* --------------------------------------------------------------------------
  * Remove all sparks from the spark queues which should not spark any
  * more.  Called after GC. We assume exclusive access to the structure
index d714cb5..e3ddc0c 100644 (file)
@@ -30,7 +30,7 @@ INLINE_HEADER StgClosure* reclaimSpark(SparkPool *pool);
 // if the pool is almost empty).
 INLINE_HEADER rtsBool looksEmpty(SparkPool* deque);
 
-StgClosure * tryStealSpark     (Capability *cap);
+INLINE_HEADER StgClosure * tryStealSpark (SparkPool *cap);
 INLINE_HEADER rtsBool      fizzledSpark  (StgClosure *);
 
 void         freeSparkPool     (SparkPool *pool);
@@ -65,6 +65,27 @@ INLINE_HEADER void discardSparks (SparkPool *pool)
     discardElements(pool);
 }
 
+/* ----------------------------------------------------------------------------
+ * 
+ * tryStealSpark: try to steal a spark from a Capability.
+ *
+ * Returns either:
+ *  (a) a useful spark;
+ *  (b) a fizzled spark (use fizzledSpark to check);
+ *  (c) or NULL if the pool was empty, and can occasionally return NULL
+ *      if there was a race with another thread stealing from the same
+ *      pool.  In this case, try again later.
+ *
+ -------------------------------------------------------------------------- */
+
+INLINE_HEADER StgClosure * tryStealSpark (SparkPool *pool)
+{
+    return stealWSDeque_(pool);
+    // use the no-loopy version, stealWSDeque_(), since if we get a
+    // spurious NULL here the caller may want to try stealing from
+    // other pools before trying again.
+}
+
 INLINE_HEADER rtsBool fizzledSpark (StgClosure *spark)
 {
     return (GET_CLOSURE_TAG(spark) != 0 || !closure_SHOULD_SPARK(spark));