diff options
Diffstat (limited to 'rts/win32')
-rw-r--r-- | rts/win32/ConsoleHandler.c | 36 | ||||
-rw-r--r-- | rts/win32/ConsoleHandler.h | 15 | ||||
-rw-r--r-- | rts/win32/ThrIOManager.c | 144 |
3 files changed, 179 insertions, 16 deletions
diff --git a/rts/win32/ConsoleHandler.c b/rts/win32/ConsoleHandler.c index afaa4245b8..5b5cfc338b 100644 --- a/rts/win32/ConsoleHandler.c +++ b/rts/win32/ConsoleHandler.c @@ -18,7 +18,9 @@ static BOOL WINAPI shutdown_handler(DWORD dwCtrlType); static BOOL WINAPI generic_handler(DWORD dwCtrlType); static rtsBool deliver_event = rtsTrue; -static StgInt console_handler = STG_SIG_DFL; +StgInt console_handler = STG_SIG_DFL; + +#if !defined(THREADED_RTS) static HANDLE hConsoleEvent = INVALID_HANDLE_VALUE; @@ -26,6 +28,8 @@ static HANDLE hConsoleEvent = INVALID_HANDLE_VALUE; StgInt stg_pending_events = 0; /* number of undelivered events */ DWORD stg_pending_buf[N_PENDING_EVENTS]; /* their associated event numbers. */ +#endif + /* * Function: initUserSignals() * @@ -34,8 +38,9 @@ DWORD stg_pending_buf[N_PENDING_EVENTS]; /* their associated event numbers. */ void initUserSignals(void) { - stg_pending_events = 0; console_handler = STG_SIG_DFL; +#if !defined (THREADED_RTS) + stg_pending_events = 0; if (hConsoleEvent == INVALID_HANDLE_VALUE) { hConsoleEvent = CreateEvent ( NULL, /* default security attributes */ @@ -43,6 +48,7 @@ initUserSignals(void) FALSE, /* initially non-signalled */ NULL); /* no name */ } +#endif return; } @@ -50,9 +56,11 @@ initUserSignals(void) void finiUserSignals(void) { +#if !defined (THREADED_RTS) if (hConsoleEvent != INVALID_HANDLE_VALUE) { CloseHandle(hConsoleEvent); } +#endif } /* @@ -83,9 +91,6 @@ static BOOL WINAPI shutdown_handler(DWORD dwCtrlType) stg_exit(EXIT_INTERRUPTED); } else { interruptStgRts(); - /* Cheesy pulsing of an event to wake up a waiting RTS thread, if any */ - abandonRequestWait(); - resetAbandonRequestWait(); } return TRUE; @@ -148,6 +153,7 @@ void awaitUserSignals(void) } +#if !defined (THREADED_RTS) /* * Function: startSignalHandlers() * @@ -180,6 +186,7 @@ void startSignalHandlers(Capability *cap) RELEASE_LOCK(&sched_mutex); unblockUserSignals(); } +#endif /* !THREADED_RTS */ /* * Function: markSignalHandlers() @@ -202,8 +209,6 @@ void markSignalHandlers (evac_fn evac STG_UNUSED) */ static BOOL WINAPI generic_handler(DWORD dwCtrlType) { - ACQUIRE_LOCK(&sched_mutex); - /* Ultra-simple -- up the counter + signal a switch. */ switch(dwCtrlType) { case CTRL_CLOSE_EVENT: @@ -217,17 +222,16 @@ static BOOL WINAPI generic_handler(DWORD dwCtrlType) default: if (!deliver_event) return TRUE; +#if defined(THREADED_RTS) + sendIOManagerEvent((StgWord8) ((dwCtrlType<<1) | 1)); +#else if ( stg_pending_events < N_PENDING_EVENTS ) { stg_pending_buf[stg_pending_events] = dwCtrlType; stg_pending_events++; } - /* Cheesy pulsing of an event to wake up a waiting RTS thread, if any */ - abandonRequestWait(); - resetAbandonRequestWait(); +#endif return TRUE; } - - RELEASE_LOCK(&sched_mutex); } @@ -293,17 +297,22 @@ rts_InstallConsoleEvent(int action, StgStablePtr *handler) * */ void -rts_ConsoleHandlerDone(int ev) +rts_ConsoleHandlerDone (int ev USED_IF_NOT_THREADS) { +#if !defined(THREADED_RTS) if ( (DWORD)ev == CTRL_BREAK_EVENT || (DWORD)ev == CTRL_C_EVENT ) { /* only these two cause stdin system calls to abort.. */ SetEvent(hConsoleEvent); /* event is manual-reset */ Sleep(0); /* yield */ ResetEvent(hConsoleEvent); /* turn it back off again */ + // SDM: yeuch, this can't possibly work reliably. + // I'm not having it in THREADED_RTS. } +#endif } +#if !defined(THREADED_RTS) /* * Function: rts_waitConsoleHandlerCompletion() * @@ -318,3 +327,4 @@ rts_waitConsoleHandlerCompletion() */ return (WaitForSingleObject(hConsoleEvent, INFINITE) == WAIT_OBJECT_0); } +#endif diff --git a/rts/win32/ConsoleHandler.h b/rts/win32/ConsoleHandler.h index b09adf71cb..33fa065733 100644 --- a/rts/win32/ConsoleHandler.h +++ b/rts/win32/ConsoleHandler.h @@ -9,9 +9,16 @@ * Console control handlers lets an application handle Ctrl+C, Ctrl+Break etc. * in Haskell under Win32. Akin to the Unix signal SIGINT. * - * The API offered by ConsoleHandler.h is identical to that of the signal handling - * code (which isn't supported under win32.) Unsurprisingly, the underlying impl - * is derived from the signal handling code also. + * The API offered by ConsoleHandler.h is identical to that of the + * signal handling code (which isn't supported under win32.) + * Unsurprisingly, the underlying impl is derived from the signal + * handling code also. + */ + +#if !defined(THREADED_RTS) +/* + * under THREADED_RTS, console events are passed to the IO manager + * thread, which starts up the handler. See ThrIOManager.c. */ /* @@ -60,4 +67,6 @@ extern void handleSignalsInThisThread(void); */ extern int rts_waitConsoleHandlerCompletion(void); +#endif /* THREADED_RTS */ + #endif /* __CONSOLEHANDLER_H__ */ diff --git a/rts/win32/ThrIOManager.c b/rts/win32/ThrIOManager.c new file mode 100644 index 0000000000..b0da0deee9 --- /dev/null +++ b/rts/win32/ThrIOManager.c @@ -0,0 +1,144 @@ +/* -----------------------------------------------------------------------------
+ *
+ * (c) The GHC Team, 1998-2006
+ *
+ * The IO manager thread in THREADED_RTS.
+ * See also libraries/base/GHC/Conc.lhs.
+ *
+ * ---------------------------------------------------------------------------*/
+
+#include "Rts.h"
+#include "ThrIOManager.h"
+#include "Prelude.h"
+#include <windows.h>
+
+// Here's the Event that we use to wake up the IO manager thread
+static HANDLE io_manager_event = INVALID_HANDLE_VALUE;
+
+// must agree with values in GHC.Conc:
+#define IO_MANAGER_WAKEUP 0xffffffff
+#define IO_MANAGER_DIE 0xfffffffe
+// spurios wakeups are returned as zero.
+// console events are ((event<<1) | 1)
+
+HANDLE
+getIOManagerEvent (void)
+{
+ // This function has to exist even in the non-THREADED_RTS,
+ // because code in GHC.Conc refers to it. It won't ever be called
+ // unless we're in the threaded RTS, however.
+#ifdef THREADED_RTS
+ HANDLE hRes;
+
+ if (io_manager_event == INVALID_HANDLE_VALUE) {
+ hRes = CreateEvent ( NULL, // no security attrs
+ TRUE, // manual reset
+ FALSE, // initial state,
+ "IO Manager Event" );
+ if (hRes == NULL) {
+ sysErrorBelch("getIOManagerEvent");
+ stg_exit(EXIT_FAILURE);
+ }
+ io_manager_event = hRes;
+ return hRes;
+ } else {
+ return io_manager_event;
+ }
+#else
+ return NULL;
+#endif
+}
+
+
+#if defined(THREADED_RTS)
+
+#define EVENT_BUFSIZ 256
+Mutex event_buf_mutex;
+StgWord32 event_buf[EVENT_BUFSIZ];
+nat next_event;
+
+#endif
+
+StgWord32
+readIOManagerEvent (void)
+{
+ // This function must exist even in non-THREADED_RTS,
+ // see getIOManagerEvent() above.
+#if defined(THREADED_RTS)
+ StgWord32 res;
+
+ ACQUIRE_LOCK(&event_buf_mutex);
+ if (io_manager_event != INVALID_HANDLE_VALUE) {
+ if (next_event == 0) {
+ res = 0; // no event to return
+ } else {
+ res = event_buf[--next_event];
+ if (next_event == 0) {
+ if (!ResetEvent(io_manager_event)) {
+ sysErrorBelch("readIOManagerEvent");
+ stg_exit(EXIT_FAILURE);
+ }
+ }
+ }
+ } else {
+ res = 0;
+ }
+ RELEASE_LOCK(&event_buf_mutex);
+ // debugBelch("readIOManagerEvent: %d\n", res);
+ return res;
+#else
+ return 0;
+#endif
+}
+
+void
+sendIOManagerEvent (StgWord32 event)
+{
+#if defined(THREADED_RTS)
+ // debugBelch("sendIOManagerEvent: %d\n", event);
+ ACQUIRE_LOCK(&event_buf_mutex);
+ if (io_manager_event != INVALID_HANDLE_VALUE) {
+ if (next_event == EVENT_BUFSIZ) {
+ errorBelch("event buffer overflowed; event dropped");
+ } else {
+ if (!SetEvent(io_manager_event)) {
+ sysErrorBelch("sendIOManagerEvent");
+ stg_exit(EXIT_FAILURE);
+ }
+ event_buf[next_event++] = event;
+ }
+ }
+ RELEASE_LOCK(&event_buf_mutex);
+#endif
+}
+
+#if defined(THREADED_RTS)
+void
+ioManagerWakeup (void)
+{
+ sendIOManagerEvent(IO_MANAGER_WAKEUP);
+}
+
+void
+ioManagerDie (void)
+{
+ sendIOManagerEvent(IO_MANAGER_DIE);
+ // ToDo: wait for the IO manager to pick up the event, and
+ // then release the Event and Mutex objects we've allocated.
+}
+
+void
+ioManagerStart (void)
+{
+ initMutex(&event_buf_mutex);
+ next_event = 0;
+
+ // Make sure the IO manager thread is running
+ Capability *cap;
+ if (io_manager_event == INVALID_HANDLE_VALUE) {
+ cap = rts_lock();
+ rts_evalIO(cap,&base_GHCziConc_ensureIOManagerIsRunning_closure,NULL);
+ rts_unlock(cap);
+ }
+}
+#endif
|