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