fix haddock submodule pointer
[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 "IOManager.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 #if defined(THREADED_RTS)\r
25 \r
26 #define EVENT_BUFSIZ 256\r
27 Mutex event_buf_mutex;\r
28 StgWord32 event_buf[EVENT_BUFSIZ];\r
29 nat next_event;\r
30 \r
31 #endif\r
32 \r
33 HANDLE\r
34 getIOManagerEvent (void)\r
35 {\r
36     // This function has to exist even in the non-THREADED_RTS,\r
37     // because code in GHC.Conc refers to it.  It won't ever be called\r
38     // unless we're in the threaded RTS, however.\r
39 #ifdef THREADED_RTS\r
40     HANDLE hRes;\r
41 \r
42     ACQUIRE_LOCK(&event_buf_mutex);\r
43 \r
44     if (io_manager_event == INVALID_HANDLE_VALUE) {\r
45         hRes = CreateEvent ( NULL, // no security attrs\r
46                              TRUE, // manual reset\r
47                              FALSE, // initial state,\r
48                              NULL ); // event name: NULL for private events\r
49         if (hRes == NULL) {\r
50             sysErrorBelch("getIOManagerEvent");\r
51             stg_exit(EXIT_FAILURE);\r
52         }\r
53         io_manager_event = hRes;\r
54     } else {\r
55         hRes = io_manager_event;\r
56     }\r
57 \r
58     RELEASE_LOCK(&event_buf_mutex);\r
59     return hRes;\r
60 #else\r
61     return NULL;\r
62 #endif\r
63 }\r
64 \r
65 \r
66 HsWord32\r
67 readIOManagerEvent (void)\r
68 {\r
69     // This function must exist even in non-THREADED_RTS, \r
70     // see getIOManagerEvent() above.\r
71 #if defined(THREADED_RTS)\r
72     HsWord32 res;\r
73 \r
74     ACQUIRE_LOCK(&event_buf_mutex);\r
75 \r
76     if (io_manager_event != INVALID_HANDLE_VALUE) {\r
77         if (next_event == 0) {\r
78             res = 0; // no event to return\r
79         } else {\r
80             res = (HsWord32)(event_buf[--next_event]);\r
81             if (next_event == 0) {\r
82                 if (!ResetEvent(io_manager_event)) {\r
83                     sysErrorBelch("readIOManagerEvent");\r
84                     stg_exit(EXIT_FAILURE);\r
85                 }\r
86             }\r
87         }\r
88     } else {\r
89         res = 0;\r
90     }\r
91 \r
92     RELEASE_LOCK(&event_buf_mutex);\r
93 \r
94     // debugBelch("readIOManagerEvent: %d\n", res);\r
95     return res;\r
96 #else\r
97     return 0;\r
98 #endif\r
99 }\r
100 \r
101 void\r
102 sendIOManagerEvent (HsWord32 event)\r
103 {\r
104 #if defined(THREADED_RTS)\r
105     ACQUIRE_LOCK(&event_buf_mutex);\r
106 \r
107     // debugBelch("sendIOManagerEvent: %d\n", event);\r
108     if (io_manager_event != INVALID_HANDLE_VALUE) {\r
109         if (next_event == EVENT_BUFSIZ) {\r
110             errorBelch("event buffer overflowed; event dropped");\r
111         } else {\r
112             if (!SetEvent(io_manager_event)) {\r
113                 sysErrorBelch("sendIOManagerEvent");\r
114                 stg_exit(EXIT_FAILURE);\r
115             }        \r
116             event_buf[next_event++] = (StgWord32)event;\r
117         }\r
118     }\r
119 \r
120     RELEASE_LOCK(&event_buf_mutex);\r
121 #endif\r
122 }    \r
123 \r
124 void\r
125 ioManagerWakeup (void)\r
126 {\r
127     sendIOManagerEvent(IO_MANAGER_WAKEUP);\r
128 }\r
129 \r
130 #if defined(THREADED_RTS)\r
131 void\r
132 ioManagerDie (void)\r
133 {\r
134     sendIOManagerEvent(IO_MANAGER_DIE);\r
135     // IO_MANAGER_DIE must be idempotent, as it is called\r
136     // repeatedly by shutdownCapability().  Try conc059(threaded1) to\r
137     // illustrate the problem.\r
138     ACQUIRE_LOCK(&event_buf_mutex);\r
139     io_manager_event = INVALID_HANDLE_VALUE;\r
140     RELEASE_LOCK(&event_buf_mutex);\r
141     // ToDo: wait for the IO manager to pick up the event, and\r
142     // then release the Event and Mutex objects we've allocated.\r
143 }\r
144 \r
145 void\r
146 ioManagerStart (void)\r
147 {\r
148     initMutex(&event_buf_mutex);\r
149     next_event = 0;\r
150 \r
151     // Make sure the IO manager thread is running\r
152     Capability *cap;\r
153     if (io_manager_event == INVALID_HANDLE_VALUE) {\r
154         cap = rts_lock();\r
155 #if defined(mingw32_HOST_OS) && defined(__PIC__)\r
156         rts_evalIO(cap,_imp__base_GHCziConcziIO_ensureIOManagerIsRunning_closure,NULL);\r
157 #else\r
158         rts_evalIO(cap,&base_GHCziConcziIO_ensureIOManagerIsRunning_closure,NULL);\r
159 #endif\r
160         rts_unlock(cap);\r
161     }\r
162 }\r
163 #endif\r