summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Marlow <simonmar@microsoft.com>2006-06-08 14:44:57 +0000
committerSimon Marlow <simonmar@microsoft.com>2006-06-08 14:44:57 +0000
commit7434fb5be86c7cc59c520dc07dc96b27b4fb1406 (patch)
tree2d1a6b2467cab24f780b356832d0dcb1307caf5a
parent5a2769f0273dd389977e8283375e7920d183bdd4 (diff)
downloadhaskell-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.c31
-rw-r--r--rts/Schedule.h6
-rw-r--r--rts/Timer.c14
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;