Fix for crash in setnumcapabilities001
authorSimon Marlow <marlowsd@gmail.com>
Fri, 19 Jun 2015 13:41:32 +0000 (14:41 +0100)
committerSimon Marlow <marlowsd@gmail.com>
Fri, 26 Jun 2015 08:25:35 +0000 (09:25 +0100)
getNewNursery() was unconditionally incrementing next_nursery, which
is normally fine but it broke an assumption in
storageAddCapabilities().  This manifested as an occasional crash in
the setnumcapabilities001 test.

rts/sm/Storage.c

index 7779601..6e9b063 100644 (file)
@@ -576,6 +576,7 @@ allocNursery (bdescr *tail, W_ blocks)
 STATIC_INLINE void
 assignNurseryToCapability (Capability *cap, nat n)
 {
+    ASSERT(n < n_nurseries);
     cap->r.rNursery = &nurseries[n];
     cap->r.rCurrentNursery = nurseries[n].blocks;
     newNurseryBlock(nurseries[n].blocks);
@@ -726,14 +727,19 @@ resizeNurseries (W_ blocks)
 rtsBool
 getNewNursery (Capability *cap)
 {
-    StgWord i = atomic_inc(&next_nursery, 1) - 1;
-    if (i >= n_nurseries) {
-        return rtsFalse;
+    StgWord i;
+
+    for(;;) {
+        i = next_nursery;
+        if (i >= n_nurseries) {
+            return rtsFalse;
+        }
+        if (cas(&next_nursery, i, i+1) == i) {
+            assignNurseryToCapability(cap, i);
+            return rtsTrue;
+        }
     }
-    assignNurseryToCapability(cap, i);
-    return rtsTrue;
 }
-
 /* -----------------------------------------------------------------------------
    move_STACK is called to update the TSO structure after it has been
    moved from one place to another.