Make it less fatal to not call ioManagerStart()
[ghc-hetmet.git] / rts / win32 / ThrIOManager.c
1 /* -----------------------------------------------------------------------------\r
2  *\r
3  * (c) The GHC Team, 1998-2006\r
4  *\r
5  * The IO manager thread in THREADED_RTS.  \r
6  * See also libraries/base/GHC/Conc.lhs.\r
7  *\r
8  * ---------------------------------------------------------------------------*/\r
9 \r
10 #include "Rts.h"\r
11 #include "ThrIOManager.h"\r
12 #include "Prelude.h"\r
13 #include <windows.h>\r
14 \r
15 // Here's the Event that we use to wake up the IO manager thread\r
16 static HANDLE io_manager_event = INVALID_HANDLE_VALUE;\r
17 \r
18 // must agree with values in GHC.Conc:\r
19 #define IO_MANAGER_WAKEUP 0xffffffff\r
20 #define IO_MANAGER_DIE    0xfffffffe\r
21 // spurios wakeups are returned as zero.\r
22 // console events are ((event<<1) | 1)\r
23 \r
24 HANDLE\r
25 getIOManagerEvent (void)\r
26 {\r
27     // This function has to exist even in the non-THREADED_RTS,\r
28     // because code in GHC.Conc refers to it.  It won't ever be called\r
29     // unless we're in the threaded RTS, however.\r
30 #ifdef THREADED_RTS\r
31     HANDLE hRes;\r
32 \r
33     if (io_manager_event == INVALID_HANDLE_VALUE) {\r
34         hRes = CreateEvent ( NULL, // no security attrs\r
35                              TRUE, // manual reset\r
36                              FALSE, // initial state,\r
37                              "IO Manager Event" );\r
38         if (hRes == NULL) {\r
39             sysErrorBelch("getIOManagerEvent");\r
40             stg_exit(EXIT_FAILURE);\r
41         }\r
42         io_manager_event = hRes;\r
43         return hRes;\r
44     } else {\r
45         return io_manager_event;\r
46     }\r
47 #else\r
48     return NULL;\r
49 #endif\r
50 }\r
51 \r
52 \r
53 #if defined(THREADED_RTS)\r
54 \r
55 #define EVENT_BUFSIZ 256\r
56 Mutex event_buf_mutex;\r
57 StgWord32 event_buf[EVENT_BUFSIZ];\r
58 nat next_event;\r
59 \r
60 #endif\r
61 \r
62 HsWord32\r
63 readIOManagerEvent (void)\r
64 {\r
65     // This function must exist even in non-THREADED_RTS, \r
66     // see getIOManagerEvent() above.\r
67 #if defined(THREADED_RTS)\r
68     HsWord32 res;\r
69 \r
70     if (io_manager_event != INVALID_HANDLE_VALUE) {\r
71         ACQUIRE_LOCK(&event_buf_mutex);\r
72         if (next_event == 0) {\r
73             res = 0; // no event to return\r
74         } else {\r
75             res = (HsWord32)(event_buf[--next_event]);\r
76             if (next_event == 0) {\r
77                 if (!ResetEvent(io_manager_event)) {\r
78                     sysErrorBelch("readIOManagerEvent");\r
79                     stg_exit(EXIT_FAILURE);\r
80                 }\r
81             }\r
82         }\r
83         RELEASE_LOCK(&event_buf_mutex);\r
84     } else {\r
85         res = 0;\r
86     }\r
87     // debugBelch("readIOManagerEvent: %d\n", res);\r
88     return res;\r
89 #else\r
90     return 0;\r
91 #endif\r
92 }\r
93 \r
94 void\r
95 sendIOManagerEvent (HsWord32 event)\r
96 {\r
97 #if defined(THREADED_RTS)\r
98     // debugBelch("sendIOManagerEvent: %d\n", event);\r
99     if (io_manager_event != INVALID_HANDLE_VALUE) {\r
100         ACQUIRE_LOCK(&event_buf_mutex);\r
101         if (next_event == EVENT_BUFSIZ) {\r
102             errorBelch("event buffer overflowed; event dropped");\r
103         } else {\r
104             if (!SetEvent(io_manager_event)) {\r
105                 sysErrorBelch("sendIOManagerEvent");\r
106                 stg_exit(EXIT_FAILURE);\r
107             }        \r
108             event_buf[next_event++] = (StgWord32)event;\r
109         }\r
110         RELEASE_LOCK(&event_buf_mutex);\r
111     }\r
112 #endif\r
113 }    \r
114 \r
115 #if defined(THREADED_RTS)\r
116 void\r
117 ioManagerWakeup (void)\r
118 {\r
119     sendIOManagerEvent(IO_MANAGER_WAKEUP);\r
120 }\r
121 \r
122 void\r
123 ioManagerDie (void)\r
124 {\r
125     sendIOManagerEvent(IO_MANAGER_DIE);\r
126     // ToDo: wait for the IO manager to pick up the event, and\r
127     // then release the Event and Mutex objects we've allocated.\r
128 }\r
129 \r
130 void\r
131 ioManagerStart (void)\r
132 {\r
133     initMutex(&event_buf_mutex);\r
134     next_event = 0;\r
135 \r
136     // Make sure the IO manager thread is running\r
137     Capability *cap;\r
138     if (io_manager_event == INVALID_HANDLE_VALUE) {\r
139         cap = rts_lock();\r
140         rts_evalIO(cap,&base_GHCziConc_ensureIOManagerIsRunning_closure,NULL);\r
141         rts_unlock(cap);\r
142     }\r
143 }\r
144 #endif\r