update rx (mobile builds).
[mono-project.git] / mono / io-layer / wthreads.c
blobb5d6d6c551181d3a322bf3f8f49a783c6fec3b83
1 /*
2 * threads.c: Thread handles
4 * Author:
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002-2006 Ximian, Inc.
8 * Copyright 2003-2011 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
12 #include <config.h>
13 #include <stdio.h>
14 #include <glib.h>
15 #include <string.h>
16 #include <pthread.h>
17 #include <signal.h>
18 #include <sched.h>
19 #include <sys/time.h>
20 #include <errno.h>
21 #include <sys/types.h>
22 #include <unistd.h>
24 #include <mono/io-layer/wapi.h>
25 #include <mono/io-layer/wapi-private.h>
26 #include <mono/io-layer/handles-private.h>
27 #include <mono/io-layer/misc-private.h>
28 #include <mono/io-layer/mono-mutex.h>
29 #include <mono/io-layer/thread-private.h>
30 #include <mono/io-layer/mutex-private.h>
31 #include <mono/io-layer/atomic.h>
33 #include <mono/utils/mono-threads.h>
34 #include <mono/utils/gc_wrapper.h>
36 #ifdef HAVE_VALGRIND_MEMCHECK_H
37 #include <valgrind/memcheck.h>
38 #endif
40 #if 0
41 #define DEBUG(...) g_message(__VA_ARGS__)
42 #else
43 #define DEBUG(...)
44 #endif
46 #if 0
47 #define WAIT_DEBUG(code) do { code } while (0)
48 #else
49 #define WAIT_DEBUG(code) do { } while (0)
50 #endif
52 /* Hash threads with tids. I thought of using TLS for this, but that
53 * would have to set the data in the new thread, which is more hassle
55 static mono_once_t thread_hash_once = MONO_ONCE_INIT;
56 static pthread_key_t thread_hash_key;
58 /* This key is used with attached threads and a destructor to signal
59 * when attached threads exit, as they don't have the thread_exit()
60 * infrastructure
62 static pthread_key_t thread_attached_key;
64 struct _WapiHandleOps _wapi_thread_ops = {
65 NULL, /* close */
66 NULL, /* signal */
67 NULL, /* own */
68 NULL, /* is_owned */
69 NULL, /* special_wait */
70 NULL /* prewait */
73 static mono_once_t thread_ops_once=MONO_ONCE_INIT;
75 static void thread_ops_init (void)
77 _wapi_handle_register_capabilities (WAPI_HANDLE_THREAD,
78 WAPI_HANDLE_CAP_WAIT);
81 void _wapi_thread_cleanup (void)
83 int ret;
85 ret = pthread_key_delete (thread_hash_key);
86 g_assert (ret == 0);
88 ret = pthread_key_delete (thread_attached_key);
89 g_assert (ret == 0);
92 /* Called by thread_exit(), but maybe indirectly by
93 * mono_thread_manage() via mono_thread_signal_self() too
95 static void _wapi_thread_abandon_mutexes (gpointer handle)
97 struct _WapiHandle_thread *thread_handle;
98 gboolean ok;
99 int i;
100 pid_t pid = _wapi_getpid ();
101 pthread_t tid = pthread_self ();
103 DEBUG ("%s: Thread %p abandoning held mutexes", __func__, handle);
105 if (handle == NULL) {
106 handle = _wapi_thread_handle_from_id (pthread_self ());
107 if (handle == NULL) {
108 /* Something gone badly wrong... */
109 return;
113 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
114 (gpointer *)&thread_handle);
115 if (ok == FALSE) {
116 g_warning ("%s: error looking up thread handle %p", __func__,
117 handle);
118 return;
121 if (!pthread_equal (thread_handle->id, tid)) {
122 return;
125 for (i = 0; i < thread_handle->owned_mutexes->len; i++) {
126 gpointer mutex = g_ptr_array_index (thread_handle->owned_mutexes, i);
128 _wapi_mutex_abandon (mutex, pid, tid);
129 _wapi_thread_disown_mutex (mutex);
133 void _wapi_thread_set_termination_details (gpointer handle,
134 guint32 exitstatus)
136 struct _WapiHandle_thread *thread_handle;
137 gboolean ok;
138 int thr_ret;
140 if (_wapi_handle_issignalled (handle) ||
141 _wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) {
142 /* We must have already deliberately finished with
143 * this thread, so don't do any more now
145 return;
148 DEBUG ("%s: Thread %p terminating", __func__, handle);
150 _wapi_thread_abandon_mutexes (handle);
152 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
153 (gpointer *)&thread_handle);
154 if (ok == FALSE) {
155 g_warning ("%s: error looking up thread handle %p", __func__,
156 handle);
158 return;
161 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
162 handle);
163 thr_ret = _wapi_handle_lock_handle (handle);
164 g_assert (thr_ret == 0);
166 thread_handle->exitstatus = exitstatus;
167 thread_handle->state = THREAD_STATE_EXITED;
168 MONO_SEM_DESTROY (&thread_handle->suspend_sem);
169 g_ptr_array_free (thread_handle->owned_mutexes, TRUE);
171 _wapi_handle_set_signal_state (handle, TRUE, TRUE);
173 thr_ret = _wapi_handle_unlock_handle (handle);
174 g_assert (thr_ret == 0);
175 pthread_cleanup_pop (0);
177 DEBUG("%s: Recording thread handle %p id %ld status as %d",
178 __func__, handle, thread_handle->id, exitstatus);
180 /* The thread is no longer active, so unref it */
181 _wapi_handle_unref (handle);
184 void _wapi_thread_signal_self (guint32 exitstatus)
186 gpointer handle;
188 handle = _wapi_thread_handle_from_id (pthread_self ());
189 if (handle == NULL) {
190 /* Something gone badly wrong... */
191 return;
194 _wapi_thread_set_termination_details (handle, exitstatus);
197 /* Called by the thread creation code as a thread is finishing up, and
198 * by ExitThread()
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
206 * thread
208 mono_gc_pthread_exit (NULL);
211 static void thread_attached_exit (gpointer handle)
213 /* Drop the extra reference we take in thread_attach, now this
214 * thread is dead
217 _wapi_thread_set_termination_details (handle, 0);
220 static void thread_hash_init(void)
222 int thr_ret;
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 &&
237 errno == EINTR);
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;
249 int thr_ret;
251 if (!(thread->create_flags & CREATE_NO_DETACH)) {
252 thr_ret = mono_gc_pthread_detach (pthread_self ());
253 g_assert (thr_ret == 0);
256 thr_ret = pthread_setspecific (thread_hash_key,
257 (void *)thread->handle);
258 if (thr_ret != 0) {
259 /* This is only supposed to happen when Mono is
260 shutting down. We cannot assert on it, though,
261 because we must not depend on metadata, which is
262 where the shutdown code is.
264 This is a race condition which arises because
265 pthreads don't allow creation of suspended threads.
266 Once Mono is set to shut down no new thread is
267 allowed to start, even though threads may still be
268 created. We emulate suspended threads in this
269 function by calling _wapi_thread_suspend() below.
271 So it can happen that even though Mono is already
272 shutting down we still end up here, and at this
273 point the thread_hash_key might already be
274 destroyed. */
275 mono_gc_pthread_exit (NULL);
278 DEBUG ("%s: started thread id %ld", __func__, thread->id);
280 /* We set it again here since passing &thread->id to pthread_create is racy
281 as the thread can start running before the value is set.*/
282 thread->id = pthread_self ();
284 if (thread->create_flags & CREATE_SUSPENDED) {
285 _wapi_thread_suspend (thread);
288 thread_exit (thread->start_routine (thread->start_arg),
289 thread->handle);
291 #ifndef __GNUC__
292 /* Even though we tell gcc that this function doesn't return,
293 * other compilers won't see that.
295 return(NULL);
296 #endif
300 * CreateThread:
301 * @security: Ignored for now.
302 * @stacksize: the size in bytes of the new thread's stack. Use 0 to
303 * default to the normal stack size. (Ignored for now).
304 * @start: The function that the new thread should start with
305 * @param: The parameter to give to @start.
306 * @create: If 0, the new thread is ready to run immediately. If
307 * %CREATE_SUSPENDED, the new thread will be in the suspended state,
308 * requiring a ResumeThread() call to continue running.
309 * @tid: If non-NULL, the ID of the new thread is stored here. NB
310 * this is defined as a DWORD (ie 32bit) in the MS API, but we need to
311 * cope with 64 bit IDs for s390x and amd64.
313 * Creates a new threading handle.
315 * Return value: a new handle, or NULL
317 gpointer CreateThread(WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 stacksize,
318 WapiThreadStart start, gpointer param, guint32 create,
319 gsize *tid)
321 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
322 pthread_attr_t attr;
323 gpointer handle;
324 gboolean ok;
325 int ret;
326 int thr_ret;
327 int i, unrefs = 0;
328 gpointer ct_ret = NULL;
330 mono_once (&thread_hash_once, thread_hash_init);
331 mono_once (&thread_ops_once, thread_ops_init);
333 if (start == NULL) {
334 return(NULL);
337 thread_handle.state = THREAD_STATE_START;
338 thread_handle.owned_mutexes = g_ptr_array_new ();
339 thread_handle.create_flags = create;
340 thread_handle.start_routine = start;
341 thread_handle.start_arg = param;
343 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
344 if (handle == _WAPI_HANDLE_INVALID) {
345 g_warning ("%s: error creating thread handle", __func__);
346 SetLastError (ERROR_GEN_FAILURE);
348 return (NULL);
351 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
352 handle);
353 thr_ret = _wapi_handle_lock_handle (handle);
354 g_assert (thr_ret == 0);
356 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
357 (gpointer *)&thread_handle_p);
358 if (ok == FALSE) {
359 g_warning ("%s: error looking up thread handle %p", __func__,
360 handle);
361 SetLastError (ERROR_GEN_FAILURE);
363 goto cleanup;
366 /* Hold a reference while the thread is active, because we use
367 * the handle to store thread exit information
369 _wapi_handle_ref (handle);
371 /* Set a 2M stack size. This is the default on Linux, but BSD
372 * needs it. (The original bug report from Martin Dvorak <md@9ll.cz>
373 * set the size to 2M-4k. I don't know why it's short by 4k, so
374 * I'm leaving it as 2M until I'm told differently.)
376 thr_ret = pthread_attr_init(&attr);
377 g_assert (thr_ret == 0);
379 /* defaults of 2Mb for 32bits and 4Mb for 64bits */
380 /* temporarily changed to use 1 MB: this allows more threads
381 * to be used, as well as using less virtual memory and so
382 * more is available for the GC heap.
384 if (stacksize == 0){
385 #if HAVE_VALGRIND_MEMCHECK_H
386 if (RUNNING_ON_VALGRIND) {
387 stacksize = 1 << 20;
388 } else {
389 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
391 #else
392 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
393 #endif
396 #ifdef PTHREAD_STACK_MIN
397 if (stacksize < PTHREAD_STACK_MIN)
398 stacksize = PTHREAD_STACK_MIN;
399 #endif
401 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
402 thr_ret = pthread_attr_setstacksize(&attr, stacksize);
403 g_assert (thr_ret == 0);
404 #endif
406 MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
407 thread_handle_p->handle = handle;
410 ret = mono_threads_pthread_create (&thread_handle_p->id, &attr,
411 thread_start_routine, (void *)thread_handle_p);
413 if (ret != 0) {
414 g_warning ("%s: Error creating native thread handle %s (%d)", __func__,
415 strerror (ret), ret);
416 SetLastError (ERROR_GEN_FAILURE);
418 /* Two, because of the reference we took above */
419 unrefs = 2;
421 goto cleanup;
423 ct_ret = handle;
425 DEBUG("%s: Started thread handle %p ID %ld", __func__, handle,
426 thread_handle_p->id);
428 if (tid != NULL) {
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
432 * would overflow
434 *tid = (gsize)(thread_handle_p->id);
435 #else
436 *tid = thread_handle_p->id;
437 #endif
440 cleanup:
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
446 * already locked
448 for (i = 0; i < unrefs; i++) {
449 _wapi_handle_unref (handle);
452 return(ct_ret);
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)
462 gpointer ret;
464 if (pthread_equal (tid, pthread_self ()) &&
465 (ret = pthread_getspecific (thread_hash_key)) != NULL) {
466 /* We know the handle */
468 DEBUG ("%s: Returning %p for self thread %ld from TLS",
469 __func__, ret, tid);
471 return(ret);
474 DEBUG ("%s: Returning NULL for unknown or non-self thread %ld",
475 __func__, tid);
478 return(NULL);
481 static gboolean find_thread_by_id (gpointer handle, gpointer user_data)
483 pthread_t tid = (pthread_t)user_data;
484 struct _WapiHandle_thread *thread_handle;
485 gboolean ok;
487 /* Ignore threads that have already exited (ie they are signalled) */
488 if (_wapi_handle_issignalled (handle) == FALSE) {
489 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
490 (gpointer *)&thread_handle);
491 if (ok == FALSE) {
492 /* It's possible that the handle has vanished
493 * during the _wapi_search_handle before it
494 * gets here, so don't spam the console with
495 * warnings.
497 return(FALSE);
500 DEBUG ("%s: looking at thread %ld from process %d", __func__, thread_handle->id, 0);
502 if (pthread_equal (thread_handle->id, tid)) {
503 DEBUG ("%s: found the thread we are looking for",
504 __func__);
505 return(TRUE);
509 DEBUG ("%s: not found %ld, returning FALSE", __func__, tid);
511 return(FALSE);
514 /* NB tid is 32bit in MS API, but we need 64bit on amd64 and s390x
515 * (and probably others)
517 gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, gsize tid)
519 gpointer ret=NULL;
521 mono_once (&thread_hash_once, thread_hash_init);
522 mono_once (&thread_ops_once, thread_ops_init);
524 DEBUG ("%s: looking up thread %"G_GSIZE_FORMAT, __func__, tid);
526 ret = _wapi_thread_handle_from_id ((pthread_t)tid);
527 if (ret == NULL) {
528 /* We need to search for this thread */
529 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 */
530 } else {
531 /* if _wapi_search_handle() returns a found handle, it
532 * refs it itself
534 _wapi_handle_ref (ret);
537 DEBUG ("%s: returning thread handle %p", __func__, ret);
539 return(ret);
543 * ExitThread:
544 * @exitcode: Sets the thread's exit code, which can be read from
545 * another thread with GetExitCodeThread().
547 * Terminates the calling thread. A thread can also exit by returning
548 * from its start function. When the last thread in a process
549 * terminates, the process itself terminates.
551 void ExitThread(guint32 exitcode)
553 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
555 if (thread != NULL) {
556 thread_exit(exitcode, thread);
557 } else {
558 /* Just blow this thread away */
559 mono_gc_pthread_exit (NULL);
564 * GetExitCodeThread:
565 * @handle: The thread handle to query
566 * @exitcode: The thread @handle exit code is stored here
568 * Finds the exit code of @handle, and stores it in @exitcode. If the
569 * thread @handle is still running, the value stored is %STILL_ACTIVE.
571 * Return value: %TRUE, or %FALSE on error.
573 gboolean GetExitCodeThread(gpointer handle, guint32 *exitcode)
575 struct _WapiHandle_thread *thread_handle;
576 gboolean ok;
578 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
579 (gpointer *)&thread_handle);
580 if (ok == FALSE) {
581 g_warning ("%s: error looking up thread handle %p", __func__,
582 handle);
583 return (FALSE);
586 DEBUG ("%s: Finding exit status for thread handle %p id %ld",
587 __func__, handle, thread_handle->id);
589 if (exitcode == NULL) {
590 DEBUG ("%s: Nowhere to store exit code", __func__);
591 return(FALSE);
594 if (thread_handle->state != THREAD_STATE_EXITED) {
595 DEBUG ("%s: Thread still active (state %d, exited is %d)",
596 __func__, thread_handle->state,
597 THREAD_STATE_EXITED);
598 *exitcode = STILL_ACTIVE;
599 return(TRUE);
602 *exitcode = thread_handle->exitstatus;
604 return(TRUE);
608 * GetCurrentThreadId:
610 * Looks up the thread ID of the current thread. This ID can be
611 * passed to OpenThread() to create a new handle on this thread.
613 * Return value: the thread ID. NB this is defined as DWORD (ie 32
614 * bit) in the MS API, but we need to cope with 64 bit IDs for s390x
615 * and amd64. This doesn't really break the API, it just embraces and
616 * extends it on 64bit platforms :)
618 gsize GetCurrentThreadId(void)
620 pthread_t tid = pthread_self();
622 #ifdef PTHREAD_POINTER_ID
623 /* Don't use GPOINTER_TO_UINT here, it can't cope with
624 * sizeof(void *) > sizeof(uint) when a cast to uint would
625 * overflow
627 return((gsize)tid);
628 #else
629 return(tid);
630 #endif
633 static gpointer thread_attach(gsize *tid)
635 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
636 gpointer handle;
637 gboolean ok;
638 int thr_ret;
640 mono_once (&thread_hash_once, thread_hash_init);
641 mono_once (&thread_ops_once, thread_ops_init);
643 thread_handle.state = THREAD_STATE_START;
644 thread_handle.owned_mutexes = g_ptr_array_new ();
646 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
647 if (handle == _WAPI_HANDLE_INVALID) {
648 g_warning ("%s: error creating thread handle", __func__);
650 SetLastError (ERROR_GEN_FAILURE);
651 return (NULL);
654 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
655 handle);
656 thr_ret = _wapi_handle_lock_handle (handle);
657 g_assert (thr_ret == 0);
659 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
660 (gpointer *)&thread_handle_p);
661 if (ok == FALSE) {
662 g_warning ("%s: error looking up thread handle %p", __func__,
663 handle);
665 SetLastError (ERROR_GEN_FAILURE);
666 goto cleanup;
669 /* Hold a reference while the thread is active, because we use
670 * the handle to store thread exit information
672 _wapi_handle_ref (handle);
674 /* suspend_sem is not used for attached threads, but
675 * thread_exit() might try to destroy it
677 MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
678 thread_handle_p->handle = handle;
679 thread_handle_p->id = pthread_self ();
681 thr_ret = pthread_setspecific (thread_hash_key, (void *)handle);
682 g_assert (thr_ret == 0);
684 thr_ret = pthread_setspecific (thread_attached_key, (void *)handle);
685 g_assert (thr_ret == 0);
687 DEBUG("%s: Attached thread handle %p ID %ld", __func__, handle,
688 thread_handle_p->id);
690 if (tid != NULL) {
691 #ifdef PTHREAD_POINTER_ID
692 /* Don't use GPOINTER_TO_UINT here, it can't cope with
693 * sizeof(void *) > sizeof(uint) when a cast to uint
694 * would overflow
696 *tid = (gsize)(thread_handle_p->id);
697 #else
698 *tid = thread_handle_p->id;
699 #endif
702 cleanup:
703 thr_ret = _wapi_handle_unlock_handle (handle);
704 g_assert (thr_ret == 0);
705 pthread_cleanup_pop (0);
707 return(handle);
710 gpointer _wapi_thread_duplicate ()
712 gpointer ret = NULL;
714 mono_once (&thread_hash_once, thread_hash_init);
715 mono_once (&thread_ops_once, thread_ops_init);
717 ret = _wapi_thread_handle_from_id (pthread_self ());
718 if (!ret) {
719 ret = thread_attach (NULL);
720 } else {
721 _wapi_handle_ref (ret);
724 return(ret);
728 * GetCurrentThread:
730 * Looks up the handle associated with the current thread. Under
731 * Windows this is a pseudohandle, and must be duplicated with
732 * DuplicateHandle() for some operations.
734 * Return value: The current thread handle, or %NULL on failure.
735 * (Unknown whether Windows has a possible failure here. It may be
736 * necessary to implement the pseudohandle-constant behaviour).
738 gpointer GetCurrentThread(void)
740 mono_once(&thread_hash_once, thread_hash_init);
741 mono_once (&thread_ops_once, thread_ops_init);
743 return(_WAPI_THREAD_CURRENT);
747 * ResumeThread:
748 * @handle: the thread handle to resume
750 * Decrements the suspend count of thread @handle. A thread can only
751 * run if its suspend count is zero.
753 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
755 guint32 ResumeThread(gpointer handle)
757 struct _WapiHandle_thread *thread_handle;
758 gboolean ok;
760 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
761 (gpointer *)&thread_handle);
762 if (ok == FALSE) {
763 g_warning ("%s: error looking up thread handle %p", __func__,
764 handle);
766 return (0xFFFFFFFF);
769 /* This is still a kludge that only copes with starting a
770 * thread that was suspended on create, so don't bother with
771 * the suspend count crap yet
773 _wapi_thread_resume (thread_handle);
774 return(0xFFFFFFFF);
778 * SuspendThread:
779 * @handle: the thread handle to suspend
781 * Increments the suspend count of thread @handle. A thread can only
782 * run if its suspend count is zero.
784 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
786 guint32 SuspendThread(gpointer handle)
788 return(0xFFFFFFFF);
792 * SleepEx:
793 * @ms: The time in milliseconds to suspend for
794 * @alertable: if TRUE, the wait can be interrupted by an APC call
796 * Suspends execution of the current thread for @ms milliseconds. A
797 * value of zero causes the thread to relinquish its time slice. A
798 * value of %INFINITE causes an infinite delay.
800 guint32 SleepEx(guint32 ms, gboolean alertable)
802 struct timespec req, rem;
803 int ms_quot, ms_rem;
804 int ret;
805 gpointer current_thread = NULL;
807 DEBUG("%s: Sleeping for %d ms", __func__, ms);
809 if (alertable) {
810 current_thread = _wapi_thread_handle_from_id (pthread_self ());
811 if (current_thread == NULL) {
812 SetLastError (ERROR_INVALID_HANDLE);
813 return(WAIT_FAILED);
816 if (_wapi_thread_apc_pending (current_thread)) {
817 _wapi_thread_dispatch_apc_queue (current_thread);
818 return WAIT_IO_COMPLETION;
822 if(ms==0) {
823 sched_yield();
824 return 0;
827 /* FIXME: check for INFINITE and sleep forever */
828 ms_quot = ms / 1000;
829 ms_rem = ms % 1000;
831 req.tv_sec=ms_quot;
832 req.tv_nsec=ms_rem*1000000;
834 again:
835 memset (&rem, 0, sizeof (rem));
836 ret=nanosleep(&req, &rem);
838 if (alertable && _wapi_thread_apc_pending (current_thread)) {
839 _wapi_thread_dispatch_apc_queue (current_thread);
840 return WAIT_IO_COMPLETION;
843 if(ret==-1) {
844 /* Sleep interrupted with rem time remaining */
845 #ifdef DEBUG_ENABLED
846 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
848 g_message("%s: Still got %d ms to go", __func__, rems);
849 #endif
850 req=rem;
851 goto again;
854 return 0;
857 void Sleep(guint32 ms)
859 SleepEx(ms, FALSE);
862 gboolean _wapi_thread_cur_apc_pending (void)
864 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
866 if (thread == NULL) {
867 SetLastError (ERROR_INVALID_HANDLE);
868 return(FALSE);
871 return(_wapi_thread_apc_pending (thread));
874 gboolean _wapi_thread_apc_pending (gpointer handle)
876 struct _WapiHandle_thread *thread;
877 gboolean ok;
879 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
880 (gpointer *)&thread);
881 if (ok == FALSE) {
882 /* This might happen at process shutdown, as all
883 * thread handles are forcibly closed. If a thread
884 * still has an alertable wait the final
885 * _wapi_thread_apc_pending check will probably fail
886 * to find the handle
888 DEBUG ("%s: error looking up thread handle %p", __func__,
889 handle);
890 return (FALSE);
893 return(thread->has_apc || thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE);
896 gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
898 /* We don't support calling APC functions */
899 struct _WapiHandle_thread *thread;
900 gboolean ok;
902 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
903 (gpointer *)&thread);
904 g_assert (ok);
906 thread->has_apc = FALSE;
908 return(TRUE);
912 * In this implementation, APC_CALLBACK is ignored.
913 * if HANDLE refers to the current thread, the only effect this function has
914 * that if called from a signal handler, and the thread was waiting when receiving
915 * the signal, the wait will be broken after the signal handler returns.
916 * In this case, this function is async-signal-safe.
918 guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer handle,
919 gpointer param)
921 struct _WapiHandle_thread *thread_handle;
922 gboolean ok;
924 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
925 (gpointer *)&thread_handle);
926 if (ok == FALSE) {
927 g_warning ("%s: error looking up thread handle %p", __func__,
928 handle);
929 return (0);
932 g_assert (thread_handle->id == (pthread_t)GetCurrentThreadId ());
933 /* No locking/memory barriers are needed here */
934 thread_handle->has_apc = TRUE;
935 return(1);
939 * wapi_interrupt_thread:
941 * This is not part of the WIN32 API.
942 * The state of the thread handle HANDLE is set to 'interrupted' which means that
943 * if the thread calls one of the WaitFor functions, the function will return with
944 * WAIT_IO_COMPLETION instead of waiting. Also, if the thread was waiting when
945 * this function was called, the wait will be broken.
946 * It is possible that the wait functions return WAIT_IO_COMPLETION, but the
947 * target thread didn't receive the interrupt signal yet, in this case it should
948 * call the wait function again. This essentially means that the target thread will
949 * busy wait until it is ready to process the interruption.
950 * FIXME: get rid of QueueUserAPC and thread->has_apc, SleepEx seems to require it.
952 void wapi_interrupt_thread (gpointer thread_handle)
954 struct _WapiHandle_thread *thread;
955 gboolean ok;
956 gpointer prev_handle, wait_handle;
957 guint32 idx;
958 pthread_cond_t *cond;
959 mono_mutex_t *mutex;
961 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
962 (gpointer *)&thread);
963 g_assert (ok);
965 while (TRUE) {
966 wait_handle = thread->wait_handle;
969 * Atomically obtain the handle the thread is waiting on, and
970 * change it to a flag value.
972 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
973 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
974 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
975 /* Already interrupted */
976 return;
977 if (prev_handle == wait_handle)
978 break;
980 /* Try again */
983 WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread_handle->id););
985 if (!wait_handle)
986 /* Not waiting */
987 return;
989 /* If we reach here, then wait_handle is set to the flag value,
990 * which means that the target thread is either
991 * - before the first CAS in timedwait, which means it won't enter the
992 * wait.
993 * - it is after the first CAS, so it is already waiting, or it will
994 * enter the wait, and it will be interrupted by the broadcast.
996 idx = GPOINTER_TO_UINT(wait_handle);
997 cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
998 mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
1000 mono_mutex_lock (mutex);
1001 mono_cond_broadcast (cond);
1002 mono_mutex_unlock (mutex);
1004 /* ref added by set_wait_handle */
1005 _wapi_handle_unref (wait_handle);
1009 gpointer wapi_prepare_interrupt_thread (gpointer thread_handle)
1011 struct _WapiHandle_thread *thread;
1012 gboolean ok;
1013 gpointer prev_handle, wait_handle;
1015 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1016 (gpointer *)&thread);
1017 g_assert (ok);
1019 while (TRUE) {
1020 wait_handle = thread->wait_handle;
1023 * Atomically obtain the handle the thread is waiting on, and
1024 * change it to a flag value.
1026 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1027 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1028 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1029 /* Already interrupted */
1030 return 0;
1031 if (prev_handle == wait_handle)
1032 break;
1034 /* Try again */
1037 WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread_handle->id););
1039 return wait_handle;
1042 void wapi_finish_interrupt_thread (gpointer wait_handle)
1044 pthread_cond_t *cond;
1045 mono_mutex_t *mutex;
1046 guint32 idx;
1048 if (!wait_handle)
1049 /* Not waiting */
1050 return;
1052 /* If we reach here, then wait_handle is set to the flag value,
1053 * which means that the target thread is either
1054 * - before the first CAS in timedwait, which means it won't enter the
1055 * wait.
1056 * - it is after the first CAS, so it is already waiting, or it will
1057 * enter the wait, and it will be interrupted by the broadcast.
1059 idx = GPOINTER_TO_UINT(wait_handle);
1060 cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
1061 mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
1063 mono_mutex_lock (mutex);
1064 mono_cond_broadcast (cond);
1065 mono_mutex_unlock (mutex);
1067 /* ref added by set_wait_handle */
1068 _wapi_handle_unref (wait_handle);
1073 * wapi_self_interrupt:
1075 * This is not part of the WIN32 API.
1076 * Set the 'interrupted' state of the calling thread if it's NULL.
1078 void wapi_self_interrupt (void)
1080 struct _WapiHandle_thread *thread;
1081 gboolean ok;
1082 gpointer prev_handle, wait_handle;
1083 gpointer thread_handle;
1086 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1087 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1088 (gpointer *)&thread);
1089 g_assert (ok);
1091 while (TRUE) {
1092 wait_handle = thread->wait_handle;
1095 * Atomically obtain the handle the thread is waiting on, and
1096 * change it to a flag value.
1098 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1099 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1100 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1101 /* Already interrupted */
1102 goto cleanup;
1103 /*We did not get interrupted*/
1104 if (prev_handle == wait_handle)
1105 break;
1107 /* Try again */
1110 if (wait_handle) {
1111 /* ref added by set_wait_handle */
1112 _wapi_handle_unref (wait_handle);
1115 cleanup:
1116 _wapi_handle_unref (thread_handle);
1120 * wapi_clear_interruption:
1122 * This is not part of the WIN32 API.
1123 * Clear the 'interrupted' state of the calling thread.
1124 * This function is signal safe
1126 void wapi_clear_interruption (void)
1128 struct _WapiHandle_thread *thread;
1129 gboolean ok;
1130 gpointer prev_handle;
1131 gpointer thread_handle;
1133 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1134 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1135 (gpointer *)&thread);
1136 g_assert (ok);
1138 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1139 NULL, INTERRUPTION_REQUESTED_HANDLE);
1140 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1141 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1143 _wapi_handle_unref (thread_handle);
1146 char* wapi_current_thread_desc ()
1148 struct _WapiHandle_thread *thread;
1149 int i;
1150 gboolean ok;
1151 gpointer handle;
1152 gpointer thread_handle;
1153 GString* text;
1154 char *res;
1156 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1157 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1158 (gpointer *)&thread);
1159 if (!ok)
1160 return g_strdup_printf ("thread handle %p state : lookup failure", thread_handle);
1162 handle = thread->wait_handle;
1163 text = g_string_new (0);
1164 g_string_append_printf (text, "thread handle %p state : ", thread_handle);
1166 if (!handle)
1167 g_string_append_printf (text, "not waiting");
1168 else if (handle == INTERRUPTION_REQUESTED_HANDLE)
1169 g_string_append_printf (text, "interrupted state");
1170 else
1171 g_string_append_printf (text, "waiting on %p : %s ", handle, _wapi_handle_typename[_wapi_handle_type (handle)]);
1172 g_string_append_printf (text, " owns (");
1173 for (i = 0; i < thread->owned_mutexes->len; i++) {
1174 gpointer mutex = g_ptr_array_index (thread->owned_mutexes, i);
1175 if (i > 0)
1176 g_string_append_printf (text, ", %p", mutex);
1177 else
1178 g_string_append_printf (text, "%p", mutex);
1180 g_string_append_printf (text, ")");
1182 res = text->str;
1183 g_string_free (text, FALSE);
1184 return res;
1188 * wapi_thread_set_wait_handle:
1190 * Set the wait handle for the current thread to HANDLE. Return TRUE on success, FALSE
1191 * if the thread is in interrupted state, and cannot start waiting.
1193 gboolean wapi_thread_set_wait_handle (gpointer handle)
1195 struct _WapiHandle_thread *thread;
1196 gboolean ok;
1197 gpointer prev_handle;
1198 gpointer thread_handle;
1200 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1201 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1202 (gpointer *)&thread);
1203 g_assert (ok);
1205 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1206 handle, NULL);
1207 _wapi_handle_unref (thread_handle);
1209 if (prev_handle == NULL) {
1210 /* thread->wait_handle acts as an additional reference to the handle */
1211 _wapi_handle_ref (handle);
1213 WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
1214 } else {
1215 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
1216 WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
1219 return prev_handle == NULL;
1223 * wapi_thread_clear_wait_handle:
1225 * Clear the wait handle of the current thread.
1227 void wapi_thread_clear_wait_handle (gpointer handle)
1229 struct _WapiHandle_thread *thread;
1230 gboolean ok;
1231 gpointer prev_handle;
1232 gpointer thread_handle;
1234 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1235 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1236 (gpointer *)&thread);
1237 g_assert (ok);
1239 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1240 NULL, handle);
1242 if (prev_handle == handle) {
1243 _wapi_handle_unref (handle);
1244 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1245 } else {
1246 /*It can be NULL if it was asynchronously cleared*/
1247 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE || prev_handle == NULL);
1248 WAIT_DEBUG (printf ("%p: finished waiting.\n", GetCurrentThreadId ()););
1251 _wapi_handle_unref (thread_handle);
1254 void _wapi_thread_own_mutex (gpointer mutex)
1256 struct _WapiHandle_thread *thread_handle;
1257 gboolean ok;
1258 gpointer thread;
1260 thread = _wapi_thread_handle_from_id (pthread_self ());
1261 if (thread == NULL) {
1262 g_warning ("%s: error looking up thread by ID", __func__);
1263 return;
1266 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1267 (gpointer *)&thread_handle);
1268 if (ok == FALSE) {
1269 g_warning ("%s: error looking up thread handle %p", __func__,
1270 thread);
1271 return;
1274 _wapi_handle_ref (mutex);
1276 g_ptr_array_add (thread_handle->owned_mutexes, mutex);
1279 void _wapi_thread_disown_mutex (gpointer mutex)
1281 struct _WapiHandle_thread *thread_handle;
1282 gboolean ok;
1283 gpointer thread;
1285 thread = _wapi_thread_handle_from_id (pthread_self ());
1286 if (thread == NULL) {
1287 g_warning ("%s: error looking up thread by ID", __func__);
1288 return;
1291 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1292 (gpointer *)&thread_handle);
1293 if (ok == FALSE) {
1294 g_warning ("%s: error looking up thread handle %p", __func__,
1295 thread);
1296 return;
1299 _wapi_handle_unref (mutex);
1301 g_ptr_array_remove (thread_handle->owned_mutexes, mutex);