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/atomic.h>
33 #include <mono/utils/mono-mutex.h>
35 #ifdef HAVE_VALGRIND_MEMCHECK_H
36 #include <valgrind/memcheck.h>
40 #define DEBUG(...) g_message(__VA_ARGS__)
46 #define WAIT_DEBUG(code) do { code } while (0)
48 #define WAIT_DEBUG(code) do { } while (0)
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
54 static mono_once_t thread_hash_once = MONO_ONCE_INIT;
55 static pthread_key_t thread_hash_key;
57 struct _WapiHandleOps _wapi_thread_ops = {
62 NULL, /* special_wait */
66 static mono_once_t thread_ops_once=MONO_ONCE_INIT;
68 static void thread_ops_init (void)
70 _wapi_handle_register_capabilities (WAPI_HANDLE_THREAD,
71 WAPI_HANDLE_CAP_WAIT);
74 void _wapi_thread_cleanup (void)
78 ret = pthread_key_delete (thread_hash_key);
82 /* Called by thread_exit(), but maybe indirectly by
83 * mono_thread_manage() via mono_thread_signal_self() too
85 static void _wapi_thread_abandon_mutexes (gpointer handle)
87 struct _WapiHandle_thread *thread_handle;
90 pid_t pid = _wapi_getpid ();
91 pthread_t tid = pthread_self ();
93 DEBUG ("%s: Thread %p abandoning held mutexes", __func__, handle);
96 handle = _wapi_thread_handle_from_id (pthread_self ());
98 /* Something gone badly wrong... */
103 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
104 (gpointer *)&thread_handle);
106 g_warning ("%s: error looking up thread handle %p", __func__,
111 if (!pthread_equal (thread_handle->id, tid)) {
115 for (i = 0; i < thread_handle->owned_mutexes->len; i++) {
116 gpointer mutex = g_ptr_array_index (thread_handle->owned_mutexes, i);
118 _wapi_mutex_abandon (mutex, pid, tid);
119 _wapi_thread_disown_mutex (mutex);
124 _wapi_thread_set_termination_details (gpointer handle,
127 struct _WapiHandle_thread *thread_handle;
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
139 DEBUG ("%s: Thread %p terminating", __func__, handle);
141 _wapi_thread_abandon_mutexes (handle);
143 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
144 (gpointer *)&thread_handle);
146 g_warning ("%s: error looking up thread handle %p", __func__,
152 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
154 thr_ret = _wapi_handle_lock_handle (handle);
155 g_assert (thr_ret == 0);
157 g_ptr_array_free (thread_handle->owned_mutexes, TRUE);
159 _wapi_handle_set_signal_state (handle, TRUE, TRUE);
161 thr_ret = _wapi_handle_unlock_handle (handle);
162 g_assert (thr_ret == 0);
163 pthread_cleanup_pop (0);
165 DEBUG("%s: Recording thread handle %p id %ld status as %d",
166 __func__, handle, thread_handle->id, exitstatus);
168 /* The thread is no longer active, so unref it */
169 _wapi_handle_unref (handle);
172 void _wapi_thread_signal_self (guint32 exitstatus)
176 handle = _wapi_thread_handle_from_id (pthread_self ());
177 if (handle == NULL) {
178 /* Something gone badly wrong... */
182 _wapi_thread_set_termination_details (handle, exitstatus);
186 wapi_thread_handle_set_exited (gpointer handle, guint32 exitstatus)
188 _wapi_thread_set_termination_details (handle, exitstatus);
191 static void thread_hash_init(void)
195 thr_ret = pthread_key_create (&thread_hash_key, NULL);
196 g_assert (thr_ret == 0);
200 * wapi_create_thread_handle:
202 * Create a thread handle for the current thread.
205 wapi_create_thread_handle (void)
207 struct _WapiHandle_thread thread_handle = {0}, *thread;
211 mono_once (&thread_hash_once, thread_hash_init);
212 mono_once (&thread_ops_once, thread_ops_init);
214 thread_handle.owned_mutexes = g_ptr_array_new ();
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);
224 res = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
225 (gpointer *)&thread);
228 res = pthread_setspecific (thread_hash_key, handle);
231 thread->id = pthread_self ();
234 * Hold a reference while the thread is active, because we use
235 * the handle to store thread exit information
237 _wapi_handle_ref (handle);
239 DEBUG ("%s: started thread id %ld", __func__, thread->id);
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.
249 gpointer _wapi_thread_handle_from_id (pthread_t tid)
253 if (pthread_equal (tid, pthread_self ()) &&
254 (ret = pthread_getspecific (thread_hash_key)) != NULL) {
255 /* We know the handle */
257 DEBUG ("%s: Returning %p for self thread %ld from TLS",
263 DEBUG ("%s: Returning NULL for unknown or non-self thread %ld",
270 static gboolean find_thread_by_id (gpointer handle, gpointer user_data)
272 pthread_t tid = (pthread_t)user_data;
273 struct _WapiHandle_thread *thread_handle;
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);
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
289 DEBUG ("%s: looking at thread %ld from process %d", __func__, thread_handle->id, 0);
291 if (pthread_equal (thread_handle->id, tid)) {
292 DEBUG ("%s: found the thread we are looking for",
298 DEBUG ("%s: not found %ld, returning FALSE", __func__, tid);
303 /* NB tid is 32bit in MS API, but we need 64bit on amd64 and s390x
304 * (and probably others)
306 gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, gsize tid)
310 mono_once (&thread_hash_once, thread_hash_init);
311 mono_once (&thread_ops_once, thread_ops_init);
313 DEBUG ("%s: looking up thread %"G_GSIZE_FORMAT, __func__, tid);
315 ret = _wapi_thread_handle_from_id ((pthread_t)tid);
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 */
320 /* if _wapi_search_handle() returns a found handle, it
323 _wapi_handle_ref (ret);
326 DEBUG ("%s: returning thread handle %p", __func__, ret);
332 * GetCurrentThreadId:
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.
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 :)
342 gsize GetCurrentThreadId(void)
344 pthread_t tid = pthread_self();
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
357 gpointer _wapi_thread_duplicate ()
359 MonoThreadInfo *info;
361 mono_once (&thread_hash_once, thread_hash_init);
362 mono_once (&thread_ops_once, thread_ops_init);
364 info = mono_thread_info_current ();
366 info->handle = wapi_create_thread_handle ();
368 _wapi_handle_ref (info->handle);
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.
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).
384 gpointer GetCurrentThread(void)
386 mono_once(&thread_hash_once, thread_hash_init);
387 mono_once (&thread_ops_once, thread_ops_init);
389 return(_WAPI_THREAD_CURRENT);
394 * @ms: The time in milliseconds to suspend for
395 * @alertable: if TRUE, the wait can be interrupted by an APC call
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.
401 guint32 SleepEx(guint32 ms, gboolean alertable)
403 struct timespec req, rem;
406 gpointer current_thread = NULL;
408 DEBUG("%s: Sleeping for %d ms", __func__, ms);
411 current_thread = _wapi_thread_handle_from_id (pthread_self ());
412 if (current_thread == NULL) {
413 SetLastError (ERROR_INVALID_HANDLE);
417 if (_wapi_thread_apc_pending (current_thread)) {
418 _wapi_thread_dispatch_apc_queue (current_thread);
419 return WAIT_IO_COMPLETION;
428 /* FIXME: check for INFINITE and sleep forever */
433 req.tv_nsec=ms_rem*1000000;
436 memset (&rem, 0, sizeof (rem));
437 ret=nanosleep(&req, &rem);
439 if (alertable && _wapi_thread_apc_pending (current_thread)) {
440 _wapi_thread_dispatch_apc_queue (current_thread);
441 return WAIT_IO_COMPLETION;
445 /* Sleep interrupted with rem time remaining */
447 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
449 g_message("%s: Still got %d ms to go", __func__, rems);
458 void Sleep(guint32 ms)
463 gboolean _wapi_thread_cur_apc_pending (void)
465 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
467 if (thread == NULL) {
468 SetLastError (ERROR_INVALID_HANDLE);
472 return(_wapi_thread_apc_pending (thread));
475 gboolean _wapi_thread_apc_pending (gpointer handle)
477 struct _WapiHandle_thread *thread;
480 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
481 (gpointer *)&thread);
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
489 DEBUG ("%s: error looking up thread handle %p", __func__,
494 return(thread->has_apc || thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE);
497 gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
499 /* We don't support calling APC functions */
500 struct _WapiHandle_thread *thread;
503 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
504 (gpointer *)&thread);
507 thread->has_apc = FALSE;
513 * wapi_interrupt_self:
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.
520 wapi_thread_interrupt_self (void)
523 struct _WapiHandle_thread *thread_handle;
526 handle = _wapi_thread_handle_from_id (pthread_self ());
529 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
530 (gpointer *)&thread_handle);
532 g_warning ("%s: error looking up thread handle %p", __func__,
537 /* No locking/memory barriers are needed here */
538 thread_handle->has_apc = TRUE;
542 * wapi_interrupt_thread:
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.
555 void wapi_interrupt_thread (gpointer thread_handle)
557 gpointer wait_handle;
559 wait_handle = wapi_prepare_interrupt_thread (thread_handle);
560 wapi_finish_interrupt_thread (wait_handle);
563 gpointer wapi_prepare_interrupt_thread (gpointer thread_handle)
565 struct _WapiHandle_thread *thread;
567 gpointer prev_handle, wait_handle;
569 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
570 (gpointer *)&thread);
574 wait_handle = thread->wait_handle;
577 * Atomically obtain the handle the thread is waiting on, and
578 * change it to a flag value.
580 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
581 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
582 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
583 /* Already interrupted */
585 if (prev_handle == wait_handle)
591 WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread->id););
596 void wapi_finish_interrupt_thread (gpointer wait_handle)
598 pthread_cond_t *cond;
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
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.
613 idx = GPOINTER_TO_UINT(wait_handle);
614 cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
615 mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
617 mono_mutex_lock (mutex);
618 mono_cond_broadcast (cond);
619 mono_mutex_unlock (mutex);
621 /* ref added by set_wait_handle */
622 _wapi_handle_unref (wait_handle);
626 * wapi_self_interrupt:
628 * This is not part of the WIN32 API.
629 * Set the 'interrupted' state of the calling thread if it's NULL.
631 void wapi_self_interrupt (void)
633 gpointer wait_handle;
634 gpointer thread_handle;
636 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
637 wait_handle = wapi_prepare_interrupt_thread (thread_handle);
639 /* ref added by set_wait_handle */
640 _wapi_handle_unref (wait_handle);
642 _wapi_handle_unref (thread_handle);
646 * wapi_clear_interruption:
648 * This is not part of the WIN32 API.
649 * Clear the 'interrupted' state of the calling thread.
650 * This function is signal safe
652 void wapi_clear_interruption (void)
654 struct _WapiHandle_thread *thread;
656 gpointer prev_handle;
657 gpointer thread_handle;
659 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
660 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
661 (gpointer *)&thread);
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 ()););
669 _wapi_handle_unref (thread_handle);
672 char* wapi_current_thread_desc ()
674 struct _WapiHandle_thread *thread;
678 gpointer thread_handle;
682 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
683 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
684 (gpointer *)&thread);
686 return g_strdup_printf ("thread handle %p state : lookup failure", thread_handle);
688 handle = thread->wait_handle;
689 text = g_string_new (0);
690 g_string_append_printf (text, "thread handle %p state : ", thread_handle);
693 g_string_append_printf (text, "not waiting");
694 else if (handle == INTERRUPTION_REQUESTED_HANDLE)
695 g_string_append_printf (text, "interrupted state");
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);
702 g_string_append_printf (text, ", %p", mutex);
704 g_string_append_printf (text, "%p", mutex);
706 g_string_append_printf (text, ")");
709 g_string_free (text, FALSE);
714 * wapi_thread_set_wait_handle:
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.
719 gboolean wapi_thread_set_wait_handle (gpointer handle)
721 struct _WapiHandle_thread *thread;
723 gpointer prev_handle;
724 gpointer thread_handle;
726 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
727 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
728 (gpointer *)&thread);
731 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
733 _wapi_handle_unref (thread_handle);
735 if (prev_handle == NULL) {
736 /* thread->wait_handle acts as an additional reference to the handle */
737 _wapi_handle_ref (handle);
739 WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
741 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
742 WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
745 return prev_handle == NULL;
749 * wapi_thread_clear_wait_handle:
751 * Clear the wait handle of the current thread.
753 void wapi_thread_clear_wait_handle (gpointer handle)
755 struct _WapiHandle_thread *thread;
757 gpointer prev_handle;
758 gpointer thread_handle;
760 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
761 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
762 (gpointer *)&thread);
765 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
768 if (prev_handle == handle) {
769 _wapi_handle_unref (handle);
770 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
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 ()););
777 _wapi_handle_unref (thread_handle);
780 void _wapi_thread_own_mutex (gpointer mutex)
782 struct _WapiHandle_thread *thread_handle;
786 thread = _wapi_thread_handle_from_id (pthread_self ());
787 if (thread == NULL) {
788 g_warning ("%s: error looking up thread by ID", __func__);
792 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
793 (gpointer *)&thread_handle);
795 g_warning ("%s: error looking up thread handle %p", __func__,
800 _wapi_handle_ref (mutex);
802 g_ptr_array_add (thread_handle->owned_mutexes, mutex);
805 void _wapi_thread_disown_mutex (gpointer mutex)
807 struct _WapiHandle_thread *thread_handle;
811 thread = _wapi_thread_handle_from_id (pthread_self ());
812 if (thread == NULL) {
813 g_warning ("%s: error looking up thread by ID", __func__);
817 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
818 (gpointer *)&thread_handle);
820 g_warning ("%s: error looking up thread handle %p", __func__,
825 _wapi_handle_unref (mutex);
827 g_ptr_array_remove (thread_handle->owned_mutexes, mutex);