Merge pull request #1936 from esdrubal/DotNetRelativeOrAbsolute
[mono.git] / mono / io-layer / wait.c
1 /*
2  * wait.c:  wait for handles to become signalled
3  *
4  * Author:
5  *      Dick Porter (dick@ximian.com)
6  *
7  * (C) 2002-2006 Novell, Inc.
8  */
9
10 #include <config.h>
11 #include <glib.h>
12 #include <string.h>
13 #include <errno.h>
14
15 #include <mono/io-layer/wapi.h>
16 #include <mono/io-layer/handles-private.h>
17 #include <mono/io-layer/wapi-private.h>
18 #include <mono/io-layer/misc-private.h>
19
20 #include <mono/utils/mono-mutex.h>
21
22 #if 0
23 #define DEBUG(...) g_message(__VA_ARGS__)
24 #else
25 #define DEBUG(...)
26 #endif
27
28 static gboolean own_if_signalled(gpointer handle)
29 {
30         gboolean ret = FALSE;
31         
32         if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) {
33                 if (_wapi_handle_trylock_shared_handles () == EBUSY) {
34                         return (FALSE);
35                 }
36         }
37         
38         if (_wapi_handle_issignalled (handle)) {
39                 _wapi_handle_ops_own (handle);
40                 ret = TRUE;
41         }
42
43         if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) {
44                 _wapi_handle_unlock_shared_handles ();
45         }
46
47         return(ret);
48 }
49
50 static gboolean own_if_owned(gpointer handle)
51 {
52         gboolean ret = FALSE;
53         
54         if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) {
55                 if (_wapi_handle_trylock_shared_handles () == EBUSY) {
56                         return (FALSE);
57                 }
58         }
59         
60         if (_wapi_handle_ops_isowned (handle)) {
61                 _wapi_handle_ops_own (handle);
62                 ret = TRUE;
63         }
64
65         if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handle))) {
66                 _wapi_handle_unlock_shared_handles ();
67         }
68
69         return(ret);
70 }
71
72 /**
73  * WaitForSingleObjectEx:
74  * @handle: an object to wait for
75  * @timeout: the maximum time in milliseconds to wait for
76  * @alertable: if TRUE, the wait can be interrupted by an APC call
77  *
78  * This function returns when either @handle is signalled, or @timeout
79  * ms elapses.  If @timeout is zero, the object's state is tested and
80  * the function returns immediately.  If @timeout is %INFINITE, the
81  * function waits forever.
82  *
83  * Return value: %WAIT_ABANDONED - @handle is a mutex that was not
84  * released by the owning thread when it exited.  Ownership of the
85  * mutex object is granted to the calling thread and the mutex is set
86  * to nonsignalled.  %WAIT_OBJECT_0 - The state of @handle is
87  * signalled.  %WAIT_TIMEOUT - The @timeout interval elapsed and
88  * @handle's state is still not signalled.  %WAIT_FAILED - an error
89  * occurred. %WAIT_IO_COMPLETION - the wait was ended by an APC.
90  */
91 guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout,
92                               gboolean alertable)
93 {
94         guint32 ret, waited;
95         struct timespec abstime;
96         int thr_ret;
97         gboolean apc_pending = FALSE;
98         gpointer current_thread = wapi_get_current_thread_handle ();
99         
100         if (current_thread == NULL) {
101                 SetLastError (ERROR_INVALID_HANDLE);
102                 return(WAIT_FAILED);
103         }
104
105         if (handle == _WAPI_THREAD_CURRENT) {
106                 handle = wapi_get_current_thread_handle ();
107                 if (handle == NULL) {
108                         SetLastError (ERROR_INVALID_HANDLE);
109                         return(WAIT_FAILED);
110                 }
111         }
112
113         if ((GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
114                 SetLastError (ERROR_INVALID_HANDLE);
115                 return(WAIT_FAILED);
116         }
117         
118         if (_wapi_handle_test_capabilities (handle,
119                                             WAPI_HANDLE_CAP_WAIT) == FALSE) {
120                 DEBUG ("%s: handle %p can't be waited for", __func__,
121                            handle);
122
123                 return(WAIT_FAILED);
124         }
125
126         _wapi_handle_ops_prewait (handle);
127         
128         if (_wapi_handle_test_capabilities (handle, WAPI_HANDLE_CAP_SPECIAL_WAIT) == TRUE) {
129                 DEBUG ("%s: handle %p has special wait", __func__, handle);
130
131                 ret = _wapi_handle_ops_special_wait (handle, timeout, alertable);
132         
133                 if (alertable && _wapi_thread_cur_apc_pending ())
134                         ret = WAIT_IO_COMPLETION;
135
136                 return ret;
137         }
138         
139         
140         DEBUG ("%s: locking handle %p", __func__, handle);
141
142         thr_ret = _wapi_handle_lock_handle (handle);
143         g_assert (thr_ret == 0);
144
145         if (_wapi_handle_test_capabilities (handle,
146                                             WAPI_HANDLE_CAP_OWN) == TRUE) {
147                 if (own_if_owned (handle) == TRUE) {
148                         DEBUG ("%s: handle %p already owned", __func__,
149                                    handle);
150                         ret = WAIT_OBJECT_0;
151                         goto done;
152                 }
153         }
154
155         if (own_if_signalled (handle) == TRUE) {
156                 DEBUG ("%s: handle %p already signalled", __func__,
157                            handle);
158
159                 ret=WAIT_OBJECT_0;
160                 goto done;
161         }
162
163         if (timeout == 0) {
164                 ret = WAIT_TIMEOUT;
165                 goto done;
166         }
167         /* Have to wait for it */
168         if (timeout != INFINITE) {
169                 _wapi_calc_timeout (&abstime, timeout);
170         }
171         
172         do {
173                 /* Check before waiting on the condition, just in case
174                  */
175                 _wapi_handle_ops_prewait (handle);
176
177                 if (own_if_signalled (handle)) {
178                         DEBUG ("%s: handle %p signalled", __func__,
179                                    handle);
180
181                         ret = WAIT_OBJECT_0;
182                         goto done;
183                 }
184
185                 waited = _wapi_handle_timedwait_signal_handle (handle, timeout == INFINITE ? NULL : &abstime, alertable, FALSE, &apc_pending);
186
187                 if(waited==0 && !apc_pending) {
188                         /* Condition was signalled, so hopefully
189                          * handle is signalled now.  (It might not be
190                          * if someone else got in before us.)
191                          */
192                         if (own_if_signalled (handle)) {
193                                 DEBUG ("%s: handle %p signalled", __func__,
194                                            handle);
195
196                                 ret=WAIT_OBJECT_0;
197                                 goto done;
198                         }
199                 
200                         /* Better luck next time */
201                 }
202         } while(waited == 0 && !apc_pending);
203
204         /* Timeout or other error */
205         DEBUG ("%s: wait on handle %p error: %s", __func__, handle,
206                    strerror (waited));
207
208         ret = apc_pending ? WAIT_IO_COMPLETION : WAIT_TIMEOUT;
209
210 done:
211
212         DEBUG ("%s: unlocking handle %p", __func__, handle);
213         
214         thr_ret = _wapi_handle_unlock_handle (handle);
215         g_assert (thr_ret == 0);
216
217         return(ret);
218 }
219
220 guint32 WaitForSingleObject(gpointer handle, guint32 timeout)
221 {
222         return WaitForSingleObjectEx (handle, timeout, FALSE);
223 }
224
225
226 /**
227  * SignalObjectAndWait:
228  * @signal_handle: An object to signal
229  * @wait: An object to wait for
230  * @timeout: The maximum time in milliseconds to wait for
231  * @alertable: Specifies whether the function returnes when the system
232  * queues an I/O completion routine or an APC for the calling thread.
233  *
234  * Atomically signals @signal and waits for @wait to become signalled,
235  * or @timeout ms elapses.  If @timeout is zero, the object's state is
236  * tested and the function returns immediately.  If @timeout is
237  * %INFINITE, the function waits forever.
238  *
239  * @signal can be a semaphore, mutex or event object.
240  *
241  * If @alertable is %TRUE and the system queues an I/O completion
242  * routine or an APC for the calling thread, the function returns and
243  * the thread calls the completion routine or APC function.  If
244  * %FALSE, the function does not return, and the thread does not call
245  * the completion routine or APC function.  A completion routine is
246  * queued when the ReadFileEx() or WriteFileEx() function in which it
247  * was specified has completed.  The calling thread is the thread that
248  * initiated the read or write operation.  An APC is queued when
249  * QueueUserAPC() is called.  Currently completion routines and APC
250  * functions are not supported.
251  *
252  * Return value: %WAIT_ABANDONED - @wait is a mutex that was not
253  * released by the owning thread when it exited.  Ownershop of the
254  * mutex object is granted to the calling thread and the mutex is set
255  * to nonsignalled.  %WAIT_IO_COMPLETION - the wait was ended by one
256  * or more user-mode asynchronous procedure calls queued to the
257  * thread.  %WAIT_OBJECT_0 - The state of @wait is signalled.
258  * %WAIT_TIMEOUT - The @timeout interval elapsed and @wait's state is
259  * still not signalled.  %WAIT_FAILED - an error occurred.
260  */
261 guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait,
262                             guint32 timeout, gboolean alertable)
263 {
264         guint32 ret, waited;
265         struct timespec abstime;
266         int thr_ret;
267         gboolean apc_pending = FALSE;
268         gpointer current_thread = wapi_get_current_thread_handle ();
269         
270         if (current_thread == NULL) {
271                 SetLastError (ERROR_INVALID_HANDLE);
272                 return(WAIT_FAILED);
273         }
274
275         if (signal_handle == _WAPI_THREAD_CURRENT) {
276                 signal_handle = wapi_get_current_thread_handle ();
277                 if (signal_handle == NULL) {
278                         SetLastError (ERROR_INVALID_HANDLE);
279                         return(WAIT_FAILED);
280                 }
281         }
282
283         if (wait == _WAPI_THREAD_CURRENT) {
284                 wait = wapi_get_current_thread_handle ();
285                 if (wait == NULL) {
286                         SetLastError (ERROR_INVALID_HANDLE);
287                         return(WAIT_FAILED);
288                 }
289         }
290
291         if ((GPOINTER_TO_UINT (signal_handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
292                 SetLastError (ERROR_INVALID_HANDLE);
293                 return(WAIT_FAILED);
294         }
295
296         if ((GPOINTER_TO_UINT (wait) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
297                 SetLastError (ERROR_INVALID_HANDLE);
298                 return(WAIT_FAILED);
299         }
300         
301         if (_wapi_handle_test_capabilities (signal_handle,
302                                             WAPI_HANDLE_CAP_SIGNAL)==FALSE) {
303                 return(WAIT_FAILED);
304         }
305         
306         if (_wapi_handle_test_capabilities (wait,
307                                             WAPI_HANDLE_CAP_WAIT)==FALSE) {
308                 return(WAIT_FAILED);
309         }
310
311         _wapi_handle_ops_prewait (wait);
312         
313         if (_wapi_handle_test_capabilities (wait, WAPI_HANDLE_CAP_SPECIAL_WAIT) == TRUE) {
314                 g_warning ("%s: handle %p has special wait, implement me!!",
315                            __func__, wait);
316
317                 return (WAIT_FAILED);
318         }
319
320         DEBUG ("%s: locking handle %p", __func__, wait);
321
322         thr_ret = _wapi_handle_lock_handle (wait);
323         g_assert (thr_ret == 0);
324
325         _wapi_handle_ops_signal (signal_handle);
326
327         if (_wapi_handle_test_capabilities (wait, WAPI_HANDLE_CAP_OWN)==TRUE) {
328                 if (own_if_owned (wait)) {
329                         DEBUG ("%s: handle %p already owned", __func__,
330                                    wait);
331                         ret = WAIT_OBJECT_0;
332                         goto done;
333                 }
334         }
335
336         if (own_if_signalled (wait)) {
337                 DEBUG ("%s: handle %p already signalled", __func__, wait);
338
339                 ret = WAIT_OBJECT_0;
340                 goto done;
341         }
342
343         /* Have to wait for it */
344         if (timeout != INFINITE) {
345                 _wapi_calc_timeout (&abstime, timeout);
346         }
347         
348         do {
349                 /* Check before waiting on the condition, just in case
350                  */
351                 _wapi_handle_ops_prewait (wait);
352         
353                 if (own_if_signalled (wait)) {
354                         DEBUG ("%s: handle %p signalled", __func__, wait);
355
356                         ret = WAIT_OBJECT_0;
357                         goto done;
358                 }
359
360                 waited = _wapi_handle_timedwait_signal_handle (wait, timeout == INFINITE ? NULL : &abstime, alertable, FALSE, &apc_pending);
361
362                 if (waited==0 && !apc_pending) {
363                         /* Condition was signalled, so hopefully
364                          * handle is signalled now.  (It might not be
365                          * if someone else got in before us.)
366                          */
367                         if (own_if_signalled (wait)) {
368                                 DEBUG ("%s: handle %p signalled", __func__,
369                                            wait);
370
371                                 ret = WAIT_OBJECT_0;
372                                 goto done;
373                         }
374                 
375                         /* Better luck next time */
376                 }
377         } while(waited == 0 && !apc_pending);
378
379         /* Timeout or other error */
380         DEBUG ("%s: wait on handle %p error: %s", __func__, wait,
381                    strerror (ret));
382
383         ret = apc_pending ? WAIT_IO_COMPLETION : WAIT_TIMEOUT;
384
385 done:
386
387         DEBUG ("%s: unlocking handle %p", __func__, wait);
388
389         thr_ret = _wapi_handle_unlock_handle (wait);
390         g_assert (thr_ret == 0);
391
392         return(ret);
393 }
394
395 static gboolean test_and_own (guint32 numobjects, gpointer *handles,
396                               gboolean waitall, guint32 *count,
397                               guint32 *lowest)
398 {
399         gboolean done;
400         int i;
401         
402         DEBUG ("%s: locking handles", __func__);
403         
404         done = _wapi_handle_count_signalled_handles (numobjects, handles,
405                                                      waitall, count, lowest);
406         if (done == TRUE) {
407                 if (waitall == TRUE) {
408                         for (i = 0; i < numobjects; i++) {
409                                 own_if_signalled (handles[i]);
410                         }
411                 } else {
412                         own_if_signalled (handles[*lowest]);
413                 }
414         }
415         
416         DEBUG ("%s: unlocking handles", __func__);
417
418         _wapi_handle_unlock_handles (numobjects, handles);
419
420         return(done);
421 }
422
423 /**
424  * WaitForMultipleObjectsEx:
425  * @numobjects: The number of objects in @handles. The maximum allowed
426  * is %MAXIMUM_WAIT_OBJECTS.
427  * @handles: An array of object handles.  Duplicates are not allowed.
428  * @waitall: If %TRUE, this function waits until all of the handles
429  * are signalled.  If %FALSE, this function returns when any object is
430  * signalled.
431  * @timeout: The maximum time in milliseconds to wait for.
432  * @alertable: if TRUE, the wait can be interrupted by an APC call
433  * 
434  * This function returns when either one or more of @handles is
435  * signalled, or @timeout ms elapses.  If @timeout is zero, the state
436  * of each item of @handles is tested and the function returns
437  * immediately.  If @timeout is %INFINITE, the function waits forever.
438  *
439  * Return value: %WAIT_OBJECT_0 to %WAIT_OBJECT_0 + @numobjects - 1 -
440  * if @waitall is %TRUE, indicates that all objects are signalled.  If
441  * @waitall is %FALSE, the return value minus %WAIT_OBJECT_0 indicates
442  * the first index into @handles of the objects that are signalled.
443  * %WAIT_ABANDONED_0 to %WAIT_ABANDONED_0 + @numobjects - 1 - if
444  * @waitall is %TRUE, indicates that all objects are signalled, and at
445  * least one object is an abandoned mutex object (See
446  * WaitForSingleObject() for a description of abandoned mutexes.)  If
447  * @waitall is %FALSE, the return value minus %WAIT_ABANDONED_0
448  * indicates the first index into @handles of an abandoned mutex.
449  * %WAIT_TIMEOUT - The @timeout interval elapsed and no objects in
450  * @handles are signalled.  %WAIT_FAILED - an error occurred.
451  * %WAIT_IO_COMPLETION - the wait was ended by an APC.
452  */
453 guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
454                                  gboolean waitall, guint32 timeout,
455                                  gboolean alertable)
456 {
457         gboolean duplicate = FALSE, bogustype = FALSE, done;
458         guint32 count, lowest;
459         struct timespec abstime;
460         guint i;
461         guint32 ret;
462         int thr_ret;
463         gpointer current_thread = wapi_get_current_thread_handle ();
464         guint32 retval;
465         gboolean poll;
466         gpointer sorted_handles [MAXIMUM_WAIT_OBJECTS];
467         gboolean apc_pending = FALSE;
468         
469         if (current_thread == NULL) {
470                 SetLastError (ERROR_INVALID_HANDLE);
471                 return(WAIT_FAILED);
472         }
473         
474         if (numobjects > MAXIMUM_WAIT_OBJECTS) {
475                 DEBUG ("%s: Too many handles: %d", __func__, numobjects);
476
477                 return(WAIT_FAILED);
478         }
479         
480         if (numobjects == 1) {
481                 return WaitForSingleObjectEx (handles [0], timeout, alertable);
482         }
483
484         /* Check for duplicates */
485         for (i = 0; i < numobjects; i++) {
486                 if (handles[i] == _WAPI_THREAD_CURRENT) {
487                         handles[i] = wapi_get_current_thread_handle ();
488                         
489                         if (handles[i] == NULL) {
490                                 DEBUG ("%s: Handle %d bogus", __func__, i);
491
492                                 bogustype = TRUE;
493                                 break;
494                         }
495                 }
496
497                 if ((GPOINTER_TO_UINT (handles[i]) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
498                         DEBUG ("%s: Handle %d pseudo process", __func__,
499                                    i);
500
501                         bogustype = TRUE;
502                         break;
503                 }
504
505                 if (_wapi_handle_test_capabilities (handles[i], WAPI_HANDLE_CAP_WAIT) == FALSE) {
506                         DEBUG ("%s: Handle %p can't be waited for",
507                                    __func__, handles[i]);
508
509                         bogustype = TRUE;
510                         break;
511                 }
512
513                 sorted_handles [i] = handles [i];
514                 _wapi_handle_ops_prewait (handles[i]);
515         }
516
517         qsort (sorted_handles, numobjects, sizeof (gpointer), g_direct_equal);
518         for (i = 1; i < numobjects; i++) {
519                 if (sorted_handles [i - 1] == sorted_handles [i]) {
520                         duplicate = TRUE;
521                         break;
522                 }
523         }
524
525         if (duplicate == TRUE) {
526                 DEBUG ("%s: Returning due to duplicates", __func__);
527
528                 return(WAIT_FAILED);
529         }
530
531         if (bogustype == TRUE) {
532                 DEBUG ("%s: Returning due to bogus type", __func__);
533
534                 return(WAIT_FAILED);
535         }
536
537         poll = FALSE;
538         for (i = 0; i < numobjects; ++i)
539                 if (_wapi_handle_type (handles [i]) == WAPI_HANDLE_PROCESS || _WAPI_SHARED_HANDLE (_wapi_handle_type (handles[i]))) 
540                         /* Can't wait for a process handle + another handle without polling */
541                         poll = TRUE;
542
543         done = test_and_own (numobjects, handles, waitall, &count, &lowest);
544         if (done == TRUE) {
545                 return(WAIT_OBJECT_0+lowest);
546         }
547         
548         if (timeout == 0) {
549                 return WAIT_TIMEOUT;
550         }
551         /* Have to wait for some or all handles to become signalled
552          */
553
554         if(timeout!=INFINITE) {
555                 _wapi_calc_timeout (&abstime, timeout);
556         }
557
558         for (i = 0; i < numobjects; i++) {
559                 /* Add a reference, as we need to ensure the handle wont
560                  * disappear from under us while we're waiting in the loop
561                  * (not lock, as we don't want exclusive access here)
562                  */
563                 _wapi_handle_ref (handles[i]);
564         }
565
566         while(1) {
567                 /* Prod all handles with prewait methods and
568                  * special-wait handles that aren't already signalled
569                  */
570                 for (i = 0; i < numobjects; i++) {
571                         _wapi_handle_ops_prewait (handles[i]);
572                 
573                         if (_wapi_handle_test_capabilities (handles[i], WAPI_HANDLE_CAP_SPECIAL_WAIT) == TRUE && _wapi_handle_issignalled (handles[i]) == FALSE) {
574                                 _wapi_handle_ops_special_wait (handles[i], 0, alertable);
575                         }
576                 }
577                 
578                 DEBUG ("%s: locking signal mutex", __func__);
579
580                 thr_ret = _wapi_handle_lock_signal_mutex ();
581                 g_assert (thr_ret == 0);
582
583                 /* Check the signalled state of handles inside the critical section */
584                 if (waitall) {
585                         done = TRUE;
586                         for (i = 0; i < numobjects; i++)
587                                 if (!_wapi_handle_issignalled (handles [i]))
588                                         done = FALSE;
589                 } else {
590                         done = FALSE;
591                         for (i = 0; i < numobjects; i++)
592                                 if (_wapi_handle_issignalled (handles [i]))
593                                         done = TRUE;
594                 }
595                 
596                 if (!done) {
597                         /* Enter the wait */
598                         ret = _wapi_handle_timedwait_signal (timeout == INFINITE ? NULL : &abstime, poll, &apc_pending);
599                 } else {
600                         /* No need to wait */
601                         ret = 0;
602                 }
603
604                 DEBUG ("%s: unlocking signal mutex", __func__);
605
606                 thr_ret = _wapi_handle_unlock_signal_mutex (NULL);
607                 g_assert (thr_ret == 0);
608                 
609                 if (alertable && apc_pending) {
610                         retval = WAIT_IO_COMPLETION;
611                         break;
612                 }
613         
614                 /* Check if everything is signalled, as we can't
615                  * guarantee to notice a shared signal even if the
616                  * wait timed out
617                  */
618                 done = test_and_own (numobjects, handles, waitall,
619                                      &count, &lowest);
620                 if (done == TRUE) {
621                         retval = WAIT_OBJECT_0+lowest;
622                         break;
623                 } else if (ret != 0) {
624                         /* Didn't get all handles, and there was a
625                          * timeout or other error
626                          */
627                         DEBUG ("%s: wait returned error: %s", __func__,
628                                    strerror (ret));
629
630                         if(ret==ETIMEDOUT) {
631                                 retval = WAIT_TIMEOUT;
632                         } else {
633                                 retval = WAIT_FAILED;
634                         }
635                         break;
636                 }
637         }
638
639         for (i = 0; i < numobjects; i++) {
640                 /* Unref everything we reffed above */
641                 _wapi_handle_unref (handles[i]);
642         }
643
644         return retval;
645 }
646
647 guint32 WaitForMultipleObjects(guint32 numobjects, gpointer *handles,
648                                gboolean waitall, guint32 timeout)
649 {
650         return WaitForMultipleObjectsEx(numobjects, handles, waitall, timeout, FALSE);
651 }
652
653 /**
654  * WaitForInputIdle:
655  * @handle: a handle to the process to wait for
656  * @timeout: the maximum time in milliseconds to wait for
657  *
658  * This function returns when either @handle process is waiting
659  * for input, or @timeout ms elapses.  If @timeout is zero, the
660  * process state is tested and the function returns immediately.
661  * If @timeout is %INFINITE, the function waits forever.
662  *
663  * Return value: 0 - @handle process is waiting for input.
664  * %WAIT_TIMEOUT - The @timeout interval elapsed and
665  * @handle process is not waiting for input.  %WAIT_FAILED - an error
666  * occurred. 
667  */
668 guint32 WaitForInputIdle(gpointer handle, guint32 timeout)
669 {
670         /*TODO: Not implemented*/
671         return WAIT_TIMEOUT;
672 }
673