10 #include <mono/io-layer/wapi.h>
11 #include <mono/io-layer/handles-private.h>
12 #include <mono/io-layer/wapi-private.h>
13 #include <mono/io-layer/mono-mutex.h>
14 #include <mono/io-layer/misc-private.h>
19 * WaitForSingleObject:
20 * @handle: an object to wait for
21 * @timeout: the maximum time in milliseconds to wait for
23 * This function returns when either @handle is signalled, or @timeout
24 * ms elapses. If @timeout is zero, the object's state is tested and
25 * the function returns immediately. If @timeout is %INFINITE, the
26 * function waits forever.
28 * Return value: %WAIT_ABANDONED - @handle is a mutex that was not
29 * released by the owning thread when it exited. Ownership of the
30 * mutex object is granted to the calling thread and the mutex is set
31 * to nonsignalled. %WAIT_OBJECT_0 - The state of @handle is
32 * signalled. %WAIT_TIMEOUT - The @timeout interval elapsed and
33 * @handle's state is still not signalled. %WAIT_FAILED - an error
36 guint32 WaitForSingleObject(gpointer handle, guint32 timeout)
39 struct timespec abstime;
41 if(_wapi_handle_test_capabilities (handle,
42 WAPI_HANDLE_CAP_WAIT)==FALSE) {
44 g_message (G_GNUC_PRETTY_FUNCTION
45 ": handle %p can't be waited for", handle);
51 _wapi_handle_lock_handle (handle);
53 if(_wapi_handle_test_capabilities (handle,
54 WAPI_HANDLE_CAP_OWN)==TRUE) {
55 if(_wapi_handle_ops_isowned (handle)==TRUE) {
57 g_message (G_GNUC_PRETTY_FUNCTION
58 ": handle %p already owned", handle);
60 _wapi_handle_ops_own (handle);
66 if(_wapi_handle_issignalled (handle)) {
68 g_message (G_GNUC_PRETTY_FUNCTION
69 ": handle %p already signalled", handle);
72 _wapi_handle_ops_own (handle);
77 /* Have to wait for it */
78 if(timeout!=INFINITE) {
79 _wapi_calc_timeout (&abstime, timeout);
83 if(timeout==INFINITE) {
84 waited=_wapi_handle_wait_signal_handle (handle);
86 waited=_wapi_handle_timedwait_signal_handle (handle,
91 /* Condition was signalled, so hopefully
92 * handle is signalled now. (It might not be
93 * if someone else got in before us.)
95 if(_wapi_handle_issignalled (handle)) {
97 g_message (G_GNUC_PRETTY_FUNCTION
98 ": handle %p signalled", handle);
101 _wapi_handle_ops_own (handle);
106 /* Better luck next time */
110 /* Timeout or other error */
112 g_message (G_GNUC_PRETTY_FUNCTION ": wait on handle %p error: %s",
113 handle, strerror (ret));
119 _wapi_handle_unlock_handle (handle);
124 * SignalObjectAndWait:
125 * @signal_handle: An object to signal
126 * @wait: An object to wait for
127 * @timeout: The maximum time in milliseconds to wait for
128 * @alertable: Specifies whether the function returnes when the system
129 * queues an I/O completion routine or an APC for the calling thread.
131 * Atomically signals @signal and waits for @wait to become signalled,
132 * or @timeout ms elapses. If @timeout is zero, the object's state is
133 * tested and the function returns immediately. If @timeout is
134 * %INFINITE, the function waits forever.
136 * @signal can be a semaphore, mutex or event object.
138 * If @alertable is %TRUE and the system queues an I/O completion
139 * routine or an APC for the calling thread, the function returns and
140 * the thread calls the completion routine or APC function. If
141 * %FALSE, the function does not return, and the thread does not call
142 * the completion routine or APC function. A completion routine is
143 * queued when the ReadFileEx() or WriteFileEx() function in which it
144 * was specified has completed. The calling thread is the thread that
145 * initiated the read or write operation. An APC is queued when
146 * QueueUserAPC() is called. Currently completion routines and APC
147 * functions are not supported.
149 * Return value: %WAIT_ABANDONED - @wait is a mutex that was not
150 * released by the owning thread when it exited. Ownershop of the
151 * mutex object is granted to the calling thread and the mutex is set
152 * to nonsignalled. %WAIT_IO_COMPLETION - the wait was ended by one
153 * or more user-mode asynchronous procedure calls queued to the
154 * thread. %WAIT_OBJECT_0 - The state of @wait is signalled.
155 * %WAIT_TIMEOUT - The @timeout interval elapsed and @wait's state is
156 * still not signalled. %WAIT_FAILED - an error occurred.
158 guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait,
159 guint32 timeout, gboolean alertable)
162 struct timespec abstime;
164 if(_wapi_handle_test_capabilities (signal_handle,
165 WAPI_HANDLE_CAP_SIGNAL)==FALSE) {
169 if(_wapi_handle_test_capabilities (wait,
170 WAPI_HANDLE_CAP_WAIT)==FALSE) {
174 _wapi_handle_lock_handle (wait);
176 _wapi_handle_ops_signal (signal_handle);
178 if(_wapi_handle_test_capabilities (wait, WAPI_HANDLE_CAP_OWN)==TRUE) {
179 if(_wapi_handle_ops_isowned (wait)==TRUE) {
181 g_message (G_GNUC_PRETTY_FUNCTION
182 ": handle %p already owned", wait);
184 _wapi_handle_ops_own (wait);
190 if(_wapi_handle_issignalled (wait)) {
192 g_message (G_GNUC_PRETTY_FUNCTION
193 ": handle %p already signalled", wait);
196 _wapi_handle_ops_own (wait);
201 /* Have to wait for it */
202 if(timeout!=INFINITE) {
203 _wapi_calc_timeout (&abstime, timeout);
207 if(timeout==INFINITE) {
208 waited=_wapi_handle_wait_signal_handle (wait);
210 waited=_wapi_handle_timedwait_signal_handle (wait,
215 /* Condition was signalled, so hopefully
216 * handle is signalled now. (It might not be
217 * if someone else got in before us.)
219 if(_wapi_handle_issignalled (wait)) {
221 g_message (G_GNUC_PRETTY_FUNCTION
222 ": handle %p signalled", wait);
225 _wapi_handle_ops_own (wait);
230 /* Better luck next time */
234 /* Timeout or other error */
236 g_message (G_GNUC_PRETTY_FUNCTION ": wait on handle %p error: %s",
237 wait, strerror (ret));
243 _wapi_handle_unlock_handle (wait);
245 if(alertable==TRUE) {
246 /* Deal with queued APC or IO completion routines */
253 * WaitForMultipleObjects:
254 * @numobjects: The number of objects in @handles. The maximum allowed
255 * is %MAXIMUM_WAIT_OBJECTS.
256 * @handles: An array of object handles. Duplicates are not allowed.
257 * @waitall: If %TRUE, this function waits until all of the handles
258 * are signalled. If %FALSE, this function returns when any object is
260 * @timeout: The maximum time in milliseconds to wait for.
262 * This function returns when either one or more of @handles is
263 * signalled, or @timeout ms elapses. If @timeout is zero, the state
264 * of each item of @handles is tested and the function returns
265 * immediately. If @timeout is %INFINITE, the function waits forever.
267 * Return value: %WAIT_OBJECT_0 to %WAIT_OBJECT_0 + @numobjects - 1 -
268 * if @waitall is %TRUE, indicates that all objects are signalled. If
269 * @waitall is %FALSE, the return value minus %WAIT_OBJECT_0 indicates
270 * the first index into @handles of the objects that are signalled.
271 * %WAIT_ABANDONED_0 to %WAIT_ABANDONED_0 + @numobjects - 1 - if
272 * @waitall is %TRUE, indicates that all objects are signalled, and at
273 * least one object is an abandoned mutex object (See
274 * WaitForSingleObject() for a description of abandoned mutexes.) If
275 * @waitall is %FALSE, the return value minus %WAIT_ABANDONED_0
276 * indicates the first index into @handles of an abandoned mutex.
277 * %WAIT_TIMEOUT - The @timeout interval elapsed and no objects in
278 * @handles are signalled. %WAIT_FAILED - an error occurred.
280 guint32 WaitForMultipleObjects(guint32 numobjects, gpointer *handles,
281 gboolean waitall, guint32 timeout)
284 gboolean duplicate=FALSE, bogustype=FALSE, done;
285 guint32 count, lowest;
286 struct timespec abstime;
290 if(numobjects>MAXIMUM_WAIT_OBJECTS) {
292 g_message(G_GNUC_PRETTY_FUNCTION ": Too many handles: %d",
299 /* Check for duplicates */
300 dups=g_hash_table_new(g_direct_hash, g_direct_equal);
301 for(i=0; i<numobjects; i++) {
302 gpointer exists=g_hash_table_lookup(dups, handles[i]);
305 g_message(G_GNUC_PRETTY_FUNCTION
306 ": Handle %p duplicated", handles[i]);
313 if(_wapi_handle_test_capabilities (handles[i], WAPI_HANDLE_CAP_WAIT)==FALSE) {
315 g_message (G_GNUC_PRETTY_FUNCTION
316 ": Handle %p can't be waited for",
323 g_hash_table_insert(dups, handles[i], handles[i]);
325 g_hash_table_destroy(dups);
327 if(duplicate==TRUE) {
329 g_message(G_GNUC_PRETTY_FUNCTION
330 ": Returning due to duplicates");
336 if(bogustype==TRUE) {
338 g_message(G_GNUC_PRETTY_FUNCTION
339 ": Returning due to bogus type");
345 done=_wapi_handle_count_signalled_handles (numobjects, handles,
346 waitall, &count, &lowest);
348 for(i=0; i<numobjects; i++) {
349 _wapi_handle_ops_own (handles[i]);
352 _wapi_handle_unlock_handles (numobjects, handles);
353 return(WAIT_OBJECT_0+lowest);
356 /* Have to wait for some or all handles to become signalled
359 _wapi_handle_unlock_handles (numobjects, handles);
361 if(timeout!=INFINITE) {
362 _wapi_calc_timeout (&abstime, timeout);
365 _wapi_handle_lock_signal_mutex ();
368 if(timeout==INFINITE) {
369 ret=_wapi_handle_wait_signal ();
371 ret=_wapi_handle_timedwait_signal (&abstime);
375 /* Something was signalled ... */
376 done=_wapi_handle_count_signalled_handles (numobjects,
382 for(i=0; i<numobjects; i++) {
383 _wapi_handle_ops_own (handles[i]);
386 _wapi_handle_unlock_handles (numobjects,
388 _wapi_handle_unlock_signal_mutex ();
389 return(WAIT_OBJECT_0+lowest);
391 _wapi_handle_unlock_handles (numobjects, handles);
393 /* Timeout or other error */
395 g_message (G_GNUC_PRETTY_FUNCTION ": wait returned error: %s", strerror (ret));
398 _wapi_handle_unlock_signal_mutex ();
400 return(WAIT_TIMEOUT);