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/mono-spinlock.h>
30 #include <mono/io-layer/mutex-private.h>
31 #include <mono/io-layer/atomic.h>
33 #ifdef HAVE_VALGRIND_MEMCHECK_H
34 #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 = 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
276 thread->id = pthread_self();
279 g_message ("%s: started thread id %ld", __func__, thread->id);
282 if (thread->create_flags & CREATE_SUSPENDED) {
283 _wapi_thread_suspend (thread);
286 thread_exit (thread->start_routine (thread->start_arg),
290 /* Even though we tell gcc that this function doesn't return,
291 * other compilers won't see that.
299 * @security: Ignored for now.
300 * @stacksize: the size in bytes of the new thread's stack. Use 0 to
301 * default to the normal stack size. (Ignored for now).
302 * @start: The function that the new thread should start with
303 * @param: The parameter to give to @start.
304 * @create: If 0, the new thread is ready to run immediately. If
305 * %CREATE_SUSPENDED, the new thread will be in the suspended state,
306 * requiring a ResumeThread() call to continue running.
307 * @tid: If non-NULL, the ID of the new thread is stored here. NB
308 * this is defined as a DWORD (ie 32bit) in the MS API, but we need to
309 * cope with 64 bit IDs for s390x and amd64.
311 * Creates a new threading handle.
313 * Return value: a new handle, or NULL
315 gpointer CreateThread(WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 stacksize,
316 WapiThreadStart start, gpointer param, guint32 create,
319 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
326 gpointer ct_ret = NULL;
328 mono_once (&thread_hash_once, thread_hash_init);
329 mono_once (&thread_ops_once, thread_ops_init);
335 thread_handle.state = THREAD_STATE_START;
336 thread_handle.owned_mutexes = g_ptr_array_new ();
337 thread_handle.create_flags = create;
338 thread_handle.start_routine = start;
339 thread_handle.start_arg = param;
341 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
342 if (handle == _WAPI_HANDLE_INVALID) {
343 g_warning ("%s: error creating thread handle", __func__);
344 SetLastError (ERROR_GEN_FAILURE);
349 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
351 thr_ret = _wapi_handle_lock_handle (handle);
352 g_assert (thr_ret == 0);
354 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
355 (gpointer *)&thread_handle_p);
357 g_warning ("%s: error looking up thread handle %p", __func__,
359 SetLastError (ERROR_GEN_FAILURE);
364 /* Hold a reference while the thread is active, because we use
365 * the handle to store thread exit information
367 _wapi_handle_ref (handle);
369 /* Set a 2M stack size. This is the default on Linux, but BSD
370 * needs it. (The original bug report from Martin Dvorak <md@9ll.cz>
371 * set the size to 2M-4k. I don't know why it's short by 4k, so
372 * I'm leaving it as 2M until I'm told differently.)
374 thr_ret = pthread_attr_init(&attr);
375 g_assert (thr_ret == 0);
377 /* defaults of 2Mb for 32bits and 4Mb for 64bits */
378 /* temporarily changed to use 1 MB: this allows more threads
379 * to be used, as well as using less virtual memory and so
380 * more is available for the GC heap.
383 #if HAVE_VALGRIND_MEMCHECK_H
384 if (RUNNING_ON_VALGRIND) {
387 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
390 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
394 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
395 thr_ret = pthread_attr_setstacksize(&attr, stacksize);
396 g_assert (thr_ret == 0);
399 MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
400 thread_handle_p->handle = handle;
403 ret = pthread_create (&thread_handle_p->id, &attr,
404 thread_start_routine, (void *)thread_handle_p);
405 #ifdef MONO_REGISTER_THREAD_ATTR
406 mono_register_thread_attr (&attr, &thread_handle_p->id);
411 g_message ("%s: Thread create error: %s", __func__,
415 /* Two, because of the reference we took above */
423 g_message("%s: Started thread handle %p ID %ld", __func__, handle,
424 thread_handle_p->id);
428 #ifdef PTHREAD_POINTER_ID
429 /* Don't use GPOINTER_TO_UINT here, it can't cope with
430 * sizeof(void *) > sizeof(uint) when a cast to uint
433 *tid = (gsize)(thread_handle_p->id);
435 *tid = thread_handle_p->id;
440 thr_ret = _wapi_handle_unlock_handle (handle);
441 g_assert (thr_ret == 0);
442 pthread_cleanup_pop (0);
444 /* Must not call _wapi_handle_unref() with the shared handles
447 for (i = 0; i < unrefs; i++) {
448 _wapi_handle_unref (handle);
454 /* The only time this function is called when tid != pthread_self ()
455 * is from OpenThread (), so we can fast-path most cases by just
456 * looking up the handle in TLS. OpenThread () must cope with a NULL
457 * return and do a handle search in that case.
459 gpointer _wapi_thread_handle_from_id (pthread_t tid)
463 if (pthread_equal (tid, pthread_self ()) &&
464 (ret = pthread_getspecific (thread_hash_key)) != NULL) {
465 /* We know the handle */
468 g_message ("%s: Returning %p for self thread %ld from TLS",
476 g_message ("%s: Returning NULL for unknown or non-self thread %ld",
484 static gboolean find_thread_by_id (gpointer handle, gpointer user_data)
486 pthread_t tid = (pthread_t)user_data;
487 struct _WapiHandle_thread *thread_handle;
490 /* Ignore threads that have already exited (ie they are signalled) */
491 if (_wapi_handle_issignalled (handle) == FALSE) {
492 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
493 (gpointer *)&thread_handle);
495 /* It's possible that the handle has vanished
496 * during the _wapi_search_handle before it
497 * gets here, so don't spam the console with
504 g_message ("%s: looking at thread %ld from process %d", __func__, thread_handle->id, 0);
507 if (pthread_equal (thread_handle->id, tid)) {
509 g_message ("%s: found the thread we are looking for",
517 g_message ("%s: not found %ld, returning FALSE", __func__, tid);
523 /* NB tid is 32bit in MS API, but we need 64bit on amd64 and s390x
524 * (and probably others)
526 gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, gsize tid)
530 mono_once (&thread_hash_once, thread_hash_init);
531 mono_once (&thread_ops_once, thread_ops_init);
534 g_message ("%s: looking up thread %"G_GSIZE_FORMAT, __func__, tid);
537 ret = _wapi_thread_handle_from_id ((pthread_t)tid);
539 /* We need to search for this thread */
540 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 */
542 /* if _wapi_search_handle() returns a found handle, it
545 _wapi_handle_ref (ret);
549 g_message ("%s: returning thread handle %p", __func__, ret);
557 * @exitcode: Sets the thread's exit code, which can be read from
558 * another thread with GetExitCodeThread().
560 * Terminates the calling thread. A thread can also exit by returning
561 * from its start function. When the last thread in a process
562 * terminates, the process itself terminates.
564 void ExitThread(guint32 exitcode)
566 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
568 if (thread != NULL) {
569 thread_exit(exitcode, thread);
571 /* Just blow this thread away */
578 * @handle: The thread handle to query
579 * @exitcode: The thread @handle exit code is stored here
581 * Finds the exit code of @handle, and stores it in @exitcode. If the
582 * thread @handle is still running, the value stored is %STILL_ACTIVE.
584 * Return value: %TRUE, or %FALSE on error.
586 gboolean GetExitCodeThread(gpointer handle, guint32 *exitcode)
588 struct _WapiHandle_thread *thread_handle;
591 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
592 (gpointer *)&thread_handle);
594 g_warning ("%s: error looking up thread handle %p", __func__,
600 g_message ("%s: Finding exit status for thread handle %p id %ld",
601 __func__, handle, thread_handle->id);
604 if (exitcode == NULL) {
606 g_message ("%s: Nowhere to store exit code", __func__);
611 if (thread_handle->state != THREAD_STATE_EXITED) {
613 g_message ("%s: Thread still active (state %d, exited is %d)",
614 __func__, thread_handle->state,
615 THREAD_STATE_EXITED);
617 *exitcode = STILL_ACTIVE;
621 *exitcode = thread_handle->exitstatus;
627 * GetCurrentThreadId:
629 * Looks up the thread ID of the current thread. This ID can be
630 * passed to OpenThread() to create a new handle on this thread.
632 * Return value: the thread ID. NB this is defined as DWORD (ie 32
633 * bit) in the MS API, but we need to cope with 64 bit IDs for s390x
634 * and amd64. This doesn't really break the API, it just embraces and
635 * extends it on 64bit platforms :)
637 gsize GetCurrentThreadId(void)
639 pthread_t tid = pthread_self();
641 #ifdef PTHREAD_POINTER_ID
642 /* Don't use GPOINTER_TO_UINT here, it can't cope with
643 * sizeof(void *) > sizeof(uint) when a cast to uint would
652 static gpointer thread_attach(gsize *tid)
654 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
659 mono_once (&thread_hash_once, thread_hash_init);
660 mono_once (&thread_ops_once, thread_ops_init);
662 thread_handle.state = THREAD_STATE_START;
663 thread_handle.owned_mutexes = g_ptr_array_new ();
665 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
666 if (handle == _WAPI_HANDLE_INVALID) {
667 g_warning ("%s: error creating thread handle", __func__);
669 SetLastError (ERROR_GEN_FAILURE);
673 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
675 thr_ret = _wapi_handle_lock_handle (handle);
676 g_assert (thr_ret == 0);
678 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
679 (gpointer *)&thread_handle_p);
681 g_warning ("%s: error looking up thread handle %p", __func__,
684 SetLastError (ERROR_GEN_FAILURE);
688 /* Hold a reference while the thread is active, because we use
689 * the handle to store thread exit information
691 _wapi_handle_ref (handle);
693 /* suspend_sem is not used for attached threads, but
694 * thread_exit() might try to destroy it
696 MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
697 thread_handle_p->handle = handle;
698 thread_handle_p->id = pthread_self ();
700 thr_ret = pthread_setspecific (thread_hash_key, (void *)handle);
701 g_assert (thr_ret == 0);
703 thr_ret = pthread_setspecific (thread_attached_key, (void *)handle);
704 g_assert (thr_ret == 0);
707 g_message("%s: Attached thread handle %p ID %ld", __func__, handle,
708 thread_handle_p->id);
712 #ifdef PTHREAD_POINTER_ID
713 /* Don't use GPOINTER_TO_UINT here, it can't cope with
714 * sizeof(void *) > sizeof(uint) when a cast to uint
717 *tid = (gsize)(thread_handle_p->id);
719 *tid = thread_handle_p->id;
724 thr_ret = _wapi_handle_unlock_handle (handle);
725 g_assert (thr_ret == 0);
726 pthread_cleanup_pop (0);
731 gpointer _wapi_thread_duplicate ()
735 mono_once (&thread_hash_once, thread_hash_init);
736 mono_once (&thread_ops_once, thread_ops_init);
738 ret = _wapi_thread_handle_from_id (pthread_self ());
740 ret = thread_attach (NULL);
742 _wapi_handle_ref (ret);
751 * Looks up the handle associated with the current thread. Under
752 * Windows this is a pseudohandle, and must be duplicated with
753 * DuplicateHandle() for some operations.
755 * Return value: The current thread handle, or %NULL on failure.
756 * (Unknown whether Windows has a possible failure here. It may be
757 * necessary to implement the pseudohandle-constant behaviour).
759 gpointer GetCurrentThread(void)
761 mono_once(&thread_hash_once, thread_hash_init);
762 mono_once (&thread_ops_once, thread_ops_init);
764 return(_WAPI_THREAD_CURRENT);
769 * @handle: the thread handle to resume
771 * Decrements the suspend count of thread @handle. A thread can only
772 * run if its suspend count is zero.
774 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
776 guint32 ResumeThread(gpointer handle)
778 struct _WapiHandle_thread *thread_handle;
781 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
782 (gpointer *)&thread_handle);
784 g_warning ("%s: error looking up thread handle %p", __func__,
790 /* This is still a kludge that only copes with starting a
791 * thread that was suspended on create, so don't bother with
792 * the suspend count crap yet
794 _wapi_thread_resume (thread_handle);
800 * @handle: the thread handle to suspend
802 * Increments the suspend count of thread @handle. A thread can only
803 * run if its suspend count is zero.
805 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
807 guint32 SuspendThread(gpointer handle)
813 * We assume here that TLS_MINIMUM_AVAILABLE is less than
814 * PTHREAD_KEYS_MAX, allowing enough overhead for a few TLS keys for
817 * Currently TLS_MINIMUM_AVAILABLE is 64 and _POSIX_THREAD_KEYS_MAX
818 * (the minimum value for PTHREAD_KEYS_MAX) is 128, so we should be
822 static pthread_key_t TLS_keys[TLS_MINIMUM_AVAILABLE];
823 static gboolean TLS_used[TLS_MINIMUM_AVAILABLE]={FALSE};
824 static guint32 TLS_spinlock=0;
827 mono_pthread_key_for_tls (guint32 idx)
829 return (guint32)TLS_keys [idx];
835 * Allocates a Thread Local Storage (TLS) index. Any thread in the
836 * same process can use this index to store and retrieve values that
837 * are local to that thread.
839 * Return value: The index value, or %TLS_OUT_OF_INDEXES if no index
842 guint32 TlsAlloc(void)
847 MONO_SPIN_LOCK (TLS_spinlock);
849 for(i=0; i<TLS_MINIMUM_AVAILABLE; i++) {
850 if(TLS_used[i]==FALSE) {
852 thr_ret = pthread_key_create(&TLS_keys[i], NULL);
853 g_assert (thr_ret == 0);
855 MONO_SPIN_UNLOCK (TLS_spinlock);
858 g_message ("%s: returning key %d", __func__, i);
865 MONO_SPIN_UNLOCK (TLS_spinlock);
868 g_message ("%s: out of indices", __func__);
872 return(TLS_OUT_OF_INDEXES);
875 #define MAKE_GC_ID(idx) (GUINT_TO_POINTER((idx)|(GetCurrentThreadId()<<8)))
879 * @idx: The TLS index to free
881 * Releases a TLS index, making it available for reuse. This call
882 * will delete any TLS data stored under index @idx in all threads.
884 * Return value: %TRUE on success, %FALSE otherwise.
886 gboolean TlsFree(guint32 idx)
891 g_message ("%s: freeing key %d", __func__, idx);
894 MONO_SPIN_LOCK (TLS_spinlock);
896 if(TLS_used[idx]==FALSE) {
897 MONO_SPIN_UNLOCK (TLS_spinlock);
903 thr_ret = pthread_key_delete(TLS_keys[idx]);
904 g_assert (thr_ret == 0);
906 MONO_SPIN_UNLOCK (TLS_spinlock);
913 * @idx: The TLS index to retrieve
915 * Retrieves the TLS data stored under index @idx.
917 * Return value: The value stored in the TLS index @idx in the current
918 * thread, or %NULL on error. As %NULL can be a valid return value,
919 * in this case GetLastError() returns %ERROR_SUCCESS.
921 gpointer TlsGetValue(guint32 idx)
926 g_message ("%s: looking up key %d", __func__, idx);
929 ret=pthread_getspecific(TLS_keys[idx]);
932 g_message ("%s: returning %p", __func__, ret);
940 * @idx: The TLS index to store
941 * @value: The value to store under index @idx
943 * Stores @value at TLS index @idx.
945 * Return value: %TRUE on success, %FALSE otherwise.
947 gboolean TlsSetValue(guint32 idx, gpointer value)
952 g_message ("%s: setting key %d to %p", __func__, idx, value);
955 MONO_SPIN_LOCK (TLS_spinlock);
957 if(TLS_used[idx]==FALSE) {
959 g_message ("%s: key %d unused", __func__, idx);
962 MONO_SPIN_UNLOCK (TLS_spinlock);
967 ret=pthread_setspecific(TLS_keys[idx], value);
970 g_message ("%s: pthread_setspecific error: %s", __func__,
974 MONO_SPIN_UNLOCK (TLS_spinlock);
979 MONO_SPIN_UNLOCK (TLS_spinlock);
986 * @ms: The time in milliseconds to suspend for
987 * @alertable: if TRUE, the wait can be interrupted by an APC call
989 * Suspends execution of the current thread for @ms milliseconds. A
990 * value of zero causes the thread to relinquish its time slice. A
991 * value of %INFINITE causes an infinite delay.
993 guint32 SleepEx(guint32 ms, gboolean alertable)
995 struct timespec req, rem;
998 gpointer current_thread = NULL;
1001 g_message("%s: Sleeping for %d ms", __func__, ms);
1005 current_thread = _wapi_thread_handle_from_id (pthread_self ());
1006 if (current_thread == NULL) {
1007 SetLastError (ERROR_INVALID_HANDLE);
1008 return(WAIT_FAILED);
1011 if (_wapi_thread_apc_pending (current_thread)) {
1012 _wapi_thread_dispatch_apc_queue (current_thread);
1013 return WAIT_IO_COMPLETION;
1022 /* FIXME: check for INFINITE and sleep forever */
1023 ms_quot = ms / 1000;
1027 req.tv_nsec=ms_rem*1000000;
1030 ret=nanosleep(&req, &rem);
1032 if (alertable && _wapi_thread_apc_pending (current_thread)) {
1033 _wapi_thread_dispatch_apc_queue (current_thread);
1034 return WAIT_IO_COMPLETION;
1038 /* Sleep interrupted with rem time remaining */
1040 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
1042 g_message("%s: Still got %d ms to go", __func__, rems);
1051 void Sleep(guint32 ms)
1056 gboolean _wapi_thread_cur_apc_pending (void)
1058 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
1060 if (thread == NULL) {
1061 SetLastError (ERROR_INVALID_HANDLE);
1065 return(_wapi_thread_apc_pending (thread));
1068 gboolean _wapi_thread_apc_pending (gpointer handle)
1070 struct _WapiHandle_thread *thread;
1073 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1074 (gpointer *)&thread);
1077 /* This might happen at process shutdown, as all
1078 * thread handles are forcibly closed. If a thread
1079 * still has an alertable wait the final
1080 * _wapi_thread_apc_pending check will probably fail
1081 * to find the handle
1083 g_warning ("%s: error looking up thread handle %p", __func__,
1089 return(thread->has_apc || thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE);
1092 gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
1094 /* We don't support calling APC functions */
1095 struct _WapiHandle_thread *thread;
1098 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1099 (gpointer *)&thread);
1102 thread->has_apc = FALSE;
1108 * In this implementation, APC_CALLBACK is ignored.
1109 * if HANDLE refers to the current thread, the only effect this function has
1110 * that if called from a signal handler, and the thread was waiting when receiving
1111 * the signal, the wait will be broken after the signal handler returns.
1112 * In this case, this function is async-signal-safe.
1114 guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer handle,
1117 struct _WapiHandle_thread *thread_handle;
1120 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1121 (gpointer *)&thread_handle);
1123 g_warning ("%s: error looking up thread handle %p", __func__,
1128 g_assert (thread_handle->id == GetCurrentThreadId ());
1129 /* No locking/memory barriers are needed here */
1130 thread_handle->has_apc = TRUE;
1135 * wapi_interrupt_thread:
1137 * This is not part of the WIN32 API.
1138 * The state of the thread handle HANDLE is set to 'interrupted' which means that
1139 * if the thread calls one of the WaitFor functions, the function will return with
1140 * WAIT_IO_COMPLETION instead of waiting. Also, if the thread was waiting when
1141 * this function was called, the wait will be broken.
1142 * It is possible that the wait functions return WAIT_IO_COMPLETION, but the
1143 * target thread didn't receive the interrupt signal yet, in this case it should
1144 * call the wait function again. This essentially means that the target thread will
1145 * busy wait until it is ready to process the interruption.
1146 * FIXME: get rid of QueueUserAPC and thread->has_apc, SleepEx seems to require it.
1148 void wapi_interrupt_thread (gpointer thread_handle)
1150 struct _WapiHandle_thread *thread;
1152 gpointer prev_handle, wait_handle;
1154 pthread_cond_t *cond;
1155 mono_mutex_t *mutex;
1157 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1158 (gpointer *)&thread);
1162 wait_handle = thread->wait_handle;
1165 * Atomically obtain the handle the thread is waiting on, and
1166 * change it to a flag value.
1168 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1169 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1170 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1171 /* Already interrupted */
1173 if (prev_handle == wait_handle)
1179 WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread_handle->id););
1185 /* If we reach here, then wait_handle is set to the flag value,
1186 * which means that the target thread is either
1187 * - before the first CAS in timedwait, which means it won't enter the
1189 * - it is after the first CAS, so it is already waiting, or it will
1190 * enter the wait, and it will be interrupted by the broadcast.
1192 idx = GPOINTER_TO_UINT(wait_handle);
1193 cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
1194 mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
1196 mono_mutex_lock (mutex);
1197 mono_cond_broadcast (cond);
1198 mono_mutex_unlock (mutex);
1200 /* ref added by set_wait_handle */
1201 _wapi_handle_unref (wait_handle);
1205 * wapi_clear_interruption:
1207 * This is not part of the WIN32 API.
1208 * Clear the 'interrupted' state of the calling thread.
1210 void wapi_clear_interruption (void)
1212 struct _WapiHandle_thread *thread;
1214 gpointer prev_handle;
1215 gpointer thread_handle;
1217 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1218 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1219 (gpointer *)&thread);
1222 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1223 NULL, INTERRUPTION_REQUESTED_HANDLE);
1224 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1225 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1227 _wapi_handle_unref (thread_handle);
1230 char* wapi_current_thread_desc ()
1232 struct _WapiHandle_thread *thread;
1236 gpointer thread_handle;
1240 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1241 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1242 (gpointer *)&thread);
1244 return g_strdup_printf ("thread handle %p state : lookup failure", thread_handle);
1246 handle = thread->wait_handle;
1247 text = g_string_new (0);
1248 g_string_append_printf (text, "thread handle %p state : ", thread_handle);
1251 g_string_append_printf (text, "not waiting");
1252 else if (handle == INTERRUPTION_REQUESTED_HANDLE)
1253 g_string_append_printf (text, "interrupted state");
1255 g_string_append_printf (text, "waiting on %p : %s ", handle, _wapi_handle_typename[_wapi_handle_type (handle)]);
1256 g_string_append_printf (text, " owns (");
1257 for (i = 0; i < thread->owned_mutexes->len; i++) {
1258 gpointer mutex = g_ptr_array_index (thread->owned_mutexes, i);
1260 g_string_append_printf (text, ", %p", mutex);
1262 g_string_append_printf (text, "%p", mutex);
1264 g_string_append_printf (text, ")");
1267 g_string_free (text, FALSE);
1272 * wapi_thread_set_wait_handle:
1274 * Set the wait handle for the current thread to HANDLE. Return TRUE on success, FALSE
1275 * if the thread is in interrupted state, and cannot start waiting.
1277 gboolean wapi_thread_set_wait_handle (gpointer handle)
1279 struct _WapiHandle_thread *thread;
1281 gpointer prev_handle;
1282 gpointer thread_handle;
1284 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1285 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1286 (gpointer *)&thread);
1289 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1291 _wapi_handle_unref (thread_handle);
1293 if (prev_handle == NULL) {
1294 /* thread->wait_handle acts as an additional reference to the handle */
1295 _wapi_handle_ref (handle);
1297 WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
1299 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
1300 WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
1303 return prev_handle == NULL;
1307 * wapi_thread_clear_wait_handle:
1309 * Clear the wait handle of the current thread.
1311 void wapi_thread_clear_wait_handle (gpointer handle)
1313 struct _WapiHandle_thread *thread;
1315 gpointer prev_handle;
1316 gpointer thread_handle;
1318 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1319 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1320 (gpointer *)&thread);
1323 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1326 if (prev_handle == handle) {
1327 _wapi_handle_unref (handle);
1328 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1330 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
1331 WAIT_DEBUG (printf ("%p: finished waiting.\n", GetCurrentThreadId ()););
1334 _wapi_handle_unref (thread_handle);
1337 void _wapi_thread_own_mutex (gpointer mutex)
1339 struct _WapiHandle_thread *thread_handle;
1343 thread = _wapi_thread_handle_from_id (pthread_self ());
1344 if (thread == NULL) {
1345 g_warning ("%s: error looking up thread by ID", __func__);
1349 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1350 (gpointer *)&thread_handle);
1352 g_warning ("%s: error looking up thread handle %p", __func__,
1357 _wapi_handle_ref (mutex);
1359 g_ptr_array_add (thread_handle->owned_mutexes, mutex);
1362 void _wapi_thread_disown_mutex (gpointer mutex)
1364 struct _WapiHandle_thread *thread_handle;
1368 thread = _wapi_thread_handle_from_id (pthread_self ());
1369 if (thread == NULL) {
1370 g_warning ("%s: error looking up thread by ID", __func__);
1374 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1375 (gpointer *)&thread_handle);
1377 g_warning ("%s: error looking up thread handle %p", __func__,
1382 _wapi_handle_unref (mutex);
1384 g_ptr_array_remove (thread_handle->owned_mutexes, mutex);