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 MONO_SEM_DESTROY (&thread_handle->suspend_sem);
169 g_ptr_array_free (thread_handle->owned_mutexes, TRUE);
171 _wapi_handle_set_signal_state (handle, TRUE, TRUE);
173 thr_ret = _wapi_handle_unlock_handle (handle);
174 g_assert (thr_ret == 0);
175 pthread_cleanup_pop (0);
177 DEBUG("%s: Recording thread handle %p id %ld status as %d",
178 __func__, handle, thread_handle->id, exitstatus);
180 /* The thread is no longer active, so unref it */
181 _wapi_handle_unref (handle);
184 void _wapi_thread_signal_self (guint32 exitstatus)
188 handle = _wapi_thread_handle_from_id (pthread_self ());
189 if (handle == NULL) {
190 /* Something gone badly wrong... */
194 _wapi_thread_set_termination_details (handle, exitstatus);
197 /* Called by the thread creation code as a thread is finishing up, and
200 static void thread_exit (guint32 exitstatus, gpointer handle) G_GNUC_NORETURN;
201 #if defined(__native_client__)
202 void nacl_shutdown_gc_thread(void);
204 static void thread_exit (guint32 exitstatus, gpointer handle)
206 #if defined(__native_client__)
207 nacl_shutdown_gc_thread();
209 _wapi_thread_set_termination_details (handle, exitstatus);
211 /* Call pthread_exit() to call destructors and really exit the
214 mono_gc_pthread_exit (NULL);
217 static void thread_attached_exit (gpointer handle)
219 /* Drop the extra reference we take in thread_attach, now this
223 _wapi_thread_set_termination_details (handle, 0);
226 static void thread_hash_init(void)
230 thr_ret = pthread_key_create (&thread_hash_key, NULL);
231 g_assert (thr_ret == 0);
233 thr_ret = pthread_key_create (&thread_attached_key,
234 thread_attached_exit);
235 g_assert (thr_ret == 0);
238 static void _wapi_thread_suspend (struct _WapiHandle_thread *thread)
240 g_assert (pthread_equal (thread->id, pthread_self ()));
242 while (MONO_SEM_WAIT (&thread->suspend_sem) != 0 &&
246 static void _wapi_thread_resume (struct _WapiHandle_thread *thread)
248 MONO_SEM_POST (&thread->suspend_sem);
251 static void *thread_start_routine (gpointer args) G_GNUC_NORETURN;
252 static void *thread_start_routine (gpointer args)
254 struct _WapiHandle_thread *thread = (struct _WapiHandle_thread *)args;
257 if (!(thread->create_flags & CREATE_NO_DETACH)) {
258 thr_ret = mono_gc_pthread_detach (pthread_self ());
259 g_assert (thr_ret == 0);
262 thr_ret = pthread_setspecific (thread_hash_key,
263 (void *)thread->handle);
265 /* This is only supposed to happen when Mono is
266 shutting down. We cannot assert on it, though,
267 because we must not depend on metadata, which is
268 where the shutdown code is.
270 This is a race condition which arises because
271 pthreads don't allow creation of suspended threads.
272 Once Mono is set to shut down no new thread is
273 allowed to start, even though threads may still be
274 created. We emulate suspended threads in this
275 function by calling _wapi_thread_suspend() below.
277 So it can happen that even though Mono is already
278 shutting down we still end up here, and at this
279 point the thread_hash_key might already be
281 mono_gc_pthread_exit (NULL);
284 DEBUG ("%s: started thread id %ld", __func__, thread->id);
286 /* We set it again here since passing &thread->id to pthread_create is racy
287 as the thread can start running before the value is set.*/
288 thread->id = pthread_self ();
290 if (thread->create_flags & CREATE_SUSPENDED) {
291 _wapi_thread_suspend (thread);
294 thread_exit (thread->start_routine (thread->start_arg),
298 /* Even though we tell gcc that this function doesn't return,
299 * other compilers won't see that.
307 * @security: Ignored for now.
308 * @stacksize: the size in bytes of the new thread's stack. Use 0 to
309 * default to the normal stack size. (Ignored for now).
310 * @start: The function that the new thread should start with
311 * @param: The parameter to give to @start.
312 * @create: If 0, the new thread is ready to run immediately. If
313 * %CREATE_SUSPENDED, the new thread will be in the suspended state,
314 * requiring a ResumeThread() call to continue running.
315 * @tid: If non-NULL, the ID of the new thread is stored here. NB
316 * this is defined as a DWORD (ie 32bit) in the MS API, but we need to
317 * cope with 64 bit IDs for s390x and amd64.
319 * Creates a new threading handle.
321 * Return value: a new handle, or NULL
323 gpointer CreateThread(WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 stacksize,
324 WapiThreadStart start, gpointer param, guint32 create,
327 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
334 gpointer ct_ret = NULL;
336 mono_once (&thread_hash_once, thread_hash_init);
337 mono_once (&thread_ops_once, thread_ops_init);
343 thread_handle.state = THREAD_STATE_START;
344 thread_handle.owned_mutexes = g_ptr_array_new ();
345 thread_handle.create_flags = create;
346 thread_handle.start_routine = start;
347 thread_handle.start_arg = param;
349 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
350 if (handle == _WAPI_HANDLE_INVALID) {
351 g_warning ("%s: error creating thread handle", __func__);
352 SetLastError (ERROR_GEN_FAILURE);
357 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
359 thr_ret = _wapi_handle_lock_handle (handle);
360 g_assert (thr_ret == 0);
362 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
363 (gpointer *)&thread_handle_p);
365 g_warning ("%s: error looking up thread handle %p", __func__,
367 SetLastError (ERROR_GEN_FAILURE);
372 /* Hold a reference while the thread is active, because we use
373 * the handle to store thread exit information
375 _wapi_handle_ref (handle);
377 /* Set a 2M stack size. This is the default on Linux, but BSD
378 * needs it. (The original bug report from Martin Dvorak <md@9ll.cz>
379 * set the size to 2M-4k. I don't know why it's short by 4k, so
380 * I'm leaving it as 2M until I'm told differently.)
382 thr_ret = pthread_attr_init(&attr);
383 g_assert (thr_ret == 0);
385 /* defaults of 2Mb for 32bits and 4Mb for 64bits */
386 /* temporarily changed to use 1 MB: this allows more threads
387 * to be used, as well as using less virtual memory and so
388 * more is available for the GC heap.
391 #if HAVE_VALGRIND_MEMCHECK_H
392 if (RUNNING_ON_VALGRIND) {
395 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
398 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
402 #ifdef PTHREAD_STACK_MIN
403 if (stacksize < PTHREAD_STACK_MIN)
404 stacksize = PTHREAD_STACK_MIN;
407 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
408 thr_ret = pthread_attr_setstacksize(&attr, stacksize);
409 g_assert (thr_ret == 0);
412 MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
413 thread_handle_p->handle = handle;
416 ret = mono_threads_pthread_create (&thread_handle_p->id, &attr,
417 thread_start_routine, (void *)thread_handle_p);
420 g_warning ("%s: Error creating native thread handle %s (%d)", __func__,
421 strerror (ret), ret);
422 SetLastError (ERROR_GEN_FAILURE);
424 /* Two, because of the reference we took above */
431 DEBUG("%s: Started thread handle %p ID %ld", __func__, handle,
432 thread_handle_p->id);
435 #ifdef PTHREAD_POINTER_ID
436 /* Don't use GPOINTER_TO_UINT here, it can't cope with
437 * sizeof(void *) > sizeof(uint) when a cast to uint
440 *tid = (gsize)(thread_handle_p->id);
442 *tid = thread_handle_p->id;
447 thr_ret = _wapi_handle_unlock_handle (handle);
448 g_assert (thr_ret == 0);
449 pthread_cleanup_pop (0);
451 /* Must not call _wapi_handle_unref() with the shared handles
454 for (i = 0; i < unrefs; i++) {
455 _wapi_handle_unref (handle);
461 /* The only time this function is called when tid != pthread_self ()
462 * is from OpenThread (), so we can fast-path most cases by just
463 * looking up the handle in TLS. OpenThread () must cope with a NULL
464 * return and do a handle search in that case.
466 gpointer _wapi_thread_handle_from_id (pthread_t tid)
470 if (pthread_equal (tid, pthread_self ()) &&
471 (ret = pthread_getspecific (thread_hash_key)) != NULL) {
472 /* We know the handle */
474 DEBUG ("%s: Returning %p for self thread %ld from TLS",
480 DEBUG ("%s: Returning NULL for unknown or non-self thread %ld",
487 static gboolean find_thread_by_id (gpointer handle, gpointer user_data)
489 pthread_t tid = (pthread_t)user_data;
490 struct _WapiHandle_thread *thread_handle;
493 /* Ignore threads that have already exited (ie they are signalled) */
494 if (_wapi_handle_issignalled (handle) == FALSE) {
495 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
496 (gpointer *)&thread_handle);
498 /* It's possible that the handle has vanished
499 * during the _wapi_search_handle before it
500 * gets here, so don't spam the console with
506 DEBUG ("%s: looking at thread %ld from process %d", __func__, thread_handle->id, 0);
508 if (pthread_equal (thread_handle->id, tid)) {
509 DEBUG ("%s: found the thread we are looking for",
515 DEBUG ("%s: not found %ld, returning FALSE", __func__, tid);
520 /* NB tid is 32bit in MS API, but we need 64bit on amd64 and s390x
521 * (and probably others)
523 gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, gsize tid)
527 mono_once (&thread_hash_once, thread_hash_init);
528 mono_once (&thread_ops_once, thread_ops_init);
530 DEBUG ("%s: looking up thread %"G_GSIZE_FORMAT, __func__, tid);
532 ret = _wapi_thread_handle_from_id ((pthread_t)tid);
534 /* We need to search for this thread */
535 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 */
537 /* if _wapi_search_handle() returns a found handle, it
540 _wapi_handle_ref (ret);
543 DEBUG ("%s: returning thread handle %p", __func__, ret);
550 * @exitcode: Sets the thread's exit code, which can be read from
551 * another thread with GetExitCodeThread().
553 * Terminates the calling thread. A thread can also exit by returning
554 * from its start function. When the last thread in a process
555 * terminates, the process itself terminates.
557 void ExitThread(guint32 exitcode)
559 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
561 if (thread != NULL) {
562 thread_exit(exitcode, thread);
564 /* Just blow this thread away */
565 mono_gc_pthread_exit (NULL);
571 * @handle: The thread handle to query
572 * @exitcode: The thread @handle exit code is stored here
574 * Finds the exit code of @handle, and stores it in @exitcode. If the
575 * thread @handle is still running, the value stored is %STILL_ACTIVE.
577 * Return value: %TRUE, or %FALSE on error.
579 gboolean GetExitCodeThread(gpointer handle, guint32 *exitcode)
581 struct _WapiHandle_thread *thread_handle;
584 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
585 (gpointer *)&thread_handle);
587 g_warning ("%s: error looking up thread handle %p", __func__,
592 DEBUG ("%s: Finding exit status for thread handle %p id %ld",
593 __func__, handle, thread_handle->id);
595 if (exitcode == NULL) {
596 DEBUG ("%s: Nowhere to store exit code", __func__);
600 if (thread_handle->state != THREAD_STATE_EXITED) {
601 DEBUG ("%s: Thread still active (state %d, exited is %d)",
602 __func__, thread_handle->state,
603 THREAD_STATE_EXITED);
604 *exitcode = STILL_ACTIVE;
608 *exitcode = thread_handle->exitstatus;
614 * GetCurrentThreadId:
616 * Looks up the thread ID of the current thread. This ID can be
617 * passed to OpenThread() to create a new handle on this thread.
619 * Return value: the thread ID. NB this is defined as DWORD (ie 32
620 * bit) in the MS API, but we need to cope with 64 bit IDs for s390x
621 * and amd64. This doesn't really break the API, it just embraces and
622 * extends it on 64bit platforms :)
624 gsize GetCurrentThreadId(void)
626 pthread_t tid = pthread_self();
628 #ifdef PTHREAD_POINTER_ID
629 /* Don't use GPOINTER_TO_UINT here, it can't cope with
630 * sizeof(void *) > sizeof(uint) when a cast to uint would
639 static gpointer thread_attach(gsize *tid)
641 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
646 mono_once (&thread_hash_once, thread_hash_init);
647 mono_once (&thread_ops_once, thread_ops_init);
649 thread_handle.state = THREAD_STATE_START;
650 thread_handle.owned_mutexes = g_ptr_array_new ();
652 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
653 if (handle == _WAPI_HANDLE_INVALID) {
654 g_warning ("%s: error creating thread handle", __func__);
656 SetLastError (ERROR_GEN_FAILURE);
660 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
662 thr_ret = _wapi_handle_lock_handle (handle);
663 g_assert (thr_ret == 0);
665 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
666 (gpointer *)&thread_handle_p);
668 g_warning ("%s: error looking up thread handle %p", __func__,
671 SetLastError (ERROR_GEN_FAILURE);
675 /* Hold a reference while the thread is active, because we use
676 * the handle to store thread exit information
678 _wapi_handle_ref (handle);
680 /* suspend_sem is not used for attached threads, but
681 * thread_exit() might try to destroy it
683 MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
684 thread_handle_p->handle = handle;
685 thread_handle_p->id = pthread_self ();
687 thr_ret = pthread_setspecific (thread_hash_key, (void *)handle);
688 g_assert (thr_ret == 0);
690 thr_ret = pthread_setspecific (thread_attached_key, (void *)handle);
691 g_assert (thr_ret == 0);
693 DEBUG("%s: Attached thread handle %p ID %ld", __func__, handle,
694 thread_handle_p->id);
697 #ifdef PTHREAD_POINTER_ID
698 /* Don't use GPOINTER_TO_UINT here, it can't cope with
699 * sizeof(void *) > sizeof(uint) when a cast to uint
702 *tid = (gsize)(thread_handle_p->id);
704 *tid = thread_handle_p->id;
709 thr_ret = _wapi_handle_unlock_handle (handle);
710 g_assert (thr_ret == 0);
711 pthread_cleanup_pop (0);
716 gpointer _wapi_thread_duplicate ()
720 mono_once (&thread_hash_once, thread_hash_init);
721 mono_once (&thread_ops_once, thread_ops_init);
723 ret = _wapi_thread_handle_from_id (pthread_self ());
725 ret = thread_attach (NULL);
727 _wapi_handle_ref (ret);
736 * Looks up the handle associated with the current thread. Under
737 * Windows this is a pseudohandle, and must be duplicated with
738 * DuplicateHandle() for some operations.
740 * Return value: The current thread handle, or %NULL on failure.
741 * (Unknown whether Windows has a possible failure here. It may be
742 * necessary to implement the pseudohandle-constant behaviour).
744 gpointer GetCurrentThread(void)
746 mono_once(&thread_hash_once, thread_hash_init);
747 mono_once (&thread_ops_once, thread_ops_init);
749 return(_WAPI_THREAD_CURRENT);
754 * @handle: the thread handle to resume
756 * Decrements the suspend count of thread @handle. A thread can only
757 * run if its suspend count is zero.
759 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
761 guint32 ResumeThread(gpointer handle)
763 struct _WapiHandle_thread *thread_handle;
766 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
767 (gpointer *)&thread_handle);
769 g_warning ("%s: error looking up thread handle %p", __func__,
775 /* This is still a kludge that only copes with starting a
776 * thread that was suspended on create, so don't bother with
777 * the suspend count crap yet
779 _wapi_thread_resume (thread_handle);
785 * @handle: the thread handle to suspend
787 * Increments the suspend count of thread @handle. A thread can only
788 * run if its suspend count is zero.
790 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
792 guint32 SuspendThread(gpointer handle)
799 * @ms: The time in milliseconds to suspend for
800 * @alertable: if TRUE, the wait can be interrupted by an APC call
802 * Suspends execution of the current thread for @ms milliseconds. A
803 * value of zero causes the thread to relinquish its time slice. A
804 * value of %INFINITE causes an infinite delay.
806 guint32 SleepEx(guint32 ms, gboolean alertable)
808 struct timespec req, rem;
811 gpointer current_thread = NULL;
813 DEBUG("%s: Sleeping for %d ms", __func__, ms);
816 current_thread = _wapi_thread_handle_from_id (pthread_self ());
817 if (current_thread == NULL) {
818 SetLastError (ERROR_INVALID_HANDLE);
822 if (_wapi_thread_apc_pending (current_thread)) {
823 _wapi_thread_dispatch_apc_queue (current_thread);
824 return WAIT_IO_COMPLETION;
833 /* FIXME: check for INFINITE and sleep forever */
838 req.tv_nsec=ms_rem*1000000;
841 memset (&rem, 0, sizeof (rem));
842 ret=nanosleep(&req, &rem);
844 if (alertable && _wapi_thread_apc_pending (current_thread)) {
845 _wapi_thread_dispatch_apc_queue (current_thread);
846 return WAIT_IO_COMPLETION;
850 /* Sleep interrupted with rem time remaining */
852 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
854 g_message("%s: Still got %d ms to go", __func__, rems);
863 void Sleep(guint32 ms)
868 gboolean _wapi_thread_cur_apc_pending (void)
870 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
872 if (thread == NULL) {
873 SetLastError (ERROR_INVALID_HANDLE);
877 return(_wapi_thread_apc_pending (thread));
880 gboolean _wapi_thread_apc_pending (gpointer handle)
882 struct _WapiHandle_thread *thread;
885 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
886 (gpointer *)&thread);
888 /* This might happen at process shutdown, as all
889 * thread handles are forcibly closed. If a thread
890 * still has an alertable wait the final
891 * _wapi_thread_apc_pending check will probably fail
894 DEBUG ("%s: error looking up thread handle %p", __func__,
899 return(thread->has_apc || thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE);
902 gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
904 /* We don't support calling APC functions */
905 struct _WapiHandle_thread *thread;
908 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
909 (gpointer *)&thread);
912 thread->has_apc = FALSE;
918 * In this implementation, APC_CALLBACK is ignored.
919 * if HANDLE refers to the current thread, the only effect this function has
920 * that if called from a signal handler, and the thread was waiting when receiving
921 * the signal, the wait will be broken after the signal handler returns.
922 * In this case, this function is async-signal-safe.
924 guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer handle,
927 struct _WapiHandle_thread *thread_handle;
930 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
931 (gpointer *)&thread_handle);
933 g_warning ("%s: error looking up thread handle %p", __func__,
938 g_assert (thread_handle->id == (pthread_t)GetCurrentThreadId ());
939 /* No locking/memory barriers are needed here */
940 thread_handle->has_apc = TRUE;
945 * wapi_interrupt_thread:
947 * This is not part of the WIN32 API.
948 * The state of the thread handle HANDLE is set to 'interrupted' which means that
949 * if the thread calls one of the WaitFor functions, the function will return with
950 * WAIT_IO_COMPLETION instead of waiting. Also, if the thread was waiting when
951 * this function was called, the wait will be broken.
952 * It is possible that the wait functions return WAIT_IO_COMPLETION, but the
953 * target thread didn't receive the interrupt signal yet, in this case it should
954 * call the wait function again. This essentially means that the target thread will
955 * busy wait until it is ready to process the interruption.
956 * FIXME: get rid of QueueUserAPC and thread->has_apc, SleepEx seems to require it.
958 void wapi_interrupt_thread (gpointer thread_handle)
960 struct _WapiHandle_thread *thread;
962 gpointer prev_handle, wait_handle;
964 pthread_cond_t *cond;
967 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
968 (gpointer *)&thread);
972 wait_handle = thread->wait_handle;
975 * Atomically obtain the handle the thread is waiting on, and
976 * change it to a flag value.
978 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
979 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
980 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
981 /* Already interrupted */
983 if (prev_handle == wait_handle)
989 WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread->id););
995 /* If we reach here, then wait_handle is set to the flag value,
996 * which means that the target thread is either
997 * - before the first CAS in timedwait, which means it won't enter the
999 * - it is after the first CAS, so it is already waiting, or it will
1000 * enter the wait, and it will be interrupted by the broadcast.
1002 idx = GPOINTER_TO_UINT(wait_handle);
1003 cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
1004 mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
1006 mono_mutex_lock (mutex);
1007 mono_cond_broadcast (cond);
1008 mono_mutex_unlock (mutex);
1010 /* ref added by set_wait_handle */
1011 _wapi_handle_unref (wait_handle);
1015 gpointer wapi_prepare_interrupt_thread (gpointer thread_handle)
1017 struct _WapiHandle_thread *thread;
1019 gpointer prev_handle, wait_handle;
1021 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1022 (gpointer *)&thread);
1026 wait_handle = thread->wait_handle;
1029 * Atomically obtain the handle the thread is waiting on, and
1030 * change it to a flag value.
1032 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1033 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1034 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1035 /* Already interrupted */
1037 if (prev_handle == wait_handle)
1043 WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread->id););
1048 void wapi_finish_interrupt_thread (gpointer wait_handle)
1050 pthread_cond_t *cond;
1051 mono_mutex_t *mutex;
1058 /* If we reach here, then wait_handle is set to the flag value,
1059 * which means that the target thread is either
1060 * - before the first CAS in timedwait, which means it won't enter the
1062 * - it is after the first CAS, so it is already waiting, or it will
1063 * enter the wait, and it will be interrupted by the broadcast.
1065 idx = GPOINTER_TO_UINT(wait_handle);
1066 cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
1067 mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
1069 mono_mutex_lock (mutex);
1070 mono_cond_broadcast (cond);
1071 mono_mutex_unlock (mutex);
1073 /* ref added by set_wait_handle */
1074 _wapi_handle_unref (wait_handle);
1079 * wapi_self_interrupt:
1081 * This is not part of the WIN32 API.
1082 * Set the 'interrupted' state of the calling thread if it's NULL.
1084 void wapi_self_interrupt (void)
1086 struct _WapiHandle_thread *thread;
1088 gpointer prev_handle, wait_handle;
1089 gpointer thread_handle;
1092 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1093 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1094 (gpointer *)&thread);
1098 wait_handle = thread->wait_handle;
1101 * Atomically obtain the handle the thread is waiting on, and
1102 * change it to a flag value.
1104 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1105 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1106 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1107 /* Already interrupted */
1109 /*We did not get interrupted*/
1110 if (prev_handle == wait_handle)
1117 /* ref added by set_wait_handle */
1118 _wapi_handle_unref (wait_handle);
1122 _wapi_handle_unref (thread_handle);
1126 * wapi_clear_interruption:
1128 * This is not part of the WIN32 API.
1129 * Clear the 'interrupted' state of the calling thread.
1130 * This function is signal safe
1132 void wapi_clear_interruption (void)
1134 struct _WapiHandle_thread *thread;
1136 gpointer prev_handle;
1137 gpointer thread_handle;
1139 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1140 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1141 (gpointer *)&thread);
1144 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1145 NULL, INTERRUPTION_REQUESTED_HANDLE);
1146 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1147 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1149 _wapi_handle_unref (thread_handle);
1152 char* wapi_current_thread_desc ()
1154 struct _WapiHandle_thread *thread;
1158 gpointer thread_handle;
1162 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1163 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1164 (gpointer *)&thread);
1166 return g_strdup_printf ("thread handle %p state : lookup failure", thread_handle);
1168 handle = thread->wait_handle;
1169 text = g_string_new (0);
1170 g_string_append_printf (text, "thread handle %p state : ", thread_handle);
1173 g_string_append_printf (text, "not waiting");
1174 else if (handle == INTERRUPTION_REQUESTED_HANDLE)
1175 g_string_append_printf (text, "interrupted state");
1177 g_string_append_printf (text, "waiting on %p : %s ", handle, _wapi_handle_typename[_wapi_handle_type (handle)]);
1178 g_string_append_printf (text, " owns (");
1179 for (i = 0; i < thread->owned_mutexes->len; i++) {
1180 gpointer mutex = g_ptr_array_index (thread->owned_mutexes, i);
1182 g_string_append_printf (text, ", %p", mutex);
1184 g_string_append_printf (text, "%p", mutex);
1186 g_string_append_printf (text, ")");
1189 g_string_free (text, FALSE);
1194 * wapi_thread_set_wait_handle:
1196 * Set the wait handle for the current thread to HANDLE. Return TRUE on success, FALSE
1197 * if the thread is in interrupted state, and cannot start waiting.
1199 gboolean wapi_thread_set_wait_handle (gpointer handle)
1201 struct _WapiHandle_thread *thread;
1203 gpointer prev_handle;
1204 gpointer thread_handle;
1206 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1207 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1208 (gpointer *)&thread);
1211 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1213 _wapi_handle_unref (thread_handle);
1215 if (prev_handle == NULL) {
1216 /* thread->wait_handle acts as an additional reference to the handle */
1217 _wapi_handle_ref (handle);
1219 WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
1221 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
1222 WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
1225 return prev_handle == NULL;
1229 * wapi_thread_clear_wait_handle:
1231 * Clear the wait handle of the current thread.
1233 void wapi_thread_clear_wait_handle (gpointer handle)
1235 struct _WapiHandle_thread *thread;
1237 gpointer prev_handle;
1238 gpointer thread_handle;
1240 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1241 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1242 (gpointer *)&thread);
1245 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1248 if (prev_handle == handle) {
1249 _wapi_handle_unref (handle);
1250 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1252 /*It can be NULL if it was asynchronously cleared*/
1253 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE || prev_handle == NULL);
1254 WAIT_DEBUG (printf ("%p: finished waiting.\n", GetCurrentThreadId ()););
1257 _wapi_handle_unref (thread_handle);
1260 void _wapi_thread_own_mutex (gpointer mutex)
1262 struct _WapiHandle_thread *thread_handle;
1266 thread = _wapi_thread_handle_from_id (pthread_self ());
1267 if (thread == NULL) {
1268 g_warning ("%s: error looking up thread by ID", __func__);
1272 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1273 (gpointer *)&thread_handle);
1275 g_warning ("%s: error looking up thread handle %p", __func__,
1280 _wapi_handle_ref (mutex);
1282 g_ptr_array_add (thread_handle->owned_mutexes, mutex);
1285 void _wapi_thread_disown_mutex (gpointer mutex)
1287 struct _WapiHandle_thread *thread_handle;
1291 thread = _wapi_thread_handle_from_id (pthread_self ());
1292 if (thread == NULL) {
1293 g_warning ("%s: error looking up thread by ID", __func__);
1297 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1298 (gpointer *)&thread_handle);
1300 g_warning ("%s: error looking up thread handle %p", __func__,
1305 _wapi_handle_unref (mutex);
1307 g_ptr_array_remove (thread_handle->owned_mutexes, mutex);