/* ---------------------------------------------------------------------------
- * $Id: Schedule.c,v 1.137 2002/04/13 05:33:02 sof Exp $
+ * $Id: Schedule.c,v 1.138 2002/04/23 06:34:27 sof Exp $
*
* (c) The GHC Team, 1998-2000
*
/* Check to see whether there are any worker threads
waiting to deposit external call results. If so,
yield our capability */
- yieldToReturningWorker(&sched_mutex, cap);
+ yieldToReturningWorker(&sched_mutex, &cap);
#endif
/* If we're interrupted (the user pressed ^C, or some other
/* check for signals each time around the scheduler */
#ifndef mingw32_TARGET_OS
if (signals_pending()) {
+ RELEASE_LOCK(&sched_mutex); /* ToDo: kill */
startSignalHandlers();
+ ACQUIRE_LOCK(&sched_mutex);
}
#endif
* for signals to arrive rather then bombing out with a
* deadlock.
*/
+#if defined(RTS_SUPPORTS_THREADS)
+ if ( 0 ) { /* hmm..what to do? Simply stop waiting for
+ a signal with no runnable threads (or I/O
+ suspended ones) leads nowhere quick.
+ For now, simply shut down when we reach this
+ condition.
+
+ ToDo: define precisely under what conditions
+ the Scheduler should shut down in an MT setting.
+ */
+#else
if ( anyUserHandlers() ) {
+#endif
IF_DEBUG(scheduler,
sched_belch("still deadlocked, waiting for signals..."));
if (interrupted) { continue; }
if (signals_pending()) {
+ RELEASE_LOCK(&sched_mutex);
startSignalHandlers();
+ ACQUIRE_LOCK(&sched_mutex);
}
ASSERT(!EMPTY_RUN_QUEUE());
goto not_deadlocked;
for (m = main_threads; m != NULL; m = m->link) {
switch (m->tso->why_blocked) {
case BlockedOnBlackHole:
- raiseAsyncWithLock(m->tso, (StgClosure *)NonTermination_closure);
+ raiseAsync(m->tso, (StgClosure *)NonTermination_closure);
break;
case BlockedOnException:
case BlockedOnMVar:
- raiseAsyncWithLock(m->tso, (StgClosure *)Deadlock_closure);
+ raiseAsync(m->tso, (StgClosure *)Deadlock_closure);
break;
default:
barf("deadlock: main thread blocked in a strange way");
m = main_threads;
switch (m->tso->why_blocked) {
case BlockedOnBlackHole:
- raiseAsyncWithLock(m->tso, (StgClosure *)NonTermination_closure);
+ raiseAsync(m->tso, (StgClosure *)NonTermination_closure);
break;
case BlockedOnException:
case BlockedOnMVar:
- raiseAsyncWithLock(m->tso, (StgClosure *)Deadlock_closure);
+ raiseAsync(m->tso, (StgClosure *)Deadlock_closure);
break;
default:
barf("deadlock: main thread blocked in a strange way");
*
* This is used when we catch a user interrupt (^C), before performing
* any necessary cleanups and running finalizers.
+ *
+ * Locks: sched_mutex held.
* ------------------------------------------------------------------------- */
void deleteAllThreads ( void )
/* Reset blocking status */
tso->why_blocked = NotBlocked;
- RELEASE_LOCK(&sched_mutex);
-
cap->r.rCurrentTSO = tso;
+ RELEASE_LOCK(&sched_mutex);
return &cap->r;
}
* protect the increment operation on next_thread_id.
* In future, we could use an atomic increment instead.
*/
+#ifdef SMP
if (!have_lock) { ACQUIRE_LOCK(&sched_mutex); }
+#endif
tso->id = next_thread_id++;
+#ifdef SMP
if (!have_lock) { RELEASE_LOCK(&sched_mutex); }
+#endif
tso->why_blocked = NotBlocked;
tso->blocked_exceptions = NULL;
{
StgBlockingQueueElement *t, **last;
- ACQUIRE_LOCK(&sched_mutex);
switch (tso->why_blocked) {
case NotBlocked:
tso->why_blocked = NotBlocked;
tso->block_info.closure = NULL;
PUSH_ON_RUN_QUEUE(tso);
- RELEASE_LOCK(&sched_mutex);
}
#else
static void
return;
}
- ACQUIRE_LOCK(&sched_mutex);
switch (tso->why_blocked) {
case BlockedOnMVar:
tso->why_blocked = NotBlocked;
tso->block_info.closure = NULL;
PUSH_ON_RUN_QUEUE(tso);
- RELEASE_LOCK(&sched_mutex);
}
#endif
* CATCH_FRAME on the stack. In either case, we strip the entire
* stack and replace the thread with a zombie.
*
- * Locks: sched_mutex not held upon entry nor exit.
+ * Locks: sched_mutex held upon entry nor exit.
*
* -------------------------------------------------------------------------- */
void
raiseAsyncWithLock(StgTSO *tso, StgClosure *exception)
{
- /* When raising async exs from contexts where sched_mutex is held;
+ /* When raising async exs from contexts where sched_mutex isn't held;
use raiseAsyncWithLock(). */
- RELEASE_LOCK(&sched_mutex);
- raiseAsync(tso,exception);
ACQUIRE_LOCK(&sched_mutex);
+ raiseAsync(tso,exception);
+ RELEASE_LOCK(&sched_mutex);
}
void
case BlockedOnMVar:
case BlockedOnException:
/* Called by GC - sched_mutex lock is currently held. */
- raiseAsyncWithLock(tso,(StgClosure *)BlockedOnDeadMVar_closure);
+ raiseAsync(tso,(StgClosure *)BlockedOnDeadMVar_closure);
break;
case BlockedOnBlackHole:
- raiseAsyncWithLock(tso,(StgClosure *)NonTermination_closure);
+ raiseAsync(tso,(StgClosure *)NonTermination_closure);
break;
case NotBlocked:
/* This might happen if the thread was blocked on a black hole
*/
IF_DEBUG(scheduler,
sched_belch("thread %d is blocked on itself", t->id));
- raiseAsyncWithLock(t, (StgClosure *)NonTermination_closure);
+ raiseAsync(t, (StgClosure *)NonTermination_closure);
goto done;
}
else {