summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Z. Yang <ezyang@mit.edu>2010-09-25 03:30:26 +0000
committerEdward Z. Yang <ezyang@mit.edu>2010-09-25 03:30:26 +0000
commit539d3adec64f51a3fb13bb65b7a494d7eded01a0 (patch)
treed70b17364ff81c6888e3ac9338aaa5239c426515
parent83d563cb9ede0ba792836e529b1e2929db926355 (diff)
downloadhaskell-539d3adec64f51a3fb13bb65b7a494d7eded01a0.tar.gz
Don't interrupt when task blocks exceptions, don't immediately start exception.
-rw-r--r--rts/Interpreter.c7
-rw-r--r--rts/RaiseAsync.c16
-rw-r--r--rts/Schedule.c2
-rw-r--r--rts/sm/MarkWeak.c3
4 files changed, 23 insertions, 5 deletions
diff --git a/rts/Interpreter.c b/rts/Interpreter.c
index da7ee2196a..58ffd257af 100644
--- a/rts/Interpreter.c
+++ b/rts/Interpreter.c
@@ -1454,6 +1454,13 @@ run_BCO:
cap = (Capability *)((void *)((unsigned char*)resumeThread(tok) - STG_FIELD_OFFSET(Capability,r)));
LOAD_STACK_POINTERS;
+ if (Sp[0] == (W_)&stg_enter_info) {
+ // Sp got clobbered due to an exception; so we should
+ // go run it instead.
+ Sp++;
+ goto eval;
+ }
+
// Re-load the pointer to the BCO from the RET_DYN frame,
// it might have moved during the call. Also reload the
// pointers to the components of the BCO.
diff --git a/rts/RaiseAsync.c b/rts/RaiseAsync.c
index b94ccea283..cbbdc95beb 100644
--- a/rts/RaiseAsync.c
+++ b/rts/RaiseAsync.c
@@ -405,9 +405,11 @@ check_target:
}
}
if (task != NULL) {
- raiseAsync(cap, target, msg->exception, rtsFalse, NULL);
- interruptWorkerTask(task);
- return THROWTO_SUCCESS;
+ blockedThrowTo(cap, target, msg);
+ if (!((target->flags & TSO_BLOCKEX) && ((target->flags & TSO_INTERRUPTIBLE) == 0))) {
+ interruptWorkerTask(task);
+ }
+ return THROWTO_BLOCKED;
} else {
debugTraceCap(DEBUG_sched, cap, "throwTo: could not find worker thread to kill");
}
@@ -665,6 +667,14 @@ removeFromQueues(Capability *cap, StgTSO *tso)
goto done;
#endif
+ case BlockedOnCCall_Interruptible:
+ case BlockedOnCCall:
+ // ccall shouldn't be put on the run queue, because whenever
+ // we raise an exception for such a blocked thread, it's only
+ // when we're /exiting/ the call.
+ tso->why_blocked = NotBlocked;
+ return;
+
default:
barf("removeFromQueues: %d", tso->why_blocked);
}
diff --git a/rts/Schedule.c b/rts/Schedule.c
index 0850749b36..456258c885 100644
--- a/rts/Schedule.c
+++ b/rts/Schedule.c
@@ -1820,7 +1820,7 @@ resumeThread (void *task_)
if ((tso->flags & TSO_BLOCKEX) == 0) {
// avoid locking the TSO if we don't have to
if (tso->blocked_exceptions != END_BLOCKED_EXCEPTIONS_QUEUE) {
- awakenBlockedExceptionQueue(cap,tso);
+ maybePerformBlockedException(cap,tso);
}
}
diff --git a/rts/sm/MarkWeak.c b/rts/sm/MarkWeak.c
index d4d708e72c..aadd5757af 100644
--- a/rts/sm/MarkWeak.c
+++ b/rts/sm/MarkWeak.c
@@ -271,9 +271,10 @@ static rtsBool tidyThreadList (generation *gen)
// if the thread is not masking exceptions but there are
// pending exceptions on its queue, then something has gone
// wrong. However, pending exceptions are OK if there is an
- // uninterruptible FFI call.
+ // FFI call.
ASSERT(t->blocked_exceptions == END_BLOCKED_EXCEPTIONS_QUEUE
|| t->why_blocked == BlockedOnCCall
+ || t->why_blocked == BlockedOnCCall_Interruptible
|| (t->flags & TSO_BLOCKEX));
if (tmp == NULL) {