Maintain Task/Capability invariants in performPendingThrowTos
authorSimon Marlow <marlowsd@gmail.com>
Sat, 29 Aug 2009 09:26:07 +0000 (09:26 +0000)
committerSimon Marlow <marlowsd@gmail.com>
Sat, 29 Aug 2009 09:26:07 +0000 (09:26 +0000)
Fixes an ASSERTION failure with concprog001, -threaded -debug, +RTS -N2

rts/Schedule.c

index e9d4327..07af0bf 100644 (file)
@@ -2710,8 +2710,12 @@ performPendingThrowTos (StgTSO *threads)
 {
     StgTSO *tso, *next;
     Capability *cap;
+    Task *task, *saved_task;;
     step *step;
 
+    task = myTask();
+    cap = task->cap;
+
     for (tso = threads; tso != END_TSO_QUEUE; tso = next) {
        next = tso->global_link;
 
@@ -2721,7 +2725,17 @@ performPendingThrowTos (StgTSO *threads)
 
        debugTrace(DEBUG_sched, "performing blocked throwTo to thread %lu", (unsigned long)tso->id);
        
-       cap = tso->cap;
-        maybePerformBlockedException(cap, tso);
-    }
+        // We must pretend this Capability belongs to the current Task
+        // for the time being, as invariants will be broken otherwise.
+        // In fact the current Task has exclusive access to the systme
+        // at this point, so this is just bookkeeping:
+       task->cap = tso->cap;
+        saved_task = tso->cap->running_task;
+        tso->cap->running_task = task;
+        maybePerformBlockedException(tso->cap, tso);
+        tso->cap->running_task = saved_task;
+    }
+
+    // Restore our original Capability:
+    task->cap = cap;
 }