+ * Pending Handlers
+ *
+ * The mechanism for starting handlers differs between the threaded
+ * (RTS_SUPPORTS_THREADS) and non-threaded versions of the RTS.
+ *
+ * When the RTS is single-threaded, we just write the pending signal
+ * handlers into a buffer, and start a thread for each one in the
+ * scheduler loop.
+ *
+ * When RTS_SUPPORTS_THREADS, the problem is that signals might be
+ * delivered to multiple threads, so we would need to synchronise
+ * access to pending_handler_buf somehow. Using thread
+ * synchronisation from a signal handler isn't possible in general
+ * (some OSs support it, eg. MacOS X, but not all). So instead:
+ *
+ * - the signal handler writes the signal number into the pipe
+ * managed by the IO manager thread (see GHC.Conc).
+ * - the IO manager picks up the signal number and calls
+ * startSignalHandler() to start the thread.
+ *
+ * This also has the nice property that we don't need to arrange to
+ * wake up a worker task to start the signal handler: the IO manager
+ * wakes up when we write into the pipe.
+ *
+ * -------------------------------------------------------------------------- */
+
+// Here's the pipe into which we will send our signals
+static int io_manager_pipe = -1;
+
+void
+setIOManagerPipe (int fd)
+{
+ // only called when RTS_SUPPORTS_THREADS, but unconditionally
+ // compiled here because GHC.Conc depends on it.
+ io_manager_pipe = fd;
+}
+
+#if !defined(RTS_SUPPORTS_THREADS)
+
+#define N_PENDING_HANDLERS 16
+
+StgPtr pending_handler_buf[N_PENDING_HANDLERS];
+StgPtr *next_pending_handler = pending_handler_buf;
+
+#endif /* RTS_SUPPORTS_THREADS */
+
+/* -----------------------------------------------------------------------------