[xbuild] Set @(CollectedBuildOutput) for projects build from .sln .
[mono.git] / mono / io-layer / wthreads.c
1 /*
2  * threads.c:  Thread 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 <stdio.h>
12 #include <glib.h>
13 #include <string.h>
14 #include <mono/utils/gc_wrapper.h>
15 #include <pthread.h>
16 #include <signal.h>
17 #include <sched.h>
18 #include <sys/time.h>
19 #include <errno.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22
23 #include <mono/io-layer/wapi.h>
24 #include <mono/io-layer/wapi-private.h>
25 #include <mono/io-layer/handles-private.h>
26 #include <mono/io-layer/misc-private.h>
27 #include <mono/io-layer/mono-mutex.h>
28 #include <mono/io-layer/thread-private.h>
29 #include <mono/io-layer/mutex-private.h>
30 #include <mono/io-layer/atomic.h>
31
32 #ifdef HAVE_VALGRIND_MEMCHECK_H
33 #include <valgrind/memcheck.h>
34 #endif
35
36 #undef DEBUG
37 #undef TLS_DEBUG
38
39 #if 0
40 #define WAIT_DEBUG(code) do { code } while (0)
41 #else
42 #define WAIT_DEBUG(code) do { } while (0)
43 #endif
44
45 /* Hash threads with tids. I thought of using TLS for this, but that
46  * would have to set the data in the new thread, which is more hassle
47  */
48 static mono_once_t thread_hash_once = MONO_ONCE_INIT;
49 static pthread_key_t thread_hash_key;
50
51 /* This key is used with attached threads and a destructor to signal
52  * when attached threads exit, as they don't have the thread_exit()
53  * infrastructure
54  */
55 static pthread_key_t thread_attached_key;
56
57 struct _WapiHandleOps _wapi_thread_ops = {
58         NULL,                           /* close */
59         NULL,                           /* signal */
60         NULL,                           /* own */
61         NULL,                           /* is_owned */
62         NULL,                           /* special_wait */
63         NULL                            /* prewait */
64 };
65
66 static mono_once_t thread_ops_once=MONO_ONCE_INIT;
67
68 static void thread_ops_init (void)
69 {
70         _wapi_handle_register_capabilities (WAPI_HANDLE_THREAD,
71                                             WAPI_HANDLE_CAP_WAIT);
72 }
73
74 void _wapi_thread_cleanup (void)
75 {
76         int ret;
77         
78         ret = pthread_key_delete (thread_hash_key);
79         g_assert (ret == 0);
80         
81         ret = pthread_key_delete (thread_attached_key);
82         g_assert (ret == 0);
83 }
84
85 /* Called by thread_exit(), but maybe indirectly by
86  * mono_thread_manage() via mono_thread_signal_self() too
87  */
88 static void _wapi_thread_abandon_mutexes (gpointer handle)
89 {
90         struct _WapiHandle_thread *thread_handle;
91         gboolean ok;
92         int i;
93         pid_t pid = _wapi_getpid ();
94         pthread_t tid = pthread_self ();
95         
96 #ifdef DEBUG
97         g_message ("%s: Thread %p abandoning held mutexes", __func__, handle);
98 #endif
99
100         if (handle == NULL) {
101                 handle = _wapi_thread_handle_from_id (pthread_self ());
102                 if (handle == NULL) {
103                         /* Something gone badly wrong... */
104                         return;
105                 }
106         }
107         
108         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
109                                   (gpointer *)&thread_handle);
110         if (ok == FALSE) {
111                 g_warning ("%s: error looking up thread handle %p", __func__,
112                            handle);
113                 return;
114         }
115         
116         if (!pthread_equal (thread_handle->id, tid)) {
117                 return;
118         }
119         
120         for (i = 0; i < thread_handle->owned_mutexes->len; i++) {
121                 gpointer mutex = g_ptr_array_index (thread_handle->owned_mutexes, i);
122                 
123                 _wapi_mutex_abandon (mutex, pid, tid);
124                 _wapi_thread_disown_mutex (mutex);
125         }
126 }
127
128 void _wapi_thread_set_termination_details (gpointer handle,
129                                            guint32 exitstatus)
130 {
131         struct _WapiHandle_thread *thread_handle;
132         gboolean ok;
133         int thr_ret;
134         
135         if (_wapi_handle_issignalled (handle) ||
136             _wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) {
137                 /* We must have already deliberately finished with
138                  * this thread, so don't do any more now
139                  */
140                 return;
141         }
142
143 #ifdef DEBUG
144         g_message ("%s: Thread %p terminating", __func__, handle);
145 #endif
146
147         _wapi_thread_abandon_mutexes (handle);
148         
149         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
150                                   (gpointer *)&thread_handle);
151         if (ok == FALSE) {
152                 g_warning ("%s: error looking up thread handle %p", __func__,
153                            handle);
154
155                 return;
156         }
157         
158         pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
159                               handle);
160         thr_ret = _wapi_handle_lock_handle (handle);
161         g_assert (thr_ret == 0);
162         
163         thread_handle->exitstatus = exitstatus;
164         thread_handle->state = THREAD_STATE_EXITED;
165         MONO_SEM_DESTROY (&thread_handle->suspend_sem);
166         g_ptr_array_free (thread_handle->owned_mutexes, TRUE);
167
168         _wapi_handle_set_signal_state (handle, TRUE, TRUE);
169
170         thr_ret = _wapi_handle_unlock_handle (handle);
171         g_assert (thr_ret == 0);
172         pthread_cleanup_pop (0);
173         
174 #ifdef DEBUG
175         g_message("%s: Recording thread handle %p id %ld status as %d",
176                   __func__, handle, thread_handle->id, exitstatus);
177 #endif
178         
179         /* The thread is no longer active, so unref it */
180         _wapi_handle_unref (handle);
181 }
182
183 void _wapi_thread_signal_self (guint32 exitstatus)
184 {
185         gpointer handle;
186         
187         handle = _wapi_thread_handle_from_id (pthread_self ());
188         if (handle == NULL) {
189                 /* Something gone badly wrong... */
190                 return;
191         }
192         
193         _wapi_thread_set_termination_details (handle, exitstatus);
194 }
195
196 /* Called by the thread creation code as a thread is finishing up, and
197  * by ExitThread()
198 */
199 static void thread_exit (guint32 exitstatus, gpointer handle) G_GNUC_NORETURN;
200 static void thread_exit (guint32 exitstatus, gpointer handle)
201 {
202         _wapi_thread_set_termination_details (handle, exitstatus);
203         
204         /* Call pthread_exit() to call destructors and really exit the
205          * thread
206          */
207         pthread_exit (NULL);
208 }
209
210 static void thread_attached_exit (gpointer handle)
211 {
212         /* Drop the extra reference we take in thread_attach, now this
213          * thread is dead
214          */
215         
216         _wapi_thread_set_termination_details (handle, 0);
217 }
218
219 static void thread_hash_init(void)
220 {
221         int thr_ret;
222         
223         thr_ret = pthread_key_create (&thread_hash_key, NULL);
224         g_assert (thr_ret == 0);
225
226         thr_ret = pthread_key_create (&thread_attached_key,
227                                       thread_attached_exit);
228         g_assert (thr_ret == 0);
229 }
230
231 static void _wapi_thread_suspend (struct _WapiHandle_thread *thread)
232 {
233         g_assert (pthread_equal (thread->id, pthread_self ()));
234         
235         while (MONO_SEM_WAIT (&thread->suspend_sem) != 0 &&
236                errno == EINTR);
237 }
238
239 static void _wapi_thread_resume (struct _WapiHandle_thread *thread)
240 {
241         MONO_SEM_POST (&thread->suspend_sem);
242 }
243
244 static void *thread_start_routine (gpointer args) G_GNUC_NORETURN;
245 static void *thread_start_routine (gpointer args)
246 {
247         struct _WapiHandle_thread *thread = (struct _WapiHandle_thread *)args;
248         int thr_ret;
249         
250         thr_ret = mono_gc_pthread_detach (pthread_self ());
251         g_assert (thr_ret == 0);
252
253         thr_ret = pthread_setspecific (thread_hash_key,
254                                        (void *)thread->handle);
255         if (thr_ret != 0) {
256                 /* This is only supposed to happen when Mono is
257                    shutting down.  We cannot assert on it, though,
258                    because we must not depend on metadata, which is
259                    where the shutdown code is.
260
261                    This is a race condition which arises because
262                    pthreads don't allow creation of suspended threads.
263                    Once Mono is set to shut down no new thread is
264                    allowed to start, even though threads may still be
265                    created.  We emulate suspended threads in this
266                    function by calling _wapi_thread_suspend() below.
267
268                    So it can happen that even though Mono is already
269                    shutting down we still end up here, and at this
270                    point the thread_hash_key might already be
271                    destroyed. */
272                 pthread_exit (NULL);
273         }
274
275         thread->id = pthread_self();
276
277 #ifdef DEBUG
278         g_message ("%s: started thread id %ld", __func__, thread->id);
279 #endif
280
281         if (thread->create_flags & CREATE_SUSPENDED) {
282                 _wapi_thread_suspend (thread);
283         }
284         
285         thread_exit (thread->start_routine (thread->start_arg),
286                      thread->handle);
287
288 #ifndef __GNUC__
289         /* Even though we tell gcc that this function doesn't return,
290          * other compilers won't see that.
291          */
292         return(NULL);
293 #endif
294 }
295
296 /**
297  * CreateThread:
298  * @security: Ignored for now.
299  * @stacksize: the size in bytes of the new thread's stack. Use 0 to
300  * default to the normal stack size. (Ignored for now).
301  * @start: The function that the new thread should start with
302  * @param: The parameter to give to @start.
303  * @create: If 0, the new thread is ready to run immediately.  If
304  * %CREATE_SUSPENDED, the new thread will be in the suspended state,
305  * requiring a ResumeThread() call to continue running.
306  * @tid: If non-NULL, the ID of the new thread is stored here.  NB
307  * this is defined as a DWORD (ie 32bit) in the MS API, but we need to
308  * cope with 64 bit IDs for s390x and amd64.
309  *
310  * Creates a new threading handle.
311  *
312  * Return value: a new handle, or NULL
313  */
314 gpointer CreateThread(WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 stacksize,
315                       WapiThreadStart start, gpointer param, guint32 create,
316                       gsize *tid) 
317 {
318         struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
319         pthread_attr_t attr;
320         gpointer handle;
321         gboolean ok;
322         int ret;
323         int thr_ret;
324         int i, unrefs = 0;
325         gpointer ct_ret = NULL;
326         
327         mono_once (&thread_hash_once, thread_hash_init);
328         mono_once (&thread_ops_once, thread_ops_init);
329         
330         if (start == NULL) {
331                 return(NULL);
332         }
333
334         thread_handle.state = THREAD_STATE_START;
335         thread_handle.owned_mutexes = g_ptr_array_new ();
336         thread_handle.create_flags = create;
337         thread_handle.start_routine = start;
338         thread_handle.start_arg = param;
339         
340         handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
341         if (handle == _WAPI_HANDLE_INVALID) {
342                 g_warning ("%s: error creating thread handle", __func__);
343                 SetLastError (ERROR_GEN_FAILURE);
344                 
345                 return (NULL);
346         }
347
348         pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
349                               handle);
350         thr_ret = _wapi_handle_lock_handle (handle);
351         g_assert (thr_ret == 0);
352         
353         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
354                                   (gpointer *)&thread_handle_p);
355         if (ok == FALSE) {
356                 g_warning ("%s: error looking up thread handle %p", __func__,
357                            handle);
358                 SetLastError (ERROR_GEN_FAILURE);
359                 
360                 goto cleanup;
361         }
362
363         /* Hold a reference while the thread is active, because we use
364          * the handle to store thread exit information
365          */
366         _wapi_handle_ref (handle);
367         
368         /* Set a 2M stack size.  This is the default on Linux, but BSD
369          * needs it.  (The original bug report from Martin Dvorak <md@9ll.cz>
370          * set the size to 2M-4k.  I don't know why it's short by 4k, so
371          * I'm leaving it as 2M until I'm told differently.)
372          */
373         thr_ret = pthread_attr_init(&attr);
374         g_assert (thr_ret == 0);
375         
376         /* defaults of 2Mb for 32bits and 4Mb for 64bits */
377         /* temporarily changed to use 1 MB: this allows more threads
378          * to be used, as well as using less virtual memory and so
379          * more is available for the GC heap.
380          */
381         if (stacksize == 0){
382 #if HAVE_VALGRIND_MEMCHECK_H
383                 if (RUNNING_ON_VALGRIND) {
384                         stacksize = 1 << 20;
385                 } else {
386                         stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
387                 }
388 #else
389                 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
390 #endif
391         }
392
393 #ifdef PTHREAD_STACK_MIN
394         if (stacksize < PTHREAD_STACK_MIN)
395                 stacksize = PTHREAD_STACK_MIN;
396 #endif
397
398 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
399         thr_ret = pthread_attr_setstacksize(&attr, stacksize);
400         g_assert (thr_ret == 0);
401 #endif
402
403         MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
404         thread_handle_p->handle = handle;
405         
406
407         ret = mono_gc_pthread_create (&thread_handle_p->id, &attr,
408                                                                   thread_start_routine, (void *)thread_handle_p);
409
410         if (ret != 0) {
411 #ifdef DEBUG
412                 g_message ("%s: Thread create error: %s", __func__,
413                            strerror(ret));
414 #endif
415
416                 /* Two, because of the reference we took above */
417                 unrefs = 2;
418                 
419                 goto cleanup;
420         }
421         ct_ret = handle;
422         
423 #ifdef DEBUG
424         g_message("%s: Started thread handle %p ID %ld", __func__, handle,
425                   thread_handle_p->id);
426 #endif
427         
428         if (tid != NULL) {
429 #ifdef PTHREAD_POINTER_ID
430                 /* Don't use GPOINTER_TO_UINT here, it can't cope with
431                  * sizeof(void *) > sizeof(uint) when a cast to uint
432                  * would overflow
433                  */
434                 *tid = (gsize)(thread_handle_p->id);
435 #else
436                 *tid = thread_handle_p->id;
437 #endif
438         }
439
440 cleanup:
441         thr_ret = _wapi_handle_unlock_handle (handle);
442         g_assert (thr_ret == 0);
443         pthread_cleanup_pop (0);
444         
445         /* Must not call _wapi_handle_unref() with the shared handles
446          * already locked
447          */
448         for (i = 0; i < unrefs; i++) {
449                 _wapi_handle_unref (handle);
450         }
451         
452         return(ct_ret);
453 }
454
455 /* The only time this function is called when tid != pthread_self ()
456  * is from OpenThread (), so we can fast-path most cases by just
457  * looking up the handle in TLS.  OpenThread () must cope with a NULL
458  * return and do a handle search in that case.
459  */
460 gpointer _wapi_thread_handle_from_id (pthread_t tid)
461 {
462         gpointer ret;
463
464         if (pthread_equal (tid, pthread_self ()) &&
465             (ret = pthread_getspecific (thread_hash_key)) != NULL) {
466                 /* We know the handle */
467
468 #ifdef DEBUG
469                 g_message ("%s: Returning %p for self thread %ld from TLS",
470                            __func__, ret, tid);
471 #endif
472                 
473                 return(ret);
474         }
475         
476 #ifdef DEBUG
477         g_message ("%s: Returning NULL for unknown or non-self thread %ld",
478                    __func__, tid);
479 #endif
480                 
481
482         return(NULL);
483 }
484
485 static gboolean find_thread_by_id (gpointer handle, gpointer user_data)
486 {
487         pthread_t tid = (pthread_t)user_data;
488         struct _WapiHandle_thread *thread_handle;
489         gboolean ok;
490         
491         /* Ignore threads that have already exited (ie they are signalled) */
492         if (_wapi_handle_issignalled (handle) == FALSE) {
493                 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
494                                           (gpointer *)&thread_handle);
495                 if (ok == FALSE) {
496                         /* It's possible that the handle has vanished
497                          * during the _wapi_search_handle before it
498                          * gets here, so don't spam the console with
499                          * warnings.
500                          */
501                         return(FALSE);
502                 }
503                 
504 #ifdef DEBUG
505                 g_message ("%s: looking at thread %ld from process %d", __func__, thread_handle->id, 0);
506 #endif
507
508                 if (pthread_equal (thread_handle->id, tid)) {
509 #ifdef DEBUG
510                         g_message ("%s: found the thread we are looking for",
511                                    __func__);
512 #endif
513                         return(TRUE);
514                 }
515         }
516         
517 #ifdef DEBUG
518         g_message ("%s: not found %ld, returning FALSE", __func__, tid);
519 #endif
520         
521         return(FALSE);
522 }
523
524 /* NB tid is 32bit in MS API, but we need 64bit on amd64 and s390x
525  * (and probably others)
526  */
527 gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, gsize tid)
528 {
529         gpointer ret=NULL;
530         
531         mono_once (&thread_hash_once, thread_hash_init);
532         mono_once (&thread_ops_once, thread_ops_init);
533         
534 #ifdef DEBUG
535         g_message ("%s: looking up thread %"G_GSIZE_FORMAT, __func__, tid);
536 #endif
537
538         ret = _wapi_thread_handle_from_id ((pthread_t)tid);
539         if (ret == NULL) {
540                 /* We need to search for this thread */
541                 ret = _wapi_search_handle (WAPI_HANDLE_THREAD, find_thread_by_id, (gpointer)tid, NULL, FALSE/*TRUE*/);  /* FIXME: have a proper look at this, me might not need to set search_shared = TRUE */
542         } else {
543                 /* if _wapi_search_handle() returns a found handle, it
544                  * refs it itself
545                  */
546                 _wapi_handle_ref (ret);
547         }
548         
549 #ifdef DEBUG
550         g_message ("%s: returning thread handle %p", __func__, ret);
551 #endif
552         
553         return(ret);
554 }
555
556 /**
557  * ExitThread:
558  * @exitcode: Sets the thread's exit code, which can be read from
559  * another thread with GetExitCodeThread().
560  *
561  * Terminates the calling thread.  A thread can also exit by returning
562  * from its start function. When the last thread in a process
563  * terminates, the process itself terminates.
564  */
565 void ExitThread(guint32 exitcode)
566 {
567         gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
568         
569         if (thread != NULL) {
570                 thread_exit(exitcode, thread);
571         } else {
572                 /* Just blow this thread away */
573                 pthread_exit (NULL);
574         }
575 }
576
577 /**
578  * GetExitCodeThread:
579  * @handle: The thread handle to query
580  * @exitcode: The thread @handle exit code is stored here
581  *
582  * Finds the exit code of @handle, and stores it in @exitcode.  If the
583  * thread @handle is still running, the value stored is %STILL_ACTIVE.
584  *
585  * Return value: %TRUE, or %FALSE on error.
586  */
587 gboolean GetExitCodeThread(gpointer handle, guint32 *exitcode)
588 {
589         struct _WapiHandle_thread *thread_handle;
590         gboolean ok;
591         
592         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
593                                   (gpointer *)&thread_handle);
594         if (ok == FALSE) {
595                 g_warning ("%s: error looking up thread handle %p", __func__,
596                            handle);
597                 return (FALSE);
598         }
599         
600 #ifdef DEBUG
601         g_message ("%s: Finding exit status for thread handle %p id %ld",
602                    __func__, handle, thread_handle->id);
603 #endif
604
605         if (exitcode == NULL) {
606 #ifdef DEBUG
607                 g_message ("%s: Nowhere to store exit code", __func__);
608 #endif
609                 return(FALSE);
610         }
611         
612         if (thread_handle->state != THREAD_STATE_EXITED) {
613 #ifdef DEBUG
614                 g_message ("%s: Thread still active (state %d, exited is %d)",
615                            __func__, thread_handle->state,
616                            THREAD_STATE_EXITED);
617 #endif
618                 *exitcode = STILL_ACTIVE;
619                 return(TRUE);
620         }
621         
622         *exitcode = thread_handle->exitstatus;
623         
624         return(TRUE);
625 }
626
627 /**
628  * GetCurrentThreadId:
629  *
630  * Looks up the thread ID of the current thread.  This ID can be
631  * passed to OpenThread() to create a new handle on this thread.
632  *
633  * Return value: the thread ID.  NB this is defined as DWORD (ie 32
634  * bit) in the MS API, but we need to cope with 64 bit IDs for s390x
635  * and amd64.  This doesn't really break the API, it just embraces and
636  * extends it on 64bit platforms :)
637  */
638 gsize GetCurrentThreadId(void)
639 {
640         pthread_t tid = pthread_self();
641         
642 #ifdef PTHREAD_POINTER_ID
643         /* Don't use GPOINTER_TO_UINT here, it can't cope with
644          * sizeof(void *) > sizeof(uint) when a cast to uint would
645          * overflow
646          */
647         return((gsize)tid);
648 #else
649         return(tid);
650 #endif
651 }
652
653 static gpointer thread_attach(gsize *tid)
654 {
655         struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
656         gpointer handle;
657         gboolean ok;
658         int thr_ret;
659         
660         mono_once (&thread_hash_once, thread_hash_init);
661         mono_once (&thread_ops_once, thread_ops_init);
662
663         thread_handle.state = THREAD_STATE_START;
664         thread_handle.owned_mutexes = g_ptr_array_new ();
665
666         handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
667         if (handle == _WAPI_HANDLE_INVALID) {
668                 g_warning ("%s: error creating thread handle", __func__);
669                 
670                 SetLastError (ERROR_GEN_FAILURE);
671                 return (NULL);
672         }
673
674         pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
675                               handle);
676         thr_ret = _wapi_handle_lock_handle (handle);
677         g_assert (thr_ret == 0);
678         
679         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
680                                   (gpointer *)&thread_handle_p);
681         if (ok == FALSE) {
682                 g_warning ("%s: error looking up thread handle %p", __func__,
683                            handle);
684                 
685                 SetLastError (ERROR_GEN_FAILURE);
686                 goto cleanup;
687         }
688
689         /* Hold a reference while the thread is active, because we use
690          * the handle to store thread exit information
691          */
692         _wapi_handle_ref (handle);
693
694         /* suspend_sem is not used for attached threads, but
695          * thread_exit() might try to destroy it
696          */
697         MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
698         thread_handle_p->handle = handle;
699         thread_handle_p->id = pthread_self ();
700
701         thr_ret = pthread_setspecific (thread_hash_key, (void *)handle);
702         g_assert (thr_ret == 0);
703
704         thr_ret = pthread_setspecific (thread_attached_key, (void *)handle);
705         g_assert (thr_ret == 0);
706         
707 #ifdef DEBUG
708         g_message("%s: Attached thread handle %p ID %ld", __func__, handle,
709                   thread_handle_p->id);
710 #endif
711
712         if (tid != NULL) {
713 #ifdef PTHREAD_POINTER_ID
714                 /* Don't use GPOINTER_TO_UINT here, it can't cope with
715                  * sizeof(void *) > sizeof(uint) when a cast to uint
716                  * would overflow
717                  */
718                 *tid = (gsize)(thread_handle_p->id);
719 #else
720                 *tid = thread_handle_p->id;
721 #endif
722         }
723
724 cleanup:
725         thr_ret = _wapi_handle_unlock_handle (handle);
726         g_assert (thr_ret == 0);
727         pthread_cleanup_pop (0);
728         
729         return(handle);
730 }
731
732 gpointer _wapi_thread_duplicate ()
733 {
734         gpointer ret = NULL;
735         
736         mono_once (&thread_hash_once, thread_hash_init);
737         mono_once (&thread_ops_once, thread_ops_init);
738         
739         ret = _wapi_thread_handle_from_id (pthread_self ());
740         if (!ret) {
741                 ret = thread_attach (NULL);
742         } else {
743                 _wapi_handle_ref (ret);
744         }
745         
746         return(ret);
747 }
748
749 /**
750  * GetCurrentThread:
751  *
752  * Looks up the handle associated with the current thread.  Under
753  * Windows this is a pseudohandle, and must be duplicated with
754  * DuplicateHandle() for some operations.
755  *
756  * Return value: The current thread handle, or %NULL on failure.
757  * (Unknown whether Windows has a possible failure here.  It may be
758  * necessary to implement the pseudohandle-constant behaviour).
759  */
760 gpointer GetCurrentThread(void)
761 {
762         mono_once(&thread_hash_once, thread_hash_init);
763         mono_once (&thread_ops_once, thread_ops_init);
764         
765         return(_WAPI_THREAD_CURRENT);
766 }
767
768 /**
769  * ResumeThread:
770  * @handle: the thread handle to resume
771  *
772  * Decrements the suspend count of thread @handle. A thread can only
773  * run if its suspend count is zero.
774  *
775  * Return value: the previous suspend count, or 0xFFFFFFFF on error.
776  */
777 guint32 ResumeThread(gpointer handle)
778 {
779         struct _WapiHandle_thread *thread_handle;
780         gboolean ok;
781         
782         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
783                                   (gpointer *)&thread_handle);
784         if (ok == FALSE) {
785                 g_warning ("%s: error looking up thread handle %p", __func__,
786                            handle);
787                 
788                 return (0xFFFFFFFF);
789         }
790
791         /* This is still a kludge that only copes with starting a
792          * thread that was suspended on create, so don't bother with
793          * the suspend count crap yet
794          */
795         _wapi_thread_resume (thread_handle);
796         return(0xFFFFFFFF);
797 }
798
799 /**
800  * SuspendThread:
801  * @handle: the thread handle to suspend
802  *
803  * Increments the suspend count of thread @handle. A thread can only
804  * run if its suspend count is zero.
805  *
806  * Return value: the previous suspend count, or 0xFFFFFFFF on error.
807  */
808 guint32 SuspendThread(gpointer handle)
809 {
810         return(0xFFFFFFFF);
811 }
812
813 /*
814  * We assume here that TLS_MINIMUM_AVAILABLE is less than
815  * PTHREAD_KEYS_MAX, allowing enough overhead for a few TLS keys for
816  * library usage.
817  *
818  * Currently TLS_MINIMUM_AVAILABLE is 64 and _POSIX_THREAD_KEYS_MAX
819  * (the minimum value for PTHREAD_KEYS_MAX) is 128, so we should be
820  * fine.
821  */
822
823 static pthread_key_t TLS_keys[TLS_MINIMUM_AVAILABLE];
824 static gboolean TLS_used[TLS_MINIMUM_AVAILABLE]={FALSE};
825 static pthread_mutex_t TLS_mutex = PTHREAD_MUTEX_INITIALIZER;
826
827 guint32
828 mono_pthread_key_for_tls (guint32 idx)
829 {
830         return (guint32)TLS_keys [idx];
831 }
832
833 /**
834  * TlsAlloc:
835  *
836  * Allocates a Thread Local Storage (TLS) index.  Any thread in the
837  * same process can use this index to store and retrieve values that
838  * are local to that thread.
839  *
840  * Return value: The index value, or %TLS_OUT_OF_INDEXES if no index
841  * is available.
842  */
843 guint32 TlsAlloc(void)
844 {
845         guint32 i;
846         int thr_ret;
847         
848         pthread_mutex_lock (&TLS_mutex);
849         
850         for(i=0; i<TLS_MINIMUM_AVAILABLE; i++) {
851                 if(TLS_used[i]==FALSE) {
852                         TLS_used[i]=TRUE;
853                         thr_ret = pthread_key_create(&TLS_keys[i], NULL);
854                         g_assert (thr_ret == 0);
855
856                         pthread_mutex_unlock (&TLS_mutex);
857         
858 #ifdef TLS_DEBUG
859                         g_message ("%s: returning key %d", __func__, i);
860 #endif
861                         
862                         return(i);
863                 }
864         }
865
866         pthread_mutex_unlock (&TLS_mutex);
867         
868 #ifdef TLS_DEBUG
869         g_message ("%s: out of indices", __func__);
870 #endif
871                         
872         
873         return(TLS_OUT_OF_INDEXES);
874 }
875
876 #define MAKE_GC_ID(idx) (GUINT_TO_POINTER((idx)|(GetCurrentThreadId()<<8)))
877
878 /**
879  * TlsFree:
880  * @idx: The TLS index to free
881  *
882  * Releases a TLS index, making it available for reuse.  This call
883  * will delete any TLS data stored under index @idx in all threads.
884  *
885  * Return value: %TRUE on success, %FALSE otherwise.
886  */
887 gboolean TlsFree(guint32 idx)
888 {
889         int thr_ret;
890         
891 #ifdef TLS_DEBUG
892         g_message ("%s: freeing key %d", __func__, idx);
893 #endif
894
895         if (idx >= TLS_MINIMUM_AVAILABLE) {
896                 SetLastError (ERROR_INVALID_PARAMETER);
897                 return FALSE;
898         }
899
900         pthread_mutex_lock (&TLS_mutex);
901         
902         if(TLS_used[idx]==FALSE) {
903                 pthread_mutex_unlock (&TLS_mutex);
904                 SetLastError (ERROR_INVALID_PARAMETER);
905                 return(FALSE);
906         }
907         
908         TLS_used[idx]=FALSE;
909         thr_ret = pthread_key_delete(TLS_keys[idx]);
910         g_assert (thr_ret == 0);
911         
912         pthread_mutex_unlock (&TLS_mutex);
913         
914         return(TRUE);
915 }
916
917 /**
918  * TlsGetValue:
919  * @idx: The TLS index to retrieve
920  *
921  * Retrieves the TLS data stored under index @idx.
922  *
923  * Return value: The value stored in the TLS index @idx in the current
924  * thread, or %NULL on error.  As %NULL can be a valid return value,
925  * in this case GetLastError() returns %ERROR_SUCCESS.
926  */
927 gpointer TlsGetValue(guint32 idx)
928 {
929         gpointer ret;
930         
931 #ifdef TLS_DEBUG
932         g_message ("%s: looking up key %d", __func__, idx);
933 #endif
934         if (idx >= TLS_MINIMUM_AVAILABLE) {
935                 SetLastError (ERROR_INVALID_PARAMETER);
936                 return NULL;
937         }
938         ret=pthread_getspecific(TLS_keys[idx]);
939
940 #ifdef TLS_DEBUG
941         g_message ("%s: returning %p", __func__, ret);
942 #endif
943
944         SetLastError (ERROR_SUCCESS);
945         return(ret);
946 }
947
948 /**
949  * TlsSetValue:
950  * @idx: The TLS index to store
951  * @value: The value to store under index @idx
952  *
953  * Stores @value at TLS index @idx.
954  *
955  * Return value: %TRUE on success, %FALSE otherwise.
956  */
957 gboolean TlsSetValue(guint32 idx, gpointer value)
958 {
959         int ret;
960
961 #ifdef TLS_DEBUG
962         g_message ("%s: setting key %d to %p", __func__, idx, value);
963 #endif
964         if (idx >= TLS_MINIMUM_AVAILABLE) {
965                 SetLastError (ERROR_INVALID_PARAMETER);
966                 return FALSE;
967         }
968         
969         ret=pthread_setspecific(TLS_keys[idx], value);
970 #ifdef TLS_DEBUG
971         if(ret!=0)
972                 g_message ("%s: pthread_setspecific error: %s", __func__,
973                            strerror (ret));
974 #endif
975         
976         return(ret == 0);
977 }
978
979 /**
980  * SleepEx:
981  * @ms: The time in milliseconds to suspend for
982  * @alertable: if TRUE, the wait can be interrupted by an APC call
983  *
984  * Suspends execution of the current thread for @ms milliseconds.  A
985  * value of zero causes the thread to relinquish its time slice.  A
986  * value of %INFINITE causes an infinite delay.
987  */
988 guint32 SleepEx(guint32 ms, gboolean alertable)
989 {
990         struct timespec req, rem;
991         int ms_quot, ms_rem;
992         int ret;
993         gpointer current_thread = NULL;
994         
995 #ifdef DEBUG
996         g_message("%s: Sleeping for %d ms", __func__, ms);
997 #endif
998
999         if (alertable) {
1000                 current_thread = _wapi_thread_handle_from_id (pthread_self ());
1001                 if (current_thread == NULL) {
1002                         SetLastError (ERROR_INVALID_HANDLE);
1003                         return(WAIT_FAILED);
1004                 }
1005                 
1006                 if (_wapi_thread_apc_pending (current_thread)) {
1007                         _wapi_thread_dispatch_apc_queue (current_thread);
1008                         return WAIT_IO_COMPLETION;
1009                 }
1010         }
1011         
1012         if(ms==0) {
1013                 sched_yield();
1014                 return 0;
1015         }
1016         
1017         /* FIXME: check for INFINITE and sleep forever */
1018         ms_quot = ms / 1000;
1019         ms_rem = ms % 1000;
1020         
1021         req.tv_sec=ms_quot;
1022         req.tv_nsec=ms_rem*1000000;
1023         
1024 again:
1025         ret=nanosleep(&req, &rem);
1026
1027         if (alertable && _wapi_thread_apc_pending (current_thread)) {
1028                 _wapi_thread_dispatch_apc_queue (current_thread);
1029                 return WAIT_IO_COMPLETION;
1030         }
1031         
1032         if(ret==-1) {
1033                 /* Sleep interrupted with rem time remaining */
1034 #ifdef DEBUG
1035                 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
1036                 
1037                 g_message("%s: Still got %d ms to go", __func__, rems);
1038 #endif
1039                 req=rem;
1040                 goto again;
1041         }
1042
1043         return 0;
1044 }
1045
1046 void Sleep(guint32 ms)
1047 {
1048         SleepEx(ms, FALSE);
1049 }
1050
1051 gboolean _wapi_thread_cur_apc_pending (void)
1052 {
1053         gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
1054         
1055         if (thread == NULL) {
1056                 SetLastError (ERROR_INVALID_HANDLE);
1057                 return(FALSE);
1058         }
1059         
1060         return(_wapi_thread_apc_pending (thread));
1061 }
1062
1063 gboolean _wapi_thread_apc_pending (gpointer handle)
1064 {
1065         struct _WapiHandle_thread *thread;
1066         gboolean ok;
1067         
1068         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1069                                   (gpointer *)&thread);
1070         if (ok == FALSE) {
1071 #ifdef DEBUG
1072                 /* This might happen at process shutdown, as all
1073                  * thread handles are forcibly closed.  If a thread
1074                  * still has an alertable wait the final
1075                  * _wapi_thread_apc_pending check will probably fail
1076                  * to find the handle
1077                  */
1078                 g_warning ("%s: error looking up thread handle %p", __func__,
1079                            handle);
1080 #endif
1081                 return (FALSE);
1082         }
1083         
1084         return(thread->has_apc || thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE);
1085 }
1086
1087 gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
1088 {
1089         /* We don't support calling APC functions */
1090         struct _WapiHandle_thread *thread;
1091         gboolean ok;
1092         
1093         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1094                                   (gpointer *)&thread);
1095         g_assert (ok);
1096
1097         thread->has_apc = FALSE;
1098
1099         return(TRUE);
1100 }
1101
1102 /*
1103  * In this implementation, APC_CALLBACK is ignored.
1104  * if HANDLE refers to the current thread, the only effect this function has 
1105  * that if called from a signal handler, and the thread was waiting when receiving 
1106  * the signal, the wait will be broken after the signal handler returns.
1107  * In this case, this function is async-signal-safe.
1108  */
1109 guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer handle, 
1110                       gpointer param)
1111 {
1112         struct _WapiHandle_thread *thread_handle;
1113         gboolean ok;
1114         
1115         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1116                                   (gpointer *)&thread_handle);
1117         if (ok == FALSE) {
1118                 g_warning ("%s: error looking up thread handle %p", __func__,
1119                            handle);
1120                 return (0);
1121         }
1122
1123         g_assert (thread_handle->id == GetCurrentThreadId ());
1124         /* No locking/memory barriers are needed here */
1125         thread_handle->has_apc = TRUE;
1126         return(1);
1127 }
1128
1129 /*
1130  * wapi_interrupt_thread:
1131  *
1132  *   This is not part of the WIN32 API.
1133  * The state of the thread handle HANDLE is set to 'interrupted' which means that
1134  * if the thread calls one of the WaitFor functions, the function will return with 
1135  * WAIT_IO_COMPLETION instead of waiting. Also, if the thread was waiting when
1136  * this function was called, the wait will be broken.
1137  * It is possible that the wait functions return WAIT_IO_COMPLETION, but the
1138  * target thread didn't receive the interrupt signal yet, in this case it should
1139  * call the wait function again. This essentially means that the target thread will
1140  * busy wait until it is ready to process the interruption.
1141  * FIXME: get rid of QueueUserAPC and thread->has_apc, SleepEx seems to require it.
1142  */
1143 void wapi_interrupt_thread (gpointer thread_handle)
1144 {
1145         struct _WapiHandle_thread *thread;
1146         gboolean ok;
1147         gpointer prev_handle, wait_handle;
1148         guint32 idx;
1149         pthread_cond_t *cond;
1150         mono_mutex_t *mutex;
1151         
1152         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1153                                   (gpointer *)&thread);
1154         g_assert (ok);
1155
1156         while (TRUE) {
1157                 wait_handle = thread->wait_handle;
1158
1159                 /* 
1160                  * Atomically obtain the handle the thread is waiting on, and
1161                  * change it to a flag value.
1162                  */
1163                 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1164                                                                                                                  INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1165                 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1166                         /* Already interrupted */
1167                         return;
1168                 if (prev_handle == wait_handle)
1169                         break;
1170
1171                 /* Try again */
1172         }
1173
1174         WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread_handle->id););
1175
1176         if (!wait_handle)
1177                 /* Not waiting */
1178                 return;
1179
1180         /* If we reach here, then wait_handle is set to the flag value, 
1181          * which means that the target thread is either
1182          * - before the first CAS in timedwait, which means it won't enter the
1183          * wait.
1184          * - it is after the first CAS, so it is already waiting, or it will 
1185          * enter the wait, and it will be interrupted by the broadcast.
1186          */
1187         idx = GPOINTER_TO_UINT(wait_handle);
1188         cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
1189         mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
1190
1191         mono_mutex_lock (mutex);
1192         mono_cond_broadcast (cond);
1193         mono_mutex_unlock (mutex);
1194
1195         /* ref added by set_wait_handle */
1196         _wapi_handle_unref (wait_handle);
1197 }
1198
1199 /*
1200  * wapi_self_interrupt:
1201  *
1202  *   This is not part of the WIN32 API.
1203  * Set the 'interrupted' state of the calling thread if it's NULL.
1204  */
1205 void wapi_self_interrupt (void)
1206 {
1207         struct _WapiHandle_thread *thread;
1208         gboolean ok;
1209         gpointer prev_handle, wait_handle;
1210         gpointer thread_handle;
1211
1212
1213         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1214         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1215                                                           (gpointer *)&thread);
1216         g_assert (ok);
1217
1218         while (TRUE) {
1219                 wait_handle = thread->wait_handle;
1220
1221                 /*
1222                  * Atomically obtain the handle the thread is waiting on, and
1223                  * change it to a flag value.
1224                  */
1225                 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1226                                                                                                                  INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1227                 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1228                         /* Already interrupted */
1229                         goto cleanup;
1230                 /*We did not get interrupted*/
1231                 if (prev_handle == wait_handle)
1232                         break;
1233
1234                 /* Try again */
1235         }
1236
1237         if (wait_handle) {
1238                 /* ref added by set_wait_handle */
1239                 _wapi_handle_unref (wait_handle);
1240         }
1241
1242 cleanup:
1243         _wapi_handle_unref (thread_handle);
1244 }
1245
1246 /*
1247  * wapi_clear_interruption:
1248  *
1249  *   This is not part of the WIN32 API. 
1250  * Clear the 'interrupted' state of the calling thread.
1251  * This function is signal safe
1252  */
1253 void wapi_clear_interruption (void)
1254 {
1255         struct _WapiHandle_thread *thread;
1256         gboolean ok;
1257         gpointer prev_handle;
1258         gpointer thread_handle;
1259
1260         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1261         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1262                                                           (gpointer *)&thread);
1263         g_assert (ok);
1264
1265         prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1266                                                                                                          NULL, INTERRUPTION_REQUESTED_HANDLE);
1267         if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1268                 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1269
1270         _wapi_handle_unref (thread_handle);
1271 }
1272
1273 char* wapi_current_thread_desc ()
1274 {
1275         struct _WapiHandle_thread *thread;
1276         int i;
1277         gboolean ok;
1278         gpointer handle;
1279         gpointer thread_handle;
1280         GString* text;
1281         char *res;
1282
1283         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1284         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1285                                                           (gpointer *)&thread);
1286         if (!ok)
1287                 return g_strdup_printf ("thread handle %p state : lookup failure", thread_handle);
1288
1289         handle = thread->wait_handle;
1290         text = g_string_new (0);
1291         g_string_append_printf (text, "thread handle %p state : ", thread_handle);
1292
1293         if (!handle)
1294                 g_string_append_printf (text, "not waiting");
1295         else if (handle == INTERRUPTION_REQUESTED_HANDLE)
1296                 g_string_append_printf (text, "interrupted state");
1297         else
1298                 g_string_append_printf (text, "waiting on %p : %s ", handle, _wapi_handle_typename[_wapi_handle_type (handle)]);
1299         g_string_append_printf (text, " owns (");
1300         for (i = 0; i < thread->owned_mutexes->len; i++) {
1301                 gpointer mutex = g_ptr_array_index (thread->owned_mutexes, i);
1302                 if (i > 0)
1303                         g_string_append_printf (text, ", %p", mutex);
1304                 else
1305                         g_string_append_printf (text, "%p", mutex);
1306         }
1307         g_string_append_printf (text, ")");
1308
1309         res = text->str;
1310         g_string_free (text, FALSE);
1311         return res;
1312 }
1313
1314 /**
1315  * wapi_thread_set_wait_handle:
1316  *
1317  *   Set the wait handle for the current thread to HANDLE. Return TRUE on success, FALSE
1318  * if the thread is in interrupted state, and cannot start waiting.
1319  */
1320 gboolean wapi_thread_set_wait_handle (gpointer handle)
1321 {
1322         struct _WapiHandle_thread *thread;
1323         gboolean ok;
1324         gpointer prev_handle;
1325         gpointer thread_handle;
1326
1327         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1328         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1329                                                           (gpointer *)&thread);
1330         g_assert (ok);
1331
1332         prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1333                                                                                                          handle, NULL);
1334         _wapi_handle_unref (thread_handle);
1335
1336         if (prev_handle == NULL) {
1337                 /* thread->wait_handle acts as an additional reference to the handle */
1338                 _wapi_handle_ref (handle);
1339
1340                 WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
1341         } else {
1342                 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
1343                 WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
1344         }
1345
1346         return prev_handle == NULL;
1347 }
1348
1349 /**
1350  * wapi_thread_clear_wait_handle:
1351  *
1352  *   Clear the wait handle of the current thread.
1353  */
1354 void wapi_thread_clear_wait_handle (gpointer handle)
1355 {
1356         struct _WapiHandle_thread *thread;
1357         gboolean ok;
1358         gpointer prev_handle;
1359         gpointer thread_handle;
1360
1361         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1362         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1363                                                           (gpointer *)&thread);
1364         g_assert (ok);
1365
1366         prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1367                                                                                                          NULL, handle);
1368
1369         if (prev_handle == handle) {
1370                 _wapi_handle_unref (handle);
1371                 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1372         } else {
1373                 /*It can be NULL if it was asynchronously cleared*/
1374                 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE || prev_handle == NULL);
1375                 WAIT_DEBUG (printf ("%p: finished waiting.\n", GetCurrentThreadId ()););
1376         }
1377
1378         _wapi_handle_unref (thread_handle);
1379 }
1380
1381 void _wapi_thread_own_mutex (gpointer mutex)
1382 {
1383         struct _WapiHandle_thread *thread_handle;
1384         gboolean ok;
1385         gpointer thread;
1386         
1387         thread = _wapi_thread_handle_from_id (pthread_self ());
1388         if (thread == NULL) {
1389                 g_warning ("%s: error looking up thread by ID", __func__);
1390                 return;
1391         }
1392
1393         ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1394                                   (gpointer *)&thread_handle);
1395         if (ok == FALSE) {
1396                 g_warning ("%s: error looking up thread handle %p", __func__,
1397                            thread);
1398                 return;
1399         }
1400
1401         _wapi_handle_ref (mutex);
1402         
1403         g_ptr_array_add (thread_handle->owned_mutexes, mutex);
1404 }
1405
1406 void _wapi_thread_disown_mutex (gpointer mutex)
1407 {
1408         struct _WapiHandle_thread *thread_handle;
1409         gboolean ok;
1410         gpointer thread;
1411
1412         thread = _wapi_thread_handle_from_id (pthread_self ());
1413         if (thread == NULL) {
1414                 g_warning ("%s: error looking up thread by ID", __func__);
1415                 return;
1416         }
1417
1418         ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1419                                   (gpointer *)&thread_handle);
1420         if (ok == FALSE) {
1421                 g_warning ("%s: error looking up thread handle %p", __func__,
1422                            thread);
1423                 return;
1424         }
1425
1426         _wapi_handle_unref (mutex);
1427         
1428         g_ptr_array_remove (thread_handle->owned_mutexes, mutex);
1429 }