2 * threads.c: Thread handles
5 * Dick Porter (dick@ximian.com)
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)
21 #include <sys/types.h>
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>
31 #include <mono/utils/mono-threads.h>
32 #include <mono/utils/gc_wrapper.h>
33 #include <mono/utils/atomic.h>
34 #include <mono/utils/mono-mutex.h>
36 #ifdef HAVE_VALGRIND_MEMCHECK_H
37 #include <valgrind/memcheck.h>
41 #define DEBUG(...) g_message(__VA_ARGS__)
47 #define WAIT_DEBUG(code) do { code } while (0)
49 #define WAIT_DEBUG(code) do { } while (0)
52 /* Hash threads with tids. I thought of using TLS for this, but that
53 * would have to set the data in the new thread, which is more hassle
55 static mono_once_t thread_hash_once = MONO_ONCE_INIT;
56 static pthread_key_t thread_hash_key;
58 /* This key is used with attached threads and a destructor to signal
59 * when attached threads exit, as they don't have the thread_exit()
62 static pthread_key_t thread_attached_key;
64 struct _WapiHandleOps _wapi_thread_ops = {
69 NULL, /* special_wait */
73 static mono_once_t thread_ops_once=MONO_ONCE_INIT;
75 static void thread_ops_init (void)
77 _wapi_handle_register_capabilities (WAPI_HANDLE_THREAD,
78 WAPI_HANDLE_CAP_WAIT);
81 void _wapi_thread_cleanup (void)
85 ret = pthread_key_delete (thread_hash_key);
88 ret = pthread_key_delete (thread_attached_key);
92 /* Called by thread_exit(), but maybe indirectly by
93 * mono_thread_manage() via mono_thread_signal_self() too
95 static void _wapi_thread_abandon_mutexes (gpointer handle)
97 struct _WapiHandle_thread *thread_handle;
100 pid_t pid = _wapi_getpid ();
101 pthread_t tid = pthread_self ();
103 DEBUG ("%s: Thread %p abandoning held mutexes", __func__, handle);
105 if (handle == NULL) {
106 handle = _wapi_thread_handle_from_id (pthread_self ());
107 if (handle == NULL) {
108 /* Something gone badly wrong... */
113 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
114 (gpointer *)&thread_handle);
116 g_warning ("%s: error looking up thread handle %p", __func__,
121 if (!pthread_equal (thread_handle->id, tid)) {
125 for (i = 0; i < thread_handle->owned_mutexes->len; i++) {
126 gpointer mutex = g_ptr_array_index (thread_handle->owned_mutexes, i);
128 _wapi_mutex_abandon (mutex, pid, tid);
129 _wapi_thread_disown_mutex (mutex);
133 void _wapi_thread_set_termination_details (gpointer handle,
136 struct _WapiHandle_thread *thread_handle;
140 if (_wapi_handle_issignalled (handle) ||
141 _wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) {
142 /* We must have already deliberately finished with
143 * this thread, so don't do any more now
148 DEBUG ("%s: Thread %p terminating", __func__, handle);
150 _wapi_thread_abandon_mutexes (handle);
152 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
153 (gpointer *)&thread_handle);
155 g_warning ("%s: error looking up thread handle %p", __func__,
161 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
163 thr_ret = _wapi_handle_lock_handle (handle);
164 g_assert (thr_ret == 0);
166 thread_handle->exitstatus = exitstatus;
167 thread_handle->state = THREAD_STATE_EXITED;
168 g_ptr_array_free (thread_handle->owned_mutexes, TRUE);
170 _wapi_handle_set_signal_state (handle, TRUE, TRUE);
172 thr_ret = _wapi_handle_unlock_handle (handle);
173 g_assert (thr_ret == 0);
174 pthread_cleanup_pop (0);
176 DEBUG("%s: Recording thread handle %p id %ld status as %d",
177 __func__, handle, thread_handle->id, exitstatus);
179 /* The thread is no longer active, so unref it */
180 _wapi_handle_unref (handle);
183 void _wapi_thread_signal_self (guint32 exitstatus)
187 handle = _wapi_thread_handle_from_id (pthread_self ());
188 if (handle == NULL) {
189 /* Something gone badly wrong... */
193 _wapi_thread_set_termination_details (handle, exitstatus);
197 wapi_thread_handle_set_exited (gpointer handle, guint32 exitstatus)
199 _wapi_thread_set_termination_details (handle, exitstatus);
202 static void thread_attached_exit (gpointer handle)
204 /* Drop the extra reference we take in thread_attach, now this
208 _wapi_thread_set_termination_details (handle, 0);
211 static void thread_hash_init(void)
215 thr_ret = pthread_key_create (&thread_hash_key, NULL);
216 g_assert (thr_ret == 0);
218 thr_ret = pthread_key_create (&thread_attached_key,
219 thread_attached_exit);
220 g_assert (thr_ret == 0);
224 * wapi_create_thread_handle:
226 * Create a thread handle for the current thread.
229 wapi_create_thread_handle (void)
231 struct _WapiHandle_thread thread_handle = {0}, *thread;
235 mono_once (&thread_hash_once, thread_hash_init);
236 mono_once (&thread_ops_once, thread_ops_init);
238 thread_handle.state = THREAD_STATE_START;
239 thread_handle.owned_mutexes = g_ptr_array_new ();
241 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
242 if (handle == _WAPI_HANDLE_INVALID) {
243 g_warning ("%s: error creating thread handle", __func__);
244 SetLastError (ERROR_GEN_FAILURE);
249 res = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
250 (gpointer *)&thread);
253 thread->handle = handle;
255 res = pthread_setspecific (thread_hash_key, handle);
258 thread->id = pthread_self ();
261 * Hold a reference while the thread is active, because we use
262 * the handle to store thread exit information
264 _wapi_handle_ref (handle);
266 DEBUG ("%s: started thread id %ld", __func__, thread->id);
271 /* The only time this function is called when tid != pthread_self ()
272 * is from OpenThread (), so we can fast-path most cases by just
273 * looking up the handle in TLS. OpenThread () must cope with a NULL
274 * return and do a handle search in that case.
276 gpointer _wapi_thread_handle_from_id (pthread_t tid)
280 if (pthread_equal (tid, pthread_self ()) &&
281 (ret = pthread_getspecific (thread_hash_key)) != NULL) {
282 /* We know the handle */
284 DEBUG ("%s: Returning %p for self thread %ld from TLS",
290 DEBUG ("%s: Returning NULL for unknown or non-self thread %ld",
297 static gboolean find_thread_by_id (gpointer handle, gpointer user_data)
299 pthread_t tid = (pthread_t)user_data;
300 struct _WapiHandle_thread *thread_handle;
303 /* Ignore threads that have already exited (ie they are signalled) */
304 if (_wapi_handle_issignalled (handle) == FALSE) {
305 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
306 (gpointer *)&thread_handle);
308 /* It's possible that the handle has vanished
309 * during the _wapi_search_handle before it
310 * gets here, so don't spam the console with
316 DEBUG ("%s: looking at thread %ld from process %d", __func__, thread_handle->id, 0);
318 if (pthread_equal (thread_handle->id, tid)) {
319 DEBUG ("%s: found the thread we are looking for",
325 DEBUG ("%s: not found %ld, returning FALSE", __func__, tid);
330 /* NB tid is 32bit in MS API, but we need 64bit on amd64 and s390x
331 * (and probably others)
333 gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, gsize tid)
337 mono_once (&thread_hash_once, thread_hash_init);
338 mono_once (&thread_ops_once, thread_ops_init);
340 DEBUG ("%s: looking up thread %"G_GSIZE_FORMAT, __func__, tid);
342 ret = _wapi_thread_handle_from_id ((pthread_t)tid);
344 /* We need to search for this thread */
345 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 */
347 /* if _wapi_search_handle() returns a found handle, it
350 _wapi_handle_ref (ret);
353 DEBUG ("%s: returning thread handle %p", __func__, ret);
359 * GetCurrentThreadId:
361 * Looks up the thread ID of the current thread. This ID can be
362 * passed to OpenThread() to create a new handle on this thread.
364 * Return value: the thread ID. NB this is defined as DWORD (ie 32
365 * bit) in the MS API, but we need to cope with 64 bit IDs for s390x
366 * and amd64. This doesn't really break the API, it just embraces and
367 * extends it on 64bit platforms :)
369 gsize GetCurrentThreadId(void)
371 pthread_t tid = pthread_self();
373 #ifdef PTHREAD_POINTER_ID
374 /* Don't use GPOINTER_TO_UINT here, it can't cope with
375 * sizeof(void *) > sizeof(uint) when a cast to uint would
384 static gpointer thread_attach(gsize *tid)
386 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
391 mono_once (&thread_hash_once, thread_hash_init);
392 mono_once (&thread_ops_once, thread_ops_init);
394 thread_handle.state = THREAD_STATE_START;
395 thread_handle.owned_mutexes = g_ptr_array_new ();
397 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
398 if (handle == _WAPI_HANDLE_INVALID) {
399 g_warning ("%s: error creating thread handle", __func__);
401 SetLastError (ERROR_GEN_FAILURE);
405 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
407 thr_ret = _wapi_handle_lock_handle (handle);
408 g_assert (thr_ret == 0);
410 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
411 (gpointer *)&thread_handle_p);
413 g_warning ("%s: error looking up thread handle %p", __func__,
416 SetLastError (ERROR_GEN_FAILURE);
420 /* Hold a reference while the thread is active, because we use
421 * the handle to store thread exit information
423 _wapi_handle_ref (handle);
425 thread_handle_p->handle = handle;
426 thread_handle_p->id = pthread_self ();
428 thr_ret = pthread_setspecific (thread_hash_key, (void *)handle);
429 g_assert (thr_ret == 0);
431 thr_ret = pthread_setspecific (thread_attached_key, (void *)handle);
432 g_assert (thr_ret == 0);
434 DEBUG("%s: Attached thread handle %p ID %ld", __func__, handle,
435 thread_handle_p->id);
438 #ifdef PTHREAD_POINTER_ID
439 /* Don't use GPOINTER_TO_UINT here, it can't cope with
440 * sizeof(void *) > sizeof(uint) when a cast to uint
443 *tid = (gsize)(thread_handle_p->id);
445 *tid = thread_handle_p->id;
450 thr_ret = _wapi_handle_unlock_handle (handle);
451 g_assert (thr_ret == 0);
452 pthread_cleanup_pop (0);
457 gpointer _wapi_thread_duplicate ()
461 mono_once (&thread_hash_once, thread_hash_init);
462 mono_once (&thread_ops_once, thread_ops_init);
464 ret = _wapi_thread_handle_from_id (pthread_self ());
466 ret = thread_attach (NULL);
468 _wapi_handle_ref (ret);
477 * Looks up the handle associated with the current thread. Under
478 * Windows this is a pseudohandle, and must be duplicated with
479 * DuplicateHandle() for some operations.
481 * Return value: The current thread handle, or %NULL on failure.
482 * (Unknown whether Windows has a possible failure here. It may be
483 * necessary to implement the pseudohandle-constant behaviour).
485 gpointer GetCurrentThread(void)
487 mono_once(&thread_hash_once, thread_hash_init);
488 mono_once (&thread_ops_once, thread_ops_init);
490 return(_WAPI_THREAD_CURRENT);
495 * @ms: The time in milliseconds to suspend for
496 * @alertable: if TRUE, the wait can be interrupted by an APC call
498 * Suspends execution of the current thread for @ms milliseconds. A
499 * value of zero causes the thread to relinquish its time slice. A
500 * value of %INFINITE causes an infinite delay.
502 guint32 SleepEx(guint32 ms, gboolean alertable)
504 struct timespec req, rem;
507 gpointer current_thread = NULL;
509 DEBUG("%s: Sleeping for %d ms", __func__, ms);
512 current_thread = _wapi_thread_handle_from_id (pthread_self ());
513 if (current_thread == NULL) {
514 SetLastError (ERROR_INVALID_HANDLE);
518 if (_wapi_thread_apc_pending (current_thread)) {
519 _wapi_thread_dispatch_apc_queue (current_thread);
520 return WAIT_IO_COMPLETION;
529 /* FIXME: check for INFINITE and sleep forever */
534 req.tv_nsec=ms_rem*1000000;
537 memset (&rem, 0, sizeof (rem));
538 ret=nanosleep(&req, &rem);
540 if (alertable && _wapi_thread_apc_pending (current_thread)) {
541 _wapi_thread_dispatch_apc_queue (current_thread);
542 return WAIT_IO_COMPLETION;
546 /* Sleep interrupted with rem time remaining */
548 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
550 g_message("%s: Still got %d ms to go", __func__, rems);
559 void Sleep(guint32 ms)
564 gboolean _wapi_thread_cur_apc_pending (void)
566 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
568 if (thread == NULL) {
569 SetLastError (ERROR_INVALID_HANDLE);
573 return(_wapi_thread_apc_pending (thread));
576 gboolean _wapi_thread_apc_pending (gpointer handle)
578 struct _WapiHandle_thread *thread;
581 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
582 (gpointer *)&thread);
584 /* This might happen at process shutdown, as all
585 * thread handles are forcibly closed. If a thread
586 * still has an alertable wait the final
587 * _wapi_thread_apc_pending check will probably fail
590 DEBUG ("%s: error looking up thread handle %p", __func__,
595 return(thread->has_apc || thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE);
598 gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
600 /* We don't support calling APC functions */
601 struct _WapiHandle_thread *thread;
604 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
605 (gpointer *)&thread);
608 thread->has_apc = FALSE;
614 * wapi_interrupt_self:
616 * If this function called from a signal handler, and the thread was waiting when receiving
617 * the signal, the wait will be broken after the signal handler returns.
618 * This function is async-signal-safe.
621 wapi_thread_interrupt_self (void)
624 struct _WapiHandle_thread *thread_handle;
627 handle = _wapi_thread_handle_from_id (pthread_self ());
630 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
631 (gpointer *)&thread_handle);
633 g_warning ("%s: error looking up thread handle %p", __func__,
638 /* No locking/memory barriers are needed here */
639 thread_handle->has_apc = TRUE;
643 * wapi_interrupt_thread:
645 * This is not part of the WIN32 API.
646 * The state of the thread handle HANDLE is set to 'interrupted' which means that
647 * if the thread calls one of the WaitFor functions, the function will return with
648 * WAIT_IO_COMPLETION instead of waiting. Also, if the thread was waiting when
649 * this function was called, the wait will be broken.
650 * It is possible that the wait functions return WAIT_IO_COMPLETION, but the
651 * target thread didn't receive the interrupt signal yet, in this case it should
652 * call the wait function again. This essentially means that the target thread will
653 * busy wait until it is ready to process the interruption.
654 * FIXME: get rid of QueueUserAPC and thread->has_apc, SleepEx seems to require it.
656 void wapi_interrupt_thread (gpointer thread_handle)
658 struct _WapiHandle_thread *thread;
660 gpointer prev_handle, wait_handle;
662 pthread_cond_t *cond;
665 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
666 (gpointer *)&thread);
670 wait_handle = thread->wait_handle;
673 * Atomically obtain the handle the thread is waiting on, and
674 * change it to a flag value.
676 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
677 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
678 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
679 /* Already interrupted */
681 if (prev_handle == wait_handle)
687 WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread->id););
693 /* If we reach here, then wait_handle is set to the flag value,
694 * which means that the target thread is either
695 * - before the first CAS in timedwait, which means it won't enter the
697 * - it is after the first CAS, so it is already waiting, or it will
698 * enter the wait, and it will be interrupted by the broadcast.
700 idx = GPOINTER_TO_UINT(wait_handle);
701 cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
702 mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
704 mono_mutex_lock (mutex);
705 mono_cond_broadcast (cond);
706 mono_mutex_unlock (mutex);
708 /* ref added by set_wait_handle */
709 _wapi_handle_unref (wait_handle);
713 gpointer wapi_prepare_interrupt_thread (gpointer thread_handle)
715 struct _WapiHandle_thread *thread;
717 gpointer prev_handle, wait_handle;
719 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
720 (gpointer *)&thread);
724 wait_handle = thread->wait_handle;
727 * Atomically obtain the handle the thread is waiting on, and
728 * change it to a flag value.
730 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
731 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
732 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
733 /* Already interrupted */
735 if (prev_handle == wait_handle)
741 WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread->id););
746 void wapi_finish_interrupt_thread (gpointer wait_handle)
748 pthread_cond_t *cond;
756 /* If we reach here, then wait_handle is set to the flag value,
757 * which means that the target thread is either
758 * - before the first CAS in timedwait, which means it won't enter the
760 * - it is after the first CAS, so it is already waiting, or it will
761 * enter the wait, and it will be interrupted by the broadcast.
763 idx = GPOINTER_TO_UINT(wait_handle);
764 cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
765 mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
767 mono_mutex_lock (mutex);
768 mono_cond_broadcast (cond);
769 mono_mutex_unlock (mutex);
771 /* ref added by set_wait_handle */
772 _wapi_handle_unref (wait_handle);
777 * wapi_self_interrupt:
779 * This is not part of the WIN32 API.
780 * Set the 'interrupted' state of the calling thread if it's NULL.
782 void wapi_self_interrupt (void)
784 struct _WapiHandle_thread *thread;
786 gpointer prev_handle, wait_handle;
787 gpointer thread_handle;
790 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
791 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
792 (gpointer *)&thread);
796 wait_handle = thread->wait_handle;
799 * Atomically obtain the handle the thread is waiting on, and
800 * change it to a flag value.
802 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
803 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
804 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
805 /* Already interrupted */
807 /*We did not get interrupted*/
808 if (prev_handle == wait_handle)
815 /* ref added by set_wait_handle */
816 _wapi_handle_unref (wait_handle);
820 _wapi_handle_unref (thread_handle);
824 * wapi_clear_interruption:
826 * This is not part of the WIN32 API.
827 * Clear the 'interrupted' state of the calling thread.
828 * This function is signal safe
830 void wapi_clear_interruption (void)
832 struct _WapiHandle_thread *thread;
834 gpointer prev_handle;
835 gpointer thread_handle;
837 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
838 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
839 (gpointer *)&thread);
842 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
843 NULL, INTERRUPTION_REQUESTED_HANDLE);
844 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
845 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
847 _wapi_handle_unref (thread_handle);
850 char* wapi_current_thread_desc ()
852 struct _WapiHandle_thread *thread;
856 gpointer thread_handle;
860 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
861 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
862 (gpointer *)&thread);
864 return g_strdup_printf ("thread handle %p state : lookup failure", thread_handle);
866 handle = thread->wait_handle;
867 text = g_string_new (0);
868 g_string_append_printf (text, "thread handle %p state : ", thread_handle);
871 g_string_append_printf (text, "not waiting");
872 else if (handle == INTERRUPTION_REQUESTED_HANDLE)
873 g_string_append_printf (text, "interrupted state");
875 g_string_append_printf (text, "waiting on %p : %s ", handle, _wapi_handle_typename[_wapi_handle_type (handle)]);
876 g_string_append_printf (text, " owns (");
877 for (i = 0; i < thread->owned_mutexes->len; i++) {
878 gpointer mutex = g_ptr_array_index (thread->owned_mutexes, i);
880 g_string_append_printf (text, ", %p", mutex);
882 g_string_append_printf (text, "%p", mutex);
884 g_string_append_printf (text, ")");
887 g_string_free (text, FALSE);
892 * wapi_thread_set_wait_handle:
894 * Set the wait handle for the current thread to HANDLE. Return TRUE on success, FALSE
895 * if the thread is in interrupted state, and cannot start waiting.
897 gboolean wapi_thread_set_wait_handle (gpointer handle)
899 struct _WapiHandle_thread *thread;
901 gpointer prev_handle;
902 gpointer thread_handle;
904 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
905 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
906 (gpointer *)&thread);
909 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
911 _wapi_handle_unref (thread_handle);
913 if (prev_handle == NULL) {
914 /* thread->wait_handle acts as an additional reference to the handle */
915 _wapi_handle_ref (handle);
917 WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
919 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
920 WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
923 return prev_handle == NULL;
927 * wapi_thread_clear_wait_handle:
929 * Clear the wait handle of the current thread.
931 void wapi_thread_clear_wait_handle (gpointer handle)
933 struct _WapiHandle_thread *thread;
935 gpointer prev_handle;
936 gpointer thread_handle;
938 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
939 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
940 (gpointer *)&thread);
943 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
946 if (prev_handle == handle) {
947 _wapi_handle_unref (handle);
948 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
950 /*It can be NULL if it was asynchronously cleared*/
951 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE || prev_handle == NULL);
952 WAIT_DEBUG (printf ("%p: finished waiting.\n", GetCurrentThreadId ()););
955 _wapi_handle_unref (thread_handle);
958 void _wapi_thread_own_mutex (gpointer mutex)
960 struct _WapiHandle_thread *thread_handle;
964 thread = _wapi_thread_handle_from_id (pthread_self ());
965 if (thread == NULL) {
966 g_warning ("%s: error looking up thread by ID", __func__);
970 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
971 (gpointer *)&thread_handle);
973 g_warning ("%s: error looking up thread handle %p", __func__,
978 _wapi_handle_ref (mutex);
980 g_ptr_array_add (thread_handle->owned_mutexes, mutex);
983 void _wapi_thread_disown_mutex (gpointer mutex)
985 struct _WapiHandle_thread *thread_handle;
989 thread = _wapi_thread_handle_from_id (pthread_self ());
990 if (thread == NULL) {
991 g_warning ("%s: error looking up thread by ID", __func__);
995 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
996 (gpointer *)&thread_handle);
998 g_warning ("%s: error looking up thread handle %p", __func__,
1003 _wapi_handle_unref (mutex);
1005 g_ptr_array_remove (thread_handle->owned_mutexes, mutex);