2 * threads.c: Thread handles
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002-2006 Ximian, Inc.
19 #include <sys/types.h>
22 #include <mono/io-layer/wapi.h>
23 #include <mono/io-layer/wapi-private.h>
24 #include <mono/io-layer/handles-private.h>
25 #include <mono/io-layer/misc-private.h>
26 #include <mono/io-layer/mono-mutex.h>
27 #include <mono/io-layer/thread-private.h>
28 #include <mono/io-layer/mutex-private.h>
29 #include <mono/io-layer/atomic.h>
31 #include <mono/utils/mono-threads.h>
32 #include <mono/utils/gc_wrapper.h>
34 #ifdef HAVE_VALGRIND_MEMCHECK_H
35 #include <valgrind/memcheck.h>
41 #define WAIT_DEBUG(code) do { code } while (0)
43 #define WAIT_DEBUG(code) do { } while (0)
46 /* Hash threads with tids. I thought of using TLS for this, but that
47 * would have to set the data in the new thread, which is more hassle
49 static mono_once_t thread_hash_once = MONO_ONCE_INIT;
50 static pthread_key_t thread_hash_key;
52 /* This key is used with attached threads and a destructor to signal
53 * when attached threads exit, as they don't have the thread_exit()
56 static pthread_key_t thread_attached_key;
58 struct _WapiHandleOps _wapi_thread_ops = {
63 NULL, /* special_wait */
67 static mono_once_t thread_ops_once=MONO_ONCE_INIT;
69 static void thread_ops_init (void)
71 _wapi_handle_register_capabilities (WAPI_HANDLE_THREAD,
72 WAPI_HANDLE_CAP_WAIT);
75 void _wapi_thread_cleanup (void)
79 ret = pthread_key_delete (thread_hash_key);
82 ret = pthread_key_delete (thread_attached_key);
86 /* Called by thread_exit(), but maybe indirectly by
87 * mono_thread_manage() via mono_thread_signal_self() too
89 static void _wapi_thread_abandon_mutexes (gpointer handle)
91 struct _WapiHandle_thread *thread_handle;
94 pid_t pid = _wapi_getpid ();
95 pthread_t tid = pthread_self ();
98 g_message ("%s: Thread %p abandoning held mutexes", __func__, handle);
101 if (handle == NULL) {
102 handle = _wapi_thread_handle_from_id (pthread_self ());
103 if (handle == NULL) {
104 /* Something gone badly wrong... */
109 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
110 (gpointer *)&thread_handle);
112 g_warning ("%s: error looking up thread handle %p", __func__,
117 if (!pthread_equal (thread_handle->id, tid)) {
121 for (i = 0; i < thread_handle->owned_mutexes->len; i++) {
122 gpointer mutex = g_ptr_array_index (thread_handle->owned_mutexes, i);
124 _wapi_mutex_abandon (mutex, pid, tid);
125 _wapi_thread_disown_mutex (mutex);
129 void _wapi_thread_set_termination_details (gpointer handle,
132 struct _WapiHandle_thread *thread_handle;
136 if (_wapi_handle_issignalled (handle) ||
137 _wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) {
138 /* We must have already deliberately finished with
139 * this thread, so don't do any more now
145 g_message ("%s: Thread %p terminating", __func__, handle);
148 _wapi_thread_abandon_mutexes (handle);
150 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
151 (gpointer *)&thread_handle);
153 g_warning ("%s: error looking up thread handle %p", __func__,
159 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
161 thr_ret = _wapi_handle_lock_handle (handle);
162 g_assert (thr_ret == 0);
164 thread_handle->exitstatus = exitstatus;
165 thread_handle->state = THREAD_STATE_EXITED;
166 MONO_SEM_DESTROY (&thread_handle->suspend_sem);
167 g_ptr_array_free (thread_handle->owned_mutexes, TRUE);
169 _wapi_handle_set_signal_state (handle, TRUE, TRUE);
171 thr_ret = _wapi_handle_unlock_handle (handle);
172 g_assert (thr_ret == 0);
173 pthread_cleanup_pop (0);
176 g_message("%s: Recording thread handle %p id %ld status as %d",
177 __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 static void thread_exit (guint32 exitstatus, gpointer handle)
203 _wapi_thread_set_termination_details (handle, exitstatus);
205 /* Call pthread_exit() to call destructors and really exit the
211 static void thread_attached_exit (gpointer handle)
213 /* Drop the extra reference we take in thread_attach, now this
217 _wapi_thread_set_termination_details (handle, 0);
220 static void thread_hash_init(void)
224 thr_ret = pthread_key_create (&thread_hash_key, NULL);
225 g_assert (thr_ret == 0);
227 thr_ret = pthread_key_create (&thread_attached_key,
228 thread_attached_exit);
229 g_assert (thr_ret == 0);
232 static void _wapi_thread_suspend (struct _WapiHandle_thread *thread)
234 g_assert (pthread_equal (thread->id, pthread_self ()));
236 while (MONO_SEM_WAIT (&thread->suspend_sem) != 0 &&
240 static void _wapi_thread_resume (struct _WapiHandle_thread *thread)
242 MONO_SEM_POST (&thread->suspend_sem);
245 static void *thread_start_routine (gpointer args) G_GNUC_NORETURN;
246 static void *thread_start_routine (gpointer args)
248 struct _WapiHandle_thread *thread = (struct _WapiHandle_thread *)args;
251 thr_ret = mono_gc_pthread_detach (pthread_self ());
252 g_assert (thr_ret == 0);
254 thr_ret = pthread_setspecific (thread_hash_key,
255 (void *)thread->handle);
257 /* This is only supposed to happen when Mono is
258 shutting down. We cannot assert on it, though,
259 because we must not depend on metadata, which is
260 where the shutdown code is.
262 This is a race condition which arises because
263 pthreads don't allow creation of suspended threads.
264 Once Mono is set to shut down no new thread is
265 allowed to start, even though threads may still be
266 created. We emulate suspended threads in this
267 function by calling _wapi_thread_suspend() below.
269 So it can happen that even though Mono is already
270 shutting down we still end up here, and at this
271 point the thread_hash_key might already be
277 g_message ("%s: started thread id %ld", __func__, thread->id);
280 /* We set it again here since passing &thread->id to pthread_create is racy
281 as the thread can start running before the value is set.*/
282 thread->id = pthread_self ();
284 if (thread->create_flags & CREATE_SUSPENDED) {
285 _wapi_thread_suspend (thread);
288 thread_exit (thread->start_routine (thread->start_arg),
292 /* Even though we tell gcc that this function doesn't return,
293 * other compilers won't see that.
301 * @security: Ignored for now.
302 * @stacksize: the size in bytes of the new thread's stack. Use 0 to
303 * default to the normal stack size. (Ignored for now).
304 * @start: The function that the new thread should start with
305 * @param: The parameter to give to @start.
306 * @create: If 0, the new thread is ready to run immediately. If
307 * %CREATE_SUSPENDED, the new thread will be in the suspended state,
308 * requiring a ResumeThread() call to continue running.
309 * @tid: If non-NULL, the ID of the new thread is stored here. NB
310 * this is defined as a DWORD (ie 32bit) in the MS API, but we need to
311 * cope with 64 bit IDs for s390x and amd64.
313 * Creates a new threading handle.
315 * Return value: a new handle, or NULL
317 gpointer CreateThread(WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 stacksize,
318 WapiThreadStart start, gpointer param, guint32 create,
321 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
328 gpointer ct_ret = NULL;
330 mono_once (&thread_hash_once, thread_hash_init);
331 mono_once (&thread_ops_once, thread_ops_init);
337 thread_handle.state = THREAD_STATE_START;
338 thread_handle.owned_mutexes = g_ptr_array_new ();
339 thread_handle.create_flags = create;
340 thread_handle.start_routine = start;
341 thread_handle.start_arg = param;
343 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
344 if (handle == _WAPI_HANDLE_INVALID) {
345 g_warning ("%s: error creating thread handle", __func__);
346 SetLastError (ERROR_GEN_FAILURE);
351 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
353 thr_ret = _wapi_handle_lock_handle (handle);
354 g_assert (thr_ret == 0);
356 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
357 (gpointer *)&thread_handle_p);
359 g_warning ("%s: error looking up thread handle %p", __func__,
361 SetLastError (ERROR_GEN_FAILURE);
366 /* Hold a reference while the thread is active, because we use
367 * the handle to store thread exit information
369 _wapi_handle_ref (handle);
371 /* Set a 2M stack size. This is the default on Linux, but BSD
372 * needs it. (The original bug report from Martin Dvorak <md@9ll.cz>
373 * set the size to 2M-4k. I don't know why it's short by 4k, so
374 * I'm leaving it as 2M until I'm told differently.)
376 thr_ret = pthread_attr_init(&attr);
377 g_assert (thr_ret == 0);
379 /* defaults of 2Mb for 32bits and 4Mb for 64bits */
380 /* temporarily changed to use 1 MB: this allows more threads
381 * to be used, as well as using less virtual memory and so
382 * more is available for the GC heap.
385 #if HAVE_VALGRIND_MEMCHECK_H
386 if (RUNNING_ON_VALGRIND) {
389 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
392 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
396 #ifdef PTHREAD_STACK_MIN
397 if (stacksize < PTHREAD_STACK_MIN)
398 stacksize = PTHREAD_STACK_MIN;
401 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
402 thr_ret = pthread_attr_setstacksize(&attr, stacksize);
403 g_assert (thr_ret == 0);
406 MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
407 thread_handle_p->handle = handle;
410 ret = mono_threads_pthread_create (&thread_handle_p->id, &attr,
411 thread_start_routine, (void *)thread_handle_p);
415 g_message ("%s: Thread create error: %s", __func__,
419 /* Two, because of the reference we took above */
427 g_message("%s: Started thread handle %p ID %ld", __func__, handle,
428 thread_handle_p->id);
432 #ifdef PTHREAD_POINTER_ID
433 /* Don't use GPOINTER_TO_UINT here, it can't cope with
434 * sizeof(void *) > sizeof(uint) when a cast to uint
437 *tid = (gsize)(thread_handle_p->id);
439 *tid = thread_handle_p->id;
444 thr_ret = _wapi_handle_unlock_handle (handle);
445 g_assert (thr_ret == 0);
446 pthread_cleanup_pop (0);
448 /* Must not call _wapi_handle_unref() with the shared handles
451 for (i = 0; i < unrefs; i++) {
452 _wapi_handle_unref (handle);
458 /* The only time this function is called when tid != pthread_self ()
459 * is from OpenThread (), so we can fast-path most cases by just
460 * looking up the handle in TLS. OpenThread () must cope with a NULL
461 * return and do a handle search in that case.
463 gpointer _wapi_thread_handle_from_id (pthread_t tid)
467 if (pthread_equal (tid, pthread_self ()) &&
468 (ret = pthread_getspecific (thread_hash_key)) != NULL) {
469 /* We know the handle */
472 g_message ("%s: Returning %p for self thread %ld from TLS",
480 g_message ("%s: Returning NULL for unknown or non-self thread %ld",
488 static gboolean find_thread_by_id (gpointer handle, gpointer user_data)
490 pthread_t tid = (pthread_t)user_data;
491 struct _WapiHandle_thread *thread_handle;
494 /* Ignore threads that have already exited (ie they are signalled) */
495 if (_wapi_handle_issignalled (handle) == FALSE) {
496 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
497 (gpointer *)&thread_handle);
499 /* It's possible that the handle has vanished
500 * during the _wapi_search_handle before it
501 * gets here, so don't spam the console with
508 g_message ("%s: looking at thread %ld from process %d", __func__, thread_handle->id, 0);
511 if (pthread_equal (thread_handle->id, tid)) {
513 g_message ("%s: found the thread we are looking for",
521 g_message ("%s: not found %ld, returning FALSE", __func__, tid);
527 /* NB tid is 32bit in MS API, but we need 64bit on amd64 and s390x
528 * (and probably others)
530 gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, gsize tid)
534 mono_once (&thread_hash_once, thread_hash_init);
535 mono_once (&thread_ops_once, thread_ops_init);
538 g_message ("%s: looking up thread %"G_GSIZE_FORMAT, __func__, tid);
541 ret = _wapi_thread_handle_from_id ((pthread_t)tid);
543 /* We need to search for this thread */
544 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 */
546 /* if _wapi_search_handle() returns a found handle, it
549 _wapi_handle_ref (ret);
553 g_message ("%s: returning thread handle %p", __func__, ret);
561 * @exitcode: Sets the thread's exit code, which can be read from
562 * another thread with GetExitCodeThread().
564 * Terminates the calling thread. A thread can also exit by returning
565 * from its start function. When the last thread in a process
566 * terminates, the process itself terminates.
568 void ExitThread(guint32 exitcode)
570 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
572 if (thread != NULL) {
573 thread_exit(exitcode, thread);
575 /* Just blow this thread away */
582 * @handle: The thread handle to query
583 * @exitcode: The thread @handle exit code is stored here
585 * Finds the exit code of @handle, and stores it in @exitcode. If the
586 * thread @handle is still running, the value stored is %STILL_ACTIVE.
588 * Return value: %TRUE, or %FALSE on error.
590 gboolean GetExitCodeThread(gpointer handle, guint32 *exitcode)
592 struct _WapiHandle_thread *thread_handle;
595 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
596 (gpointer *)&thread_handle);
598 g_warning ("%s: error looking up thread handle %p", __func__,
604 g_message ("%s: Finding exit status for thread handle %p id %ld",
605 __func__, handle, thread_handle->id);
608 if (exitcode == NULL) {
610 g_message ("%s: Nowhere to store exit code", __func__);
615 if (thread_handle->state != THREAD_STATE_EXITED) {
617 g_message ("%s: Thread still active (state %d, exited is %d)",
618 __func__, thread_handle->state,
619 THREAD_STATE_EXITED);
621 *exitcode = STILL_ACTIVE;
625 *exitcode = thread_handle->exitstatus;
631 * GetCurrentThreadId:
633 * Looks up the thread ID of the current thread. This ID can be
634 * passed to OpenThread() to create a new handle on this thread.
636 * Return value: the thread ID. NB this is defined as DWORD (ie 32
637 * bit) in the MS API, but we need to cope with 64 bit IDs for s390x
638 * and amd64. This doesn't really break the API, it just embraces and
639 * extends it on 64bit platforms :)
641 gsize GetCurrentThreadId(void)
643 pthread_t tid = pthread_self();
645 #ifdef PTHREAD_POINTER_ID
646 /* Don't use GPOINTER_TO_UINT here, it can't cope with
647 * sizeof(void *) > sizeof(uint) when a cast to uint would
656 static gpointer thread_attach(gsize *tid)
658 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
663 mono_once (&thread_hash_once, thread_hash_init);
664 mono_once (&thread_ops_once, thread_ops_init);
666 thread_handle.state = THREAD_STATE_START;
667 thread_handle.owned_mutexes = g_ptr_array_new ();
669 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
670 if (handle == _WAPI_HANDLE_INVALID) {
671 g_warning ("%s: error creating thread handle", __func__);
673 SetLastError (ERROR_GEN_FAILURE);
677 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
679 thr_ret = _wapi_handle_lock_handle (handle);
680 g_assert (thr_ret == 0);
682 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
683 (gpointer *)&thread_handle_p);
685 g_warning ("%s: error looking up thread handle %p", __func__,
688 SetLastError (ERROR_GEN_FAILURE);
692 /* Hold a reference while the thread is active, because we use
693 * the handle to store thread exit information
695 _wapi_handle_ref (handle);
697 /* suspend_sem is not used for attached threads, but
698 * thread_exit() might try to destroy it
700 MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
701 thread_handle_p->handle = handle;
702 thread_handle_p->id = pthread_self ();
704 thr_ret = pthread_setspecific (thread_hash_key, (void *)handle);
705 g_assert (thr_ret == 0);
707 thr_ret = pthread_setspecific (thread_attached_key, (void *)handle);
708 g_assert (thr_ret == 0);
711 g_message("%s: Attached thread handle %p ID %ld", __func__, handle,
712 thread_handle_p->id);
716 #ifdef PTHREAD_POINTER_ID
717 /* Don't use GPOINTER_TO_UINT here, it can't cope with
718 * sizeof(void *) > sizeof(uint) when a cast to uint
721 *tid = (gsize)(thread_handle_p->id);
723 *tid = thread_handle_p->id;
728 thr_ret = _wapi_handle_unlock_handle (handle);
729 g_assert (thr_ret == 0);
730 pthread_cleanup_pop (0);
735 gpointer _wapi_thread_duplicate ()
739 mono_once (&thread_hash_once, thread_hash_init);
740 mono_once (&thread_ops_once, thread_ops_init);
742 ret = _wapi_thread_handle_from_id (pthread_self ());
744 ret = thread_attach (NULL);
746 _wapi_handle_ref (ret);
755 * Looks up the handle associated with the current thread. Under
756 * Windows this is a pseudohandle, and must be duplicated with
757 * DuplicateHandle() for some operations.
759 * Return value: The current thread handle, or %NULL on failure.
760 * (Unknown whether Windows has a possible failure here. It may be
761 * necessary to implement the pseudohandle-constant behaviour).
763 gpointer GetCurrentThread(void)
765 mono_once(&thread_hash_once, thread_hash_init);
766 mono_once (&thread_ops_once, thread_ops_init);
768 return(_WAPI_THREAD_CURRENT);
773 * @handle: the thread handle to resume
775 * Decrements the suspend count of thread @handle. A thread can only
776 * run if its suspend count is zero.
778 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
780 guint32 ResumeThread(gpointer handle)
782 struct _WapiHandle_thread *thread_handle;
785 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
786 (gpointer *)&thread_handle);
788 g_warning ("%s: error looking up thread handle %p", __func__,
794 /* This is still a kludge that only copes with starting a
795 * thread that was suspended on create, so don't bother with
796 * the suspend count crap yet
798 _wapi_thread_resume (thread_handle);
804 * @handle: the thread handle to suspend
806 * Increments the suspend count of thread @handle. A thread can only
807 * run if its suspend count is zero.
809 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
811 guint32 SuspendThread(gpointer handle)
818 * @ms: The time in milliseconds to suspend for
819 * @alertable: if TRUE, the wait can be interrupted by an APC call
821 * Suspends execution of the current thread for @ms milliseconds. A
822 * value of zero causes the thread to relinquish its time slice. A
823 * value of %INFINITE causes an infinite delay.
825 guint32 SleepEx(guint32 ms, gboolean alertable)
827 struct timespec req, rem;
830 gpointer current_thread = NULL;
833 g_message("%s: Sleeping for %d ms", __func__, ms);
837 current_thread = _wapi_thread_handle_from_id (pthread_self ());
838 if (current_thread == NULL) {
839 SetLastError (ERROR_INVALID_HANDLE);
843 if (_wapi_thread_apc_pending (current_thread)) {
844 _wapi_thread_dispatch_apc_queue (current_thread);
845 return WAIT_IO_COMPLETION;
854 /* FIXME: check for INFINITE and sleep forever */
859 req.tv_nsec=ms_rem*1000000;
862 memset (&rem, 0, sizeof (rem));
863 ret=nanosleep(&req, &rem);
865 if (alertable && _wapi_thread_apc_pending (current_thread)) {
866 _wapi_thread_dispatch_apc_queue (current_thread);
867 return WAIT_IO_COMPLETION;
871 /* Sleep interrupted with rem time remaining */
873 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
875 g_message("%s: Still got %d ms to go", __func__, rems);
884 void Sleep(guint32 ms)
889 gboolean _wapi_thread_cur_apc_pending (void)
891 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
893 if (thread == NULL) {
894 SetLastError (ERROR_INVALID_HANDLE);
898 return(_wapi_thread_apc_pending (thread));
901 gboolean _wapi_thread_apc_pending (gpointer handle)
903 struct _WapiHandle_thread *thread;
906 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
907 (gpointer *)&thread);
910 /* This might happen at process shutdown, as all
911 * thread handles are forcibly closed. If a thread
912 * still has an alertable wait the final
913 * _wapi_thread_apc_pending check will probably fail
916 g_warning ("%s: error looking up thread handle %p", __func__,
922 return(thread->has_apc || thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE);
925 gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
927 /* We don't support calling APC functions */
928 struct _WapiHandle_thread *thread;
931 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
932 (gpointer *)&thread);
935 thread->has_apc = FALSE;
941 * In this implementation, APC_CALLBACK is ignored.
942 * if HANDLE refers to the current thread, the only effect this function has
943 * that if called from a signal handler, and the thread was waiting when receiving
944 * the signal, the wait will be broken after the signal handler returns.
945 * In this case, this function is async-signal-safe.
947 guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer handle,
950 struct _WapiHandle_thread *thread_handle;
953 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
954 (gpointer *)&thread_handle);
956 g_warning ("%s: error looking up thread handle %p", __func__,
961 g_assert (thread_handle->id == GetCurrentThreadId ());
962 /* No locking/memory barriers are needed here */
963 thread_handle->has_apc = TRUE;
968 * wapi_interrupt_thread:
970 * This is not part of the WIN32 API.
971 * The state of the thread handle HANDLE is set to 'interrupted' which means that
972 * if the thread calls one of the WaitFor functions, the function will return with
973 * WAIT_IO_COMPLETION instead of waiting. Also, if the thread was waiting when
974 * this function was called, the wait will be broken.
975 * It is possible that the wait functions return WAIT_IO_COMPLETION, but the
976 * target thread didn't receive the interrupt signal yet, in this case it should
977 * call the wait function again. This essentially means that the target thread will
978 * busy wait until it is ready to process the interruption.
979 * FIXME: get rid of QueueUserAPC and thread->has_apc, SleepEx seems to require it.
981 void wapi_interrupt_thread (gpointer thread_handle)
983 struct _WapiHandle_thread *thread;
985 gpointer prev_handle, wait_handle;
987 pthread_cond_t *cond;
990 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
991 (gpointer *)&thread);
995 wait_handle = thread->wait_handle;
998 * Atomically obtain the handle the thread is waiting on, and
999 * change it to a flag value.
1001 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1002 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1003 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1004 /* Already interrupted */
1006 if (prev_handle == wait_handle)
1012 WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread_handle->id););
1018 /* If we reach here, then wait_handle is set to the flag value,
1019 * which means that the target thread is either
1020 * - before the first CAS in timedwait, which means it won't enter the
1022 * - it is after the first CAS, so it is already waiting, or it will
1023 * enter the wait, and it will be interrupted by the broadcast.
1025 idx = GPOINTER_TO_UINT(wait_handle);
1026 cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
1027 mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
1029 mono_mutex_lock (mutex);
1030 mono_cond_broadcast (cond);
1031 mono_mutex_unlock (mutex);
1033 /* ref added by set_wait_handle */
1034 _wapi_handle_unref (wait_handle);
1038 * wapi_self_interrupt:
1040 * This is not part of the WIN32 API.
1041 * Set the 'interrupted' state of the calling thread if it's NULL.
1043 void wapi_self_interrupt (void)
1045 struct _WapiHandle_thread *thread;
1047 gpointer prev_handle, wait_handle;
1048 gpointer thread_handle;
1051 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1052 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1053 (gpointer *)&thread);
1057 wait_handle = thread->wait_handle;
1060 * Atomically obtain the handle the thread is waiting on, and
1061 * change it to a flag value.
1063 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1064 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1065 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1066 /* Already interrupted */
1068 /*We did not get interrupted*/
1069 if (prev_handle == wait_handle)
1076 /* ref added by set_wait_handle */
1077 _wapi_handle_unref (wait_handle);
1081 _wapi_handle_unref (thread_handle);
1085 * wapi_clear_interruption:
1087 * This is not part of the WIN32 API.
1088 * Clear the 'interrupted' state of the calling thread.
1089 * This function is signal safe
1091 void wapi_clear_interruption (void)
1093 struct _WapiHandle_thread *thread;
1095 gpointer prev_handle;
1096 gpointer thread_handle;
1098 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1099 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1100 (gpointer *)&thread);
1103 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1104 NULL, INTERRUPTION_REQUESTED_HANDLE);
1105 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1106 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1108 _wapi_handle_unref (thread_handle);
1111 char* wapi_current_thread_desc ()
1113 struct _WapiHandle_thread *thread;
1117 gpointer thread_handle;
1121 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1122 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1123 (gpointer *)&thread);
1125 return g_strdup_printf ("thread handle %p state : lookup failure", thread_handle);
1127 handle = thread->wait_handle;
1128 text = g_string_new (0);
1129 g_string_append_printf (text, "thread handle %p state : ", thread_handle);
1132 g_string_append_printf (text, "not waiting");
1133 else if (handle == INTERRUPTION_REQUESTED_HANDLE)
1134 g_string_append_printf (text, "interrupted state");
1136 g_string_append_printf (text, "waiting on %p : %s ", handle, _wapi_handle_typename[_wapi_handle_type (handle)]);
1137 g_string_append_printf (text, " owns (");
1138 for (i = 0; i < thread->owned_mutexes->len; i++) {
1139 gpointer mutex = g_ptr_array_index (thread->owned_mutexes, i);
1141 g_string_append_printf (text, ", %p", mutex);
1143 g_string_append_printf (text, "%p", mutex);
1145 g_string_append_printf (text, ")");
1148 g_string_free (text, FALSE);
1153 * wapi_thread_set_wait_handle:
1155 * Set the wait handle for the current thread to HANDLE. Return TRUE on success, FALSE
1156 * if the thread is in interrupted state, and cannot start waiting.
1158 gboolean wapi_thread_set_wait_handle (gpointer handle)
1160 struct _WapiHandle_thread *thread;
1162 gpointer prev_handle;
1163 gpointer thread_handle;
1165 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1166 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1167 (gpointer *)&thread);
1170 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1172 _wapi_handle_unref (thread_handle);
1174 if (prev_handle == NULL) {
1175 /* thread->wait_handle acts as an additional reference to the handle */
1176 _wapi_handle_ref (handle);
1178 WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
1180 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
1181 WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
1184 return prev_handle == NULL;
1188 * wapi_thread_clear_wait_handle:
1190 * Clear the wait handle of the current thread.
1192 void wapi_thread_clear_wait_handle (gpointer handle)
1194 struct _WapiHandle_thread *thread;
1196 gpointer prev_handle;
1197 gpointer thread_handle;
1199 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1200 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1201 (gpointer *)&thread);
1204 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1207 if (prev_handle == handle) {
1208 _wapi_handle_unref (handle);
1209 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1211 /*It can be NULL if it was asynchronously cleared*/
1212 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE || prev_handle == NULL);
1213 WAIT_DEBUG (printf ("%p: finished waiting.\n", GetCurrentThreadId ()););
1216 _wapi_handle_unref (thread_handle);
1219 void _wapi_thread_own_mutex (gpointer mutex)
1221 struct _WapiHandle_thread *thread_handle;
1225 thread = _wapi_thread_handle_from_id (pthread_self ());
1226 if (thread == NULL) {
1227 g_warning ("%s: error looking up thread by ID", __func__);
1231 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1232 (gpointer *)&thread_handle);
1234 g_warning ("%s: error looking up thread handle %p", __func__,
1239 _wapi_handle_ref (mutex);
1241 g_ptr_array_add (thread_handle->owned_mutexes, mutex);
1244 void _wapi_thread_disown_mutex (gpointer mutex)
1246 struct _WapiHandle_thread *thread_handle;
1250 thread = _wapi_thread_handle_from_id (pthread_self ());
1251 if (thread == NULL) {
1252 g_warning ("%s: error looking up thread by ID", __func__);
1256 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1257 (gpointer *)&thread_handle);
1259 g_warning ("%s: error looking up thread handle %p", __func__,
1264 _wapi_handle_unref (mutex);
1266 g_ptr_array_remove (thread_handle->owned_mutexes, mutex);