summaryrefslogtreecommitdiff
path: root/rts/Threads.c
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2014-05-04 20:27:42 +0100
committerSimon Marlow <marlowsd@gmail.com>2014-05-04 20:28:58 +0100
commitf0fcc41d755876a1b02d1c7c79f57515059f6417 (patch)
tree89cce0cfc61744b1c7b732619ea9de04f21fdcfe /rts/Threads.c
parent5141baf76132fe0d8f88cfa0a62698cc3b37e48a (diff)
downloadhaskell-f0fcc41d755876a1b02d1c7c79f57515059f6417.tar.gz
Revert "Per-thread allocation counters and limits"
Problems were found on 32-bit platforms, I'll commit again when I have a fix. This reverts the following commits: 54b31f744848da872c7c6366dea840748e01b5cf b0534f78a73f972e279eed4447a5687bd6a8308e
Diffstat (limited to 'rts/Threads.c')
-rw-r--r--rts/Threads.c77
1 files changed, 48 insertions, 29 deletions
diff --git a/rts/Threads.c b/rts/Threads.c
index b82295284b..af4353fc49 100644
--- a/rts/Threads.c
+++ b/rts/Threads.c
@@ -110,8 +110,6 @@ createThread(Capability *cap, W_ size)
tso->stackobj = stack;
tso->tot_stack_size = stack->stack_size;
- tso->alloc_limit = 0;
-
tso->trec = NO_TREC;
#ifdef PROFILING
@@ -166,31 +164,6 @@ rts_getThreadId(StgPtr tso)
return ((StgTSO *)tso)->id;
}
-/* ---------------------------------------------------------------------------
- * Getting & setting the thread allocation limit
- * ------------------------------------------------------------------------ */
-HsInt64 rts_getThreadAllocationCounter(StgPtr tso)
-{
- // NB. doesn't take into account allocation in the current nursery
- // block, so it might be off by up to 4k.
- return ((StgTSO *)tso)->alloc_limit;
-}
-
-void rts_setThreadAllocationCounter(StgPtr tso, HsInt64 i)
-{
- ((StgTSO *)tso)->alloc_limit = i;
-}
-
-void rts_enableThreadAllocationLimit(StgPtr tso)
-{
- ((StgTSO *)tso)->flags |= TSO_ALLOC_LIMIT;
-}
-
-void rts_disableThreadAllocationLimit(StgPtr tso)
-{
- ((StgTSO *)tso)->flags &= ~TSO_ALLOC_LIMIT;
-}
-
/* -----------------------------------------------------------------------------
Remove a thread from a queue.
Fails fatally if the TSO is not on the queue.
@@ -551,8 +524,21 @@ threadStackOverflow (Capability *cap, StgTSO *tso)
stg_min(tso->stackobj->stack + tso->stackobj->stack_size,
tso->stackobj->sp+64)));
- // Note [Throw to self when masked], also #767 and #8303.
- throwToSelf(cap, tso, (StgClosure *)stackOverflow_closure);
+ if (tso->flags & TSO_BLOCKEX) {
+ // NB. StackOverflow exceptions must be deferred if the thread is
+ // inside Control.Exception.mask. See bug #767 and bug #8303.
+ // This implementation is a minor hack, see Note [Throw to self when masked]
+ MessageThrowTo *msg = (MessageThrowTo*)allocate(cap, sizeofW(MessageThrowTo));
+ SET_HDR(msg, &stg_MSG_THROWTO_info, CCS_SYSTEM);
+ msg->source = tso;
+ msg->target = tso;
+ msg->exception = (StgClosure *)stackOverflow_closure;
+ blockedThrowTo(cap, tso, msg);
+ } else {
+ // Send this thread the StackOverflow exception
+ throwToSingleThreaded(cap, tso, (StgClosure *)stackOverflow_closure);
+ return;
+ }
}
@@ -683,6 +669,39 @@ threadStackOverflow (Capability *cap, StgTSO *tso)
// IF_DEBUG(scheduler,printTSO(new_tso));
}
+/* Note [Throw to self when masked]
+ *
+ * When a StackOverflow occurs when the thread is masked, we want to
+ * defer the exception to when the thread becomes unmasked/hits an
+ * interruptible point. We already have a mechanism for doing this,
+ * the blocked_exceptions list, but the use here is a bit unusual,
+ * because an exception is normally only added to this list upon
+ * an asynchronous 'throwTo' call (with all of the relevant
+ * multithreaded nonsense). Morally, a stack overflow should be an
+ * asynchronous exception sent by a thread to itself, and it should
+ * have the same semantics. But there are a few key differences:
+ *
+ * - If you actually tried to send an asynchronous exception to
+ * yourself using throwTo, the exception would actually immediately
+ * be delivered. This is because throwTo itself is considered an
+ * interruptible point, so the exception is always deliverable. Thus,
+ * ordinarily, we never end up with a message to onesself in the
+ * blocked_exceptions queue.
+ *
+ * - In the case of a StackOverflow, we don't actually care about the
+ * wakeup semantics; when an exception is delivered, the thread that
+ * originally threw the exception should be woken up, since throwTo
+ * blocks until the exception is successfully thrown. Fortunately,
+ * it is harmless to wakeup a thread that doesn't actually need waking
+ * up, e.g. ourselves.
+ *
+ * - No synchronization is necessary, because we own the TSO and the
+ * capability. You can observe this by tracing through the execution
+ * of throwTo. We skip synchronizing the message and inter-capability
+ * communication.
+ *
+ * We think this doesn't break any invariants, but do be careful!
+ */
/* ---------------------------------------------------------------------------