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