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