diff options
author | Simon Marlow <simonmar@microsoft.com> | 2006-06-08 14:44:57 +0000 |
---|---|---|
committer | Simon Marlow <simonmar@microsoft.com> | 2006-06-08 14:44:57 +0000 |
commit | 7434fb5be86c7cc59c520dc07dc96b27b4fb1406 (patch) | |
tree | 2d1a6b2467cab24f780b356832d0dcb1307caf5a | |
parent | 5a2769f0273dd389977e8283375e7920d183bdd4 (diff) | |
download | haskell-7434fb5be86c7cc59c520dc07dc96b27b4fb1406.tar.gz |
fix possible ^C problems
Calling prodAllCapabilities() from interruptStgRts() was wrong, for
the same reasons that we stopped doing it in handle_tick(). We now
use the same mechanism (send a byte down the pipe to the IO manager
thread), but abstract it in a wakeUpRts() function in the scheduler.
-rw-r--r-- | rts/Schedule.c | 31 | ||||
-rw-r--r-- | rts/Schedule.h | 6 | ||||
-rw-r--r-- | rts/Timer.c | 14 |
3 files changed, 37 insertions, 14 deletions
diff --git a/rts/Schedule.c b/rts/Schedule.c index 270a7d8715..d9adda415c 100644 --- a/rts/Schedule.c +++ b/rts/Schedule.c @@ -3446,8 +3446,37 @@ interruptStgRts(void) { sched_state = SCHED_INTERRUPTING; context_switch = 1; + wakeUpRts(); +} + +/* ----------------------------------------------------------------------------- + Wake up the RTS + + This function causes at least one OS thread to wake up and run the + scheduler loop. It is invoked when the RTS might be deadlocked, or + an external event has arrived that may need servicing (eg. a + keyboard interrupt). + + In the single-threaded RTS we don't do anything here; we only have + one thread anyway, and the event that caused us to want to wake up + will have interrupted any blocking system call in progress anyway. + -------------------------------------------------------------------------- */ + +void +wakeUpRts(void) +{ #if defined(THREADED_RTS) - prodAllCapabilities(); +#if !defined(mingw32_HOST_OS) + // This forces the IO Manager thread to wakeup, which will + // in turn ensure that some OS thread wakes up and runs the + // scheduler loop, which will cause a GC and deadlock check. + ioManagerWakeup(); +#else + // On Windows this might be safe enough, because we aren't + // in a signal handler. Later we should use the IO Manager, + // though. + prodOneCapability(); +#endif #endif } diff --git a/rts/Schedule.h b/rts/Schedule.h index 3adb70f4a8..e30e911e68 100644 --- a/rts/Schedule.h +++ b/rts/Schedule.h @@ -43,6 +43,12 @@ void awakenBlockedQueue(StgBlockingQueueElement *q, StgClosure *node); void awakenBlockedQueue (Capability *cap, StgTSO *tso); #endif +/* wakeUpRts() + * + * Causes an OS thread to wake up and run the scheduler, if necessary. + */ +void wakeUpRts(void); + /* unblockOne() * * Put the specified thread on the run queue of the given Capability. diff --git a/rts/Timer.c b/rts/Timer.c index 4b13be4556..b4f5f8f130 100644 --- a/rts/Timer.c +++ b/rts/Timer.c @@ -72,20 +72,8 @@ handle_tick(int unused STG_UNUSED) blackholes_need_checking = rtsTrue; /* hack: re-use the blackholes_need_checking flag */ -#if !defined(mingw32_HOST_OS) - // This forces the IO Manager thread to wakeup, which will - // in turn ensure that some OS thread wakes up and runs the - // scheduler loop, which will cause a GC and deadlock check. - ioManagerWakeup(); -#else - /* ToDo: this doesn't work. Can't invoke - * pthread_cond_signal from a signal handler. - * Furthermore, we can't prod a capability that we - * might be holding. What can we do? - */ - prodOneCapability(); -#endif } + wakeUpRts(); break; default: break; |