2009-04-06 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / io-layer / wthreads.c
blob684f84629e1067ee5b7a12f042fbce4c12138b7a
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/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>
35 #endif
37 #undef DEBUG
38 #undef TLS_DEBUG
40 #if 0
41 #define WAIT_DEBUG(code) do { code } while (0)
42 #else
43 #define WAIT_DEBUG(code) do { } while (0)
44 #endif
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()
54 * infrastructure
56 static pthread_key_t thread_attached_key;
58 struct _WapiHandleOps _wapi_thread_ops = {
59 NULL, /* close */
60 NULL, /* signal */
61 NULL, /* own */
62 NULL, /* is_owned */
63 NULL, /* special_wait */
64 NULL /* prewait */
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)
77 int ret;
79 ret = pthread_key_delete (thread_hash_key);
80 g_assert (ret == 0);
82 ret = pthread_key_delete (thread_attached_key);
83 g_assert (ret == 0);
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;
92 gboolean ok;
93 int i;
94 pid_t pid = _wapi_getpid ();
95 pthread_t tid = pthread_self ();
97 #ifdef DEBUG
98 g_message ("%s: Thread %p abandoning held mutexes", __func__, handle);
99 #endif
101 if (handle == NULL) {
102 handle = _wapi_thread_handle_from_id (pthread_self ());
103 if (handle == NULL) {
104 /* Something gone badly wrong... */
105 return;
109 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
110 (gpointer *)&thread_handle);
111 if (ok == FALSE) {
112 g_warning ("%s: error looking up thread handle %p", __func__,
113 handle);
114 return;
117 if (!pthread_equal (thread_handle->id, tid)) {
118 return;
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,
130 guint32 exitstatus)
132 struct _WapiHandle_thread *thread_handle;
133 gboolean ok;
134 int thr_ret;
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
141 return;
144 #ifdef DEBUG
145 g_message ("%s: Thread %p terminating", __func__, handle);
146 #endif
148 _wapi_thread_abandon_mutexes (handle);
150 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
151 (gpointer *)&thread_handle);
152 if (ok == FALSE) {
153 g_warning ("%s: error looking up thread handle %p", __func__,
154 handle);
156 return;
159 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
160 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);
175 #ifdef DEBUG
176 g_message("%s: Recording thread handle %p id %ld status as %d",
177 __func__, handle, thread_handle->id, exitstatus);
178 #endif
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 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 thr_ret = pthread_detach (pthread_self ());
252 g_assert (thr_ret == 0);
254 thr_ret = pthread_setspecific (thread_hash_key,
255 (void *)thread->handle);
256 if (thr_ret != 0) {
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
272 destroyed. */
273 pthread_exit (NULL);
276 thread->id = pthread_self();
278 #ifdef DEBUG
279 g_message ("%s: started thread id %ld", __func__, thread->id);
280 #endif
282 if (thread->create_flags & CREATE_SUSPENDED) {
283 _wapi_thread_suspend (thread);
286 thread_exit (thread->start_routine (thread->start_arg),
287 thread->handle);
289 #ifndef __GNUC__
290 /* Even though we tell gcc that this function doesn't return,
291 * other compilers won't see that.
293 return(NULL);
294 #endif
298 * CreateThread:
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,
317 gsize *tid)
319 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
320 pthread_attr_t attr;
321 gpointer handle;
322 gboolean ok;
323 int ret;
324 int thr_ret;
325 int i, unrefs = 0;
326 gpointer ct_ret = NULL;
328 mono_once (&thread_hash_once, thread_hash_init);
329 mono_once (&thread_ops_once, thread_ops_init);
331 if (start == NULL) {
332 return(NULL);
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);
346 return (NULL);
349 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
350 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);
356 if (ok == FALSE) {
357 g_warning ("%s: error looking up thread handle %p", __func__,
358 handle);
359 SetLastError (ERROR_GEN_FAILURE);
361 goto cleanup;
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.
382 if (stacksize == 0){
383 #if HAVE_VALGRIND_MEMCHECK_H
384 if (RUNNING_ON_VALGRIND) {
385 stacksize = 1 << 20;
386 } else {
387 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
389 #else
390 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
391 #endif
394 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
395 thr_ret = pthread_attr_setstacksize(&attr, stacksize);
396 g_assert (thr_ret == 0);
397 #endif
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);
406 if (ret != 0) {
407 #ifdef DEBUG
408 g_message ("%s: Thread create error: %s", __func__,
409 strerror(ret));
410 #endif
412 /* Two, because of the reference we took above */
413 unrefs = 2;
415 goto cleanup;
417 ct_ret = handle;
419 #ifdef DEBUG
420 g_message("%s: Started thread handle %p ID %ld", __func__, handle,
421 thread_handle_p->id);
422 #endif
424 if (tid != NULL) {
425 #ifdef PTHREAD_POINTER_ID
426 /* Don't use GPOINTER_TO_UINT here, it can't cope with
427 * sizeof(void *) > sizeof(uint) when a cast to uint
428 * would overflow
430 *tid = (gsize)(thread_handle_p->id);
431 #else
432 *tid = thread_handle_p->id;
433 #endif
436 cleanup:
437 thr_ret = _wapi_handle_unlock_handle (handle);
438 g_assert (thr_ret == 0);
439 pthread_cleanup_pop (0);
441 /* Must not call _wapi_handle_unref() with the shared handles
442 * already locked
444 for (i = 0; i < unrefs; i++) {
445 _wapi_handle_unref (handle);
448 return(ct_ret);
451 /* The only time this function is called when tid != pthread_self ()
452 * is from OpenThread (), so we can fast-path most cases by just
453 * looking up the handle in TLS. OpenThread () must cope with a NULL
454 * return and do a handle search in that case.
456 gpointer _wapi_thread_handle_from_id (pthread_t tid)
458 gpointer ret;
460 if (pthread_equal (tid, pthread_self ()) &&
461 (ret = pthread_getspecific (thread_hash_key)) != NULL) {
462 /* We know the handle */
464 #ifdef DEBUG
465 g_message ("%s: Returning %p for self thread %ld from TLS",
466 __func__, ret, tid);
467 #endif
469 return(ret);
472 #ifdef DEBUG
473 g_message ("%s: Returning NULL for unknown or non-self thread %ld",
474 __func__, tid);
475 #endif
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 #ifdef DEBUG
501 g_message ("%s: looking at thread %ld from process %d", __func__, thread_handle->id, 0);
502 #endif
504 if (pthread_equal (thread_handle->id, tid)) {
505 #ifdef DEBUG
506 g_message ("%s: found the thread we are looking for",
507 __func__);
508 #endif
509 return(TRUE);
513 #ifdef DEBUG
514 g_message ("%s: not found %ld, returning FALSE", __func__, tid);
515 #endif
517 return(FALSE);
520 /* NB tid is 32bit in MS API, but we need 64bit on amd64 and s390x
521 * (and probably others)
523 gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, gsize tid)
525 gpointer ret=NULL;
527 mono_once (&thread_hash_once, thread_hash_init);
528 mono_once (&thread_ops_once, thread_ops_init);
530 #ifdef DEBUG
531 g_message ("%s: looking up thread %"G_GSIZE_FORMAT, __func__, tid);
532 #endif
534 ret = _wapi_thread_handle_from_id ((pthread_t)tid);
535 if (ret == NULL) {
536 /* We need to search for this thread */
537 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 */
538 } else {
539 /* if _wapi_search_handle() returns a found handle, it
540 * refs it itself
542 _wapi_handle_ref (ret);
545 #ifdef DEBUG
546 g_message ("%s: returning thread handle %p", __func__, ret);
547 #endif
549 return(ret);
553 * ExitThread:
554 * @exitcode: Sets the thread's exit code, which can be read from
555 * another thread with GetExitCodeThread().
557 * Terminates the calling thread. A thread can also exit by returning
558 * from its start function. When the last thread in a process
559 * terminates, the process itself terminates.
561 void ExitThread(guint32 exitcode)
563 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
565 if (thread != NULL) {
566 thread_exit(exitcode, thread);
567 } else {
568 /* Just blow this thread away */
569 pthread_exit (NULL);
574 * GetExitCodeThread:
575 * @handle: The thread handle to query
576 * @exitcode: The thread @handle exit code is stored here
578 * Finds the exit code of @handle, and stores it in @exitcode. If the
579 * thread @handle is still running, the value stored is %STILL_ACTIVE.
581 * Return value: %TRUE, or %FALSE on error.
583 gboolean GetExitCodeThread(gpointer handle, guint32 *exitcode)
585 struct _WapiHandle_thread *thread_handle;
586 gboolean ok;
588 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
589 (gpointer *)&thread_handle);
590 if (ok == FALSE) {
591 g_warning ("%s: error looking up thread handle %p", __func__,
592 handle);
593 return (FALSE);
596 #ifdef DEBUG
597 g_message ("%s: Finding exit status for thread handle %p id %ld",
598 __func__, handle, thread_handle->id);
599 #endif
601 if (exitcode == NULL) {
602 #ifdef DEBUG
603 g_message ("%s: Nowhere to store exit code", __func__);
604 #endif
605 return(FALSE);
608 if (thread_handle->state != THREAD_STATE_EXITED) {
609 #ifdef DEBUG
610 g_message ("%s: Thread still active (state %d, exited is %d)",
611 __func__, thread_handle->state,
612 THREAD_STATE_EXITED);
613 #endif
614 *exitcode = STILL_ACTIVE;
615 return(TRUE);
618 *exitcode = thread_handle->exitstatus;
620 return(TRUE);
624 * GetCurrentThreadId:
626 * Looks up the thread ID of the current thread. This ID can be
627 * passed to OpenThread() to create a new handle on this thread.
629 * Return value: the thread ID. NB this is defined as DWORD (ie 32
630 * bit) in the MS API, but we need to cope with 64 bit IDs for s390x
631 * and amd64. This doesn't really break the API, it just embraces and
632 * extends it on 64bit platforms :)
634 gsize GetCurrentThreadId(void)
636 pthread_t tid = pthread_self();
638 #ifdef PTHREAD_POINTER_ID
639 /* Don't use GPOINTER_TO_UINT here, it can't cope with
640 * sizeof(void *) > sizeof(uint) when a cast to uint would
641 * overflow
643 return((gsize)tid);
644 #else
645 return(tid);
646 #endif
649 static gpointer thread_attach(gsize *tid)
651 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
652 gpointer handle;
653 gboolean ok;
654 int thr_ret;
656 mono_once (&thread_hash_once, thread_hash_init);
657 mono_once (&thread_ops_once, thread_ops_init);
659 thread_handle.state = THREAD_STATE_START;
660 thread_handle.owned_mutexes = g_ptr_array_new ();
662 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
663 if (handle == _WAPI_HANDLE_INVALID) {
664 g_warning ("%s: error creating thread handle", __func__);
666 SetLastError (ERROR_GEN_FAILURE);
667 return (NULL);
670 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
671 handle);
672 thr_ret = _wapi_handle_lock_handle (handle);
673 g_assert (thr_ret == 0);
675 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
676 (gpointer *)&thread_handle_p);
677 if (ok == FALSE) {
678 g_warning ("%s: error looking up thread handle %p", __func__,
679 handle);
681 SetLastError (ERROR_GEN_FAILURE);
682 goto cleanup;
685 /* Hold a reference while the thread is active, because we use
686 * the handle to store thread exit information
688 _wapi_handle_ref (handle);
690 /* suspend_sem is not used for attached threads, but
691 * thread_exit() might try to destroy it
693 MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
694 thread_handle_p->handle = handle;
695 thread_handle_p->id = pthread_self ();
697 thr_ret = pthread_setspecific (thread_hash_key, (void *)handle);
698 g_assert (thr_ret == 0);
700 thr_ret = pthread_setspecific (thread_attached_key, (void *)handle);
701 g_assert (thr_ret == 0);
703 #ifdef DEBUG
704 g_message("%s: Attached thread handle %p ID %ld", __func__, handle,
705 thread_handle_p->id);
706 #endif
708 if (tid != NULL) {
709 #ifdef PTHREAD_POINTER_ID
710 /* Don't use GPOINTER_TO_UINT here, it can't cope with
711 * sizeof(void *) > sizeof(uint) when a cast to uint
712 * would overflow
714 *tid = (gsize)(thread_handle_p->id);
715 #else
716 *tid = thread_handle_p->id;
717 #endif
720 cleanup:
721 thr_ret = _wapi_handle_unlock_handle (handle);
722 g_assert (thr_ret == 0);
723 pthread_cleanup_pop (0);
725 return(handle);
728 gpointer _wapi_thread_duplicate ()
730 gpointer ret = NULL;
732 mono_once (&thread_hash_once, thread_hash_init);
733 mono_once (&thread_ops_once, thread_ops_init);
735 ret = _wapi_thread_handle_from_id (pthread_self ());
736 if (!ret) {
737 ret = thread_attach (NULL);
738 } else {
739 _wapi_handle_ref (ret);
742 return(ret);
746 * GetCurrentThread:
748 * Looks up the handle associated with the current thread. Under
749 * Windows this is a pseudohandle, and must be duplicated with
750 * DuplicateHandle() for some operations.
752 * Return value: The current thread handle, or %NULL on failure.
753 * (Unknown whether Windows has a possible failure here. It may be
754 * necessary to implement the pseudohandle-constant behaviour).
756 gpointer GetCurrentThread(void)
758 mono_once(&thread_hash_once, thread_hash_init);
759 mono_once (&thread_ops_once, thread_ops_init);
761 return(_WAPI_THREAD_CURRENT);
765 * ResumeThread:
766 * @handle: the thread handle to resume
768 * Decrements the suspend count of thread @handle. A thread can only
769 * run if its suspend count is zero.
771 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
773 guint32 ResumeThread(gpointer handle)
775 struct _WapiHandle_thread *thread_handle;
776 gboolean ok;
778 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
779 (gpointer *)&thread_handle);
780 if (ok == FALSE) {
781 g_warning ("%s: error looking up thread handle %p", __func__,
782 handle);
784 return (0xFFFFFFFF);
787 /* This is still a kludge that only copes with starting a
788 * thread that was suspended on create, so don't bother with
789 * the suspend count crap yet
791 _wapi_thread_resume (thread_handle);
792 return(0xFFFFFFFF);
796 * SuspendThread:
797 * @handle: the thread handle to suspend
799 * Increments the suspend count of thread @handle. A thread can only
800 * run if its suspend count is zero.
802 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
804 guint32 SuspendThread(gpointer handle)
806 return(0xFFFFFFFF);
810 * We assume here that TLS_MINIMUM_AVAILABLE is less than
811 * PTHREAD_KEYS_MAX, allowing enough overhead for a few TLS keys for
812 * library usage.
814 * Currently TLS_MINIMUM_AVAILABLE is 64 and _POSIX_THREAD_KEYS_MAX
815 * (the minimum value for PTHREAD_KEYS_MAX) is 128, so we should be
816 * fine.
819 static pthread_key_t TLS_keys[TLS_MINIMUM_AVAILABLE];
820 static gboolean TLS_used[TLS_MINIMUM_AVAILABLE]={FALSE};
821 static guint32 TLS_spinlock=0;
823 guint32
824 mono_pthread_key_for_tls (guint32 idx)
826 return (guint32)TLS_keys [idx];
830 * TlsAlloc:
832 * Allocates a Thread Local Storage (TLS) index. Any thread in the
833 * same process can use this index to store and retrieve values that
834 * are local to that thread.
836 * Return value: The index value, or %TLS_OUT_OF_INDEXES if no index
837 * is available.
839 guint32 TlsAlloc(void)
841 guint32 i;
842 int thr_ret;
844 MONO_SPIN_LOCK (TLS_spinlock);
846 for(i=0; i<TLS_MINIMUM_AVAILABLE; i++) {
847 if(TLS_used[i]==FALSE) {
848 TLS_used[i]=TRUE;
849 thr_ret = pthread_key_create(&TLS_keys[i], NULL);
850 g_assert (thr_ret == 0);
852 MONO_SPIN_UNLOCK (TLS_spinlock);
854 #ifdef TLS_DEBUG
855 g_message ("%s: returning key %d", __func__, i);
856 #endif
858 return(i);
862 MONO_SPIN_UNLOCK (TLS_spinlock);
864 #ifdef TLS_DEBUG
865 g_message ("%s: out of indices", __func__);
866 #endif
869 return(TLS_OUT_OF_INDEXES);
872 #define MAKE_GC_ID(idx) (GUINT_TO_POINTER((idx)|(GetCurrentThreadId()<<8)))
875 * TlsFree:
876 * @idx: The TLS index to free
878 * Releases a TLS index, making it available for reuse. This call
879 * will delete any TLS data stored under index @idx in all threads.
881 * Return value: %TRUE on success, %FALSE otherwise.
883 gboolean TlsFree(guint32 idx)
885 int thr_ret;
887 #ifdef TLS_DEBUG
888 g_message ("%s: freeing key %d", __func__, idx);
889 #endif
891 MONO_SPIN_LOCK (TLS_spinlock);
893 if(TLS_used[idx]==FALSE) {
894 MONO_SPIN_UNLOCK (TLS_spinlock);
896 return(FALSE);
899 TLS_used[idx]=FALSE;
900 thr_ret = pthread_key_delete(TLS_keys[idx]);
901 g_assert (thr_ret == 0);
903 MONO_SPIN_UNLOCK (TLS_spinlock);
905 return(TRUE);
909 * TlsGetValue:
910 * @idx: The TLS index to retrieve
912 * Retrieves the TLS data stored under index @idx.
914 * Return value: The value stored in the TLS index @idx in the current
915 * thread, or %NULL on error. As %NULL can be a valid return value,
916 * in this case GetLastError() returns %ERROR_SUCCESS.
918 gpointer TlsGetValue(guint32 idx)
920 gpointer ret;
922 #ifdef TLS_DEBUG
923 g_message ("%s: looking up key %d", __func__, idx);
924 #endif
926 ret=pthread_getspecific(TLS_keys[idx]);
928 #ifdef TLS_DEBUG
929 g_message ("%s: returning %p", __func__, ret);
930 #endif
932 return(ret);
936 * TlsSetValue:
937 * @idx: The TLS index to store
938 * @value: The value to store under index @idx
940 * Stores @value at TLS index @idx.
942 * Return value: %TRUE on success, %FALSE otherwise.
944 gboolean TlsSetValue(guint32 idx, gpointer value)
946 int ret;
948 #ifdef TLS_DEBUG
949 g_message ("%s: setting key %d to %p", __func__, idx, value);
950 #endif
953 ret=pthread_setspecific(TLS_keys[idx], value);
954 #ifdef TLS_DEBUG
955 if(ret!=0)
956 g_message ("%s: pthread_setspecific error: %s", __func__,
957 strerror (ret));
958 #endif
960 return(ret == 0);
964 * SleepEx:
965 * @ms: The time in milliseconds to suspend for
966 * @alertable: if TRUE, the wait can be interrupted by an APC call
968 * Suspends execution of the current thread for @ms milliseconds. A
969 * value of zero causes the thread to relinquish its time slice. A
970 * value of %INFINITE causes an infinite delay.
972 guint32 SleepEx(guint32 ms, gboolean alertable)
974 struct timespec req, rem;
975 int ms_quot, ms_rem;
976 int ret;
977 gpointer current_thread = NULL;
979 #ifdef DEBUG
980 g_message("%s: Sleeping for %d ms", __func__, ms);
981 #endif
983 if (alertable) {
984 current_thread = _wapi_thread_handle_from_id (pthread_self ());
985 if (current_thread == NULL) {
986 SetLastError (ERROR_INVALID_HANDLE);
987 return(WAIT_FAILED);
990 if (_wapi_thread_apc_pending (current_thread)) {
991 _wapi_thread_dispatch_apc_queue (current_thread);
992 return WAIT_IO_COMPLETION;
996 if(ms==0) {
997 sched_yield();
998 return 0;
1001 /* FIXME: check for INFINITE and sleep forever */
1002 ms_quot = ms / 1000;
1003 ms_rem = ms % 1000;
1005 req.tv_sec=ms_quot;
1006 req.tv_nsec=ms_rem*1000000;
1008 again:
1009 ret=nanosleep(&req, &rem);
1011 if (alertable && _wapi_thread_apc_pending (current_thread)) {
1012 _wapi_thread_dispatch_apc_queue (current_thread);
1013 return WAIT_IO_COMPLETION;
1016 if(ret==-1) {
1017 /* Sleep interrupted with rem time remaining */
1018 #ifdef DEBUG
1019 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
1021 g_message("%s: Still got %d ms to go", __func__, rems);
1022 #endif
1023 req=rem;
1024 goto again;
1027 return 0;
1030 void Sleep(guint32 ms)
1032 SleepEx(ms, FALSE);
1035 gboolean _wapi_thread_cur_apc_pending (void)
1037 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
1039 if (thread == NULL) {
1040 SetLastError (ERROR_INVALID_HANDLE);
1041 return(FALSE);
1044 return(_wapi_thread_apc_pending (thread));
1047 gboolean _wapi_thread_apc_pending (gpointer handle)
1049 struct _WapiHandle_thread *thread;
1050 gboolean ok;
1052 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1053 (gpointer *)&thread);
1054 if (ok == FALSE) {
1055 #ifdef DEBUG
1056 /* This might happen at process shutdown, as all
1057 * thread handles are forcibly closed. If a thread
1058 * still has an alertable wait the final
1059 * _wapi_thread_apc_pending check will probably fail
1060 * to find the handle
1062 g_warning ("%s: error looking up thread handle %p", __func__,
1063 handle);
1064 #endif
1065 return (FALSE);
1068 return(thread->has_apc || thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE);
1071 gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
1073 /* We don't support calling APC functions */
1074 struct _WapiHandle_thread *thread;
1075 gboolean ok;
1077 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1078 (gpointer *)&thread);
1079 g_assert (ok);
1081 thread->has_apc = FALSE;
1083 return(TRUE);
1087 * In this implementation, APC_CALLBACK is ignored.
1088 * if HANDLE refers to the current thread, the only effect this function has
1089 * that if called from a signal handler, and the thread was waiting when receiving
1090 * the signal, the wait will be broken after the signal handler returns.
1091 * In this case, this function is async-signal-safe.
1093 guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer handle,
1094 gpointer param)
1096 struct _WapiHandle_thread *thread_handle;
1097 gboolean ok;
1099 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1100 (gpointer *)&thread_handle);
1101 if (ok == FALSE) {
1102 g_warning ("%s: error looking up thread handle %p", __func__,
1103 handle);
1104 return (0);
1107 g_assert (thread_handle->id == GetCurrentThreadId ());
1108 /* No locking/memory barriers are needed here */
1109 thread_handle->has_apc = TRUE;
1110 return(1);
1114 * wapi_interrupt_thread:
1116 * This is not part of the WIN32 API.
1117 * The state of the thread handle HANDLE is set to 'interrupted' which means that
1118 * if the thread calls one of the WaitFor functions, the function will return with
1119 * WAIT_IO_COMPLETION instead of waiting. Also, if the thread was waiting when
1120 * this function was called, the wait will be broken.
1121 * It is possible that the wait functions return WAIT_IO_COMPLETION, but the
1122 * target thread didn't receive the interrupt signal yet, in this case it should
1123 * call the wait function again. This essentially means that the target thread will
1124 * busy wait until it is ready to process the interruption.
1125 * FIXME: get rid of QueueUserAPC and thread->has_apc, SleepEx seems to require it.
1127 void wapi_interrupt_thread (gpointer thread_handle)
1129 struct _WapiHandle_thread *thread;
1130 gboolean ok;
1131 gpointer prev_handle, wait_handle;
1132 guint32 idx;
1133 pthread_cond_t *cond;
1134 mono_mutex_t *mutex;
1136 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1137 (gpointer *)&thread);
1138 g_assert (ok);
1140 while (TRUE) {
1141 wait_handle = thread->wait_handle;
1144 * Atomically obtain the handle the thread is waiting on, and
1145 * change it to a flag value.
1147 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1148 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1149 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1150 /* Already interrupted */
1151 return;
1152 if (prev_handle == wait_handle)
1153 break;
1155 /* Try again */
1158 WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread_handle->id););
1160 if (!wait_handle)
1161 /* Not waiting */
1162 return;
1164 /* If we reach here, then wait_handle is set to the flag value,
1165 * which means that the target thread is either
1166 * - before the first CAS in timedwait, which means it won't enter the
1167 * wait.
1168 * - it is after the first CAS, so it is already waiting, or it will
1169 * enter the wait, and it will be interrupted by the broadcast.
1171 idx = GPOINTER_TO_UINT(wait_handle);
1172 cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
1173 mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
1175 mono_mutex_lock (mutex);
1176 mono_cond_broadcast (cond);
1177 mono_mutex_unlock (mutex);
1179 /* ref added by set_wait_handle */
1180 _wapi_handle_unref (wait_handle);
1184 * wapi_self_interrupt:
1186 * This is not part of the WIN32 API.
1187 * Set the 'interrupted' state of the calling thread if it's NULL.
1189 void wapi_self_interrupt (void)
1191 struct _WapiHandle_thread *thread;
1192 gboolean ok;
1193 gpointer prev_handle, wait_handle;
1194 gpointer thread_handle;
1197 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1198 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1199 (gpointer *)&thread);
1200 g_assert (ok);
1202 while (TRUE) {
1203 wait_handle = thread->wait_handle;
1206 * Atomically obtain the handle the thread is waiting on, and
1207 * change it to a flag value.
1209 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1210 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1211 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1212 /* Already interrupted */
1213 goto cleanup;
1214 /*We did not get interrupted*/
1215 if (prev_handle == wait_handle)
1216 break;
1218 /* Try again */
1221 if (wait_handle) {
1222 /* ref added by set_wait_handle */
1223 _wapi_handle_unref (wait_handle);
1226 cleanup:
1227 _wapi_handle_unref (thread_handle);
1231 * wapi_clear_interruption:
1233 * This is not part of the WIN32 API.
1234 * Clear the 'interrupted' state of the calling thread.
1235 * This function is signal safe
1237 void wapi_clear_interruption (void)
1239 struct _WapiHandle_thread *thread;
1240 gboolean ok;
1241 gpointer prev_handle;
1242 gpointer thread_handle;
1244 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1245 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1246 (gpointer *)&thread);
1247 g_assert (ok);
1249 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1250 NULL, INTERRUPTION_REQUESTED_HANDLE);
1251 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1252 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1254 _wapi_handle_unref (thread_handle);
1257 char* wapi_current_thread_desc ()
1259 struct _WapiHandle_thread *thread;
1260 int i;
1261 gboolean ok;
1262 gpointer handle;
1263 gpointer thread_handle;
1264 GString* text;
1265 char *res;
1267 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1268 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1269 (gpointer *)&thread);
1270 if (!ok)
1271 return g_strdup_printf ("thread handle %p state : lookup failure", thread_handle);
1273 handle = thread->wait_handle;
1274 text = g_string_new (0);
1275 g_string_append_printf (text, "thread handle %p state : ", thread_handle);
1277 if (!handle)
1278 g_string_append_printf (text, "not waiting");
1279 else if (handle == INTERRUPTION_REQUESTED_HANDLE)
1280 g_string_append_printf (text, "interrupted state");
1281 else
1282 g_string_append_printf (text, "waiting on %p : %s ", handle, _wapi_handle_typename[_wapi_handle_type (handle)]);
1283 g_string_append_printf (text, " owns (");
1284 for (i = 0; i < thread->owned_mutexes->len; i++) {
1285 gpointer mutex = g_ptr_array_index (thread->owned_mutexes, i);
1286 if (i > 0)
1287 g_string_append_printf (text, ", %p", mutex);
1288 else
1289 g_string_append_printf (text, "%p", mutex);
1291 g_string_append_printf (text, ")");
1293 res = text->str;
1294 g_string_free (text, FALSE);
1295 return res;
1299 * wapi_thread_set_wait_handle:
1301 * Set the wait handle for the current thread to HANDLE. Return TRUE on success, FALSE
1302 * if the thread is in interrupted state, and cannot start waiting.
1304 gboolean wapi_thread_set_wait_handle (gpointer handle)
1306 struct _WapiHandle_thread *thread;
1307 gboolean ok;
1308 gpointer prev_handle;
1309 gpointer thread_handle;
1311 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1312 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1313 (gpointer *)&thread);
1314 g_assert (ok);
1316 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1317 handle, NULL);
1318 _wapi_handle_unref (thread_handle);
1320 if (prev_handle == NULL) {
1321 /* thread->wait_handle acts as an additional reference to the handle */
1322 _wapi_handle_ref (handle);
1324 WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
1325 } else {
1326 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
1327 WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
1330 return prev_handle == NULL;
1334 * wapi_thread_clear_wait_handle:
1336 * Clear the wait handle of the current thread.
1338 void wapi_thread_clear_wait_handle (gpointer handle)
1340 struct _WapiHandle_thread *thread;
1341 gboolean ok;
1342 gpointer prev_handle;
1343 gpointer thread_handle;
1345 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1346 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1347 (gpointer *)&thread);
1348 g_assert (ok);
1350 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1351 NULL, handle);
1353 if (prev_handle == handle) {
1354 _wapi_handle_unref (handle);
1355 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1356 } else {
1357 /*It can be NULL if it was asynchronously cleared*/
1358 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE || prev_handle == NULL);
1359 WAIT_DEBUG (printf ("%p: finished waiting.\n", GetCurrentThreadId ()););
1362 _wapi_handle_unref (thread_handle);
1365 void _wapi_thread_own_mutex (gpointer mutex)
1367 struct _WapiHandle_thread *thread_handle;
1368 gboolean ok;
1369 gpointer thread;
1371 thread = _wapi_thread_handle_from_id (pthread_self ());
1372 if (thread == NULL) {
1373 g_warning ("%s: error looking up thread by ID", __func__);
1374 return;
1377 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1378 (gpointer *)&thread_handle);
1379 if (ok == FALSE) {
1380 g_warning ("%s: error looking up thread handle %p", __func__,
1381 thread);
1382 return;
1385 _wapi_handle_ref (mutex);
1387 g_ptr_array_add (thread_handle->owned_mutexes, mutex);
1390 void _wapi_thread_disown_mutex (gpointer mutex)
1392 struct _WapiHandle_thread *thread_handle;
1393 gboolean ok;
1394 gpointer thread;
1396 thread = _wapi_thread_handle_from_id (pthread_self ());
1397 if (thread == NULL) {
1398 g_warning ("%s: error looking up thread by ID", __func__);
1399 return;
1402 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1403 (gpointer *)&thread_handle);
1404 if (ok == FALSE) {
1405 g_warning ("%s: error looking up thread handle %p", __func__,
1406 thread);
1407 return;
1410 _wapi_handle_unref (mutex);
1412 g_ptr_array_remove (thread_handle->owned_mutexes, mutex);