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 if (idx >= TLS_MINIMUM_AVAILABLE) {
896 SetLastError (ERROR_INVALID_PARAMETER);
900 pthread_mutex_lock (&TLS_mutex);
902 if(TLS_used[idx]==FALSE) {
903 pthread_mutex_unlock (&TLS_mutex);
904 SetLastError (ERROR_INVALID_PARAMETER);
909 thr_ret = pthread_key_delete(TLS_keys[idx]);
910 g_assert (thr_ret == 0);
912 pthread_mutex_unlock (&TLS_mutex);
919 * @idx: The TLS index to retrieve
921 * Retrieves the TLS data stored under index @idx.
923 * Return value: The value stored in the TLS index @idx in the current
924 * thread, or %NULL on error. As %NULL can be a valid return value,
925 * in this case GetLastError() returns %ERROR_SUCCESS.
927 gpointer TlsGetValue(guint32 idx)
932 g_message ("%s: looking up key %d", __func__, idx);
934 if (idx >= TLS_MINIMUM_AVAILABLE) {
935 SetLastError (ERROR_INVALID_PARAMETER);
938 ret=pthread_getspecific(TLS_keys[idx]);
941 g_message ("%s: returning %p", __func__, ret);
944 SetLastError (ERROR_SUCCESS);
950 * @idx: The TLS index to store
951 * @value: The value to store under index @idx
953 * Stores @value at TLS index @idx.
955 * Return value: %TRUE on success, %FALSE otherwise.
957 gboolean TlsSetValue(guint32 idx, gpointer value)
962 g_message ("%s: setting key %d to %p", __func__, idx, value);
964 if (idx >= TLS_MINIMUM_AVAILABLE) {
965 SetLastError (ERROR_INVALID_PARAMETER);
969 ret=pthread_setspecific(TLS_keys[idx], value);
972 g_message ("%s: pthread_setspecific error: %s", __func__,
981 * @ms: The time in milliseconds to suspend for
982 * @alertable: if TRUE, the wait can be interrupted by an APC call
984 * Suspends execution of the current thread for @ms milliseconds. A
985 * value of zero causes the thread to relinquish its time slice. A
986 * value of %INFINITE causes an infinite delay.
988 guint32 SleepEx(guint32 ms, gboolean alertable)
990 struct timespec req, rem;
993 gpointer current_thread = NULL;
996 g_message("%s: Sleeping for %d ms", __func__, ms);
1000 current_thread = _wapi_thread_handle_from_id (pthread_self ());
1001 if (current_thread == NULL) {
1002 SetLastError (ERROR_INVALID_HANDLE);
1003 return(WAIT_FAILED);
1006 if (_wapi_thread_apc_pending (current_thread)) {
1007 _wapi_thread_dispatch_apc_queue (current_thread);
1008 return WAIT_IO_COMPLETION;
1017 /* FIXME: check for INFINITE and sleep forever */
1018 ms_quot = ms / 1000;
1022 req.tv_nsec=ms_rem*1000000;
1025 ret=nanosleep(&req, &rem);
1027 if (alertable && _wapi_thread_apc_pending (current_thread)) {
1028 _wapi_thread_dispatch_apc_queue (current_thread);
1029 return WAIT_IO_COMPLETION;
1033 /* Sleep interrupted with rem time remaining */
1035 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
1037 g_message("%s: Still got %d ms to go", __func__, rems);
1046 void Sleep(guint32 ms)
1051 gboolean _wapi_thread_cur_apc_pending (void)
1053 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
1055 if (thread == NULL) {
1056 SetLastError (ERROR_INVALID_HANDLE);
1060 return(_wapi_thread_apc_pending (thread));
1063 gboolean _wapi_thread_apc_pending (gpointer handle)
1065 struct _WapiHandle_thread *thread;
1068 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1069 (gpointer *)&thread);
1072 /* This might happen at process shutdown, as all
1073 * thread handles are forcibly closed. If a thread
1074 * still has an alertable wait the final
1075 * _wapi_thread_apc_pending check will probably fail
1076 * to find the handle
1078 g_warning ("%s: error looking up thread handle %p", __func__,
1084 return(thread->has_apc || thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE);
1087 gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
1089 /* We don't support calling APC functions */
1090 struct _WapiHandle_thread *thread;
1093 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1094 (gpointer *)&thread);
1097 thread->has_apc = FALSE;
1103 * In this implementation, APC_CALLBACK is ignored.
1104 * if HANDLE refers to the current thread, the only effect this function has
1105 * that if called from a signal handler, and the thread was waiting when receiving
1106 * the signal, the wait will be broken after the signal handler returns.
1107 * In this case, this function is async-signal-safe.
1109 guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer handle,
1112 struct _WapiHandle_thread *thread_handle;
1115 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1116 (gpointer *)&thread_handle);
1118 g_warning ("%s: error looking up thread handle %p", __func__,
1123 g_assert (thread_handle->id == GetCurrentThreadId ());
1124 /* No locking/memory barriers are needed here */
1125 thread_handle->has_apc = TRUE;
1130 * wapi_interrupt_thread:
1132 * This is not part of the WIN32 API.
1133 * The state of the thread handle HANDLE is set to 'interrupted' which means that
1134 * if the thread calls one of the WaitFor functions, the function will return with
1135 * WAIT_IO_COMPLETION instead of waiting. Also, if the thread was waiting when
1136 * this function was called, the wait will be broken.
1137 * It is possible that the wait functions return WAIT_IO_COMPLETION, but the
1138 * target thread didn't receive the interrupt signal yet, in this case it should
1139 * call the wait function again. This essentially means that the target thread will
1140 * busy wait until it is ready to process the interruption.
1141 * FIXME: get rid of QueueUserAPC and thread->has_apc, SleepEx seems to require it.
1143 void wapi_interrupt_thread (gpointer thread_handle)
1145 struct _WapiHandle_thread *thread;
1147 gpointer prev_handle, wait_handle;
1149 pthread_cond_t *cond;
1150 mono_mutex_t *mutex;
1152 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1153 (gpointer *)&thread);
1157 wait_handle = thread->wait_handle;
1160 * Atomically obtain the handle the thread is waiting on, and
1161 * change it to a flag value.
1163 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1164 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1165 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1166 /* Already interrupted */
1168 if (prev_handle == wait_handle)
1174 WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread_handle->id););
1180 /* If we reach here, then wait_handle is set to the flag value,
1181 * which means that the target thread is either
1182 * - before the first CAS in timedwait, which means it won't enter the
1184 * - it is after the first CAS, so it is already waiting, or it will
1185 * enter the wait, and it will be interrupted by the broadcast.
1187 idx = GPOINTER_TO_UINT(wait_handle);
1188 cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
1189 mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
1191 mono_mutex_lock (mutex);
1192 mono_cond_broadcast (cond);
1193 mono_mutex_unlock (mutex);
1195 /* ref added by set_wait_handle */
1196 _wapi_handle_unref (wait_handle);
1200 * wapi_self_interrupt:
1202 * This is not part of the WIN32 API.
1203 * Set the 'interrupted' state of the calling thread if it's NULL.
1205 void wapi_self_interrupt (void)
1207 struct _WapiHandle_thread *thread;
1209 gpointer prev_handle, wait_handle;
1210 gpointer thread_handle;
1213 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1214 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1215 (gpointer *)&thread);
1219 wait_handle = thread->wait_handle;
1222 * Atomically obtain the handle the thread is waiting on, and
1223 * change it to a flag value.
1225 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1226 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1227 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1228 /* Already interrupted */
1230 /*We did not get interrupted*/
1231 if (prev_handle == wait_handle)
1238 /* ref added by set_wait_handle */
1239 _wapi_handle_unref (wait_handle);
1243 _wapi_handle_unref (thread_handle);
1247 * wapi_clear_interruption:
1249 * This is not part of the WIN32 API.
1250 * Clear the 'interrupted' state of the calling thread.
1251 * This function is signal safe
1253 void wapi_clear_interruption (void)
1255 struct _WapiHandle_thread *thread;
1257 gpointer prev_handle;
1258 gpointer thread_handle;
1260 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1261 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1262 (gpointer *)&thread);
1265 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1266 NULL, INTERRUPTION_REQUESTED_HANDLE);
1267 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1268 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1270 _wapi_handle_unref (thread_handle);
1273 char* wapi_current_thread_desc ()
1275 struct _WapiHandle_thread *thread;
1279 gpointer thread_handle;
1283 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1284 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1285 (gpointer *)&thread);
1287 return g_strdup_printf ("thread handle %p state : lookup failure", thread_handle);
1289 handle = thread->wait_handle;
1290 text = g_string_new (0);
1291 g_string_append_printf (text, "thread handle %p state : ", thread_handle);
1294 g_string_append_printf (text, "not waiting");
1295 else if (handle == INTERRUPTION_REQUESTED_HANDLE)
1296 g_string_append_printf (text, "interrupted state");
1298 g_string_append_printf (text, "waiting on %p : %s ", handle, _wapi_handle_typename[_wapi_handle_type (handle)]);
1299 g_string_append_printf (text, " owns (");
1300 for (i = 0; i < thread->owned_mutexes->len; i++) {
1301 gpointer mutex = g_ptr_array_index (thread->owned_mutexes, i);
1303 g_string_append_printf (text, ", %p", mutex);
1305 g_string_append_printf (text, "%p", mutex);
1307 g_string_append_printf (text, ")");
1310 g_string_free (text, FALSE);
1315 * wapi_thread_set_wait_handle:
1317 * Set the wait handle for the current thread to HANDLE. Return TRUE on success, FALSE
1318 * if the thread is in interrupted state, and cannot start waiting.
1320 gboolean wapi_thread_set_wait_handle (gpointer handle)
1322 struct _WapiHandle_thread *thread;
1324 gpointer prev_handle;
1325 gpointer thread_handle;
1327 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1328 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1329 (gpointer *)&thread);
1332 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1334 _wapi_handle_unref (thread_handle);
1336 if (prev_handle == NULL) {
1337 /* thread->wait_handle acts as an additional reference to the handle */
1338 _wapi_handle_ref (handle);
1340 WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
1342 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
1343 WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
1346 return prev_handle == NULL;
1350 * wapi_thread_clear_wait_handle:
1352 * Clear the wait handle of the current thread.
1354 void wapi_thread_clear_wait_handle (gpointer handle)
1356 struct _WapiHandle_thread *thread;
1358 gpointer prev_handle;
1359 gpointer thread_handle;
1361 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1362 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1363 (gpointer *)&thread);
1366 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1369 if (prev_handle == handle) {
1370 _wapi_handle_unref (handle);
1371 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1373 /*It can be NULL if it was asynchronously cleared*/
1374 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE || prev_handle == NULL);
1375 WAIT_DEBUG (printf ("%p: finished waiting.\n", GetCurrentThreadId ()););
1378 _wapi_handle_unref (thread_handle);
1381 void _wapi_thread_own_mutex (gpointer mutex)
1383 struct _WapiHandle_thread *thread_handle;
1387 thread = _wapi_thread_handle_from_id (pthread_self ());
1388 if (thread == NULL) {
1389 g_warning ("%s: error looking up thread by ID", __func__);
1393 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1394 (gpointer *)&thread_handle);
1396 g_warning ("%s: error looking up thread handle %p", __func__,
1401 _wapi_handle_ref (mutex);
1403 g_ptr_array_add (thread_handle->owned_mutexes, mutex);
1406 void _wapi_thread_disown_mutex (gpointer mutex)
1408 struct _WapiHandle_thread *thread_handle;
1412 thread = _wapi_thread_handle_from_id (pthread_self ());
1413 if (thread == NULL) {
1414 g_warning ("%s: error looking up thread by ID", __func__);
1418 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1419 (gpointer *)&thread_handle);
1421 g_warning ("%s: error looking up thread handle %p", __func__,
1426 _wapi_handle_unref (mutex);
1428 g_ptr_array_remove (thread_handle->owned_mutexes, mutex);