17f3fb6c4fe8dfa27a834a25c062accd011ec28b
[mono.git] / mono / io-layer / handles.c
1 /*
2  * handles.c:  Generic and internal operations on handles
3  *
4  * Author:
5  *      Dick Porter (dick@ximian.com)
6  *
7  * (C) 2002-2011 Novell, Inc.
8  * Copyright 2011 Xamarin Inc
9  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
10  */
11
12 #include <config.h>
13 #include <glib.h>
14 #include <pthread.h>
15 #include <errno.h>
16 #include <unistd.h>
17 #ifdef HAVE_SIGNAL_H
18 #include <signal.h>
19 #endif
20 #include <string.h>
21 #include <sys/types.h>
22 #ifdef HAVE_SYS_SOCKET_H
23 #  include <sys/socket.h>
24 #endif
25 #ifdef HAVE_SYS_UN_H
26 #  include <sys/un.h>
27 #endif
28 #ifdef HAVE_SYS_MMAN_H
29 #  include <sys/mman.h>
30 #endif
31 #ifdef HAVE_DIRENT_H
32 #  include <dirent.h>
33 #endif
34 #include <sys/stat.h>
35 #ifdef HAVE_SYS_RESOURCE_H
36 #  include <sys/resource.h>
37 #endif
38
39 #include <mono/io-layer/wapi.h>
40 #include <mono/io-layer/wapi-private.h>
41 #include <mono/io-layer/handles-private.h>
42 #include <mono/io-layer/shared.h>
43 #include <mono/io-layer/process-private.h>
44 #include <mono/io-layer/io-trace.h>
45
46 #include <mono/utils/mono-os-mutex.h>
47 #include <mono/utils/mono-proclib.h>
48 #include <mono/utils/mono-threads.h>
49 #include <mono/utils/mono-once.h>
50 #include <mono/utils/mono-logger-internals.h>
51 #undef DEBUG_REFS
52
53 #define _WAPI_PRIVATE_MAX_SLOTS         (1024 * 16)
54
55 /* must be a power of 2 */
56 #define _WAPI_HANDLE_INITIAL_COUNT      (256)
57
58 struct _WapiHandleUnshared
59 {
60         WapiHandleType type;
61         guint ref;
62         gboolean signalled;
63         mono_mutex_t signal_mutex;
64         mono_cond_t signal_cond;
65         
66         union 
67         {
68                 struct _WapiHandle_event event;
69                 struct _WapiHandle_file file;
70                 struct _WapiHandle_find find;
71                 struct _WapiHandle_mutex mutex;
72                 struct _WapiHandle_sem sem;
73                 struct _WapiHandle_socket sock;
74                 struct _WapiHandle_thread thread;
75                 struct _WapiHandle_process process;
76                 struct _WapiHandle_shared_ref shared;
77                 struct _WapiHandle_namedmutex namedmutex;
78                 struct _WapiHandle_namedsem namedsem;
79                 struct _WapiHandle_namedevent namedevent;
80         } u;
81 };
82
83 typedef struct _WapiHandleUnshared _WapiHandleUnshared;
84
85 static void (*_wapi_handle_ops_get_close_func (WapiHandleType type))(gpointer, gpointer);
86
87 static WapiHandleCapability handle_caps[WAPI_HANDLE_COUNT] = { (WapiHandleCapability)0 };
88 static struct _WapiHandleOps *handle_ops[WAPI_HANDLE_COUNT]={
89         NULL,
90         &_wapi_file_ops,
91         &_wapi_console_ops,
92         &_wapi_thread_ops,
93         &_wapi_sem_ops,
94         &_wapi_mutex_ops,
95         &_wapi_event_ops,
96 #ifndef DISABLE_SOCKETS
97         &_wapi_socket_ops,
98 #endif
99         &_wapi_find_ops,
100         &_wapi_process_ops,
101         &_wapi_pipe_ops,
102         &_wapi_namedmutex_ops,
103         &_wapi_namedsem_ops,
104         &_wapi_namedevent_ops,
105 };
106
107 static void _wapi_shared_details (gpointer handle_info);
108
109 static void (*handle_details[WAPI_HANDLE_COUNT])(gpointer) = {
110         NULL,
111         _wapi_file_details,
112         _wapi_console_details,
113         _wapi_shared_details,   /* thread */
114         _wapi_sem_details,
115         _wapi_mutex_details,
116         _wapi_event_details,
117         NULL,                   /* Nothing useful to see in a socket handle */
118         NULL,                   /* Nothing useful to see in a find handle */
119         _wapi_shared_details,   /* process */
120         _wapi_pipe_details,
121         _wapi_shared_details,   /* namedmutex */
122         _wapi_shared_details,   /* namedsem */
123         _wapi_shared_details,   /* namedevent */
124 };
125
126 const char *_wapi_handle_typename[] = {
127         "Unused",
128         "File",
129         "Console",
130         "Thread",
131         "Sem",
132         "Mutex",
133         "Event",
134         "Socket",
135         "Find",
136         "Process",
137         "Pipe",
138         "N.Mutex",
139         "N.Sem",
140         "N.Event",
141         "Error!!"
142 };
143
144 /*
145  * We can hold _WAPI_PRIVATE_MAX_SLOTS * _WAPI_HANDLE_INITIAL_COUNT handles.
146  * If 4M handles are not enough... Oh, well... we will crash.
147  */
148 #define SLOT_INDEX(x)   (x / _WAPI_HANDLE_INITIAL_COUNT)
149 #define SLOT_OFFSET(x)  (x % _WAPI_HANDLE_INITIAL_COUNT)
150
151 struct _WapiHandleUnshared *_wapi_private_handles [_WAPI_PRIVATE_MAX_SLOTS];
152 static guint32 _wapi_private_handle_count = 0;
153 static guint32 _wapi_private_handle_slot_count = 0;
154
155 /*
156  * If SHM is disabled, this will point to a hash of _WapiFileShare structures, otherwise
157  * it will be NULL. We use this instead of _wapi_fileshare_layout to avoid allocating a
158  * 4MB array.
159  */
160 static GHashTable *file_share_hash;
161 static mono_mutex_t file_share_hash_mutex;
162
163 #define file_share_hash_lock() mono_os_mutex_lock (&file_share_hash_mutex)
164 #define file_share_hash_unlock() mono_os_mutex_unlock (&file_share_hash_mutex)
165
166 guint32 _wapi_fd_reserve;
167
168 /* 
169  * This is an internal handle which is used for handling waiting for multiple handles.
170  * Threads which wait for multiple handles wait on this one handle, and when a handle
171  * is signalled, this handle is signalled too.
172  */
173 static gpointer _wapi_global_signal_handle;
174
175 /* Point to the mutex/cond inside _wapi_global_signal_handle */
176 static mono_mutex_t *_wapi_global_signal_mutex;
177 static mono_cond_t *_wapi_global_signal_cond;
178
179 int _wapi_sem_id;
180 gboolean _wapi_has_shut_down = FALSE;
181
182 /* Use this instead of getpid(), to cope with linuxthreads.  It's a
183  * function rather than a variable lookup because we need to get at
184  * this before share_init() might have been called.
185  */
186 static pid_t _wapi_pid;
187 static mono_once_t pid_init_once = MONO_ONCE_INIT;
188
189 static void _wapi_handle_unref_full (gpointer handle, gboolean ignore_private_busy_handles);
190
191 static void pid_init (void)
192 {
193         _wapi_pid = getpid ();
194 }
195
196 pid_t _wapi_getpid (void)
197 {
198         mono_once (&pid_init_once, pid_init);
199         
200         return(_wapi_pid);
201 }
202
203
204 static mono_mutex_t scan_mutex;
205
206 #define _WAPI_PRIVATE_HANDLES(x) (_wapi_private_handles [SLOT_INDEX ((guint32) x)][SLOT_OFFSET ((guint32) x)])
207
208 static gboolean
209 _WAPI_PRIVATE_HAVE_SLOT (guint32 x)
210 {
211         return (x / _WAPI_PRIVATE_MAX_SLOTS) < _WAPI_PRIVATE_MAX_SLOTS && _wapi_private_handles [SLOT_INDEX (x)];
212 }
213
214 static gboolean
215 _WAPI_PRIVATE_VALID_SLOT (guint32 x)
216 {
217         return SLOT_INDEX (x) < _WAPI_PRIVATE_MAX_SLOTS;
218 }
219
220 WapiHandleType
221 _wapi_handle_type (gpointer handle)
222 {
223         guint32 idx = GPOINTER_TO_UINT(handle);
224
225         if (!_WAPI_PRIVATE_VALID_SLOT (idx) || !_WAPI_PRIVATE_HAVE_SLOT (idx))
226                 return WAPI_HANDLE_UNUSED;      /* An impossible type */
227
228         return _WAPI_PRIVATE_HANDLES(idx).type;
229 }
230
231 void
232 _wapi_handle_set_signal_state (gpointer handle, gboolean state, gboolean broadcast)
233 {
234         guint32 idx = GPOINTER_TO_UINT(handle);
235         struct _WapiHandleUnshared *handle_data;
236         int thr_ret;
237
238         if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
239                 return;
240         }
241
242         handle_data = &_WAPI_PRIVATE_HANDLES(idx);
243         
244 #ifdef DEBUG
245         g_message ("%s: setting state of %p to %s (broadcast %s)", __func__,
246                    handle, state?"TRUE":"FALSE", broadcast?"TRUE":"FALSE");
247 #endif
248
249         if (state == TRUE) {
250                 /* Tell everyone blocking on a single handle */
251
252                 /* The condition the global signal cond is waiting on is the signalling of
253                  * _any_ handle. So lock it before setting the signalled state.
254                  */
255                 thr_ret = mono_os_mutex_lock (_wapi_global_signal_mutex);
256                 if (thr_ret != 0)
257                         g_warning ("Bad call to mono_os_mutex_lock result %d for global signal mutex", thr_ret);
258                 g_assert (thr_ret == 0);
259
260                 /* This function _must_ be called with
261                  * handle->signal_mutex locked
262                  */
263                 handle_data->signalled=state;
264                 
265                 if (broadcast == TRUE) {
266                         thr_ret = mono_os_cond_broadcast (&handle_data->signal_cond);
267                         if (thr_ret != 0)
268                                 g_warning ("Bad call to mono_os_cond_broadcast result %d for handle %p", thr_ret, handle);
269                         g_assert (thr_ret == 0);
270                 } else {
271                         thr_ret = mono_os_cond_signal (&handle_data->signal_cond);
272                         if (thr_ret != 0)
273                                 g_warning ("Bad call to mono_os_cond_signal result %d for handle %p", thr_ret, handle);
274                         g_assert (thr_ret == 0);
275                 }
276
277                 /* Tell everyone blocking on multiple handles that something
278                  * was signalled
279                  */                     
280                 thr_ret = mono_os_cond_broadcast (_wapi_global_signal_cond);
281                 if (thr_ret != 0)
282                         g_warning ("Bad call to mono_os_cond_broadcast result %d for handle %p", thr_ret, handle);
283                 g_assert (thr_ret == 0);
284                         
285                 thr_ret = mono_os_mutex_unlock (_wapi_global_signal_mutex);
286                 if (thr_ret != 0)
287                         g_warning ("Bad call to mono_os_mutex_unlock result %d for global signal mutex", thr_ret);
288                 g_assert (thr_ret == 0);
289         } else {
290                 handle_data->signalled=state;
291         }
292 }
293
294 gboolean
295 _wapi_handle_issignalled (gpointer handle)
296 {
297         guint32 idx = GPOINTER_TO_UINT(handle);
298         
299         if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
300                 return(FALSE);
301         }
302
303         return _WAPI_PRIVATE_HANDLES (idx).signalled;
304 }
305
306 int
307 _wapi_handle_lock_signal_mutex (void)
308 {
309 #ifdef DEBUG
310         g_message ("%s: lock global signal mutex", __func__);
311 #endif
312
313         return(mono_os_mutex_lock (_wapi_global_signal_mutex));
314 }
315
316 int
317 _wapi_handle_unlock_signal_mutex (void)
318 {
319 #ifdef DEBUG
320         g_message ("%s: unlock global signal mutex", __func__);
321 #endif
322
323         return(mono_os_mutex_unlock (_wapi_global_signal_mutex));
324 }
325
326 int
327 _wapi_handle_lock_handle (gpointer handle)
328 {
329         guint32 idx = GPOINTER_TO_UINT(handle);
330         
331 #ifdef DEBUG
332         g_message ("%s: locking handle %p", __func__, handle);
333 #endif
334
335         if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
336                 return(0);
337         }
338         
339         _wapi_handle_ref (handle);
340
341         return(mono_os_mutex_lock (&_WAPI_PRIVATE_HANDLES(idx).signal_mutex));
342 }
343
344 int
345 _wapi_handle_trylock_handle (gpointer handle)
346 {
347         guint32 idx = GPOINTER_TO_UINT(handle);
348         int ret;
349         
350 #ifdef DEBUG
351         g_message ("%s: locking handle %p", __func__, handle);
352 #endif
353
354         if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
355                 return(0);
356         }
357         
358         _wapi_handle_ref (handle);
359
360         ret = mono_os_mutex_trylock (&_WAPI_PRIVATE_HANDLES(idx).signal_mutex);
361         if (ret != 0) {
362                 _wapi_handle_unref (handle);
363         }
364         
365         return(ret);
366 }
367
368 int
369 _wapi_handle_unlock_handle (gpointer handle)
370 {
371         guint32 idx = GPOINTER_TO_UINT(handle);
372         int ret;
373         
374 #ifdef DEBUG
375         g_message ("%s: unlocking handle %p", __func__, handle);
376 #endif
377         
378         if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
379                 return(0);
380         }
381
382         ret = mono_os_mutex_unlock (&_WAPI_PRIVATE_HANDLES(idx).signal_mutex);
383
384         _wapi_handle_unref (handle);
385         
386         return(ret);
387 }
388
389 static void handle_cleanup (void)
390 {
391         int i, j, k;
392         
393         /* Every shared handle we were using ought really to be closed
394          * by now, but to make sure just blow them all away.  The
395          * exiting finalizer thread in particular races us to the
396          * program exit and doesn't always win, so it can be left
397          * cluttering up the shared file.  Anything else left over is
398          * really a bug.
399          */
400         for(i = SLOT_INDEX (0); _wapi_private_handles[i] != NULL; i++) {
401                 for(j = SLOT_OFFSET (0); j < _WAPI_HANDLE_INITIAL_COUNT; j++) {
402                         struct _WapiHandleUnshared *handle_data = &_wapi_private_handles[i][j];
403                         gpointer handle = GINT_TO_POINTER (i*_WAPI_HANDLE_INITIAL_COUNT+j);
404
405                         for(k = handle_data->ref; k > 0; k--) {
406                                 _wapi_handle_unref_full (handle, TRUE);
407                         }
408                 }
409         }
410         
411         _wapi_shm_semaphores_remove ();
412
413         if (file_share_hash) {
414                 g_hash_table_destroy (file_share_hash);
415                 mono_os_mutex_destroy (&file_share_hash_mutex);
416         }
417
418         for (i = 0; i < _WAPI_PRIVATE_MAX_SLOTS; ++i)
419                 g_free (_wapi_private_handles [i]);
420 }
421
422 int
423 wapi_getdtablesize (void)
424 {
425         return eg_getdtablesize ();
426 }
427
428 /*
429  * wapi_init:
430  *
431  *   Initialize the io-layer.
432  */
433 void
434 wapi_init (void)
435 {
436         g_assert ((sizeof (handle_ops) / sizeof (handle_ops[0]))
437                   == WAPI_HANDLE_COUNT);
438
439         _wapi_fd_reserve = wapi_getdtablesize ();
440
441         /* This is needed by the code in _wapi_handle_new_internal */
442         _wapi_fd_reserve = (_wapi_fd_reserve + (_WAPI_HANDLE_INITIAL_COUNT - 1)) & ~(_WAPI_HANDLE_INITIAL_COUNT - 1);
443
444         do {
445                 /* 
446                  * The entries in _wapi_private_handles reserved for fds are allocated lazily to 
447                  * save memory.
448                  */
449                 /*
450                 _wapi_private_handles [idx++] = g_new0 (struct _WapiHandleUnshared,
451                                                         _WAPI_HANDLE_INITIAL_COUNT);
452                 */
453
454                 _wapi_private_handle_count += _WAPI_HANDLE_INITIAL_COUNT;
455                 _wapi_private_handle_slot_count ++;
456         } while(_wapi_fd_reserve > _wapi_private_handle_count);
457
458         _wapi_shm_semaphores_init ();
459
460         _wapi_io_init ();
461         mono_os_mutex_init (&scan_mutex);
462
463         _wapi_global_signal_handle = _wapi_handle_new (WAPI_HANDLE_EVENT, NULL);
464
465         _wapi_global_signal_cond = &_WAPI_PRIVATE_HANDLES (GPOINTER_TO_UINT (_wapi_global_signal_handle)).signal_cond;
466         _wapi_global_signal_mutex = &_WAPI_PRIVATE_HANDLES (GPOINTER_TO_UINT (_wapi_global_signal_handle)).signal_mutex;
467
468         wapi_processes_init ();
469 }
470
471 void
472 wapi_cleanup (void)
473 {
474         g_assert (_wapi_has_shut_down == FALSE);
475         
476         _wapi_has_shut_down = TRUE;
477
478         _wapi_error_cleanup ();
479         _wapi_thread_cleanup ();
480         wapi_processes_cleanup ();
481         handle_cleanup ();
482 }
483
484 static size_t _wapi_handle_struct_size (WapiHandleType type)
485 {
486         size_t type_size;
487
488         switch (type) {
489                 case WAPI_HANDLE_FILE: case WAPI_HANDLE_CONSOLE: case WAPI_HANDLE_PIPE:
490                         type_size = sizeof (struct _WapiHandle_file);
491                         break;
492                 case WAPI_HANDLE_THREAD:
493                         type_size = sizeof (struct _WapiHandle_thread);
494                         break;
495                 case WAPI_HANDLE_SEM:
496                         type_size = sizeof (struct _WapiHandle_sem);
497                         break;
498                 case WAPI_HANDLE_MUTEX:
499                         type_size = sizeof (struct _WapiHandle_mutex);
500                         break;
501                 case WAPI_HANDLE_EVENT:
502                         type_size = sizeof (struct _WapiHandle_event);
503                         break;
504                 case WAPI_HANDLE_SOCKET:
505                         type_size = sizeof (struct _WapiHandle_socket);
506                         break;
507                 case WAPI_HANDLE_FIND:
508                         type_size = sizeof (struct _WapiHandle_find);
509                         break;
510                 case WAPI_HANDLE_PROCESS:
511                         type_size = sizeof (struct _WapiHandle_process);
512                         break;
513                 case WAPI_HANDLE_NAMEDMUTEX:
514                         type_size = sizeof (struct _WapiHandle_namedmutex);
515                         break;
516                 case WAPI_HANDLE_NAMEDSEM:
517                         type_size = sizeof (struct _WapiHandle_namedsem);
518                         break;
519                 case WAPI_HANDLE_NAMEDEVENT:
520                         type_size = sizeof (struct _WapiHandle_namedevent);
521                         break;
522
523                 default:
524                         g_error ("Unknown WapiHandleType: %d\n", type);
525         }
526
527         return type_size;
528 }
529
530 static void _wapi_handle_init (struct _WapiHandleUnshared *handle,
531                                WapiHandleType type, gpointer handle_specific)
532 {
533         int thr_ret;
534         int type_size;
535         
536         g_assert (_wapi_has_shut_down == FALSE);
537         
538         handle->type = type;
539         handle->signalled = FALSE;
540         handle->ref = 1;
541         
542         thr_ret = mono_os_cond_init (&handle->signal_cond);
543         g_assert (thr_ret == 0);
544                         
545         thr_ret = mono_os_mutex_init (&handle->signal_mutex);
546         g_assert (thr_ret == 0);
547
548         if (handle_specific != NULL) {
549                 type_size = _wapi_handle_struct_size (type);
550                 memcpy (&handle->u, handle_specific,
551                         type_size);
552         }
553 }
554
555 /*
556  * _wapi_handle_new_internal:
557  * @type: Init handle to this type
558  *
559  * Search for a free handle and initialize it. Return the handle on
560  * success and 0 on failure.  This is only called from
561  * _wapi_handle_new, and scan_mutex must be held.
562  */
563 static guint32 _wapi_handle_new_internal (WapiHandleType type,
564                                           gpointer handle_specific)
565 {
566         guint32 i, k, count;
567         static guint32 last = 0;
568         gboolean retry = FALSE;
569         
570         g_assert (_wapi_has_shut_down == FALSE);
571         
572         /* A linear scan should be fast enough.  Start from the last
573          * allocation, assuming that handles are allocated more often
574          * than they're freed. Leave the space reserved for file
575          * descriptors
576          */
577         
578         if (last < _wapi_fd_reserve) {
579                 last = _wapi_fd_reserve;
580         } else {
581                 retry = TRUE;
582         }
583
584 again:
585         count = last;
586         for(i = SLOT_INDEX (count); i < _wapi_private_handle_slot_count; i++) {
587                 if (_wapi_private_handles [i]) {
588                         for (k = SLOT_OFFSET (count); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
589                                 struct _WapiHandleUnshared *handle = &_wapi_private_handles [i][k];
590
591                                 if(handle->type == WAPI_HANDLE_UNUSED) {
592                                         last = count + 1;
593                         
594                                         _wapi_handle_init (handle, type, handle_specific);
595                                         return (count);
596                                 }
597                                 count++;
598                         }
599                 }
600         }
601
602         if(retry && last > _wapi_fd_reserve) {
603                 /* Try again from the beginning */
604                 last = _wapi_fd_reserve;
605                 goto again;
606         }
607
608         /* Will need to expand the array.  The caller will sort it out */
609
610         return(0);
611 }
612
613 gpointer 
614 _wapi_handle_new (WapiHandleType type, gpointer handle_specific)
615 {
616         guint32 handle_idx = 0;
617         gpointer handle;
618         int thr_ret;
619
620         g_assert (_wapi_has_shut_down == FALSE);
621                 
622         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating new handle of type %s", __func__,
623                    _wapi_handle_typename[type]);
624
625         g_assert(!_WAPI_FD_HANDLE(type));
626         
627         thr_ret = mono_os_mutex_lock (&scan_mutex);
628         g_assert (thr_ret == 0);
629                 
630         while ((handle_idx = _wapi_handle_new_internal (type, handle_specific)) == 0) {
631                 /* Try and expand the array, and have another go */
632                 int idx = SLOT_INDEX (_wapi_private_handle_count);
633                 if (idx >= _WAPI_PRIVATE_MAX_SLOTS) {
634                         break;
635                 }
636
637                 _wapi_private_handles [idx] = g_new0 (struct _WapiHandleUnshared,
638                                                 _WAPI_HANDLE_INITIAL_COUNT);
639
640                 _wapi_private_handle_count += _WAPI_HANDLE_INITIAL_COUNT;
641                 _wapi_private_handle_slot_count ++;
642         }
643         
644         thr_ret = mono_os_mutex_unlock (&scan_mutex);
645         g_assert (thr_ret == 0);
646
647         if (handle_idx == 0) {
648                 /* We ran out of slots */
649                 handle = _WAPI_HANDLE_INVALID;
650                 goto done;
651         }
652                 
653         /* Make sure we left the space for fd mappings */
654         g_assert (handle_idx >= _wapi_fd_reserve);
655         
656         handle = GUINT_TO_POINTER (handle_idx);
657
658         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Allocated new handle %p", __func__, handle);
659
660 done:
661         return(handle);
662 }
663
664 static void
665 init_handles_slot (int idx)
666 {
667         int thr_ret;
668
669         thr_ret = mono_os_mutex_lock (&scan_mutex);
670         g_assert (thr_ret == 0);
671
672         if (_wapi_private_handles [idx] == NULL) {
673                 _wapi_private_handles [idx] = g_new0 (struct _WapiHandleUnshared,
674                                                                                           _WAPI_HANDLE_INITIAL_COUNT);
675                 g_assert (_wapi_private_handles [idx]);
676         }
677
678         thr_ret = mono_os_mutex_unlock (&scan_mutex);
679         g_assert (thr_ret == 0);
680 }
681
682 gpointer _wapi_handle_new_fd (WapiHandleType type, int fd,
683                               gpointer handle_specific)
684 {
685         struct _WapiHandleUnshared *handle;
686         int thr_ret;
687         
688         g_assert (_wapi_has_shut_down == FALSE);
689         
690         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating new handle of type %s", __func__,
691                    _wapi_handle_typename[type]);
692         
693         g_assert(_WAPI_FD_HANDLE(type));
694
695         if (fd >= _wapi_fd_reserve) {
696                 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d is too big", __func__, fd);
697
698                 return(GUINT_TO_POINTER (_WAPI_HANDLE_INVALID));
699         }
700
701         /* Initialize the array entries on demand */
702         if (_wapi_private_handles [SLOT_INDEX (fd)] == NULL)
703                 init_handles_slot (SLOT_INDEX (fd));
704
705         handle = &_WAPI_PRIVATE_HANDLES(fd);
706         
707         if (handle->type != WAPI_HANDLE_UNUSED) {
708                 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d is already in use!", __func__, fd);
709                 /* FIXME: clean up this handle?  We can't do anything
710                  * with the fd, cos thats the new one
711                  */
712         }
713
714         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Assigning new fd handle %d", __func__, fd);
715
716         /* Prevent file share entries racing with us, when the file
717          * handle is only half initialised
718          */
719         thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_FILESHARE);
720         g_assert(thr_ret == 0);
721
722         _wapi_handle_init (handle, type, handle_specific);
723
724         thr_ret = _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_FILESHARE);
725
726         return(GUINT_TO_POINTER(fd));
727 }
728
729 gboolean 
730 _wapi_lookup_handle (gpointer handle, WapiHandleType type,
731                               gpointer *handle_specific)
732 {
733         struct _WapiHandleUnshared *handle_data;
734         guint32 handle_idx = GPOINTER_TO_UINT(handle);
735
736         if (!_WAPI_PRIVATE_VALID_SLOT (handle_idx)) {
737                 return(FALSE);
738         }
739
740         /* Initialize the array entries on demand */
741         if (_wapi_private_handles [SLOT_INDEX (handle_idx)] == NULL)
742                 init_handles_slot (SLOT_INDEX (handle_idx));
743         
744         handle_data = &_WAPI_PRIVATE_HANDLES(handle_idx);
745         
746         if (handle_data->type != type) {
747                 return(FALSE);
748         }
749
750         if (handle_specific == NULL) {
751                 return(FALSE);
752         }
753         
754         *handle_specific = &handle_data->u;
755         
756         return(TRUE);
757 }
758
759 void
760 _wapi_handle_foreach (WapiHandleType type,
761                         gboolean (*on_each)(gpointer test, gpointer user),
762                         gpointer user_data)
763 {
764         struct _WapiHandleUnshared *handle_data = NULL;
765         gpointer ret = NULL;
766         guint32 i, k;
767         int thr_ret;
768
769         thr_ret = mono_os_mutex_lock (&scan_mutex);
770         g_assert (thr_ret == 0);
771
772         for (i = SLOT_INDEX (0); i < _wapi_private_handle_slot_count; i++) {
773                 if (_wapi_private_handles [i]) {
774                         for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
775                                 handle_data = &_wapi_private_handles [i][k];
776                         
777                                 if (handle_data->type == type) {
778                                         ret = GUINT_TO_POINTER (i * _WAPI_HANDLE_INITIAL_COUNT + k);
779                                         if (on_each (ret, user_data) == TRUE)
780                                                 break;
781                                 }
782                         }
783                 }
784         }
785
786         thr_ret = mono_os_mutex_unlock (&scan_mutex);
787         g_assert (thr_ret == 0);
788 }
789
790 /* This might list some shared handles twice if they are already
791  * opened by this process, and the check function returns FALSE the
792  * first time.  Shared handles that are created during the search are
793  * unreffed if the check function returns FALSE, so callers must not
794  * rely on the handle persisting (unless the check function returns
795  * TRUE)
796  * The caller owns the returned handle.
797  */
798 gpointer _wapi_search_handle (WapiHandleType type,
799                               gboolean (*check)(gpointer test, gpointer user),
800                               gpointer user_data,
801                               gpointer *handle_specific,
802                               gboolean search_shared)
803 {
804         struct _WapiHandleUnshared *handle_data = NULL;
805         gpointer ret = NULL;
806         guint32 i, k;
807         gboolean found = FALSE;
808         int thr_ret;
809
810         thr_ret = mono_os_mutex_lock (&scan_mutex);
811         g_assert (thr_ret == 0);
812         
813         for (i = SLOT_INDEX (0); !found && i < _wapi_private_handle_slot_count; i++) {
814                 if (_wapi_private_handles [i]) {
815                         for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
816                                 handle_data = &_wapi_private_handles [i][k];
817                 
818                                 if (handle_data->type == type) {
819                                         ret = GUINT_TO_POINTER (i * _WAPI_HANDLE_INITIAL_COUNT + k);
820                                         if (check (ret, user_data) == TRUE) {
821                                                 _wapi_handle_ref (ret);
822                                                 found = TRUE;
823                                                 break;
824                                         }
825                                 }
826                         }
827                 }
828         }
829
830         thr_ret = mono_os_mutex_unlock (&scan_mutex);
831         g_assert (thr_ret == 0);
832
833         if (!found) {
834                 ret = NULL;
835                 goto done;
836         }
837         
838         if(handle_specific != NULL) {
839                 *handle_specific = &handle_data->u;
840         }
841
842 done:
843         return(ret);
844 }
845
846 /* Returns the offset of the metadata array, or _WAPI_HANDLE_INVALID on error, or NULL for
847  * not found
848  */
849 gpointer _wapi_search_handle_namespace (WapiHandleType type,
850                                       gchar *utf8_name)
851 {
852         struct _WapiHandleUnshared *handle_data;
853         guint32 i, k;
854         gpointer ret = NULL;
855         int thr_ret;
856         
857         g_assert(_WAPI_SHARED_NAMESPACE(type));
858         
859         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Lookup for handle named [%s] type %s", __func__,
860                    utf8_name, _wapi_handle_typename[type]);
861
862         thr_ret = mono_os_mutex_lock (&scan_mutex);
863         g_assert (thr_ret == 0);
864         
865         for(i = SLOT_INDEX (0); i < _wapi_private_handle_slot_count; i++) {
866                 if (!_wapi_private_handles [i])
867                         continue;
868                 for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
869                         WapiSharedNamespace *sharedns;
870                         
871                         handle_data = &_wapi_private_handles [i][k];
872
873                         /* Check mutex, event, semaphore, timer, job and
874                          * file-mapping object names.  So far only mutex,
875                          * semaphore and event are implemented.
876                          */
877                         if (!_WAPI_SHARED_NAMESPACE (handle_data->type)) {
878                                 continue;
879                         }
880
881                         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: found a shared namespace handle at 0x%x (type %s)", __func__, i, _wapi_handle_typename[handle_data->type]);
882
883                         switch (handle_data->type) {
884                         case WAPI_HANDLE_NAMEDMUTEX: sharedns = &handle_data->u.namedmutex.sharedns; break;
885                         case WAPI_HANDLE_NAMEDSEM:   sharedns = &handle_data->u.namedsem.sharedns;   break;
886                         case WAPI_HANDLE_NAMEDEVENT: sharedns = &handle_data->u.namedevent.sharedns; break;
887                         default:
888                                 g_assert_not_reached ();
889                         }
890                                 
891                         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is [%s]", __func__, sharedns->name);
892
893                         if (strcmp (sharedns->name, utf8_name) == 0) {
894                                 if (handle_data->type != type) {
895                                         /* Its the wrong type, so fail now */
896                                         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle 0x%x matches name but is wrong type: %s", __func__, i, _wapi_handle_typename[handle_data->type]);
897                                         ret = _WAPI_HANDLE_INVALID;
898                                         goto done;
899                                 } else {
900                                         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle 0x%x matches name and type", __func__, i);
901                                         ret = handle_data;
902                                         goto done;
903                                 }
904                         }
905                 }
906         }
907
908 done:
909         thr_ret = mono_os_mutex_unlock (&scan_mutex);
910         g_assert (thr_ret == 0);
911         
912         return(ret);
913 }
914
915 void _wapi_handle_ref (gpointer handle)
916 {
917         guint32 idx = GPOINTER_TO_UINT(handle);
918         struct _WapiHandleUnshared *handle_data;
919
920         if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
921                 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Attempting to ref invalid private handle %p", __func__, handle);
922                 return;
923         }
924         
925         if (_wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) {
926                 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Attempting to ref unused handle %p", __func__, handle);
927                 return;
928         }
929
930         handle_data = &_WAPI_PRIVATE_HANDLES(idx);
931         
932         InterlockedIncrement ((gint32 *)&handle_data->ref);
933         
934 #ifdef DEBUG_REFS
935         g_message ("%s: %s handle %p ref now %d", __func__, 
936                    _wapi_handle_typename[_WAPI_PRIVATE_HANDLES (idx).type],
937                    handle,
938                    _WAPI_PRIVATE_HANDLES(idx).ref);
939 #endif
940 }
941
942 /* The handle must not be locked on entry to this function */
943 static void _wapi_handle_unref_full (gpointer handle, gboolean ignore_private_busy_handles)
944 {
945         guint32 idx = GPOINTER_TO_UINT(handle);
946         gboolean destroy = FALSE, early_exit = FALSE;
947         int thr_ret;
948
949         if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
950                 return;
951         }
952         
953         if (_wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) {
954                 g_warning ("%s: Attempting to unref unused handle %p",
955                            __func__, handle);
956                 return;
957         }
958
959         /* Possible race condition here if another thread refs the
960          * handle between here and setting the type to UNUSED.  I
961          * could lock a mutex, but I'm not sure that allowing a handle
962          * reference to reach 0 isn't an application bug anyway.
963          */
964         destroy = (InterlockedDecrement ((gint32 *)&_WAPI_PRIVATE_HANDLES(idx).ref) ==0);
965         
966 #ifdef DEBUG_REFS
967         g_message ("%s: %s handle %p ref now %d (destroy %s)", __func__,
968                    _wapi_handle_typename[_WAPI_PRIVATE_HANDLES (idx).type],
969                    handle,
970                    _WAPI_PRIVATE_HANDLES(idx).ref, destroy?"TRUE":"FALSE");
971 #endif
972         
973         if(destroy==TRUE) {
974                 /* Need to copy the handle info, reset the slot in the
975                  * array, and _only then_ call the close function to
976                  * avoid race conditions (eg file descriptors being
977                  * closed, and another file being opened getting the
978                  * same fd racing the memset())
979                  */
980                 struct _WapiHandleUnshared handle_data;
981                 WapiHandleType type = _WAPI_PRIVATE_HANDLES(idx).type;
982                 void (*close_func)(gpointer, gpointer) = _wapi_handle_ops_get_close_func (type);
983
984                 thr_ret = mono_os_mutex_lock (&scan_mutex);
985
986                 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Destroying handle %p", __func__, handle);
987                 
988                 memcpy (&handle_data, &_WAPI_PRIVATE_HANDLES(idx),
989                         sizeof (struct _WapiHandleUnshared));
990
991                 memset (&_WAPI_PRIVATE_HANDLES(idx).u, '\0',
992                         sizeof(_WAPI_PRIVATE_HANDLES(idx).u));
993
994                 _WAPI_PRIVATE_HANDLES(idx).type = WAPI_HANDLE_UNUSED;
995
996                 /* Destroy the mutex and cond var.  We hope nobody
997                  * tried to grab them between the handle unlock and
998                  * now, but pthreads doesn't have a
999                  * "unlock_and_destroy" atomic function.
1000                  */
1001                 thr_ret = mono_os_mutex_destroy (&_WAPI_PRIVATE_HANDLES(idx).signal_mutex);
1002                 /*WARNING gross hack to make cleanup not crash when exiting without the whole runtime teardown.*/
1003                 if (thr_ret == EBUSY && ignore_private_busy_handles) {
1004                         early_exit = TRUE;
1005                 } else {
1006                         if (thr_ret != 0)
1007                                 g_error ("Error destroying handle %p mutex due to %d\n", handle, thr_ret);
1008
1009                         thr_ret = mono_os_cond_destroy (&_WAPI_PRIVATE_HANDLES(idx).signal_cond);
1010                         if (thr_ret == EBUSY && ignore_private_busy_handles)
1011                                 early_exit = TRUE;
1012                         else if (thr_ret != 0)
1013                                 g_error ("Error destroying handle %p cond var due to %d\n", handle, thr_ret);
1014                 }
1015
1016                 thr_ret = mono_os_mutex_unlock (&scan_mutex);
1017                 g_assert (thr_ret == 0);
1018
1019                 if (early_exit)
1020                         return;
1021                 
1022                 if (close_func != NULL) {
1023                         close_func (handle, &handle_data.u);
1024                 }
1025         }
1026 }
1027
1028 void _wapi_handle_unref (gpointer handle)
1029 {
1030         _wapi_handle_unref_full (handle, FALSE);
1031 }
1032
1033 void _wapi_handle_register_capabilities (WapiHandleType type,
1034                                          WapiHandleCapability caps)
1035 {
1036         handle_caps[type] = caps;
1037 }
1038
1039 gboolean _wapi_handle_test_capabilities (gpointer handle,
1040                                          WapiHandleCapability caps)
1041 {
1042         guint32 idx = GPOINTER_TO_UINT(handle);
1043         WapiHandleType type;
1044
1045         if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
1046                 return(FALSE);
1047         }
1048         
1049         type = _WAPI_PRIVATE_HANDLES(idx).type;
1050
1051         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: testing 0x%x against 0x%x (%d)", __func__,
1052                    handle_caps[type], caps, handle_caps[type] & caps);
1053         
1054         return((handle_caps[type] & caps) != 0);
1055 }
1056
1057 static void (*_wapi_handle_ops_get_close_func (WapiHandleType type))(gpointer, gpointer)
1058 {
1059         if (handle_ops[type] != NULL &&
1060             handle_ops[type]->close != NULL) {
1061                 return (handle_ops[type]->close);
1062         }
1063
1064         return (NULL);
1065 }
1066
1067 void _wapi_handle_ops_close (gpointer handle, gpointer data)
1068 {
1069         guint32 idx = GPOINTER_TO_UINT(handle);
1070         WapiHandleType type;
1071
1072         if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
1073                 return;
1074         }
1075         
1076         type = _WAPI_PRIVATE_HANDLES(idx).type;
1077
1078         if (handle_ops[type] != NULL &&
1079             handle_ops[type]->close != NULL) {
1080                 handle_ops[type]->close (handle, data);
1081         }
1082 }
1083
1084 void _wapi_handle_ops_signal (gpointer handle)
1085 {
1086         guint32 idx = GPOINTER_TO_UINT(handle);
1087         WapiHandleType type;
1088
1089         if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
1090                 return;
1091         }
1092         
1093         type = _WAPI_PRIVATE_HANDLES(idx).type;
1094
1095         if (handle_ops[type] != NULL && handle_ops[type]->signal != NULL) {
1096                 handle_ops[type]->signal (handle);
1097         }
1098 }
1099
1100 gboolean _wapi_handle_ops_own (gpointer handle)
1101 {
1102         guint32 idx = GPOINTER_TO_UINT(handle);
1103         WapiHandleType type;
1104         
1105         if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
1106                 return(FALSE);
1107         }
1108         
1109         type = _WAPI_PRIVATE_HANDLES(idx).type;
1110
1111         if (handle_ops[type] != NULL && handle_ops[type]->own_handle != NULL) {
1112                 return(handle_ops[type]->own_handle (handle));
1113         } else {
1114                 return(FALSE);
1115         }
1116 }
1117
1118 gboolean _wapi_handle_ops_isowned (gpointer handle)
1119 {
1120         guint32 idx = GPOINTER_TO_UINT(handle);
1121         WapiHandleType type;
1122
1123         if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
1124                 return(FALSE);
1125         }
1126         
1127         type = _WAPI_PRIVATE_HANDLES(idx).type;
1128
1129         if (handle_ops[type] != NULL && handle_ops[type]->is_owned != NULL) {
1130                 return(handle_ops[type]->is_owned (handle));
1131         } else {
1132                 return(FALSE);
1133         }
1134 }
1135
1136 guint32 _wapi_handle_ops_special_wait (gpointer handle, guint32 timeout, gboolean alertable)
1137 {
1138         guint32 idx = GPOINTER_TO_UINT(handle);
1139         WapiHandleType type;
1140         
1141         if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
1142                 return(WAIT_FAILED);
1143         }
1144         
1145         type = _WAPI_PRIVATE_HANDLES(idx).type;
1146         
1147         if (handle_ops[type] != NULL &&
1148             handle_ops[type]->special_wait != NULL) {
1149                 return(handle_ops[type]->special_wait (handle, timeout, alertable));
1150         } else {
1151                 return(WAIT_FAILED);
1152         }
1153 }
1154
1155 void _wapi_handle_ops_prewait (gpointer handle)
1156 {
1157         guint32 idx = GPOINTER_TO_UINT (handle);
1158         WapiHandleType type;
1159         
1160         if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
1161                 return;
1162         }
1163         
1164         type = _WAPI_PRIVATE_HANDLES (idx).type;
1165         
1166         if (handle_ops[type] != NULL &&
1167             handle_ops[type]->prewait != NULL) {
1168                 handle_ops[type]->prewait (handle);
1169         }
1170 }
1171
1172
1173 /**
1174  * CloseHandle:
1175  * @handle: The handle to release
1176  *
1177  * Closes and invalidates @handle, releasing any resources it
1178  * consumes.  When the last handle to a temporary or non-persistent
1179  * object is closed, that object can be deleted.  Closing the same
1180  * handle twice is an error.
1181  *
1182  * Return value: %TRUE on success, %FALSE otherwise.
1183  */
1184 gboolean CloseHandle(gpointer handle)
1185 {
1186         if (handle == NULL) {
1187                 /* Problem: because we map file descriptors to the
1188                  * same-numbered handle we can't tell the difference
1189                  * between a bogus handle and the handle to stdin.
1190                  * Assume that it's the console handle if that handle
1191                  * exists...
1192                  */
1193                 if (_WAPI_PRIVATE_HANDLES (0).type != WAPI_HANDLE_CONSOLE) {
1194                         SetLastError (ERROR_INVALID_PARAMETER);
1195                         return(FALSE);
1196                 }
1197         }
1198         if (handle == _WAPI_HANDLE_INVALID){
1199                 SetLastError (ERROR_INVALID_PARAMETER);
1200                 return(FALSE);
1201         }
1202         
1203         _wapi_handle_unref (handle);
1204         
1205         return(TRUE);
1206 }
1207
1208 /* Lots more to implement here, but this is all we need at the moment */
1209 gboolean DuplicateHandle (gpointer srcprocess, gpointer src,
1210                           gpointer targetprocess, gpointer *target,
1211                           guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 options G_GNUC_UNUSED)
1212 {
1213         if (srcprocess != _WAPI_PROCESS_CURRENT ||
1214             targetprocess != _WAPI_PROCESS_CURRENT) {
1215                 /* Duplicating other process's handles is not supported */
1216                 SetLastError (ERROR_INVALID_HANDLE);
1217                 return(FALSE);
1218         }
1219         
1220         if (src == _WAPI_PROCESS_CURRENT) {
1221                 *target = _wapi_process_duplicate ();
1222         } else if (src == _WAPI_THREAD_CURRENT) {
1223                 g_assert_not_reached ();
1224         } else {
1225                 _wapi_handle_ref (src);
1226                 *target = src;
1227         }
1228         
1229         return(TRUE);
1230 }
1231
1232 gboolean _wapi_handle_count_signalled_handles (guint32 numhandles,
1233                                                gpointer *handles,
1234                                                gboolean waitall,
1235                                                guint32 *retcount,
1236                                                guint32 *lowest)
1237 {
1238         guint32 count, i, iter=0;
1239         gboolean ret;
1240         int thr_ret;
1241         WapiHandleType type;
1242         
1243         /* Lock all the handles, with backoff */
1244 again:
1245         for(i=0; i<numhandles; i++) {
1246                 gpointer handle = handles[i];
1247                 guint32 idx = GPOINTER_TO_UINT(handle);
1248
1249                 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempting to lock %p", __func__, handle);
1250
1251                 type = _WAPI_PRIVATE_HANDLES(idx).type;
1252
1253                 thr_ret = _wapi_handle_trylock_handle (handle);
1254                 
1255                 if (thr_ret != 0) {
1256                         /* Bummer */
1257                         
1258                         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempt failed for %p: %s", __func__,
1259                                    handle, strerror (thr_ret));
1260
1261                         while (i--) {
1262                                 handle = handles[i];
1263                                 idx = GPOINTER_TO_UINT(handle);
1264
1265                                 thr_ret = _wapi_handle_unlock_handle (handle);
1266                                 g_assert (thr_ret == 0);
1267                         }
1268
1269                         /* If iter ever reaches 100 the nanosleep will
1270                          * return EINVAL immediately, but we have a
1271                          * design flaw if that happens.
1272                          */
1273                         iter++;
1274                         if(iter==100) {
1275                                 g_warning ("%s: iteration overflow!",
1276                                            __func__);
1277                                 iter=1;
1278                         }
1279                         
1280                         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Backing off for %d ms", __func__,
1281                                    iter*10);
1282                         _wapi_handle_spin (10 * iter);
1283                         
1284                         goto again;
1285                 }
1286         }
1287         
1288         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locked all handles", __func__);
1289
1290         count=0;
1291         *lowest=numhandles;
1292         
1293         for(i=0; i<numhandles; i++) {
1294                 gpointer handle = handles[i];
1295                 guint32 idx = GPOINTER_TO_UINT(handle);
1296                 
1297                 type = _WAPI_PRIVATE_HANDLES(idx).type;
1298
1299                 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Checking handle %p", __func__, handle);
1300
1301                 if(((_wapi_handle_test_capabilities (handle, WAPI_HANDLE_CAP_OWN)==TRUE) &&
1302                     (_wapi_handle_ops_isowned (handle) == TRUE)) ||
1303                    (_wapi_handle_issignalled (handle))) {
1304                         count++;
1305                         
1306                         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Handle %p signalled", __func__,
1307                                    handle);
1308                         if(*lowest>i) {
1309                                 *lowest=i;
1310                         }
1311                 }
1312         }
1313         
1314         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %d event handles signalled", __func__, count);
1315
1316         if ((waitall == TRUE && count == numhandles) ||
1317             (waitall == FALSE && count > 0)) {
1318                 ret=TRUE;
1319         } else {
1320                 ret=FALSE;
1321         }
1322         
1323         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning %d", __func__, ret);
1324
1325         *retcount=count;
1326         
1327         return(ret);
1328 }
1329
1330 void _wapi_handle_unlock_handles (guint32 numhandles, gpointer *handles)
1331 {
1332         guint32 i;
1333         int thr_ret;
1334         
1335         for(i=0; i<numhandles; i++) {
1336                 gpointer handle = handles[i];
1337                 
1338                 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking handle %p", __func__, handle);
1339
1340                 thr_ret = _wapi_handle_unlock_handle (handle);
1341                 g_assert (thr_ret == 0);
1342         }
1343 }
1344
1345 static void
1346 signal_handle_and_unref (gpointer handle)
1347 {
1348         mono_cond_t *cond;
1349         mono_mutex_t *mutex;
1350         guint32 idx;
1351
1352         g_assert (handle);
1353
1354         /* If we reach here, then interrupt token is set to the flag value, which
1355          * means that the target thread is either
1356          * - before the first CAS in timedwait, which means it won't enter the wait.
1357          * - it is after the first CAS, so it is already waiting, or it will enter
1358          *    the wait, and it will be interrupted by the broadcast. */
1359         idx = GPOINTER_TO_UINT (handle);
1360         cond = &_WAPI_PRIVATE_HANDLES (idx).signal_cond;
1361         mutex = &_WAPI_PRIVATE_HANDLES (idx).signal_mutex;
1362
1363         mono_os_mutex_lock (mutex);
1364         mono_os_cond_broadcast (cond);
1365         mono_os_mutex_unlock (mutex);
1366
1367         _wapi_handle_unref (handle);
1368 }
1369
1370 int
1371 _wapi_handle_timedwait_signal (guint32 timeout, gboolean poll, gboolean *alerted)
1372 {
1373         return _wapi_handle_timedwait_signal_handle (_wapi_global_signal_handle, timeout, poll, alerted);
1374 }
1375
1376 int
1377 _wapi_handle_timedwait_signal_handle (gpointer handle, guint32 timeout, gboolean poll, gboolean *alerted)
1378 {
1379         guint32 idx;
1380         int res;
1381         mono_cond_t *cond;
1382         mono_mutex_t *mutex;
1383
1384         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: waiting for %p (type %s)", __func__, handle,
1385                    _wapi_handle_typename[_wapi_handle_type (handle)]);
1386
1387         if (alerted)
1388                 *alerted = FALSE;
1389
1390         idx = GPOINTER_TO_UINT(handle);
1391
1392         if (alerted) {
1393                 mono_thread_info_install_interrupt (signal_handle_and_unref, handle, alerted);
1394                 if (*alerted)
1395                         return 0;
1396                 _wapi_handle_ref (handle);
1397         }
1398
1399         cond = &_WAPI_PRIVATE_HANDLES (idx).signal_cond;
1400         mutex = &_WAPI_PRIVATE_HANDLES (idx).signal_mutex;
1401
1402         if (!poll) {
1403                 res = mono_os_cond_timedwait (cond, mutex, timeout);
1404         } else {
1405                 /* This is needed when waiting for process handles */
1406                 if (!alerted) {
1407                         /*
1408                          * pthread_cond_(timed)wait() can return 0 even if the condition was not
1409                          * signalled.  This happens at least on Darwin.  We surface this, i.e., we
1410                          * get spurious wake-ups.
1411                          *
1412                          * http://pubs.opengroup.org/onlinepubs/007908775/xsh/pthread_cond_wait.html
1413                          */
1414                         res = mono_os_cond_timedwait (cond, mutex, timeout);
1415                 } else {
1416                         if (timeout < 100) {
1417                                 /* Real timeout is less than 100ms time */
1418                                 res = mono_os_cond_timedwait (cond, mutex, timeout);
1419                         } else {
1420                                 res = mono_os_cond_timedwait (cond, mutex, 100);
1421
1422                                 /* Mask the fake timeout, this will cause
1423                                  * another poll if the cond was not really signaled
1424                                  */
1425                                 if (res == ETIMEDOUT)
1426                                         res = 0;
1427                         }
1428                 }
1429         }
1430
1431         if (alerted) {
1432                 mono_thread_info_uninstall_interrupt (alerted);
1433                 if (!*alerted) {
1434                         /* if it is alerted, then the handle is unref in the interrupt callback */
1435                         _wapi_handle_unref (handle);
1436                 }
1437         }
1438
1439         return res;
1440 }
1441
1442 void
1443 _wapi_free_share_info (_WapiFileShare *share_info)
1444 {
1445         file_share_hash_lock ();
1446         g_hash_table_remove (file_share_hash, share_info);
1447         file_share_hash_unlock ();
1448         /* The hashtable dtor frees share_info */
1449 }
1450
1451 static gint
1452 wapi_share_info_equal (gconstpointer ka, gconstpointer kb)
1453 {
1454         const _WapiFileShare *s1 = (const _WapiFileShare *)ka;
1455         const _WapiFileShare *s2 = (const _WapiFileShare *)kb;
1456
1457         return (s1->device == s2->device && s1->inode == s2->inode) ? 1 : 0;
1458 }
1459
1460 static guint
1461 wapi_share_info_hash (gconstpointer data)
1462 {
1463         const _WapiFileShare *s = (const _WapiFileShare *)data;
1464
1465         return s->inode;
1466 }
1467
1468 gboolean _wapi_handle_get_or_set_share (guint64 device, guint64 inode,
1469                                         guint32 new_sharemode,
1470                                         guint32 new_access,
1471                                         guint32 *old_sharemode,
1472                                         guint32 *old_access,
1473                                         struct _WapiFileShare **share_info)
1474 {
1475         struct _WapiFileShare *file_share;
1476         int thr_ret;
1477         gboolean exists = FALSE;
1478
1479         /* Prevent new entries racing with us */
1480         thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_FILESHARE);
1481         g_assert (thr_ret == 0);
1482
1483         _WapiFileShare tmp;
1484
1485         /*
1486          * Instead of allocating a 4MB array, we use a hash table to keep track of this
1487          * info. This is needed even if SHM is disabled, to track sharing inside
1488          * the current process.
1489          */
1490         if (!file_share_hash) {
1491                 file_share_hash = g_hash_table_new_full (wapi_share_info_hash, wapi_share_info_equal, NULL, g_free);
1492                 mono_os_mutex_init_recursive (&file_share_hash_mutex);
1493         }
1494
1495         tmp.device = device;
1496         tmp.inode = inode;
1497
1498         file_share_hash_lock ();
1499
1500         file_share = (_WapiFileShare *)g_hash_table_lookup (file_share_hash, &tmp);
1501         if (file_share) {
1502                 *old_sharemode = file_share->sharemode;
1503                 *old_access = file_share->access;
1504                 *share_info = file_share;
1505
1506                 InterlockedIncrement ((gint32 *)&file_share->handle_refs);
1507                 exists = TRUE;
1508         } else {
1509                 file_share = g_new0 (_WapiFileShare, 1);
1510
1511                 file_share->device = device;
1512                 file_share->inode = inode;
1513                 file_share->opened_by_pid = _wapi_getpid ();
1514                 file_share->sharemode = new_sharemode;
1515                 file_share->access = new_access;
1516                 file_share->handle_refs = 1;
1517                 *share_info = file_share;
1518
1519                 g_hash_table_insert (file_share_hash, file_share, file_share);
1520         }
1521
1522         file_share_hash_unlock ();
1523         
1524         thr_ret = _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_FILESHARE);
1525
1526         return(exists);
1527 }
1528
1529 void _wapi_handle_dump (void)
1530 {
1531         struct _WapiHandleUnshared *handle_data;
1532         guint32 i, k;
1533         int thr_ret;
1534         
1535         thr_ret = mono_os_mutex_lock (&scan_mutex);
1536         g_assert (thr_ret == 0);
1537         
1538         for(i = SLOT_INDEX (0); i < _wapi_private_handle_slot_count; i++) {
1539                 if (_wapi_private_handles [i]) {
1540                         for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
1541                                 handle_data = &_wapi_private_handles [i][k];
1542
1543                                 if (handle_data->type == WAPI_HANDLE_UNUSED) {
1544                                         continue;
1545                                 }
1546                 
1547                                 g_print ("%3x [%7s] %s %d ",
1548                                                  i * _WAPI_HANDLE_INITIAL_COUNT + k,
1549                                                  _wapi_handle_typename[handle_data->type],
1550                                                  handle_data->signalled?"Sg":"Un",
1551                                                  handle_data->ref);
1552                                 if (handle_details[handle_data->type])
1553                                         handle_details[handle_data->type](&handle_data->u);
1554                                 g_print ("\n");
1555                         }
1556                 }
1557         }
1558
1559         thr_ret = mono_os_mutex_unlock (&scan_mutex);
1560         g_assert (thr_ret == 0);
1561 }
1562
1563 static void _wapi_shared_details (gpointer handle_info)
1564 {
1565         struct _WapiHandle_shared_ref *shared = (struct _WapiHandle_shared_ref *)handle_info;
1566         
1567         g_print ("offset: 0x%x", shared->offset);
1568 }