2 * threads.c: Thread handles
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002-2006 Ximian, Inc.
14 #include <mono/utils/gc_wrapper.h>
20 #include <sys/types.h>
23 #include <mono/io-layer/wapi.h>
24 #include <mono/io-layer/wapi-private.h>
25 #include <mono/io-layer/handles-private.h>
26 #include <mono/io-layer/misc-private.h>
27 #include <mono/io-layer/mono-mutex.h>
28 #include <mono/io-layer/thread-private.h>
29 #include <mono/io-layer/mutex-private.h>
30 #include <mono/io-layer/atomic.h>
32 #ifdef HAVE_VALGRIND_MEMCHECK_H
33 #include <valgrind/memcheck.h>
40 #define WAIT_DEBUG(code) do { code } while (0)
42 #define WAIT_DEBUG(code) do { } while (0)
45 /* Hash threads with tids. I thought of using TLS for this, but that
46 * would have to set the data in the new thread, which is more hassle
48 static mono_once_t thread_hash_once = MONO_ONCE_INIT;
49 static pthread_key_t thread_hash_key;
51 /* This key is used with attached threads and a destructor to signal
52 * when attached threads exit, as they don't have the thread_exit()
55 static pthread_key_t thread_attached_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);
81 ret = pthread_key_delete (thread_attached_key);
85 /* Called by thread_exit(), but maybe indirectly by
86 * mono_thread_manage() via mono_thread_signal_self() too
88 static void _wapi_thread_abandon_mutexes (gpointer handle)
90 struct _WapiHandle_thread *thread_handle;
93 pid_t pid = _wapi_getpid ();
94 pthread_t tid = pthread_self ();
97 g_message ("%s: Thread %p abandoning held mutexes", __func__, handle);
100 if (handle == NULL) {
101 handle = _wapi_thread_handle_from_id (pthread_self ());
102 if (handle == NULL) {
103 /* Something gone badly wrong... */
108 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
109 (gpointer *)&thread_handle);
111 g_warning ("%s: error looking up thread handle %p", __func__,
116 if (!pthread_equal (thread_handle->id, tid)) {
120 for (i = 0; i < thread_handle->owned_mutexes->len; i++) {
121 gpointer mutex = g_ptr_array_index (thread_handle->owned_mutexes, i);
123 _wapi_mutex_abandon (mutex, pid, tid);
124 _wapi_thread_disown_mutex (mutex);
128 void _wapi_thread_set_termination_details (gpointer handle,
131 struct _WapiHandle_thread *thread_handle;
135 if (_wapi_handle_issignalled (handle) ||
136 _wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) {
137 /* We must have already deliberately finished with
138 * this thread, so don't do any more now
144 g_message ("%s: Thread %p terminating", __func__, handle);
147 _wapi_thread_abandon_mutexes (handle);
149 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
150 (gpointer *)&thread_handle);
152 g_warning ("%s: error looking up thread handle %p", __func__,
158 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
160 thr_ret = _wapi_handle_lock_handle (handle);
161 g_assert (thr_ret == 0);
163 thread_handle->exitstatus = exitstatus;
164 thread_handle->state = THREAD_STATE_EXITED;
165 MONO_SEM_DESTROY (&thread_handle->suspend_sem);
166 g_ptr_array_free (thread_handle->owned_mutexes, TRUE);
168 _wapi_handle_set_signal_state (handle, TRUE, TRUE);
170 thr_ret = _wapi_handle_unlock_handle (handle);
171 g_assert (thr_ret == 0);
172 pthread_cleanup_pop (0);
175 g_message("%s: Recording thread handle %p id %ld status as %d",
176 __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);
196 /* Called by the thread creation code as a thread is finishing up, and
199 static void thread_exit (guint32 exitstatus, gpointer handle) G_GNUC_NORETURN;
200 static void thread_exit (guint32 exitstatus, gpointer handle)
202 _wapi_thread_set_termination_details (handle, exitstatus);
204 /* Call pthread_exit() to call destructors and really exit the
210 static void thread_attached_exit (gpointer handle)
212 /* Drop the extra reference we take in thread_attach, now this
216 _wapi_thread_set_termination_details (handle, 0);
219 static void thread_hash_init(void)
223 thr_ret = pthread_key_create (&thread_hash_key, NULL);
224 g_assert (thr_ret == 0);
226 thr_ret = pthread_key_create (&thread_attached_key,
227 thread_attached_exit);
228 g_assert (thr_ret == 0);
231 static void _wapi_thread_suspend (struct _WapiHandle_thread *thread)
233 g_assert (pthread_equal (thread->id, pthread_self ()));
235 while (MONO_SEM_WAIT (&thread->suspend_sem) != 0 &&
239 static void _wapi_thread_resume (struct _WapiHandle_thread *thread)
241 MONO_SEM_POST (&thread->suspend_sem);
244 static void *thread_start_routine (gpointer args) G_GNUC_NORETURN;
245 static void *thread_start_routine (gpointer args)
247 struct _WapiHandle_thread *thread = (struct _WapiHandle_thread *)args;
250 thr_ret = mono_gc_pthread_detach (pthread_self ());
251 g_assert (thr_ret == 0);
253 thr_ret = pthread_setspecific (thread_hash_key,
254 (void *)thread->handle);
256 /* This is only supposed to happen when Mono is
257 shutting down. We cannot assert on it, though,
258 because we must not depend on metadata, which is
259 where the shutdown code is.
261 This is a race condition which arises because
262 pthreads don't allow creation of suspended threads.
263 Once Mono is set to shut down no new thread is
264 allowed to start, even though threads may still be
265 created. We emulate suspended threads in this
266 function by calling _wapi_thread_suspend() below.
268 So it can happen that even though Mono is already
269 shutting down we still end up here, and at this
270 point the thread_hash_key might already be
275 thread->id = pthread_self();
278 g_message ("%s: started thread id %ld", __func__, thread->id);
281 if (thread->create_flags & CREATE_SUSPENDED) {
282 _wapi_thread_suspend (thread);
285 thread_exit (thread->start_routine (thread->start_arg),
289 /* Even though we tell gcc that this function doesn't return,
290 * other compilers won't see that.
298 * @security: Ignored for now.
299 * @stacksize: the size in bytes of the new thread's stack. Use 0 to
300 * default to the normal stack size. (Ignored for now).
301 * @start: The function that the new thread should start with
302 * @param: The parameter to give to @start.
303 * @create: If 0, the new thread is ready to run immediately. If
304 * %CREATE_SUSPENDED, the new thread will be in the suspended state,
305 * requiring a ResumeThread() call to continue running.
306 * @tid: If non-NULL, the ID of the new thread is stored here. NB
307 * this is defined as a DWORD (ie 32bit) in the MS API, but we need to
308 * cope with 64 bit IDs for s390x and amd64.
310 * Creates a new threading handle.
312 * Return value: a new handle, or NULL
314 gpointer CreateThread(WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 stacksize,
315 WapiThreadStart start, gpointer param, guint32 create,
318 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
325 gpointer ct_ret = NULL;
327 mono_once (&thread_hash_once, thread_hash_init);
328 mono_once (&thread_ops_once, thread_ops_init);
334 thread_handle.state = THREAD_STATE_START;
335 thread_handle.owned_mutexes = g_ptr_array_new ();
336 thread_handle.create_flags = create;
337 thread_handle.start_routine = start;
338 thread_handle.start_arg = param;
340 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
341 if (handle == _WAPI_HANDLE_INVALID) {
342 g_warning ("%s: error creating thread handle", __func__);
343 SetLastError (ERROR_GEN_FAILURE);
348 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
350 thr_ret = _wapi_handle_lock_handle (handle);
351 g_assert (thr_ret == 0);
353 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
354 (gpointer *)&thread_handle_p);
356 g_warning ("%s: error looking up thread handle %p", __func__,
358 SetLastError (ERROR_GEN_FAILURE);
363 /* Hold a reference while the thread is active, because we use
364 * the handle to store thread exit information
366 _wapi_handle_ref (handle);
368 /* Set a 2M stack size. This is the default on Linux, but BSD
369 * needs it. (The original bug report from Martin Dvorak <md@9ll.cz>
370 * set the size to 2M-4k. I don't know why it's short by 4k, so
371 * I'm leaving it as 2M until I'm told differently.)
373 thr_ret = pthread_attr_init(&attr);
374 g_assert (thr_ret == 0);
376 /* defaults of 2Mb for 32bits and 4Mb for 64bits */
377 /* temporarily changed to use 1 MB: this allows more threads
378 * to be used, as well as using less virtual memory and so
379 * more is available for the GC heap.
382 #if HAVE_VALGRIND_MEMCHECK_H
383 if (RUNNING_ON_VALGRIND) {
386 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
389 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
393 #ifdef PTHREAD_STACK_MIN
394 if (stacksize < PTHREAD_STACK_MIN)
395 stacksize = PTHREAD_STACK_MIN;
398 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
399 thr_ret = pthread_attr_setstacksize(&attr, stacksize);
400 g_assert (thr_ret == 0);
403 MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
404 thread_handle_p->handle = handle;
407 ret = mono_gc_pthread_create (&thread_handle_p->id, &attr,
408 thread_start_routine, (void *)thread_handle_p);
412 g_message ("%s: Thread create error: %s", __func__,
416 /* Two, because of the reference we took above */
424 g_message("%s: Started thread handle %p ID %ld", __func__, handle,
425 thread_handle_p->id);
429 #ifdef PTHREAD_POINTER_ID
430 /* Don't use GPOINTER_TO_UINT here, it can't cope with
431 * sizeof(void *) > sizeof(uint) when a cast to uint
434 *tid = (gsize)(thread_handle_p->id);
436 *tid = thread_handle_p->id;
441 thr_ret = _wapi_handle_unlock_handle (handle);
442 g_assert (thr_ret == 0);
443 pthread_cleanup_pop (0);
445 /* Must not call _wapi_handle_unref() with the shared handles
448 for (i = 0; i < unrefs; i++) {
449 _wapi_handle_unref (handle);
455 /* The only time this function is called when tid != pthread_self ()
456 * is from OpenThread (), so we can fast-path most cases by just
457 * looking up the handle in TLS. OpenThread () must cope with a NULL
458 * return and do a handle search in that case.
460 gpointer _wapi_thread_handle_from_id (pthread_t tid)
464 if (pthread_equal (tid, pthread_self ()) &&
465 (ret = pthread_getspecific (thread_hash_key)) != NULL) {
466 /* We know the handle */
469 g_message ("%s: Returning %p for self thread %ld from TLS",
477 g_message ("%s: Returning NULL for unknown or non-self thread %ld",
485 static gboolean find_thread_by_id (gpointer handle, gpointer user_data)
487 pthread_t tid = (pthread_t)user_data;
488 struct _WapiHandle_thread *thread_handle;
491 /* Ignore threads that have already exited (ie they are signalled) */
492 if (_wapi_handle_issignalled (handle) == FALSE) {
493 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
494 (gpointer *)&thread_handle);
496 /* It's possible that the handle has vanished
497 * during the _wapi_search_handle before it
498 * gets here, so don't spam the console with
505 g_message ("%s: looking at thread %ld from process %d", __func__, thread_handle->id, 0);
508 if (pthread_equal (thread_handle->id, tid)) {
510 g_message ("%s: found the thread we are looking for",
518 g_message ("%s: not found %ld, returning FALSE", __func__, tid);
524 /* NB tid is 32bit in MS API, but we need 64bit on amd64 and s390x
525 * (and probably others)
527 gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, gsize tid)
531 mono_once (&thread_hash_once, thread_hash_init);
532 mono_once (&thread_ops_once, thread_ops_init);
535 g_message ("%s: looking up thread %"G_GSIZE_FORMAT, __func__, tid);
538 ret = _wapi_thread_handle_from_id ((pthread_t)tid);
540 /* We need to search for this thread */
541 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 */
543 /* if _wapi_search_handle() returns a found handle, it
546 _wapi_handle_ref (ret);
550 g_message ("%s: returning thread handle %p", __func__, ret);
558 * @exitcode: Sets the thread's exit code, which can be read from
559 * another thread with GetExitCodeThread().
561 * Terminates the calling thread. A thread can also exit by returning
562 * from its start function. When the last thread in a process
563 * terminates, the process itself terminates.
565 void ExitThread(guint32 exitcode)
567 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
569 if (thread != NULL) {
570 thread_exit(exitcode, thread);
572 /* Just blow this thread away */
579 * @handle: The thread handle to query
580 * @exitcode: The thread @handle exit code is stored here
582 * Finds the exit code of @handle, and stores it in @exitcode. If the
583 * thread @handle is still running, the value stored is %STILL_ACTIVE.
585 * Return value: %TRUE, or %FALSE on error.
587 gboolean GetExitCodeThread(gpointer handle, guint32 *exitcode)
589 struct _WapiHandle_thread *thread_handle;
592 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
593 (gpointer *)&thread_handle);
595 g_warning ("%s: error looking up thread handle %p", __func__,
601 g_message ("%s: Finding exit status for thread handle %p id %ld",
602 __func__, handle, thread_handle->id);
605 if (exitcode == NULL) {
607 g_message ("%s: Nowhere to store exit code", __func__);
612 if (thread_handle->state != THREAD_STATE_EXITED) {
614 g_message ("%s: Thread still active (state %d, exited is %d)",
615 __func__, thread_handle->state,
616 THREAD_STATE_EXITED);
618 *exitcode = STILL_ACTIVE;
622 *exitcode = thread_handle->exitstatus;
628 * GetCurrentThreadId:
630 * Looks up the thread ID of the current thread. This ID can be
631 * passed to OpenThread() to create a new handle on this thread.
633 * Return value: the thread ID. NB this is defined as DWORD (ie 32
634 * bit) in the MS API, but we need to cope with 64 bit IDs for s390x
635 * and amd64. This doesn't really break the API, it just embraces and
636 * extends it on 64bit platforms :)
638 gsize GetCurrentThreadId(void)
640 pthread_t tid = pthread_self();
642 #ifdef PTHREAD_POINTER_ID
643 /* Don't use GPOINTER_TO_UINT here, it can't cope with
644 * sizeof(void *) > sizeof(uint) when a cast to uint would
653 static gpointer thread_attach(gsize *tid)
655 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
660 mono_once (&thread_hash_once, thread_hash_init);
661 mono_once (&thread_ops_once, thread_ops_init);
663 thread_handle.state = THREAD_STATE_START;
664 thread_handle.owned_mutexes = g_ptr_array_new ();
666 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
667 if (handle == _WAPI_HANDLE_INVALID) {
668 g_warning ("%s: error creating thread handle", __func__);
670 SetLastError (ERROR_GEN_FAILURE);
674 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
676 thr_ret = _wapi_handle_lock_handle (handle);
677 g_assert (thr_ret == 0);
679 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
680 (gpointer *)&thread_handle_p);
682 g_warning ("%s: error looking up thread handle %p", __func__,
685 SetLastError (ERROR_GEN_FAILURE);
689 /* Hold a reference while the thread is active, because we use
690 * the handle to store thread exit information
692 _wapi_handle_ref (handle);
694 /* suspend_sem is not used for attached threads, but
695 * thread_exit() might try to destroy it
697 MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
698 thread_handle_p->handle = handle;
699 thread_handle_p->id = pthread_self ();
701 thr_ret = pthread_setspecific (thread_hash_key, (void *)handle);
702 g_assert (thr_ret == 0);
704 thr_ret = pthread_setspecific (thread_attached_key, (void *)handle);
705 g_assert (thr_ret == 0);
708 g_message("%s: Attached thread handle %p ID %ld", __func__, handle,
709 thread_handle_p->id);
713 #ifdef PTHREAD_POINTER_ID
714 /* Don't use GPOINTER_TO_UINT here, it can't cope with
715 * sizeof(void *) > sizeof(uint) when a cast to uint
718 *tid = (gsize)(thread_handle_p->id);
720 *tid = thread_handle_p->id;
725 thr_ret = _wapi_handle_unlock_handle (handle);
726 g_assert (thr_ret == 0);
727 pthread_cleanup_pop (0);
732 gpointer _wapi_thread_duplicate ()
736 mono_once (&thread_hash_once, thread_hash_init);
737 mono_once (&thread_ops_once, thread_ops_init);
739 ret = _wapi_thread_handle_from_id (pthread_self ());
741 ret = thread_attach (NULL);
743 _wapi_handle_ref (ret);
752 * Looks up the handle associated with the current thread. Under
753 * Windows this is a pseudohandle, and must be duplicated with
754 * DuplicateHandle() for some operations.
756 * Return value: The current thread handle, or %NULL on failure.
757 * (Unknown whether Windows has a possible failure here. It may be
758 * necessary to implement the pseudohandle-constant behaviour).
760 gpointer GetCurrentThread(void)
762 mono_once(&thread_hash_once, thread_hash_init);
763 mono_once (&thread_ops_once, thread_ops_init);
765 return(_WAPI_THREAD_CURRENT);
770 * @handle: the thread handle to resume
772 * Decrements the suspend count of thread @handle. A thread can only
773 * run if its suspend count is zero.
775 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
777 guint32 ResumeThread(gpointer handle)
779 struct _WapiHandle_thread *thread_handle;
782 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
783 (gpointer *)&thread_handle);
785 g_warning ("%s: error looking up thread handle %p", __func__,
791 /* This is still a kludge that only copes with starting a
792 * thread that was suspended on create, so don't bother with
793 * the suspend count crap yet
795 _wapi_thread_resume (thread_handle);
801 * @handle: the thread handle to suspend
803 * Increments the suspend count of thread @handle. A thread can only
804 * run if its suspend count is zero.
806 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
808 guint32 SuspendThread(gpointer handle)
814 * We assume here that TLS_MINIMUM_AVAILABLE is less than
815 * PTHREAD_KEYS_MAX, allowing enough overhead for a few TLS keys for
818 * Currently TLS_MINIMUM_AVAILABLE is 64 and _POSIX_THREAD_KEYS_MAX
819 * (the minimum value for PTHREAD_KEYS_MAX) is 128, so we should be
823 static pthread_key_t TLS_keys[TLS_MINIMUM_AVAILABLE];
824 static gboolean TLS_used[TLS_MINIMUM_AVAILABLE]={FALSE};
825 static pthread_mutex_t TLS_mutex = PTHREAD_MUTEX_INITIALIZER;
828 mono_pthread_key_for_tls (guint32 idx)
830 return (guint32)TLS_keys [idx];
836 * Allocates a Thread Local Storage (TLS) index. Any thread in the
837 * same process can use this index to store and retrieve values that
838 * are local to that thread.
840 * Return value: The index value, or %TLS_OUT_OF_INDEXES if no index
843 guint32 TlsAlloc(void)
848 pthread_mutex_lock (&TLS_mutex);
850 for(i=0; i<TLS_MINIMUM_AVAILABLE; i++) {
851 if(TLS_used[i]==FALSE) {
853 thr_ret = pthread_key_create(&TLS_keys[i], NULL);
854 g_assert (thr_ret == 0);
856 pthread_mutex_unlock (&TLS_mutex);
859 g_message ("%s: returning key %d", __func__, i);
866 pthread_mutex_unlock (&TLS_mutex);
869 g_message ("%s: out of indices", __func__);
873 return(TLS_OUT_OF_INDEXES);
876 #define MAKE_GC_ID(idx) (GUINT_TO_POINTER((idx)|(GetCurrentThreadId()<<8)))
880 * @idx: The TLS index to free
882 * Releases a TLS index, making it available for reuse. This call
883 * will delete any TLS data stored under index @idx in all threads.
885 * Return value: %TRUE on success, %FALSE otherwise.
887 gboolean TlsFree(guint32 idx)
892 g_message ("%s: freeing key %d", __func__, idx);
895 pthread_mutex_lock (&TLS_mutex);
897 if(TLS_used[idx]==FALSE) {
898 pthread_mutex_unlock (&TLS_mutex);
904 thr_ret = pthread_key_delete(TLS_keys[idx]);
905 g_assert (thr_ret == 0);
907 pthread_mutex_unlock (&TLS_mutex);
914 * @idx: The TLS index to retrieve
916 * Retrieves the TLS data stored under index @idx.
918 * Return value: The value stored in the TLS index @idx in the current
919 * thread, or %NULL on error. As %NULL can be a valid return value,
920 * in this case GetLastError() returns %ERROR_SUCCESS.
922 gpointer TlsGetValue(guint32 idx)
927 g_message ("%s: looking up key %d", __func__, idx);
930 ret=pthread_getspecific(TLS_keys[idx]);
933 g_message ("%s: returning %p", __func__, ret);
941 * @idx: The TLS index to store
942 * @value: The value to store under index @idx
944 * Stores @value at TLS index @idx.
946 * Return value: %TRUE on success, %FALSE otherwise.
948 gboolean TlsSetValue(guint32 idx, gpointer value)
953 g_message ("%s: setting key %d to %p", __func__, idx, value);
957 ret=pthread_setspecific(TLS_keys[idx], value);
960 g_message ("%s: pthread_setspecific error: %s", __func__,
969 * @ms: The time in milliseconds to suspend for
970 * @alertable: if TRUE, the wait can be interrupted by an APC call
972 * Suspends execution of the current thread for @ms milliseconds. A
973 * value of zero causes the thread to relinquish its time slice. A
974 * value of %INFINITE causes an infinite delay.
976 guint32 SleepEx(guint32 ms, gboolean alertable)
978 struct timespec req, rem;
981 gpointer current_thread = NULL;
984 g_message("%s: Sleeping for %d ms", __func__, ms);
988 current_thread = _wapi_thread_handle_from_id (pthread_self ());
989 if (current_thread == NULL) {
990 SetLastError (ERROR_INVALID_HANDLE);
994 if (_wapi_thread_apc_pending (current_thread)) {
995 _wapi_thread_dispatch_apc_queue (current_thread);
996 return WAIT_IO_COMPLETION;
1005 /* FIXME: check for INFINITE and sleep forever */
1006 ms_quot = ms / 1000;
1010 req.tv_nsec=ms_rem*1000000;
1013 ret=nanosleep(&req, &rem);
1015 if (alertable && _wapi_thread_apc_pending (current_thread)) {
1016 _wapi_thread_dispatch_apc_queue (current_thread);
1017 return WAIT_IO_COMPLETION;
1021 /* Sleep interrupted with rem time remaining */
1023 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
1025 g_message("%s: Still got %d ms to go", __func__, rems);
1034 void Sleep(guint32 ms)
1039 gboolean _wapi_thread_cur_apc_pending (void)
1041 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
1043 if (thread == NULL) {
1044 SetLastError (ERROR_INVALID_HANDLE);
1048 return(_wapi_thread_apc_pending (thread));
1051 gboolean _wapi_thread_apc_pending (gpointer handle)
1053 struct _WapiHandle_thread *thread;
1056 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1057 (gpointer *)&thread);
1060 /* This might happen at process shutdown, as all
1061 * thread handles are forcibly closed. If a thread
1062 * still has an alertable wait the final
1063 * _wapi_thread_apc_pending check will probably fail
1064 * to find the handle
1066 g_warning ("%s: error looking up thread handle %p", __func__,
1072 return(thread->has_apc || thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE);
1075 gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
1077 /* We don't support calling APC functions */
1078 struct _WapiHandle_thread *thread;
1081 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1082 (gpointer *)&thread);
1085 thread->has_apc = FALSE;
1091 * In this implementation, APC_CALLBACK is ignored.
1092 * if HANDLE refers to the current thread, the only effect this function has
1093 * that if called from a signal handler, and the thread was waiting when receiving
1094 * the signal, the wait will be broken after the signal handler returns.
1095 * In this case, this function is async-signal-safe.
1097 guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer handle,
1100 struct _WapiHandle_thread *thread_handle;
1103 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1104 (gpointer *)&thread_handle);
1106 g_warning ("%s: error looking up thread handle %p", __func__,
1111 g_assert (thread_handle->id == GetCurrentThreadId ());
1112 /* No locking/memory barriers are needed here */
1113 thread_handle->has_apc = TRUE;
1118 * wapi_interrupt_thread:
1120 * This is not part of the WIN32 API.
1121 * The state of the thread handle HANDLE is set to 'interrupted' which means that
1122 * if the thread calls one of the WaitFor functions, the function will return with
1123 * WAIT_IO_COMPLETION instead of waiting. Also, if the thread was waiting when
1124 * this function was called, the wait will be broken.
1125 * It is possible that the wait functions return WAIT_IO_COMPLETION, but the
1126 * target thread didn't receive the interrupt signal yet, in this case it should
1127 * call the wait function again. This essentially means that the target thread will
1128 * busy wait until it is ready to process the interruption.
1129 * FIXME: get rid of QueueUserAPC and thread->has_apc, SleepEx seems to require it.
1131 void wapi_interrupt_thread (gpointer thread_handle)
1133 struct _WapiHandle_thread *thread;
1135 gpointer prev_handle, wait_handle;
1137 pthread_cond_t *cond;
1138 mono_mutex_t *mutex;
1140 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1141 (gpointer *)&thread);
1145 wait_handle = thread->wait_handle;
1148 * Atomically obtain the handle the thread is waiting on, and
1149 * change it to a flag value.
1151 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1152 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1153 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1154 /* Already interrupted */
1156 if (prev_handle == wait_handle)
1162 WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread_handle->id););
1168 /* If we reach here, then wait_handle is set to the flag value,
1169 * which means that the target thread is either
1170 * - before the first CAS in timedwait, which means it won't enter the
1172 * - it is after the first CAS, so it is already waiting, or it will
1173 * enter the wait, and it will be interrupted by the broadcast.
1175 idx = GPOINTER_TO_UINT(wait_handle);
1176 cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
1177 mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
1179 mono_mutex_lock (mutex);
1180 mono_cond_broadcast (cond);
1181 mono_mutex_unlock (mutex);
1183 /* ref added by set_wait_handle */
1184 _wapi_handle_unref (wait_handle);
1188 * wapi_self_interrupt:
1190 * This is not part of the WIN32 API.
1191 * Set the 'interrupted' state of the calling thread if it's NULL.
1193 void wapi_self_interrupt (void)
1195 struct _WapiHandle_thread *thread;
1197 gpointer prev_handle, wait_handle;
1198 gpointer thread_handle;
1201 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1202 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1203 (gpointer *)&thread);
1207 wait_handle = thread->wait_handle;
1210 * Atomically obtain the handle the thread is waiting on, and
1211 * change it to a flag value.
1213 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1214 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1215 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1216 /* Already interrupted */
1218 /*We did not get interrupted*/
1219 if (prev_handle == wait_handle)
1226 /* ref added by set_wait_handle */
1227 _wapi_handle_unref (wait_handle);
1231 _wapi_handle_unref (thread_handle);
1235 * wapi_clear_interruption:
1237 * This is not part of the WIN32 API.
1238 * Clear the 'interrupted' state of the calling thread.
1239 * This function is signal safe
1241 void wapi_clear_interruption (void)
1243 struct _WapiHandle_thread *thread;
1245 gpointer prev_handle;
1246 gpointer thread_handle;
1248 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1249 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1250 (gpointer *)&thread);
1253 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1254 NULL, INTERRUPTION_REQUESTED_HANDLE);
1255 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1256 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1258 _wapi_handle_unref (thread_handle);
1261 char* wapi_current_thread_desc ()
1263 struct _WapiHandle_thread *thread;
1267 gpointer thread_handle;
1271 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1272 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1273 (gpointer *)&thread);
1275 return g_strdup_printf ("thread handle %p state : lookup failure", thread_handle);
1277 handle = thread->wait_handle;
1278 text = g_string_new (0);
1279 g_string_append_printf (text, "thread handle %p state : ", thread_handle);
1282 g_string_append_printf (text, "not waiting");
1283 else if (handle == INTERRUPTION_REQUESTED_HANDLE)
1284 g_string_append_printf (text, "interrupted state");
1286 g_string_append_printf (text, "waiting on %p : %s ", handle, _wapi_handle_typename[_wapi_handle_type (handle)]);
1287 g_string_append_printf (text, " owns (");
1288 for (i = 0; i < thread->owned_mutexes->len; i++) {
1289 gpointer mutex = g_ptr_array_index (thread->owned_mutexes, i);
1291 g_string_append_printf (text, ", %p", mutex);
1293 g_string_append_printf (text, "%p", mutex);
1295 g_string_append_printf (text, ")");
1298 g_string_free (text, FALSE);
1303 * wapi_thread_set_wait_handle:
1305 * Set the wait handle for the current thread to HANDLE. Return TRUE on success, FALSE
1306 * if the thread is in interrupted state, and cannot start waiting.
1308 gboolean wapi_thread_set_wait_handle (gpointer handle)
1310 struct _WapiHandle_thread *thread;
1312 gpointer prev_handle;
1313 gpointer thread_handle;
1315 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1316 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1317 (gpointer *)&thread);
1320 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1322 _wapi_handle_unref (thread_handle);
1324 if (prev_handle == NULL) {
1325 /* thread->wait_handle acts as an additional reference to the handle */
1326 _wapi_handle_ref (handle);
1328 WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
1330 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
1331 WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
1334 return prev_handle == NULL;
1338 * wapi_thread_clear_wait_handle:
1340 * Clear the wait handle of the current thread.
1342 void wapi_thread_clear_wait_handle (gpointer handle)
1344 struct _WapiHandle_thread *thread;
1346 gpointer prev_handle;
1347 gpointer thread_handle;
1349 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1350 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1351 (gpointer *)&thread);
1354 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1357 if (prev_handle == handle) {
1358 _wapi_handle_unref (handle);
1359 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1361 /*It can be NULL if it was asynchronously cleared*/
1362 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE || prev_handle == NULL);
1363 WAIT_DEBUG (printf ("%p: finished waiting.\n", GetCurrentThreadId ()););
1366 _wapi_handle_unref (thread_handle);
1369 void _wapi_thread_own_mutex (gpointer mutex)
1371 struct _WapiHandle_thread *thread_handle;
1375 thread = _wapi_thread_handle_from_id (pthread_self ());
1376 if (thread == NULL) {
1377 g_warning ("%s: error looking up thread by ID", __func__);
1381 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1382 (gpointer *)&thread_handle);
1384 g_warning ("%s: error looking up thread handle %p", __func__,
1389 _wapi_handle_ref (mutex);
1391 g_ptr_array_add (thread_handle->owned_mutexes, mutex);
1394 void _wapi_thread_disown_mutex (gpointer mutex)
1396 struct _WapiHandle_thread *thread_handle;
1400 thread = _wapi_thread_handle_from_id (pthread_self ());
1401 if (thread == NULL) {
1402 g_warning ("%s: error looking up thread by ID", __func__);
1406 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1407 (gpointer *)&thread_handle);
1409 g_warning ("%s: error looking up thread handle %p", __func__,
1414 _wapi_handle_unref (mutex);
1416 g_ptr_array_remove (thread_handle->owned_mutexes, mutex);