summaryrefslogtreecommitdiff
path: root/rts/PrimOps.cmm
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2009-08-18 11:29:42 +0000
committerSimon Marlow <marlowsd@gmail.com>2009-08-18 11:29:42 +0000
commitc5cafbcca54c4b1117bc43b31d86afa583fb7f62 (patch)
tree3ae6d082522b09a05efba47e55501b6dbad91a97 /rts/PrimOps.cmm
parent0dffc568e18d34eeb6d1899ea767a3814d6be167 (diff)
downloadhaskell-c5cafbcca54c4b1117bc43b31d86afa583fb7f62.tar.gz
Fix #3429: a tricky race condition
There were two bugs, and had it not been for the first one we would not have noticed the second one, so this is quite fortunate. The first bug is in stg_unblockAsyncExceptionszh_ret, when we found a pending exception to raise, but don't end up raising it, there was a missing adjustment to the stack pointer. The second bug was that this case was actually happening at all: it ought to be incredibly rare, because the pending exception thread would have to be killed between us finding it and attempting to raise the exception. This made me suspicious. It turned out that there was a race condition on the tso->flags field; multiple threads were updating this bitmask field non-atomically (one of the bits is the dirty-bit for the generational GC). The fix is to move the dirty bit into its own field of the TSO, making the TSO one word larger (sadly).
Diffstat (limited to 'rts/PrimOps.cmm')
-rw-r--r--rts/PrimOps.cmm8
1 files changed, 4 insertions, 4 deletions
diff --git a/rts/PrimOps.cmm b/rts/PrimOps.cmm
index bc2d07a2dc..baadca402c 100644
--- a/rts/PrimOps.cmm
+++ b/rts/PrimOps.cmm
@@ -1173,7 +1173,7 @@ stg_takeMVarzh
tso = StgMVar_head(mvar);
PerformPut(tso,StgMVar_value(mvar));
- if (TO_W_(StgTSO_flags(tso)) & TSO_DIRTY == 0) {
+ if (TO_W_(StgTSO_dirty(tso)) == 0) {
foreign "C" dirty_TSO(MyCapability() "ptr", tso "ptr") [];
}
@@ -1249,7 +1249,7 @@ stg_tryTakeMVarzh
/* actually perform the putMVar for the thread that we just woke up */
tso = StgMVar_head(mvar);
PerformPut(tso,StgMVar_value(mvar));
- if (TO_W_(StgTSO_flags(tso)) & TSO_DIRTY == 0) {
+ if (TO_W_(StgTSO_dirty(tso)) == 0) {
foreign "C" dirty_TSO(MyCapability() "ptr", tso "ptr") [];
}
@@ -1329,7 +1329,7 @@ stg_putMVarzh
/* actually perform the takeMVar */
tso = StgMVar_head(mvar);
PerformTake(tso, val);
- if (TO_W_(StgTSO_flags(tso)) & TSO_DIRTY == 0) {
+ if (TO_W_(StgTSO_dirty(tso)) == 0) {
foreign "C" dirty_TSO(MyCapability() "ptr", tso "ptr") [];
}
@@ -1398,7 +1398,7 @@ stg_tryPutMVarzh
/* actually perform the takeMVar */
tso = StgMVar_head(mvar);
PerformTake(tso, R2);
- if (TO_W_(StgTSO_flags(tso)) & TSO_DIRTY == 0) {
+ if (TO_W_(StgTSO_dirty(tso)) == 0) {
foreign "C" dirty_TSO(MyCapability() "ptr", tso "ptr") [];
}