[xbuild] ImportCollections.TryGetImport and other fixes
[mono.git] / mono / io-layer / mutexes.c
1 /*
2  * mutexes.c:  Mutex handles
3  *
4  * Author:
5  *      Dick Porter (dick@ximian.com)
6  *
7  * (C) 2002-2006 Ximian, Inc.
8  */
9
10 #include <config.h>
11 #include <glib.h>
12 #include <pthread.h>
13 #include <string.h>
14 #include <unistd.h>
15
16 #include <mono/io-layer/wapi.h>
17 #include <mono/io-layer/wapi-private.h>
18 #include <mono/io-layer/misc-private.h>
19 #include <mono/io-layer/handles-private.h>
20 #include <mono/io-layer/mono-mutex.h>
21 #include <mono/io-layer/mutex-private.h>
22
23 #undef DEBUG
24
25 static void mutex_signal(gpointer handle);
26 static gboolean mutex_own (gpointer handle);
27 static gboolean mutex_is_owned (gpointer handle);
28
29 static void namedmutex_signal (gpointer handle);
30 static gboolean namedmutex_own (gpointer handle);
31 static gboolean namedmutex_is_owned (gpointer handle);
32 static void namedmutex_prewait (gpointer handle);
33
34 struct _WapiHandleOps _wapi_mutex_ops = {
35         NULL,                   /* close */
36         mutex_signal,           /* signal */
37         mutex_own,              /* own */
38         mutex_is_owned,         /* is_owned */
39         NULL,                   /* special_wait */
40         NULL                    /* prewait */
41 };
42
43 void _wapi_mutex_details (gpointer handle_info)
44 {
45         struct _WapiHandle_mutex *mut = (struct _WapiHandle_mutex *)handle_info;
46         
47 #ifdef PTHREAD_POINTER_ID
48         g_print ("own: %5d:%5p, count: %5u", mut->pid, mut->tid,
49                  mut->recursion);
50 #else
51         g_print ("own: %5d:%5ld, count: %5u", mut->pid, mut->tid,
52                  mut->recursion);
53 #endif
54 }
55
56 struct _WapiHandleOps _wapi_namedmutex_ops = {
57         NULL,                   /* close */
58         namedmutex_signal,      /* signal */
59         namedmutex_own,         /* own */
60         namedmutex_is_owned,    /* is_owned */
61         NULL,                   /* special_wait */
62         namedmutex_prewait      /* prewait */
63 };
64
65 static gboolean mutex_release (gpointer handle);
66 static gboolean namedmutex_release (gpointer handle);
67
68 static struct 
69 {
70         gboolean (*release)(gpointer handle);
71 } mutex_ops[WAPI_HANDLE_COUNT] = {
72         {NULL},
73         {NULL},
74         {NULL},
75         {NULL},
76         {NULL},
77         {mutex_release},
78         {NULL},
79         {NULL},
80         {NULL},
81         {NULL},
82         {NULL},
83         {namedmutex_release},
84 };
85
86 static mono_once_t mutex_ops_once=MONO_ONCE_INIT;
87
88 static void mutex_ops_init (void)
89 {
90         _wapi_handle_register_capabilities (WAPI_HANDLE_MUTEX,
91                                             WAPI_HANDLE_CAP_WAIT |
92                                             WAPI_HANDLE_CAP_SIGNAL |
93                                             WAPI_HANDLE_CAP_OWN);
94         _wapi_handle_register_capabilities (WAPI_HANDLE_NAMEDMUTEX,
95                                             WAPI_HANDLE_CAP_WAIT |
96                                             WAPI_HANDLE_CAP_SIGNAL |
97                                             WAPI_HANDLE_CAP_OWN);
98 }
99
100 static void mutex_signal(gpointer handle)
101 {
102         ReleaseMutex(handle);
103 }
104
105 static gboolean mutex_own (gpointer handle)
106 {
107         struct _WapiHandle_mutex *mutex_handle;
108         gboolean ok;
109         
110         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
111                                   (gpointer *)&mutex_handle);
112         if (ok == FALSE) {
113                 g_warning ("%s: error looking up mutex handle %p", __func__,
114                            handle);
115                 return(FALSE);
116         }
117
118         _wapi_thread_own_mutex (handle);
119         
120 #ifdef DEBUG
121         g_message("%s: owning mutex handle %p", __func__, handle);
122 #endif
123
124         _wapi_handle_set_signal_state (handle, FALSE, FALSE);
125         
126         mutex_handle->pid = _wapi_getpid ();
127         mutex_handle->tid = pthread_self ();
128         mutex_handle->recursion++;
129
130 #ifdef DEBUG
131         g_message ("%s: mutex handle %p locked %d times by %d:%ld", __func__,
132                    handle, mutex_handle->recursion, mutex_handle->pid,
133                    mutex_handle->tid);
134 #endif
135
136         return(TRUE);
137 }
138
139 static gboolean mutex_is_owned (gpointer handle)
140 {
141         struct _WapiHandle_mutex *mutex_handle;
142         gboolean ok;
143         
144         ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
145                                 (gpointer *)&mutex_handle);
146         if(ok==FALSE) {
147                 g_warning ("%s: error looking up mutex handle %p", __func__,
148                            handle);
149                 return(FALSE);
150         }
151         
152 #ifdef DEBUG
153         g_message("%s: testing ownership mutex handle %p", __func__, handle);
154 #endif
155
156         if (mutex_handle->recursion > 0 &&
157             mutex_handle->pid == _wapi_getpid () &&
158             pthread_equal (mutex_handle->tid, pthread_self ())) {
159 #ifdef DEBUG
160                 g_message ("%s: mutex handle %p owned by %d:%ld", __func__,
161                            handle, _wapi_getpid (), pthread_self ());
162 #endif
163
164                 return(TRUE);
165         } else {
166 #ifdef DEBUG
167                 g_message ("%s: mutex handle %p not owned by %d:%ld, but locked %d times by %d:%ld", __func__, handle, _wapi_getpid (), pthread_self (), mutex_handle->recursion, mutex_handle->pid, mutex_handle->tid);
168 #endif
169
170                 return(FALSE);
171         }
172 }
173
174 static void namedmutex_signal (gpointer handle)
175 {
176         ReleaseMutex(handle);
177 }
178
179 /* NB, always called with the shared handle lock held */
180 static gboolean namedmutex_own (gpointer handle)
181 {
182         struct _WapiHandle_namedmutex *namedmutex_handle;
183         gboolean ok;
184         
185 #ifdef DEBUG
186         g_message ("%s: owning named mutex handle %p", __func__, handle);
187 #endif
188         
189         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDMUTEX,
190                                   (gpointer *)&namedmutex_handle);
191         if (ok == FALSE) {
192                 g_warning ("%s: error looking up named mutex handle %p",
193                            __func__, handle);
194                 return(FALSE);
195         }
196
197         _wapi_thread_own_mutex (handle);
198
199         namedmutex_handle->pid = _wapi_getpid ();
200         namedmutex_handle->tid = pthread_self ();
201         namedmutex_handle->recursion++;
202
203         _wapi_shared_handle_set_signal_state (handle, FALSE);
204
205 #ifdef DEBUG
206         g_message ("%s: mutex handle %p locked %d times by %d:%ld", __func__,
207                    handle, namedmutex_handle->recursion,
208                    namedmutex_handle->pid, namedmutex_handle->tid);
209 #endif
210         
211         return(TRUE);
212 }
213
214 static gboolean namedmutex_is_owned (gpointer handle)
215 {
216         struct _WapiHandle_namedmutex *namedmutex_handle;
217         gboolean ok;
218         
219         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDMUTEX,
220                                   (gpointer *)&namedmutex_handle);
221         if (ok == FALSE) {
222                 g_warning ("%s: error looking up mutex handle %p", __func__,
223                            handle);
224                 return(FALSE);
225         }
226         
227 #ifdef DEBUG
228         g_message ("%s: testing ownership mutex handle %p", __func__, handle);
229 #endif
230
231         if (namedmutex_handle->recursion > 0 &&
232             namedmutex_handle->pid == _wapi_getpid () &&
233             pthread_equal (namedmutex_handle->tid, pthread_self ())) {
234 #ifdef DEBUG
235                 g_message ("%s: mutex handle %p owned by %d:%ld", __func__,
236                            handle, _wapi_getpid (), pthread_self ());
237 #endif
238
239                 return(TRUE);
240         } else {
241 #ifdef DEBUG
242                 g_message ("%s: mutex handle %p not owned by %d:%ld, but locked %d times by %d:%ld", __func__, handle, _wapi_getpid (), pthread_self (), namedmutex_handle->recursion, namedmutex_handle->pid, namedmutex_handle->tid);
243 #endif
244
245                 return(FALSE);
246         }
247 }
248
249 /* The shared state is not locked when prewait methods are called */
250 static void namedmutex_prewait (gpointer handle)
251 {
252         /* If the mutex is not currently owned, do nothing and let the
253          * usual wait carry on.  If it is owned, check that the owner
254          * is still alive; if it isn't we override the previous owner
255          * and assume that process exited abnormally and failed to
256          * clean up.
257          */
258         struct _WapiHandle_namedmutex *namedmutex_handle;
259         gboolean ok;
260         
261         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDMUTEX,
262                                   (gpointer *)&namedmutex_handle);
263         if (ok == FALSE) {
264                 g_warning ("%s: error looking up named mutex handle %p",
265                            __func__, handle);
266                 return;
267         }
268         
269 #ifdef DEBUG
270         g_message ("%s: Checking ownership of named mutex handle %p", __func__,
271                    handle);
272 #endif
273
274         if (namedmutex_handle->recursion == 0) {
275 #ifdef DEBUG
276                 g_message ("%s: Named mutex handle %p not owned", __func__,
277                            handle);
278 #endif
279         } else if (namedmutex_handle->pid == _wapi_getpid ()) {
280 #ifdef DEBUG
281                 g_message ("%s: Named mutex handle %p owned by this process",
282                            __func__, handle);
283 #endif
284         } else {
285                 int thr_ret;
286                 gpointer proc_handle;
287                 
288 #ifdef DEBUG
289                 g_message ("%s: Named mutex handle %p owned by another process", __func__, handle);
290 #endif
291                 proc_handle = OpenProcess (0, 0, namedmutex_handle->pid);
292                 if (proc_handle == NULL) {
293                         /* Didn't find the process that this handle
294                          * was owned by, overriding it
295                          */
296 #ifdef DEBUG
297                         g_message ("%s: overriding old owner of named mutex handle %p", __func__, handle);
298 #endif
299                         thr_ret = _wapi_handle_lock_shared_handles ();
300                         g_assert (thr_ret == 0);
301
302                         namedmutex_handle->pid = 0;
303                         namedmutex_handle->tid = 0;
304                         namedmutex_handle->recursion = 0;
305
306                         _wapi_shared_handle_set_signal_state (handle, TRUE);
307                         _wapi_handle_unlock_shared_handles ();
308                 } else {
309 #ifdef DEBUG
310                         g_message ("%s: Found active pid %d for named mutex handle %p", __func__, namedmutex_handle->pid, handle);
311 #endif
312                 }
313                 if (proc_handle != NULL)
314                         CloseProcess (proc_handle);
315         }
316 }
317
318 static void mutex_abandon (gpointer handle, pid_t pid, pthread_t tid)
319 {
320         struct _WapiHandle_mutex *mutex_handle;
321         gboolean ok;
322         int thr_ret;
323         
324         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
325                                   (gpointer *)&mutex_handle);
326         if (ok == FALSE) {
327                 g_warning ("%s: error looking up mutex handle %p", __func__,
328                            handle);
329                 return;
330         }
331
332         pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
333                               handle);
334         thr_ret = _wapi_handle_lock_handle (handle);
335         g_assert (thr_ret == 0);
336         
337         if (mutex_handle->pid == pid &&
338             pthread_equal (mutex_handle->tid, tid)) {
339 #ifdef DEBUG
340                 g_message ("%s: Mutex handle %p abandoned!", __func__, handle);
341 #endif
342
343                 mutex_handle->recursion = 0;
344                 mutex_handle->pid = 0;
345                 mutex_handle->tid = 0;
346                 
347                 _wapi_handle_set_signal_state (handle, TRUE, FALSE);
348         }
349
350         thr_ret = _wapi_handle_unlock_handle (handle);
351         g_assert (thr_ret == 0);
352         pthread_cleanup_pop (0);
353 }
354
355 static void namedmutex_abandon (gpointer handle, pid_t pid, pthread_t tid)
356 {
357         struct _WapiHandle_namedmutex *mutex_handle;
358         gboolean ok;
359         int thr_ret;
360         
361         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDMUTEX,
362                                   (gpointer *)&mutex_handle);
363         if (ok == FALSE) {
364                 g_warning ("%s: error looking up named mutex handle %p",
365                            __func__, handle);
366                 return;
367         }
368
369         thr_ret = _wapi_handle_lock_shared_handles ();
370         g_assert (thr_ret == 0);
371         
372         if (mutex_handle->pid == pid &&
373             pthread_equal (mutex_handle->tid, tid)) {
374 #ifdef DEBUG
375                 g_message ("%s: Mutex handle %p abandoned!", __func__, handle);
376 #endif
377
378                 mutex_handle->recursion = 0;
379                 mutex_handle->pid = 0;
380                 mutex_handle->tid = 0;
381                 
382                 _wapi_shared_handle_set_signal_state (handle, TRUE);
383         }
384
385         _wapi_handle_unlock_shared_handles ();
386 }
387
388 /* When a thread exits, any mutexes it still holds need to be
389  * signalled.  This function must not be called with the shared handle
390  * lock held, as namedmutex_abandon () will try to acquire it
391  */
392 void _wapi_mutex_abandon (gpointer data, pid_t pid, pthread_t tid)
393 {
394         WapiHandleType type = _wapi_handle_type (data);
395
396         if (type == WAPI_HANDLE_MUTEX) {
397                 mutex_abandon (data, pid, tid);
398         } else if (type == WAPI_HANDLE_NAMEDMUTEX) {
399                 namedmutex_abandon (data, pid, tid);
400         } else {
401                 g_assert_not_reached ();
402         }
403 }
404
405 static gpointer mutex_create (WapiSecurityAttributes *security G_GNUC_UNUSED,
406                               gboolean owned)
407 {
408         struct _WapiHandle_mutex mutex_handle = {0};
409         gpointer handle;
410         int thr_ret;
411         
412         /* Need to blow away any old errors here, because code tests
413          * for ERROR_ALREADY_EXISTS on success (!) to see if a mutex
414          * was freshly created
415          */
416         SetLastError (ERROR_SUCCESS);
417         
418 #ifdef DEBUG
419         g_message ("%s: Creating unnamed mutex", __func__);
420 #endif
421         
422         handle = _wapi_handle_new (WAPI_HANDLE_MUTEX, &mutex_handle);
423         if (handle == _WAPI_HANDLE_INVALID) {
424                 g_warning ("%s: error creating mutex handle", __func__);
425                 SetLastError (ERROR_GEN_FAILURE);
426                 return(NULL);
427         }
428
429         pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
430                               handle);
431         thr_ret = _wapi_handle_lock_handle (handle);
432         g_assert (thr_ret == 0);
433         
434         if(owned==TRUE) {
435                 mutex_own (handle);
436         } else {
437                 _wapi_handle_set_signal_state (handle, TRUE, FALSE);
438         }
439         
440 #ifdef DEBUG
441         g_message ("%s: returning mutex handle %p", __func__, handle);
442 #endif
443
444         thr_ret = _wapi_handle_unlock_handle (handle);
445         g_assert (thr_ret == 0);
446         pthread_cleanup_pop (0);
447         
448         return(handle);
449 }
450
451 static gpointer namedmutex_create (WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean owned,
452                         const gunichar2 *name)
453 {
454         struct _WapiHandle_namedmutex namedmutex_handle = {{{0}}, 0};
455         gpointer handle;
456         gchar *utf8_name;
457         int thr_ret;
458         gpointer ret = NULL;
459         guint32 namelen;
460         gint32 offset;
461
462         /* w32 seems to guarantee that opening named objects can't
463          * race each other
464          */
465         thr_ret = _wapi_namespace_lock ();
466         g_assert (thr_ret == 0);
467
468         /* Need to blow away any old errors here, because code tests
469          * for ERROR_ALREADY_EXISTS on success (!) to see if a mutex
470          * was freshly created
471          */
472         SetLastError (ERROR_SUCCESS);
473         
474         utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
475         
476 #ifdef DEBUG
477         g_message ("%s: Creating named mutex [%s]", __func__, utf8_name);
478 #endif
479         
480         offset = _wapi_search_handle_namespace (WAPI_HANDLE_NAMEDMUTEX,
481                                                 utf8_name);
482         if (offset == -1) {
483                 /* The name has already been used for a different
484                  * object.
485                  */
486                 SetLastError (ERROR_INVALID_HANDLE);
487                 goto cleanup;
488         } else if (offset != 0) {
489                 /* Not an error, but this is how the caller is
490                  * informed that the mutex wasn't freshly created
491                  */
492                 SetLastError (ERROR_ALREADY_EXISTS);
493         }
494         /* Fall through to create the mutex handle. */
495
496         if (offset == 0) {
497                 /* A new named mutex, so create both the private and
498                  * shared parts
499                  */
500         
501                 if (strlen (utf8_name) < MAX_PATH) {
502                         namelen = strlen (utf8_name);
503                 } else {
504                         namelen = MAX_PATH;
505                 }
506         
507                 memcpy (&namedmutex_handle.sharedns.name, utf8_name, namelen);
508
509                 handle = _wapi_handle_new (WAPI_HANDLE_NAMEDMUTEX,
510                                            &namedmutex_handle);
511         } else {
512                 /* A new reference to an existing named mutex, so just
513                  * create the private part
514                  */
515                 handle = _wapi_handle_new_from_offset (WAPI_HANDLE_NAMEDMUTEX,
516                                                        offset, TRUE);
517         }
518         
519         if (handle == _WAPI_HANDLE_INVALID) {
520                 g_warning ("%s: error creating mutex handle", __func__);
521                 SetLastError (ERROR_GEN_FAILURE);
522                 goto cleanup;
523         }
524         ret = handle;
525
526         if (offset == 0) {
527                 /* Set the initial state, as this is a completely new
528                  * handle
529                  */
530                 thr_ret = _wapi_handle_lock_shared_handles ();
531                 g_assert (thr_ret == 0);
532         
533                 if (owned == TRUE) {
534                         namedmutex_own (handle);
535                 } else {
536                         _wapi_shared_handle_set_signal_state (handle, TRUE);
537                 }
538
539                 _wapi_handle_unlock_shared_handles ();
540         }
541         
542 #ifdef DEBUG
543         g_message ("%s: returning mutex handle %p", __func__, handle);
544 #endif
545
546 cleanup:
547         g_free (utf8_name);
548
549         _wapi_namespace_unlock (NULL);
550         
551         return(ret);
552 }
553
554 /**
555  * CreateMutex:
556  * @security: Ignored for now.
557  * @owned: If %TRUE, the mutex is created with the calling thread
558  * already owning the mutex.
559  * @name:Pointer to a string specifying the name of this mutex, or
560  * %NULL.
561  *
562  * Creates a new mutex handle.  A mutex is signalled when no thread
563  * owns it.  A thread acquires ownership of the mutex by waiting for
564  * it with WaitForSingleObject() or WaitForMultipleObjects().  A
565  * thread relinquishes ownership with ReleaseMutex().
566  *
567  * A thread that owns a mutex can specify the same mutex in repeated
568  * wait function calls without blocking.  The thread must call
569  * ReleaseMutex() an equal number of times to release the mutex.
570  *
571  * Return value: A new handle, or %NULL on error.
572  */
573 gpointer CreateMutex(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean owned,
574                         const gunichar2 *name)
575 {
576         mono_once (&mutex_ops_once, mutex_ops_init);
577
578         if (name == NULL) {
579                 return(mutex_create (security, owned));
580         } else {
581                 return(namedmutex_create (security, owned, name));
582         }
583 }
584
585 static gboolean mutex_release (gpointer handle)
586 {
587         struct _WapiHandle_mutex *mutex_handle;
588         gboolean ok;
589         pthread_t tid = pthread_self ();
590         pid_t pid = _wapi_getpid ();
591         int thr_ret;
592         gboolean ret = FALSE;
593         
594         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
595                                   (gpointer *)&mutex_handle);
596         if (ok == FALSE) {
597                 g_warning ("%s: error looking up mutex handle %p", __func__,
598                            handle);
599                 return(FALSE);
600         }
601
602         pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
603                               handle);
604         thr_ret = _wapi_handle_lock_handle (handle);
605         g_assert (thr_ret == 0);
606         
607 #ifdef DEBUG
608         g_message("%s: Releasing mutex handle %p", __func__, handle);
609 #endif
610
611         if (!pthread_equal (mutex_handle->tid, tid) ||
612             mutex_handle->pid != pid) {
613 #ifdef DEBUG
614                 g_message("%s: We don't own mutex handle %p (owned by %d:%ld, me %d:%ld)", __func__, handle, mutex_handle->pid, mutex_handle->tid, _wapi_getpid (), tid);
615 #endif
616
617                 goto cleanup;
618         }
619         ret = TRUE;
620         
621         /* OK, we own this mutex */
622         mutex_handle->recursion--;
623         
624         if(mutex_handle->recursion==0) {
625                 _wapi_thread_disown_mutex (handle);
626
627 #ifdef DEBUG
628                 g_message("%s: Unlocking mutex handle %p", __func__, handle);
629 #endif
630
631                 mutex_handle->pid=0;
632                 mutex_handle->tid=0;
633                 _wapi_handle_set_signal_state (handle, TRUE, FALSE);
634         }
635
636 cleanup:
637         thr_ret = _wapi_handle_unlock_handle (handle);
638         g_assert (thr_ret == 0);
639         pthread_cleanup_pop (0);
640         
641         return(ret);
642 }
643
644 static gboolean namedmutex_release (gpointer handle)
645 {
646         struct _WapiHandle_namedmutex *mutex_handle;
647         gboolean ok;
648         pthread_t tid = pthread_self ();
649         pid_t pid = _wapi_getpid ();
650         int thr_ret;
651         gboolean ret = FALSE;
652         
653         ok=_wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDMUTEX,
654                                 (gpointer *)&mutex_handle);
655         if(ok==FALSE) {
656                 g_warning ("%s: error looking up named mutex handle %p",
657                            __func__, handle);
658                 return(FALSE);
659         }
660
661         thr_ret = _wapi_handle_lock_shared_handles ();
662         g_assert (thr_ret == 0);
663         
664 #ifdef DEBUG
665         g_message("%s: Releasing mutex handle %p", __func__, handle);
666 #endif
667
668         if (!pthread_equal (mutex_handle->tid, tid) ||
669             mutex_handle->pid != pid) {
670 #ifdef DEBUG
671                 g_message("%s: We don't own mutex handle %p (owned by %d:%ld, me %d:%ld)", __func__, handle, mutex_handle->pid, mutex_handle->tid, _wapi_getpid (), tid);
672 #endif
673
674                 goto cleanup;
675         }
676         ret = TRUE;
677         
678         /* OK, we own this mutex */
679         mutex_handle->recursion--;
680         
681         if(mutex_handle->recursion==0) {
682                 _wapi_thread_disown_mutex (handle);
683
684 #ifdef DEBUG
685                 g_message("%s: Unlocking mutex handle %p", __func__, handle);
686 #endif
687
688                 mutex_handle->pid=0;
689                 mutex_handle->tid=0;
690                 _wapi_shared_handle_set_signal_state (handle, TRUE);
691         }
692
693 cleanup:
694         _wapi_handle_unlock_shared_handles ();
695         
696         return(ret);
697 }
698
699 /**
700  * ReleaseMutex:
701  * @handle: The mutex handle.
702  *
703  * Releases ownership if the mutex handle @handle.
704  *
705  * Return value: %TRUE on success, %FALSE otherwise.  This function
706  * fails if the calling thread does not own the mutex @handle.
707  */
708 gboolean ReleaseMutex(gpointer handle)
709 {
710         WapiHandleType type;
711
712         if (handle == NULL) {
713                 SetLastError (ERROR_INVALID_HANDLE);
714                 return(FALSE);
715         }
716         
717         type = _wapi_handle_type (handle);
718         
719         if (mutex_ops[type].release == NULL) {
720                 SetLastError (ERROR_INVALID_HANDLE);
721                 return(FALSE);
722         }
723         
724         return(mutex_ops[type].release (handle));
725 }
726
727 gpointer OpenMutex (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, const gunichar2 *name)
728 {
729         gpointer handle;
730         gchar *utf8_name;
731         int thr_ret;
732         gpointer ret = NULL;
733         gint32 offset;
734
735         mono_once (&mutex_ops_once, mutex_ops_init);
736
737         /* w32 seems to guarantee that opening named objects can't
738          * race each other
739          */
740         thr_ret = _wapi_namespace_lock ();
741         g_assert (thr_ret == 0);
742
743         utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
744         
745 #ifdef DEBUG
746         g_message ("%s: Opening named mutex [%s]", __func__, utf8_name);
747 #endif
748         
749         offset = _wapi_search_handle_namespace (WAPI_HANDLE_NAMEDMUTEX,
750                                                 utf8_name);
751         if (offset == -1) {
752                 /* The name has already been used for a different
753                  * object.
754                  */
755                 SetLastError (ERROR_INVALID_HANDLE);
756                 goto cleanup;
757         } else if (offset == 0) {
758                 /* This name doesn't exist */
759                 SetLastError (ERROR_FILE_NOT_FOUND);    /* yes, really */
760                 goto cleanup;
761         }
762
763         /* A new reference to an existing named mutex, so just create
764          * the private part
765          */
766         handle = _wapi_handle_new_from_offset (WAPI_HANDLE_NAMEDMUTEX, offset,
767                                                TRUE);
768         
769         if (handle == _WAPI_HANDLE_INVALID) {
770                 g_warning ("%s: error opening named mutex handle", __func__);
771                 SetLastError (ERROR_GEN_FAILURE);
772                 goto cleanup;
773         }
774         ret = handle;
775
776 #ifdef DEBUG
777         g_message ("%s: returning named mutex handle %p", __func__, handle);
778 #endif
779
780 cleanup:
781         g_free (utf8_name);
782
783         _wapi_namespace_unlock (NULL);
784         
785         return(ret);
786 }