[runtime] Move thread attaching to mono-threads from the io-layer.
[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  * Copyright 2003-2011 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
10  */
11
12 #include <config.h>
13 #include <stdio.h>
14 #include <glib.h>
15 #include <string.h>
16 #include <pthread.h>
17 #include <signal.h>
18 #include <sched.h>
19 #include <sys/time.h>
20 #include <errno.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23
24 #include <mono/io-layer/wapi.h>
25 #include <mono/io-layer/wapi-private.h>
26 #include <mono/io-layer/handles-private.h>
27 #include <mono/io-layer/misc-private.h>
28 #include <mono/io-layer/thread-private.h>
29 #include <mono/io-layer/mutex-private.h>
30
31 #include <mono/utils/mono-threads.h>
32 #include <mono/utils/atomic.h>
33 #include <mono/utils/mono-mutex.h>
34
35 #ifdef HAVE_VALGRIND_MEMCHECK_H
36 #include <valgrind/memcheck.h>
37 #endif
38
39 #if 0
40 #define DEBUG(...) g_message(__VA_ARGS__)
41 #else
42 #define DEBUG(...)
43 #endif
44
45 #if 0
46 #define WAIT_DEBUG(code) do { code } while (0)
47 #else
48 #define WAIT_DEBUG(code) do { } while (0)
49 #endif
50
51 /* Hash threads with tids. I thought of using TLS for this, but that
52  * would have to set the data in the new thread, which is more hassle
53  */
54 static mono_once_t thread_hash_once = MONO_ONCE_INIT;
55 static pthread_key_t thread_hash_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
82 /* Called by thread_exit(), but maybe indirectly by
83  * mono_thread_manage() via mono_thread_signal_self() too
84  */
85 static void _wapi_thread_abandon_mutexes (gpointer handle)
86 {
87         struct _WapiHandle_thread *thread_handle;
88         gboolean ok;
89         int i;
90         pid_t pid = _wapi_getpid ();
91         pthread_t tid = pthread_self ();
92         
93         DEBUG ("%s: Thread %p abandoning held mutexes", __func__, handle);
94
95         if (handle == NULL) {
96                 handle = _wapi_thread_handle_from_id (pthread_self ());
97                 if (handle == NULL) {
98                         /* Something gone badly wrong... */
99                         return;
100                 }
101         }
102         
103         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
104                                   (gpointer *)&thread_handle);
105         if (ok == FALSE) {
106                 g_warning ("%s: error looking up thread handle %p", __func__,
107                            handle);
108                 return;
109         }
110         
111         if (!pthread_equal (thread_handle->id, tid)) {
112                 return;
113         }
114         
115         for (i = 0; i < thread_handle->owned_mutexes->len; i++) {
116                 gpointer mutex = g_ptr_array_index (thread_handle->owned_mutexes, i);
117                 
118                 _wapi_mutex_abandon (mutex, pid, tid);
119                 _wapi_thread_disown_mutex (mutex);
120         }
121 }
122
123 static void
124 _wapi_thread_set_termination_details (gpointer handle,
125                                            guint32 exitstatus)
126 {
127         struct _WapiHandle_thread *thread_handle;
128         gboolean ok;
129         int thr_ret;
130         
131         if (_wapi_handle_issignalled (handle) ||
132             _wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) {
133                 /* We must have already deliberately finished with
134                  * this thread, so don't do any more now
135                  */
136                 return;
137         }
138
139         DEBUG ("%s: Thread %p terminating", __func__, handle);
140
141         _wapi_thread_abandon_mutexes (handle);
142         
143         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
144                                   (gpointer *)&thread_handle);
145         if (ok == FALSE) {
146                 g_warning ("%s: error looking up thread handle %p", __func__,
147                            handle);
148
149                 return;
150         }
151         
152         pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
153                               handle);
154         thr_ret = _wapi_handle_lock_handle (handle);
155         g_assert (thr_ret == 0);
156         
157         g_ptr_array_free (thread_handle->owned_mutexes, TRUE);
158
159         _wapi_handle_set_signal_state (handle, TRUE, TRUE);
160
161         thr_ret = _wapi_handle_unlock_handle (handle);
162         g_assert (thr_ret == 0);
163         pthread_cleanup_pop (0);
164         
165         DEBUG("%s: Recording thread handle %p id %ld status as %d",
166                   __func__, handle, thread_handle->id, exitstatus);
167         
168         /* The thread is no longer active, so unref it */
169         _wapi_handle_unref (handle);
170 }
171
172 void _wapi_thread_signal_self (guint32 exitstatus)
173 {
174         gpointer handle;
175         
176         handle = _wapi_thread_handle_from_id (pthread_self ());
177         if (handle == NULL) {
178                 /* Something gone badly wrong... */
179                 return;
180         }
181         
182         _wapi_thread_set_termination_details (handle, exitstatus);
183 }
184
185 void
186 wapi_thread_handle_set_exited (gpointer handle, guint32 exitstatus)
187 {
188         _wapi_thread_set_termination_details (handle, exitstatus);
189 }
190
191 static void thread_hash_init(void)
192 {
193         int thr_ret;
194         
195         thr_ret = pthread_key_create (&thread_hash_key, NULL);
196         g_assert (thr_ret == 0);
197 }
198
199 /*
200  * wapi_create_thread_handle:
201  *
202  *   Create a thread handle for the current thread.
203  */
204 gpointer
205 wapi_create_thread_handle (void)
206 {
207         struct _WapiHandle_thread thread_handle = {0}, *thread;
208         gpointer handle;
209         int res;
210
211         mono_once (&thread_hash_once, thread_hash_init);
212         mono_once (&thread_ops_once, thread_ops_init);
213
214         thread_handle.owned_mutexes = g_ptr_array_new ();
215
216         handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
217         if (handle == _WAPI_HANDLE_INVALID) {
218                 g_warning ("%s: error creating thread handle", __func__);
219                 SetLastError (ERROR_GEN_FAILURE);
220                 
221                 return NULL;
222         }
223
224         res = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
225                                                            (gpointer *)&thread);
226         g_assert (res);
227
228         res = pthread_setspecific (thread_hash_key, handle);
229         g_assert (!res);
230
231         thread->id = pthread_self ();
232
233         /*
234          * Hold a reference while the thread is active, because we use
235          * the handle to store thread exit information
236          */
237         _wapi_handle_ref (handle);
238
239         DEBUG ("%s: started thread id %ld", __func__, thread->id);
240         
241         return handle;
242 }
243
244 /* The only time this function is called when tid != pthread_self ()
245  * is from OpenThread (), so we can fast-path most cases by just
246  * looking up the handle in TLS.  OpenThread () must cope with a NULL
247  * return and do a handle search in that case.
248  */
249 gpointer _wapi_thread_handle_from_id (pthread_t tid)
250 {
251         gpointer ret;
252
253         if (pthread_equal (tid, pthread_self ()) &&
254             (ret = pthread_getspecific (thread_hash_key)) != NULL) {
255                 /* We know the handle */
256
257                 DEBUG ("%s: Returning %p for self thread %ld from TLS",
258                            __func__, ret, tid);
259                 
260                 return(ret);
261         }
262         
263         DEBUG ("%s: Returning NULL for unknown or non-self thread %ld",
264                    __func__, tid);
265                 
266
267         return(NULL);
268 }
269
270 static gboolean find_thread_by_id (gpointer handle, gpointer user_data)
271 {
272         pthread_t tid = (pthread_t)user_data;
273         struct _WapiHandle_thread *thread_handle;
274         gboolean ok;
275         
276         /* Ignore threads that have already exited (ie they are signalled) */
277         if (_wapi_handle_issignalled (handle) == FALSE) {
278                 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
279                                           (gpointer *)&thread_handle);
280                 if (ok == FALSE) {
281                         /* It's possible that the handle has vanished
282                          * during the _wapi_search_handle before it
283                          * gets here, so don't spam the console with
284                          * warnings.
285                          */
286                         return(FALSE);
287                 }
288                 
289                 DEBUG ("%s: looking at thread %ld from process %d", __func__, thread_handle->id, 0);
290
291                 if (pthread_equal (thread_handle->id, tid)) {
292                         DEBUG ("%s: found the thread we are looking for",
293                                    __func__);
294                         return(TRUE);
295                 }
296         }
297         
298         DEBUG ("%s: not found %ld, returning FALSE", __func__, tid);
299         
300         return(FALSE);
301 }
302
303 /* NB tid is 32bit in MS API, but we need 64bit on amd64 and s390x
304  * (and probably others)
305  */
306 gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, gsize tid)
307 {
308         gpointer ret=NULL;
309         
310         mono_once (&thread_hash_once, thread_hash_init);
311         mono_once (&thread_ops_once, thread_ops_init);
312         
313         DEBUG ("%s: looking up thread %"G_GSIZE_FORMAT, __func__, tid);
314
315         ret = _wapi_thread_handle_from_id ((pthread_t)tid);
316         if (ret == NULL) {
317                 /* We need to search for this thread */
318                 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 */
319         } else {
320                 /* if _wapi_search_handle() returns a found handle, it
321                  * refs it itself
322                  */
323                 _wapi_handle_ref (ret);
324         }
325         
326         DEBUG ("%s: returning thread handle %p", __func__, ret);
327         
328         return(ret);
329 }
330
331 /**
332  * GetCurrentThreadId:
333  *
334  * Looks up the thread ID of the current thread.  This ID can be
335  * passed to OpenThread() to create a new handle on this thread.
336  *
337  * Return value: the thread ID.  NB this is defined as DWORD (ie 32
338  * bit) in the MS API, but we need to cope with 64 bit IDs for s390x
339  * and amd64.  This doesn't really break the API, it just embraces and
340  * extends it on 64bit platforms :)
341  */
342 gsize GetCurrentThreadId(void)
343 {
344         pthread_t tid = pthread_self();
345         
346 #ifdef PTHREAD_POINTER_ID
347         /* Don't use GPOINTER_TO_UINT here, it can't cope with
348          * sizeof(void *) > sizeof(uint) when a cast to uint would
349          * overflow
350          */
351         return((gsize)tid);
352 #else
353         return(tid);
354 #endif
355 }
356
357 gpointer _wapi_thread_duplicate ()
358 {
359         MonoThreadInfo *info;
360
361         mono_once (&thread_hash_once, thread_hash_init);
362         mono_once (&thread_ops_once, thread_ops_init);
363
364         info = mono_thread_info_current ();
365         if (!info->handle) {
366                 info->handle = wapi_create_thread_handle ();
367         } else {
368                 _wapi_handle_ref (info->handle);
369         }
370         return info->handle;
371 }
372
373 /**
374  * GetCurrentThread:
375  *
376  * Looks up the handle associated with the current thread.  Under
377  * Windows this is a pseudohandle, and must be duplicated with
378  * DuplicateHandle() for some operations.
379  *
380  * Return value: The current thread handle, or %NULL on failure.
381  * (Unknown whether Windows has a possible failure here.  It may be
382  * necessary to implement the pseudohandle-constant behaviour).
383  */
384 gpointer GetCurrentThread(void)
385 {
386         mono_once(&thread_hash_once, thread_hash_init);
387         mono_once (&thread_ops_once, thread_ops_init);
388         
389         return(_WAPI_THREAD_CURRENT);
390 }
391
392 /**
393  * SleepEx:
394  * @ms: The time in milliseconds to suspend for
395  * @alertable: if TRUE, the wait can be interrupted by an APC call
396  *
397  * Suspends execution of the current thread for @ms milliseconds.  A
398  * value of zero causes the thread to relinquish its time slice.  A
399  * value of %INFINITE causes an infinite delay.
400  */
401 guint32 SleepEx(guint32 ms, gboolean alertable)
402 {
403         struct timespec req, rem;
404         int ms_quot, ms_rem;
405         int ret;
406         gpointer current_thread = NULL;
407         
408         DEBUG("%s: Sleeping for %d ms", __func__, ms);
409
410         if (alertable) {
411                 current_thread = _wapi_thread_handle_from_id (pthread_self ());
412                 if (current_thread == NULL) {
413                         SetLastError (ERROR_INVALID_HANDLE);
414                         return(WAIT_FAILED);
415                 }
416                 
417                 if (_wapi_thread_apc_pending (current_thread)) {
418                         _wapi_thread_dispatch_apc_queue (current_thread);
419                         return WAIT_IO_COMPLETION;
420                 }
421         }
422         
423         if(ms==0) {
424                 sched_yield();
425                 return 0;
426         }
427         
428         /* FIXME: check for INFINITE and sleep forever */
429         ms_quot = ms / 1000;
430         ms_rem = ms % 1000;
431         
432         req.tv_sec=ms_quot;
433         req.tv_nsec=ms_rem*1000000;
434         
435 again:
436         memset (&rem, 0, sizeof (rem));
437         ret=nanosleep(&req, &rem);
438
439         if (alertable && _wapi_thread_apc_pending (current_thread)) {
440                 _wapi_thread_dispatch_apc_queue (current_thread);
441                 return WAIT_IO_COMPLETION;
442         }
443         
444         if(ret==-1) {
445                 /* Sleep interrupted with rem time remaining */
446 #ifdef DEBUG_ENABLED
447                 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
448                 
449                 g_message("%s: Still got %d ms to go", __func__, rems);
450 #endif
451                 req=rem;
452                 goto again;
453         }
454
455         return 0;
456 }
457
458 void Sleep(guint32 ms)
459 {
460         SleepEx(ms, FALSE);
461 }
462
463 gboolean _wapi_thread_cur_apc_pending (void)
464 {
465         gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
466         
467         if (thread == NULL) {
468                 SetLastError (ERROR_INVALID_HANDLE);
469                 return(FALSE);
470         }
471         
472         return(_wapi_thread_apc_pending (thread));
473 }
474
475 gboolean _wapi_thread_apc_pending (gpointer handle)
476 {
477         struct _WapiHandle_thread *thread;
478         gboolean ok;
479         
480         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
481                                   (gpointer *)&thread);
482         if (ok == FALSE) {
483                 /* This might happen at process shutdown, as all
484                  * thread handles are forcibly closed.  If a thread
485                  * still has an alertable wait the final
486                  * _wapi_thread_apc_pending check will probably fail
487                  * to find the handle
488                  */
489                 DEBUG ("%s: error looking up thread handle %p", __func__,
490                            handle);
491                 return (FALSE);
492         }
493         
494         return(thread->has_apc || thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE);
495 }
496
497 gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
498 {
499         /* We don't support calling APC functions */
500         struct _WapiHandle_thread *thread;
501         gboolean ok;
502         
503         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
504                                   (gpointer *)&thread);
505         g_assert (ok);
506
507         thread->has_apc = FALSE;
508
509         return(TRUE);
510 }
511
512 /*
513  * wapi_interrupt_self:
514  *
515  * If this function called from a signal handler, and the thread was waiting when receiving
516  * the signal, the wait will be broken after the signal handler returns.
517  * This function is async-signal-safe.
518  */
519 void
520 wapi_thread_interrupt_self (void)
521 {
522         HANDLE handle;
523         struct _WapiHandle_thread *thread_handle;
524         gboolean ok;
525         
526         handle = _wapi_thread_handle_from_id (pthread_self ());
527         g_assert (handle);
528
529         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
530                                   (gpointer *)&thread_handle);
531         if (ok == FALSE) {
532                 g_warning ("%s: error looking up thread handle %p", __func__,
533                            handle);
534                 return;
535         }
536
537         /* No locking/memory barriers are needed here */
538         thread_handle->has_apc = TRUE;
539 }
540
541 /*
542  * wapi_interrupt_thread:
543  *
544  *   This is not part of the WIN32 API.
545  * The state of the thread handle HANDLE is set to 'interrupted' which means that
546  * if the thread calls one of the WaitFor functions, the function will return with 
547  * WAIT_IO_COMPLETION instead of waiting. Also, if the thread was waiting when
548  * this function was called, the wait will be broken.
549  * It is possible that the wait functions return WAIT_IO_COMPLETION, but the
550  * target thread didn't receive the interrupt signal yet, in this case it should
551  * call the wait function again. This essentially means that the target thread will
552  * busy wait until it is ready to process the interruption.
553  * FIXME: get rid of QueueUserAPC and thread->has_apc, SleepEx seems to require it.
554  */
555 void wapi_interrupt_thread (gpointer thread_handle)
556 {
557         gpointer wait_handle;
558
559         wait_handle = wapi_prepare_interrupt_thread (thread_handle);
560         wapi_finish_interrupt_thread (wait_handle);
561 }
562
563 gpointer wapi_prepare_interrupt_thread (gpointer thread_handle)
564 {
565         struct _WapiHandle_thread *thread;
566         gboolean ok;
567         gpointer prev_handle, wait_handle;
568         
569         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
570                                   (gpointer *)&thread);
571         g_assert (ok);
572
573         while (TRUE) {
574                 wait_handle = thread->wait_handle;
575
576                 /* 
577                  * Atomically obtain the handle the thread is waiting on, and
578                  * change it to a flag value.
579                  */
580                 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
581                                                                                                                  INTERRUPTION_REQUESTED_HANDLE, wait_handle);
582                 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
583                         /* Already interrupted */
584                         return 0;
585                 if (prev_handle == wait_handle)
586                         break;
587
588                 /* Try again */
589         }
590
591         WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread->id););
592
593         return wait_handle;
594 }
595
596 void wapi_finish_interrupt_thread (gpointer wait_handle)
597 {
598         pthread_cond_t *cond;
599         mono_mutex_t *mutex;
600         guint32 idx;
601
602         if (!wait_handle)
603                 /* Not waiting */
604                 return;
605
606         /* If we reach here, then wait_handle is set to the flag value, 
607          * which means that the target thread is either
608          * - before the first CAS in timedwait, which means it won't enter the
609          * wait.
610          * - it is after the first CAS, so it is already waiting, or it will 
611          * enter the wait, and it will be interrupted by the broadcast.
612          */
613         idx = GPOINTER_TO_UINT(wait_handle);
614         cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
615         mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
616
617         mono_mutex_lock (mutex);
618         mono_cond_broadcast (cond);
619         mono_mutex_unlock (mutex);
620
621         /* ref added by set_wait_handle */
622         _wapi_handle_unref (wait_handle);
623 }
624
625 /*
626  * wapi_self_interrupt:
627  *
628  *   This is not part of the WIN32 API.
629  * Set the 'interrupted' state of the calling thread if it's NULL.
630  */
631 void wapi_self_interrupt (void)
632 {
633         gpointer wait_handle;
634         gpointer thread_handle;
635
636         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
637         wait_handle = wapi_prepare_interrupt_thread (thread_handle);
638         if (wait_handle)
639                 /* ref added by set_wait_handle */
640                 _wapi_handle_unref (wait_handle);
641
642         _wapi_handle_unref (thread_handle);
643 }
644
645 /*
646  * wapi_clear_interruption:
647  *
648  *   This is not part of the WIN32 API. 
649  * Clear the 'interrupted' state of the calling thread.
650  * This function is signal safe
651  */
652 void wapi_clear_interruption (void)
653 {
654         struct _WapiHandle_thread *thread;
655         gboolean ok;
656         gpointer prev_handle;
657         gpointer thread_handle;
658
659         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
660         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
661                                                           (gpointer *)&thread);
662         g_assert (ok);
663
664         prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
665                                                                                                          NULL, INTERRUPTION_REQUESTED_HANDLE);
666         if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
667                 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
668
669         _wapi_handle_unref (thread_handle);
670 }
671
672 char* wapi_current_thread_desc ()
673 {
674         struct _WapiHandle_thread *thread;
675         int i;
676         gboolean ok;
677         gpointer handle;
678         gpointer thread_handle;
679         GString* text;
680         char *res;
681
682         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
683         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
684                                                           (gpointer *)&thread);
685         if (!ok)
686                 return g_strdup_printf ("thread handle %p state : lookup failure", thread_handle);
687
688         handle = thread->wait_handle;
689         text = g_string_new (0);
690         g_string_append_printf (text, "thread handle %p state : ", thread_handle);
691
692         if (!handle)
693                 g_string_append_printf (text, "not waiting");
694         else if (handle == INTERRUPTION_REQUESTED_HANDLE)
695                 g_string_append_printf (text, "interrupted state");
696         else
697                 g_string_append_printf (text, "waiting on %p : %s ", handle, _wapi_handle_typename[_wapi_handle_type (handle)]);
698         g_string_append_printf (text, " owns (");
699         for (i = 0; i < thread->owned_mutexes->len; i++) {
700                 gpointer mutex = g_ptr_array_index (thread->owned_mutexes, i);
701                 if (i > 0)
702                         g_string_append_printf (text, ", %p", mutex);
703                 else
704                         g_string_append_printf (text, "%p", mutex);
705         }
706         g_string_append_printf (text, ")");
707
708         res = text->str;
709         g_string_free (text, FALSE);
710         return res;
711 }
712
713 /**
714  * wapi_thread_set_wait_handle:
715  *
716  *   Set the wait handle for the current thread to HANDLE. Return TRUE on success, FALSE
717  * if the thread is in interrupted state, and cannot start waiting.
718  */
719 gboolean wapi_thread_set_wait_handle (gpointer handle)
720 {
721         struct _WapiHandle_thread *thread;
722         gboolean ok;
723         gpointer prev_handle;
724         gpointer thread_handle;
725
726         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
727         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
728                                                           (gpointer *)&thread);
729         g_assert (ok);
730
731         prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
732                                                                                                          handle, NULL);
733         _wapi_handle_unref (thread_handle);
734
735         if (prev_handle == NULL) {
736                 /* thread->wait_handle acts as an additional reference to the handle */
737                 _wapi_handle_ref (handle);
738
739                 WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
740         } else {
741                 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
742                 WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
743         }
744
745         return prev_handle == NULL;
746 }
747
748 /**
749  * wapi_thread_clear_wait_handle:
750  *
751  *   Clear the wait handle of the current thread.
752  */
753 void wapi_thread_clear_wait_handle (gpointer handle)
754 {
755         struct _WapiHandle_thread *thread;
756         gboolean ok;
757         gpointer prev_handle;
758         gpointer thread_handle;
759
760         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
761         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
762                                                           (gpointer *)&thread);
763         g_assert (ok);
764
765         prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
766                                                                                                          NULL, handle);
767
768         if (prev_handle == handle) {
769                 _wapi_handle_unref (handle);
770                 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
771         } else {
772                 /*It can be NULL if it was asynchronously cleared*/
773                 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE || prev_handle == NULL);
774                 WAIT_DEBUG (printf ("%p: finished waiting.\n", GetCurrentThreadId ()););
775         }
776
777         _wapi_handle_unref (thread_handle);
778 }
779
780 void _wapi_thread_own_mutex (gpointer mutex)
781 {
782         struct _WapiHandle_thread *thread_handle;
783         gboolean ok;
784         gpointer thread;
785         
786         thread = _wapi_thread_handle_from_id (pthread_self ());
787         if (thread == NULL) {
788                 g_warning ("%s: error looking up thread by ID", __func__);
789                 return;
790         }
791
792         ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
793                                   (gpointer *)&thread_handle);
794         if (ok == FALSE) {
795                 g_warning ("%s: error looking up thread handle %p", __func__,
796                            thread);
797                 return;
798         }
799
800         _wapi_handle_ref (mutex);
801         
802         g_ptr_array_add (thread_handle->owned_mutexes, mutex);
803 }
804
805 void _wapi_thread_disown_mutex (gpointer mutex)
806 {
807         struct _WapiHandle_thread *thread_handle;
808         gboolean ok;
809         gpointer thread;
810
811         thread = _wapi_thread_handle_from_id (pthread_self ());
812         if (thread == NULL) {
813                 g_warning ("%s: error looking up thread by ID", __func__);
814                 return;
815         }
816
817         ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
818                                   (gpointer *)&thread_handle);
819         if (ok == FALSE) {
820                 g_warning ("%s: error looking up thread handle %p", __func__,
821                            thread);
822                 return;
823         }
824
825         _wapi_handle_unref (mutex);
826         
827         g_ptr_array_remove (thread_handle->owned_mutexes, mutex);
828 }