2010-06-21 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / io-layer / wthreads.c
blob3cfbfd1d2cd4db5d44379f35a12cd963ad75c80f
1 /*
2 * threads.c: Thread handles
4 * Author:
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002-2006 Ximian, Inc.
8 */
10 #include <config.h>
11 #include <stdio.h>
12 #include <glib.h>
13 #include <string.h>
14 #include <mono/utils/gc_wrapper.h>
15 #include <pthread.h>
16 #include <signal.h>
17 #include <sched.h>
18 #include <sys/time.h>
19 #include <errno.h>
20 #include <sys/types.h>
21 #include <unistd.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>
34 #endif
36 #undef DEBUG
37 #undef TLS_DEBUG
39 #if 0
40 #define WAIT_DEBUG(code) do { code } while (0)
41 #else
42 #define WAIT_DEBUG(code) do { } while (0)
43 #endif
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()
53 * infrastructure
55 static pthread_key_t thread_attached_key;
57 struct _WapiHandleOps _wapi_thread_ops = {
58 NULL, /* close */
59 NULL, /* signal */
60 NULL, /* own */
61 NULL, /* is_owned */
62 NULL, /* special_wait */
63 NULL /* prewait */
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)
76 int ret;
78 ret = pthread_key_delete (thread_hash_key);
79 g_assert (ret == 0);
81 ret = pthread_key_delete (thread_attached_key);
82 g_assert (ret == 0);
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;
91 gboolean ok;
92 int i;
93 pid_t pid = _wapi_getpid ();
94 pthread_t tid = pthread_self ();
96 #ifdef DEBUG
97 g_message ("%s: Thread %p abandoning held mutexes", __func__, handle);
98 #endif
100 if (handle == NULL) {
101 handle = _wapi_thread_handle_from_id (pthread_self ());
102 if (handle == NULL) {
103 /* Something gone badly wrong... */
104 return;
108 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
109 (gpointer *)&thread_handle);
110 if (ok == FALSE) {
111 g_warning ("%s: error looking up thread handle %p", __func__,
112 handle);
113 return;
116 if (!pthread_equal (thread_handle->id, tid)) {
117 return;
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,
129 guint32 exitstatus)
131 struct _WapiHandle_thread *thread_handle;
132 gboolean ok;
133 int thr_ret;
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
140 return;
143 #ifdef DEBUG
144 g_message ("%s: Thread %p terminating", __func__, handle);
145 #endif
147 _wapi_thread_abandon_mutexes (handle);
149 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
150 (gpointer *)&thread_handle);
151 if (ok == FALSE) {
152 g_warning ("%s: error looking up thread handle %p", __func__,
153 handle);
155 return;
158 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
159 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);
174 #ifdef DEBUG
175 g_message("%s: Recording thread handle %p id %ld status as %d",
176 __func__, handle, thread_handle->id, exitstatus);
177 #endif
179 /* The thread is no longer active, so unref it */
180 _wapi_handle_unref (handle);
183 void _wapi_thread_signal_self (guint32 exitstatus)
185 gpointer handle;
187 handle = _wapi_thread_handle_from_id (pthread_self ());
188 if (handle == NULL) {
189 /* Something gone badly wrong... */
190 return;
193 _wapi_thread_set_termination_details (handle, exitstatus);
196 /* Called by the thread creation code as a thread is finishing up, and
197 * by ExitThread()
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
205 * thread
207 pthread_exit (NULL);
210 static void thread_attached_exit (gpointer handle)
212 /* Drop the extra reference we take in thread_attach, now this
213 * thread is dead
216 _wapi_thread_set_termination_details (handle, 0);
219 static void thread_hash_init(void)
221 int thr_ret;
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 &&
236 errno == EINTR);
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;
248 int thr_ret;
250 thr_ret = pthread_detach (pthread_self ());
251 g_assert (thr_ret == 0);
253 thr_ret = pthread_setspecific (thread_hash_key,
254 (void *)thread->handle);
255 if (thr_ret != 0) {
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
271 destroyed. */
272 pthread_exit (NULL);
275 thread->id = pthread_self();
277 #ifdef DEBUG
278 g_message ("%s: started thread id %ld", __func__, thread->id);
279 #endif
281 if (thread->create_flags & CREATE_SUSPENDED) {
282 _wapi_thread_suspend (thread);
285 thread_exit (thread->start_routine (thread->start_arg),
286 thread->handle);
288 #ifndef __GNUC__
289 /* Even though we tell gcc that this function doesn't return,
290 * other compilers won't see that.
292 return(NULL);
293 #endif
297 * CreateThread:
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,
316 gsize *tid)
318 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
319 pthread_attr_t attr;
320 gpointer handle;
321 gboolean ok;
322 int ret;
323 int thr_ret;
324 int i, unrefs = 0;
325 gpointer ct_ret = NULL;
327 mono_once (&thread_hash_once, thread_hash_init);
328 mono_once (&thread_ops_once, thread_ops_init);
330 if (start == NULL) {
331 return(NULL);
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);
345 return (NULL);
348 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
349 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);
355 if (ok == FALSE) {
356 g_warning ("%s: error looking up thread handle %p", __func__,
357 handle);
358 SetLastError (ERROR_GEN_FAILURE);
360 goto cleanup;
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.
381 if (stacksize == 0){
382 #if HAVE_VALGRIND_MEMCHECK_H
383 if (RUNNING_ON_VALGRIND) {
384 stacksize = 1 << 20;
385 } else {
386 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
388 #else
389 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
390 #endif
393 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
394 thr_ret = pthread_attr_setstacksize(&attr, stacksize);
395 g_assert (thr_ret == 0);
396 #endif
398 MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
399 thread_handle_p->handle = handle;
402 ret = pthread_create (&thread_handle_p->id, &attr,
403 thread_start_routine, (void *)thread_handle_p);
405 if (ret != 0) {
406 #ifdef DEBUG
407 g_message ("%s: Thread create error: %s", __func__,
408 strerror(ret));
409 #endif
411 /* Two, because of the reference we took above */
412 unrefs = 2;
414 goto cleanup;
416 ct_ret = handle;
418 #ifdef DEBUG
419 g_message("%s: Started thread handle %p ID %ld", __func__, handle,
420 thread_handle_p->id);
421 #endif
423 if (tid != NULL) {
424 #ifdef PTHREAD_POINTER_ID
425 /* Don't use GPOINTER_TO_UINT here, it can't cope with
426 * sizeof(void *) > sizeof(uint) when a cast to uint
427 * would overflow
429 *tid = (gsize)(thread_handle_p->id);
430 #else
431 *tid = thread_handle_p->id;
432 #endif
435 cleanup:
436 thr_ret = _wapi_handle_unlock_handle (handle);
437 g_assert (thr_ret == 0);
438 pthread_cleanup_pop (0);
440 /* Must not call _wapi_handle_unref() with the shared handles
441 * already locked
443 for (i = 0; i < unrefs; i++) {
444 _wapi_handle_unref (handle);
447 return(ct_ret);
450 /* The only time this function is called when tid != pthread_self ()
451 * is from OpenThread (), so we can fast-path most cases by just
452 * looking up the handle in TLS. OpenThread () must cope with a NULL
453 * return and do a handle search in that case.
455 gpointer _wapi_thread_handle_from_id (pthread_t tid)
457 gpointer ret;
459 if (pthread_equal (tid, pthread_self ()) &&
460 (ret = pthread_getspecific (thread_hash_key)) != NULL) {
461 /* We know the handle */
463 #ifdef DEBUG
464 g_message ("%s: Returning %p for self thread %ld from TLS",
465 __func__, ret, tid);
466 #endif
468 return(ret);
471 #ifdef DEBUG
472 g_message ("%s: Returning NULL for unknown or non-self thread %ld",
473 __func__, tid);
474 #endif
477 return(NULL);
480 static gboolean find_thread_by_id (gpointer handle, gpointer user_data)
482 pthread_t tid = (pthread_t)user_data;
483 struct _WapiHandle_thread *thread_handle;
484 gboolean ok;
486 /* Ignore threads that have already exited (ie they are signalled) */
487 if (_wapi_handle_issignalled (handle) == FALSE) {
488 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
489 (gpointer *)&thread_handle);
490 if (ok == FALSE) {
491 /* It's possible that the handle has vanished
492 * during the _wapi_search_handle before it
493 * gets here, so don't spam the console with
494 * warnings.
496 return(FALSE);
499 #ifdef DEBUG
500 g_message ("%s: looking at thread %ld from process %d", __func__, thread_handle->id, 0);
501 #endif
503 if (pthread_equal (thread_handle->id, tid)) {
504 #ifdef DEBUG
505 g_message ("%s: found the thread we are looking for",
506 __func__);
507 #endif
508 return(TRUE);
512 #ifdef DEBUG
513 g_message ("%s: not found %ld, returning FALSE", __func__, tid);
514 #endif
516 return(FALSE);
519 /* NB tid is 32bit in MS API, but we need 64bit on amd64 and s390x
520 * (and probably others)
522 gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, gsize tid)
524 gpointer ret=NULL;
526 mono_once (&thread_hash_once, thread_hash_init);
527 mono_once (&thread_ops_once, thread_ops_init);
529 #ifdef DEBUG
530 g_message ("%s: looking up thread %"G_GSIZE_FORMAT, __func__, tid);
531 #endif
533 ret = _wapi_thread_handle_from_id ((pthread_t)tid);
534 if (ret == NULL) {
535 /* We need to search for this thread */
536 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 */
537 } else {
538 /* if _wapi_search_handle() returns a found handle, it
539 * refs it itself
541 _wapi_handle_ref (ret);
544 #ifdef DEBUG
545 g_message ("%s: returning thread handle %p", __func__, ret);
546 #endif
548 return(ret);
552 * ExitThread:
553 * @exitcode: Sets the thread's exit code, which can be read from
554 * another thread with GetExitCodeThread().
556 * Terminates the calling thread. A thread can also exit by returning
557 * from its start function. When the last thread in a process
558 * terminates, the process itself terminates.
560 void ExitThread(guint32 exitcode)
562 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
564 if (thread != NULL) {
565 thread_exit(exitcode, thread);
566 } else {
567 /* Just blow this thread away */
568 pthread_exit (NULL);
573 * GetExitCodeThread:
574 * @handle: The thread handle to query
575 * @exitcode: The thread @handle exit code is stored here
577 * Finds the exit code of @handle, and stores it in @exitcode. If the
578 * thread @handle is still running, the value stored is %STILL_ACTIVE.
580 * Return value: %TRUE, or %FALSE on error.
582 gboolean GetExitCodeThread(gpointer handle, guint32 *exitcode)
584 struct _WapiHandle_thread *thread_handle;
585 gboolean ok;
587 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
588 (gpointer *)&thread_handle);
589 if (ok == FALSE) {
590 g_warning ("%s: error looking up thread handle %p", __func__,
591 handle);
592 return (FALSE);
595 #ifdef DEBUG
596 g_message ("%s: Finding exit status for thread handle %p id %ld",
597 __func__, handle, thread_handle->id);
598 #endif
600 if (exitcode == NULL) {
601 #ifdef DEBUG
602 g_message ("%s: Nowhere to store exit code", __func__);
603 #endif
604 return(FALSE);
607 if (thread_handle->state != THREAD_STATE_EXITED) {
608 #ifdef DEBUG
609 g_message ("%s: Thread still active (state %d, exited is %d)",
610 __func__, thread_handle->state,
611 THREAD_STATE_EXITED);
612 #endif
613 *exitcode = STILL_ACTIVE;
614 return(TRUE);
617 *exitcode = thread_handle->exitstatus;
619 return(TRUE);
623 * GetCurrentThreadId:
625 * Looks up the thread ID of the current thread. This ID can be
626 * passed to OpenThread() to create a new handle on this thread.
628 * Return value: the thread ID. NB this is defined as DWORD (ie 32
629 * bit) in the MS API, but we need to cope with 64 bit IDs for s390x
630 * and amd64. This doesn't really break the API, it just embraces and
631 * extends it on 64bit platforms :)
633 gsize GetCurrentThreadId(void)
635 pthread_t tid = pthread_self();
637 #ifdef PTHREAD_POINTER_ID
638 /* Don't use GPOINTER_TO_UINT here, it can't cope with
639 * sizeof(void *) > sizeof(uint) when a cast to uint would
640 * overflow
642 return((gsize)tid);
643 #else
644 return(tid);
645 #endif
648 static gpointer thread_attach(gsize *tid)
650 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
651 gpointer handle;
652 gboolean ok;
653 int thr_ret;
655 mono_once (&thread_hash_once, thread_hash_init);
656 mono_once (&thread_ops_once, thread_ops_init);
658 thread_handle.state = THREAD_STATE_START;
659 thread_handle.owned_mutexes = g_ptr_array_new ();
661 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
662 if (handle == _WAPI_HANDLE_INVALID) {
663 g_warning ("%s: error creating thread handle", __func__);
665 SetLastError (ERROR_GEN_FAILURE);
666 return (NULL);
669 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
670 handle);
671 thr_ret = _wapi_handle_lock_handle (handle);
672 g_assert (thr_ret == 0);
674 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
675 (gpointer *)&thread_handle_p);
676 if (ok == FALSE) {
677 g_warning ("%s: error looking up thread handle %p", __func__,
678 handle);
680 SetLastError (ERROR_GEN_FAILURE);
681 goto cleanup;
684 /* Hold a reference while the thread is active, because we use
685 * the handle to store thread exit information
687 _wapi_handle_ref (handle);
689 /* suspend_sem is not used for attached threads, but
690 * thread_exit() might try to destroy it
692 MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
693 thread_handle_p->handle = handle;
694 thread_handle_p->id = pthread_self ();
696 thr_ret = pthread_setspecific (thread_hash_key, (void *)handle);
697 g_assert (thr_ret == 0);
699 thr_ret = pthread_setspecific (thread_attached_key, (void *)handle);
700 g_assert (thr_ret == 0);
702 #ifdef DEBUG
703 g_message("%s: Attached thread handle %p ID %ld", __func__, handle,
704 thread_handle_p->id);
705 #endif
707 if (tid != NULL) {
708 #ifdef PTHREAD_POINTER_ID
709 /* Don't use GPOINTER_TO_UINT here, it can't cope with
710 * sizeof(void *) > sizeof(uint) when a cast to uint
711 * would overflow
713 *tid = (gsize)(thread_handle_p->id);
714 #else
715 *tid = thread_handle_p->id;
716 #endif
719 cleanup:
720 thr_ret = _wapi_handle_unlock_handle (handle);
721 g_assert (thr_ret == 0);
722 pthread_cleanup_pop (0);
724 return(handle);
727 gpointer _wapi_thread_duplicate ()
729 gpointer ret = NULL;
731 mono_once (&thread_hash_once, thread_hash_init);
732 mono_once (&thread_ops_once, thread_ops_init);
734 ret = _wapi_thread_handle_from_id (pthread_self ());
735 if (!ret) {
736 ret = thread_attach (NULL);
737 } else {
738 _wapi_handle_ref (ret);
741 return(ret);
745 * GetCurrentThread:
747 * Looks up the handle associated with the current thread. Under
748 * Windows this is a pseudohandle, and must be duplicated with
749 * DuplicateHandle() for some operations.
751 * Return value: The current thread handle, or %NULL on failure.
752 * (Unknown whether Windows has a possible failure here. It may be
753 * necessary to implement the pseudohandle-constant behaviour).
755 gpointer GetCurrentThread(void)
757 mono_once(&thread_hash_once, thread_hash_init);
758 mono_once (&thread_ops_once, thread_ops_init);
760 return(_WAPI_THREAD_CURRENT);
764 * ResumeThread:
765 * @handle: the thread handle to resume
767 * Decrements the suspend count of thread @handle. A thread can only
768 * run if its suspend count is zero.
770 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
772 guint32 ResumeThread(gpointer handle)
774 struct _WapiHandle_thread *thread_handle;
775 gboolean ok;
777 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
778 (gpointer *)&thread_handle);
779 if (ok == FALSE) {
780 g_warning ("%s: error looking up thread handle %p", __func__,
781 handle);
783 return (0xFFFFFFFF);
786 /* This is still a kludge that only copes with starting a
787 * thread that was suspended on create, so don't bother with
788 * the suspend count crap yet
790 _wapi_thread_resume (thread_handle);
791 return(0xFFFFFFFF);
795 * SuspendThread:
796 * @handle: the thread handle to suspend
798 * Increments the suspend count of thread @handle. A thread can only
799 * run if its suspend count is zero.
801 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
803 guint32 SuspendThread(gpointer handle)
805 return(0xFFFFFFFF);
809 * We assume here that TLS_MINIMUM_AVAILABLE is less than
810 * PTHREAD_KEYS_MAX, allowing enough overhead for a few TLS keys for
811 * library usage.
813 * Currently TLS_MINIMUM_AVAILABLE is 64 and _POSIX_THREAD_KEYS_MAX
814 * (the minimum value for PTHREAD_KEYS_MAX) is 128, so we should be
815 * fine.
818 static pthread_key_t TLS_keys[TLS_MINIMUM_AVAILABLE];
819 static gboolean TLS_used[TLS_MINIMUM_AVAILABLE]={FALSE};
820 static pthread_mutex_t TLS_mutex = PTHREAD_MUTEX_INITIALIZER;
822 guint32
823 mono_pthread_key_for_tls (guint32 idx)
825 return (guint32)TLS_keys [idx];
829 * TlsAlloc:
831 * Allocates a Thread Local Storage (TLS) index. Any thread in the
832 * same process can use this index to store and retrieve values that
833 * are local to that thread.
835 * Return value: The index value, or %TLS_OUT_OF_INDEXES if no index
836 * is available.
838 guint32 TlsAlloc(void)
840 guint32 i;
841 int thr_ret;
843 pthread_mutex_lock (&TLS_mutex);
845 for(i=0; i<TLS_MINIMUM_AVAILABLE; i++) {
846 if(TLS_used[i]==FALSE) {
847 TLS_used[i]=TRUE;
848 thr_ret = pthread_key_create(&TLS_keys[i], NULL);
849 g_assert (thr_ret == 0);
851 pthread_mutex_unlock (&TLS_mutex);
853 #ifdef TLS_DEBUG
854 g_message ("%s: returning key %d", __func__, i);
855 #endif
857 return(i);
861 pthread_mutex_unlock (&TLS_mutex);
863 #ifdef TLS_DEBUG
864 g_message ("%s: out of indices", __func__);
865 #endif
868 return(TLS_OUT_OF_INDEXES);
871 #define MAKE_GC_ID(idx) (GUINT_TO_POINTER((idx)|(GetCurrentThreadId()<<8)))
874 * TlsFree:
875 * @idx: The TLS index to free
877 * Releases a TLS index, making it available for reuse. This call
878 * will delete any TLS data stored under index @idx in all threads.
880 * Return value: %TRUE on success, %FALSE otherwise.
882 gboolean TlsFree(guint32 idx)
884 int thr_ret;
886 #ifdef TLS_DEBUG
887 g_message ("%s: freeing key %d", __func__, idx);
888 #endif
890 pthread_mutex_lock (&TLS_mutex);
892 if(TLS_used[idx]==FALSE) {
893 pthread_mutex_unlock (&TLS_mutex);
895 return(FALSE);
898 TLS_used[idx]=FALSE;
899 thr_ret = pthread_key_delete(TLS_keys[idx]);
900 g_assert (thr_ret == 0);
902 pthread_mutex_unlock (&TLS_mutex);
904 return(TRUE);
908 * TlsGetValue:
909 * @idx: The TLS index to retrieve
911 * Retrieves the TLS data stored under index @idx.
913 * Return value: The value stored in the TLS index @idx in the current
914 * thread, or %NULL on error. As %NULL can be a valid return value,
915 * in this case GetLastError() returns %ERROR_SUCCESS.
917 gpointer TlsGetValue(guint32 idx)
919 gpointer ret;
921 #ifdef TLS_DEBUG
922 g_message ("%s: looking up key %d", __func__, idx);
923 #endif
925 ret=pthread_getspecific(TLS_keys[idx]);
927 #ifdef TLS_DEBUG
928 g_message ("%s: returning %p", __func__, ret);
929 #endif
931 return(ret);
935 * TlsSetValue:
936 * @idx: The TLS index to store
937 * @value: The value to store under index @idx
939 * Stores @value at TLS index @idx.
941 * Return value: %TRUE on success, %FALSE otherwise.
943 gboolean TlsSetValue(guint32 idx, gpointer value)
945 int ret;
947 #ifdef TLS_DEBUG
948 g_message ("%s: setting key %d to %p", __func__, idx, value);
949 #endif
952 ret=pthread_setspecific(TLS_keys[idx], value);
953 #ifdef TLS_DEBUG
954 if(ret!=0)
955 g_message ("%s: pthread_setspecific error: %s", __func__,
956 strerror (ret));
957 #endif
959 return(ret == 0);
963 * SleepEx:
964 * @ms: The time in milliseconds to suspend for
965 * @alertable: if TRUE, the wait can be interrupted by an APC call
967 * Suspends execution of the current thread for @ms milliseconds. A
968 * value of zero causes the thread to relinquish its time slice. A
969 * value of %INFINITE causes an infinite delay.
971 guint32 SleepEx(guint32 ms, gboolean alertable)
973 struct timespec req, rem;
974 int ms_quot, ms_rem;
975 int ret;
976 gpointer current_thread = NULL;
978 #ifdef DEBUG
979 g_message("%s: Sleeping for %d ms", __func__, ms);
980 #endif
982 if (alertable) {
983 current_thread = _wapi_thread_handle_from_id (pthread_self ());
984 if (current_thread == NULL) {
985 SetLastError (ERROR_INVALID_HANDLE);
986 return(WAIT_FAILED);
989 if (_wapi_thread_apc_pending (current_thread)) {
990 _wapi_thread_dispatch_apc_queue (current_thread);
991 return WAIT_IO_COMPLETION;
995 if(ms==0) {
996 sched_yield();
997 return 0;
1000 /* FIXME: check for INFINITE and sleep forever */
1001 ms_quot = ms / 1000;
1002 ms_rem = ms % 1000;
1004 req.tv_sec=ms_quot;
1005 req.tv_nsec=ms_rem*1000000;
1007 again:
1008 ret=nanosleep(&req, &rem);
1010 if (alertable && _wapi_thread_apc_pending (current_thread)) {
1011 _wapi_thread_dispatch_apc_queue (current_thread);
1012 return WAIT_IO_COMPLETION;
1015 if(ret==-1) {
1016 /* Sleep interrupted with rem time remaining */
1017 #ifdef DEBUG
1018 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
1020 g_message("%s: Still got %d ms to go", __func__, rems);
1021 #endif
1022 req=rem;
1023 goto again;
1026 return 0;
1029 void Sleep(guint32 ms)
1031 SleepEx(ms, FALSE);
1034 gboolean _wapi_thread_cur_apc_pending (void)
1036 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
1038 if (thread == NULL) {
1039 SetLastError (ERROR_INVALID_HANDLE);
1040 return(FALSE);
1043 return(_wapi_thread_apc_pending (thread));
1046 gboolean _wapi_thread_apc_pending (gpointer handle)
1048 struct _WapiHandle_thread *thread;
1049 gboolean ok;
1051 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1052 (gpointer *)&thread);
1053 if (ok == FALSE) {
1054 #ifdef DEBUG
1055 /* This might happen at process shutdown, as all
1056 * thread handles are forcibly closed. If a thread
1057 * still has an alertable wait the final
1058 * _wapi_thread_apc_pending check will probably fail
1059 * to find the handle
1061 g_warning ("%s: error looking up thread handle %p", __func__,
1062 handle);
1063 #endif
1064 return (FALSE);
1067 return(thread->has_apc || thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE);
1070 gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
1072 /* We don't support calling APC functions */
1073 struct _WapiHandle_thread *thread;
1074 gboolean ok;
1076 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1077 (gpointer *)&thread);
1078 g_assert (ok);
1080 thread->has_apc = FALSE;
1082 return(TRUE);
1086 * In this implementation, APC_CALLBACK is ignored.
1087 * if HANDLE refers to the current thread, the only effect this function has
1088 * that if called from a signal handler, and the thread was waiting when receiving
1089 * the signal, the wait will be broken after the signal handler returns.
1090 * In this case, this function is async-signal-safe.
1092 guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer handle,
1093 gpointer param)
1095 struct _WapiHandle_thread *thread_handle;
1096 gboolean ok;
1098 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1099 (gpointer *)&thread_handle);
1100 if (ok == FALSE) {
1101 g_warning ("%s: error looking up thread handle %p", __func__,
1102 handle);
1103 return (0);
1106 g_assert (thread_handle->id == GetCurrentThreadId ());
1107 /* No locking/memory barriers are needed here */
1108 thread_handle->has_apc = TRUE;
1109 return(1);
1113 * wapi_interrupt_thread:
1115 * This is not part of the WIN32 API.
1116 * The state of the thread handle HANDLE is set to 'interrupted' which means that
1117 * if the thread calls one of the WaitFor functions, the function will return with
1118 * WAIT_IO_COMPLETION instead of waiting. Also, if the thread was waiting when
1119 * this function was called, the wait will be broken.
1120 * It is possible that the wait functions return WAIT_IO_COMPLETION, but the
1121 * target thread didn't receive the interrupt signal yet, in this case it should
1122 * call the wait function again. This essentially means that the target thread will
1123 * busy wait until it is ready to process the interruption.
1124 * FIXME: get rid of QueueUserAPC and thread->has_apc, SleepEx seems to require it.
1126 void wapi_interrupt_thread (gpointer thread_handle)
1128 struct _WapiHandle_thread *thread;
1129 gboolean ok;
1130 gpointer prev_handle, wait_handle;
1131 guint32 idx;
1132 pthread_cond_t *cond;
1133 mono_mutex_t *mutex;
1135 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1136 (gpointer *)&thread);
1137 g_assert (ok);
1139 while (TRUE) {
1140 wait_handle = thread->wait_handle;
1143 * Atomically obtain the handle the thread is waiting on, and
1144 * change it to a flag value.
1146 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1147 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1148 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1149 /* Already interrupted */
1150 return;
1151 if (prev_handle == wait_handle)
1152 break;
1154 /* Try again */
1157 WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread_handle->id););
1159 if (!wait_handle)
1160 /* Not waiting */
1161 return;
1163 /* If we reach here, then wait_handle is set to the flag value,
1164 * which means that the target thread is either
1165 * - before the first CAS in timedwait, which means it won't enter the
1166 * wait.
1167 * - it is after the first CAS, so it is already waiting, or it will
1168 * enter the wait, and it will be interrupted by the broadcast.
1170 idx = GPOINTER_TO_UINT(wait_handle);
1171 cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
1172 mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
1174 mono_mutex_lock (mutex);
1175 mono_cond_broadcast (cond);
1176 mono_mutex_unlock (mutex);
1178 /* ref added by set_wait_handle */
1179 _wapi_handle_unref (wait_handle);
1183 * wapi_self_interrupt:
1185 * This is not part of the WIN32 API.
1186 * Set the 'interrupted' state of the calling thread if it's NULL.
1188 void wapi_self_interrupt (void)
1190 struct _WapiHandle_thread *thread;
1191 gboolean ok;
1192 gpointer prev_handle, wait_handle;
1193 gpointer thread_handle;
1196 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1197 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1198 (gpointer *)&thread);
1199 g_assert (ok);
1201 while (TRUE) {
1202 wait_handle = thread->wait_handle;
1205 * Atomically obtain the handle the thread is waiting on, and
1206 * change it to a flag value.
1208 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1209 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1210 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1211 /* Already interrupted */
1212 goto cleanup;
1213 /*We did not get interrupted*/
1214 if (prev_handle == wait_handle)
1215 break;
1217 /* Try again */
1220 if (wait_handle) {
1221 /* ref added by set_wait_handle */
1222 _wapi_handle_unref (wait_handle);
1225 cleanup:
1226 _wapi_handle_unref (thread_handle);
1230 * wapi_clear_interruption:
1232 * This is not part of the WIN32 API.
1233 * Clear the 'interrupted' state of the calling thread.
1234 * This function is signal safe
1236 void wapi_clear_interruption (void)
1238 struct _WapiHandle_thread *thread;
1239 gboolean ok;
1240 gpointer prev_handle;
1241 gpointer thread_handle;
1243 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1244 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1245 (gpointer *)&thread);
1246 g_assert (ok);
1248 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1249 NULL, INTERRUPTION_REQUESTED_HANDLE);
1250 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1251 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1253 _wapi_handle_unref (thread_handle);
1256 char* wapi_current_thread_desc ()
1258 struct _WapiHandle_thread *thread;
1259 int i;
1260 gboolean ok;
1261 gpointer handle;
1262 gpointer thread_handle;
1263 GString* text;
1264 char *res;
1266 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1267 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1268 (gpointer *)&thread);
1269 if (!ok)
1270 return g_strdup_printf ("thread handle %p state : lookup failure", thread_handle);
1272 handle = thread->wait_handle;
1273 text = g_string_new (0);
1274 g_string_append_printf (text, "thread handle %p state : ", thread_handle);
1276 if (!handle)
1277 g_string_append_printf (text, "not waiting");
1278 else if (handle == INTERRUPTION_REQUESTED_HANDLE)
1279 g_string_append_printf (text, "interrupted state");
1280 else
1281 g_string_append_printf (text, "waiting on %p : %s ", handle, _wapi_handle_typename[_wapi_handle_type (handle)]);
1282 g_string_append_printf (text, " owns (");
1283 for (i = 0; i < thread->owned_mutexes->len; i++) {
1284 gpointer mutex = g_ptr_array_index (thread->owned_mutexes, i);
1285 if (i > 0)
1286 g_string_append_printf (text, ", %p", mutex);
1287 else
1288 g_string_append_printf (text, "%p", mutex);
1290 g_string_append_printf (text, ")");
1292 res = text->str;
1293 g_string_free (text, FALSE);
1294 return res;
1298 * wapi_thread_set_wait_handle:
1300 * Set the wait handle for the current thread to HANDLE. Return TRUE on success, FALSE
1301 * if the thread is in interrupted state, and cannot start waiting.
1303 gboolean wapi_thread_set_wait_handle (gpointer handle)
1305 struct _WapiHandle_thread *thread;
1306 gboolean ok;
1307 gpointer prev_handle;
1308 gpointer thread_handle;
1310 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1311 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1312 (gpointer *)&thread);
1313 g_assert (ok);
1315 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1316 handle, NULL);
1317 _wapi_handle_unref (thread_handle);
1319 if (prev_handle == NULL) {
1320 /* thread->wait_handle acts as an additional reference to the handle */
1321 _wapi_handle_ref (handle);
1323 WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
1324 } else {
1325 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
1326 WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
1329 return prev_handle == NULL;
1333 * wapi_thread_clear_wait_handle:
1335 * Clear the wait handle of the current thread.
1337 void wapi_thread_clear_wait_handle (gpointer handle)
1339 struct _WapiHandle_thread *thread;
1340 gboolean ok;
1341 gpointer prev_handle;
1342 gpointer thread_handle;
1344 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1345 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1346 (gpointer *)&thread);
1347 g_assert (ok);
1349 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1350 NULL, handle);
1352 if (prev_handle == handle) {
1353 _wapi_handle_unref (handle);
1354 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1355 } else {
1356 /*It can be NULL if it was asynchronously cleared*/
1357 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE || prev_handle == NULL);
1358 WAIT_DEBUG (printf ("%p: finished waiting.\n", GetCurrentThreadId ()););
1361 _wapi_handle_unref (thread_handle);
1364 void _wapi_thread_own_mutex (gpointer mutex)
1366 struct _WapiHandle_thread *thread_handle;
1367 gboolean ok;
1368 gpointer thread;
1370 thread = _wapi_thread_handle_from_id (pthread_self ());
1371 if (thread == NULL) {
1372 g_warning ("%s: error looking up thread by ID", __func__);
1373 return;
1376 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1377 (gpointer *)&thread_handle);
1378 if (ok == FALSE) {
1379 g_warning ("%s: error looking up thread handle %p", __func__,
1380 thread);
1381 return;
1384 _wapi_handle_ref (mutex);
1386 g_ptr_array_add (thread_handle->owned_mutexes, mutex);
1389 void _wapi_thread_disown_mutex (gpointer mutex)
1391 struct _WapiHandle_thread *thread_handle;
1392 gboolean ok;
1393 gpointer thread;
1395 thread = _wapi_thread_handle_from_id (pthread_self ());
1396 if (thread == NULL) {
1397 g_warning ("%s: error looking up thread by ID", __func__);
1398 return;
1401 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1402 (gpointer *)&thread_handle);
1403 if (ok == FALSE) {
1404 g_warning ("%s: error looking up thread handle %p", __func__,
1405 thread);
1406 return;
1409 _wapi_handle_unref (mutex);
1411 g_ptr_array_remove (thread_handle->owned_mutexes, mutex);