2009-05-15 Geoff Norton <gnorton@novell.com>
[mono-project.git] / mono / io-layer / threads.c
blob29cf8561c243093f411b85c432fa47292b5ef050
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;
402 ret = pthread_create (&thread_handle_p->id, &attr,
403 thread_start_routine, (void *)thread_handle_p);
404 if (ret != 0) {
405 #ifdef DEBUG
406 g_message ("%s: Thread create error: %s", __func__,
407 strerror(ret));
408 #endif
410 /* Two, because of the reference we took above */
411 unrefs = 2;
413 goto cleanup;
415 ct_ret = handle;
417 #ifdef DEBUG
418 g_message("%s: Started thread handle %p ID %ld", __func__, handle,
419 thread_handle_p->id);
420 #endif
422 if (tid != NULL) {
423 #ifdef PTHREAD_POINTER_ID
424 /* Don't use GPOINTER_TO_UINT here, it can't cope with
425 * sizeof(void *) > sizeof(uint) when a cast to uint
426 * would overflow
428 *tid = (gsize)(thread_handle_p->id);
429 #else
430 *tid = thread_handle_p->id;
431 #endif
434 cleanup:
435 thr_ret = _wapi_handle_unlock_handle (handle);
436 g_assert (thr_ret == 0);
437 pthread_cleanup_pop (0);
439 /* Must not call _wapi_handle_unref() with the shared handles
440 * already locked
442 for (i = 0; i < unrefs; i++) {
443 _wapi_handle_unref (handle);
446 return(ct_ret);
449 /* The only time this function is called when tid != pthread_self ()
450 * is from OpenThread (), so we can fast-path most cases by just
451 * looking up the handle in TLS. OpenThread () must cope with a NULL
452 * return and do a handle search in that case.
454 gpointer _wapi_thread_handle_from_id (pthread_t tid)
456 gpointer ret;
458 if (pthread_equal (tid, pthread_self ()) &&
459 (ret = pthread_getspecific (thread_hash_key)) != NULL) {
460 /* We know the handle */
462 #ifdef DEBUG
463 g_message ("%s: Returning %p for self thread %ld from TLS",
464 __func__, ret, tid);
465 #endif
467 return(ret);
470 #ifdef DEBUG
471 g_message ("%s: Returning NULL for unknown or non-self thread %ld",
472 __func__, tid);
473 #endif
476 return(NULL);
479 static gboolean find_thread_by_id (gpointer handle, gpointer user_data)
481 pthread_t tid = (pthread_t)user_data;
482 struct _WapiHandle_thread *thread_handle;
483 gboolean ok;
485 /* Ignore threads that have already exited (ie they are signalled) */
486 if (_wapi_handle_issignalled (handle) == FALSE) {
487 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
488 (gpointer *)&thread_handle);
489 if (ok == FALSE) {
490 /* It's possible that the handle has vanished
491 * during the _wapi_search_handle before it
492 * gets here, so don't spam the console with
493 * warnings.
495 return(FALSE);
498 #ifdef DEBUG
499 g_message ("%s: looking at thread %ld from process %d", __func__, thread_handle->id, 0);
500 #endif
502 if (pthread_equal (thread_handle->id, tid)) {
503 #ifdef DEBUG
504 g_message ("%s: found the thread we are looking for",
505 __func__);
506 #endif
507 return(TRUE);
511 #ifdef DEBUG
512 g_message ("%s: not found %ld, returning FALSE", __func__, tid);
513 #endif
515 return(FALSE);
518 /* NB tid is 32bit in MS API, but we need 64bit on amd64 and s390x
519 * (and probably others)
521 gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, gsize tid)
523 gpointer ret=NULL;
525 mono_once (&thread_hash_once, thread_hash_init);
526 mono_once (&thread_ops_once, thread_ops_init);
528 #ifdef DEBUG
529 g_message ("%s: looking up thread %"G_GSIZE_FORMAT, __func__, tid);
530 #endif
532 ret = _wapi_thread_handle_from_id ((pthread_t)tid);
533 if (ret == NULL) {
534 /* We need to search for this thread */
535 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 */
536 } else {
537 /* if _wapi_search_handle() returns a found handle, it
538 * refs it itself
540 _wapi_handle_ref (ret);
543 #ifdef DEBUG
544 g_message ("%s: returning thread handle %p", __func__, ret);
545 #endif
547 return(ret);
551 * ExitThread:
552 * @exitcode: Sets the thread's exit code, which can be read from
553 * another thread with GetExitCodeThread().
555 * Terminates the calling thread. A thread can also exit by returning
556 * from its start function. When the last thread in a process
557 * terminates, the process itself terminates.
559 void ExitThread(guint32 exitcode)
561 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
563 if (thread != NULL) {
564 thread_exit(exitcode, thread);
565 } else {
566 /* Just blow this thread away */
567 pthread_exit (NULL);
572 * GetExitCodeThread:
573 * @handle: The thread handle to query
574 * @exitcode: The thread @handle exit code is stored here
576 * Finds the exit code of @handle, and stores it in @exitcode. If the
577 * thread @handle is still running, the value stored is %STILL_ACTIVE.
579 * Return value: %TRUE, or %FALSE on error.
581 gboolean GetExitCodeThread(gpointer handle, guint32 *exitcode)
583 struct _WapiHandle_thread *thread_handle;
584 gboolean ok;
586 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
587 (gpointer *)&thread_handle);
588 if (ok == FALSE) {
589 g_warning ("%s: error looking up thread handle %p", __func__,
590 handle);
591 return (FALSE);
594 #ifdef DEBUG
595 g_message ("%s: Finding exit status for thread handle %p id %ld",
596 __func__, handle, thread_handle->id);
597 #endif
599 if (exitcode == NULL) {
600 #ifdef DEBUG
601 g_message ("%s: Nowhere to store exit code", __func__);
602 #endif
603 return(FALSE);
606 if (thread_handle->state != THREAD_STATE_EXITED) {
607 #ifdef DEBUG
608 g_message ("%s: Thread still active (state %d, exited is %d)",
609 __func__, thread_handle->state,
610 THREAD_STATE_EXITED);
611 #endif
612 *exitcode = STILL_ACTIVE;
613 return(TRUE);
616 *exitcode = thread_handle->exitstatus;
618 return(TRUE);
622 * GetCurrentThreadId:
624 * Looks up the thread ID of the current thread. This ID can be
625 * passed to OpenThread() to create a new handle on this thread.
627 * Return value: the thread ID. NB this is defined as DWORD (ie 32
628 * bit) in the MS API, but we need to cope with 64 bit IDs for s390x
629 * and amd64. This doesn't really break the API, it just embraces and
630 * extends it on 64bit platforms :)
632 gsize GetCurrentThreadId(void)
634 pthread_t tid = pthread_self();
636 #ifdef PTHREAD_POINTER_ID
637 /* Don't use GPOINTER_TO_UINT here, it can't cope with
638 * sizeof(void *) > sizeof(uint) when a cast to uint would
639 * overflow
641 return((gsize)tid);
642 #else
643 return(tid);
644 #endif
647 static gpointer thread_attach(gsize *tid)
649 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
650 gpointer handle;
651 gboolean ok;
652 int thr_ret;
654 mono_once (&thread_hash_once, thread_hash_init);
655 mono_once (&thread_ops_once, thread_ops_init);
657 thread_handle.state = THREAD_STATE_START;
658 thread_handle.owned_mutexes = g_ptr_array_new ();
660 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
661 if (handle == _WAPI_HANDLE_INVALID) {
662 g_warning ("%s: error creating thread handle", __func__);
664 SetLastError (ERROR_GEN_FAILURE);
665 return (NULL);
668 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
669 handle);
670 thr_ret = _wapi_handle_lock_handle (handle);
671 g_assert (thr_ret == 0);
673 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
674 (gpointer *)&thread_handle_p);
675 if (ok == FALSE) {
676 g_warning ("%s: error looking up thread handle %p", __func__,
677 handle);
679 SetLastError (ERROR_GEN_FAILURE);
680 goto cleanup;
683 /* Hold a reference while the thread is active, because we use
684 * the handle to store thread exit information
686 _wapi_handle_ref (handle);
688 /* suspend_sem is not used for attached threads, but
689 * thread_exit() might try to destroy it
691 MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
692 thread_handle_p->handle = handle;
693 thread_handle_p->id = pthread_self ();
695 thr_ret = pthread_setspecific (thread_hash_key, (void *)handle);
696 g_assert (thr_ret == 0);
698 thr_ret = pthread_setspecific (thread_attached_key, (void *)handle);
699 g_assert (thr_ret == 0);
701 #ifdef DEBUG
702 g_message("%s: Attached thread handle %p ID %ld", __func__, handle,
703 thread_handle_p->id);
704 #endif
706 if (tid != NULL) {
707 #ifdef PTHREAD_POINTER_ID
708 /* Don't use GPOINTER_TO_UINT here, it can't cope with
709 * sizeof(void *) > sizeof(uint) when a cast to uint
710 * would overflow
712 *tid = (gsize)(thread_handle_p->id);
713 #else
714 *tid = thread_handle_p->id;
715 #endif
718 cleanup:
719 thr_ret = _wapi_handle_unlock_handle (handle);
720 g_assert (thr_ret == 0);
721 pthread_cleanup_pop (0);
723 return(handle);
726 gpointer _wapi_thread_duplicate ()
728 gpointer ret = NULL;
730 mono_once (&thread_hash_once, thread_hash_init);
731 mono_once (&thread_ops_once, thread_ops_init);
733 ret = _wapi_thread_handle_from_id (pthread_self ());
734 if (!ret) {
735 ret = thread_attach (NULL);
736 } else {
737 _wapi_handle_ref (ret);
740 return(ret);
744 * GetCurrentThread:
746 * Looks up the handle associated with the current thread. Under
747 * Windows this is a pseudohandle, and must be duplicated with
748 * DuplicateHandle() for some operations.
750 * Return value: The current thread handle, or %NULL on failure.
751 * (Unknown whether Windows has a possible failure here. It may be
752 * necessary to implement the pseudohandle-constant behaviour).
754 gpointer GetCurrentThread(void)
756 mono_once(&thread_hash_once, thread_hash_init);
757 mono_once (&thread_ops_once, thread_ops_init);
759 return(_WAPI_THREAD_CURRENT);
763 * ResumeThread:
764 * @handle: the thread handle to resume
766 * Decrements the suspend count of thread @handle. A thread can only
767 * run if its suspend count is zero.
769 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
771 guint32 ResumeThread(gpointer handle)
773 struct _WapiHandle_thread *thread_handle;
774 gboolean ok;
776 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
777 (gpointer *)&thread_handle);
778 if (ok == FALSE) {
779 g_warning ("%s: error looking up thread handle %p", __func__,
780 handle);
782 return (0xFFFFFFFF);
785 /* This is still a kludge that only copes with starting a
786 * thread that was suspended on create, so don't bother with
787 * the suspend count crap yet
789 _wapi_thread_resume (thread_handle);
790 return(0xFFFFFFFF);
794 * SuspendThread:
795 * @handle: the thread handle to suspend
797 * Increments the suspend count of thread @handle. A thread can only
798 * run if its suspend count is zero.
800 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
802 guint32 SuspendThread(gpointer handle)
804 return(0xFFFFFFFF);
808 * We assume here that TLS_MINIMUM_AVAILABLE is less than
809 * PTHREAD_KEYS_MAX, allowing enough overhead for a few TLS keys for
810 * library usage.
812 * Currently TLS_MINIMUM_AVAILABLE is 64 and _POSIX_THREAD_KEYS_MAX
813 * (the minimum value for PTHREAD_KEYS_MAX) is 128, so we should be
814 * fine.
817 static pthread_key_t TLS_keys[TLS_MINIMUM_AVAILABLE];
818 static gboolean TLS_used[TLS_MINIMUM_AVAILABLE]={FALSE};
819 static guint32 TLS_spinlock=0;
821 guint32
822 mono_pthread_key_for_tls (guint32 idx)
824 return (guint32)TLS_keys [idx];
828 * TlsAlloc:
830 * Allocates a Thread Local Storage (TLS) index. Any thread in the
831 * same process can use this index to store and retrieve values that
832 * are local to that thread.
834 * Return value: The index value, or %TLS_OUT_OF_INDEXES if no index
835 * is available.
837 guint32 TlsAlloc(void)
839 guint32 i;
840 int thr_ret;
842 MONO_SPIN_LOCK (TLS_spinlock);
844 for(i=0; i<TLS_MINIMUM_AVAILABLE; i++) {
845 if(TLS_used[i]==FALSE) {
846 TLS_used[i]=TRUE;
847 thr_ret = pthread_key_create(&TLS_keys[i], NULL);
848 g_assert (thr_ret == 0);
850 MONO_SPIN_UNLOCK (TLS_spinlock);
852 #ifdef TLS_DEBUG
853 g_message ("%s: returning key %d", __func__, i);
854 #endif
856 return(i);
860 MONO_SPIN_UNLOCK (TLS_spinlock);
862 #ifdef TLS_DEBUG
863 g_message ("%s: out of indices", __func__);
864 #endif
867 return(TLS_OUT_OF_INDEXES);
870 #define MAKE_GC_ID(idx) (GUINT_TO_POINTER((idx)|(GetCurrentThreadId()<<8)))
873 * TlsFree:
874 * @idx: The TLS index to free
876 * Releases a TLS index, making it available for reuse. This call
877 * will delete any TLS data stored under index @idx in all threads.
879 * Return value: %TRUE on success, %FALSE otherwise.
881 gboolean TlsFree(guint32 idx)
883 int thr_ret;
885 #ifdef TLS_DEBUG
886 g_message ("%s: freeing key %d", __func__, idx);
887 #endif
889 MONO_SPIN_LOCK (TLS_spinlock);
891 if(TLS_used[idx]==FALSE) {
892 MONO_SPIN_UNLOCK (TLS_spinlock);
894 return(FALSE);
897 TLS_used[idx]=FALSE;
898 thr_ret = pthread_key_delete(TLS_keys[idx]);
899 g_assert (thr_ret == 0);
901 MONO_SPIN_UNLOCK (TLS_spinlock);
903 return(TRUE);
907 * TlsGetValue:
908 * @idx: The TLS index to retrieve
910 * Retrieves the TLS data stored under index @idx.
912 * Return value: The value stored in the TLS index @idx in the current
913 * thread, or %NULL on error. As %NULL can be a valid return value,
914 * in this case GetLastError() returns %ERROR_SUCCESS.
916 gpointer TlsGetValue(guint32 idx)
918 gpointer ret;
920 #ifdef TLS_DEBUG
921 g_message ("%s: looking up key %d", __func__, idx);
922 #endif
924 ret=pthread_getspecific(TLS_keys[idx]);
926 #ifdef TLS_DEBUG
927 g_message ("%s: returning %p", __func__, ret);
928 #endif
930 return(ret);
934 * TlsSetValue:
935 * @idx: The TLS index to store
936 * @value: The value to store under index @idx
938 * Stores @value at TLS index @idx.
940 * Return value: %TRUE on success, %FALSE otherwise.
942 gboolean TlsSetValue(guint32 idx, gpointer value)
944 int ret;
946 #ifdef TLS_DEBUG
947 g_message ("%s: setting key %d to %p", __func__, idx, value);
948 #endif
950 MONO_SPIN_LOCK (TLS_spinlock);
952 if(TLS_used[idx]==FALSE) {
953 #ifdef TLS_DEBUG
954 g_message ("%s: key %d unused", __func__, idx);
955 #endif
957 MONO_SPIN_UNLOCK (TLS_spinlock);
959 return(FALSE);
962 ret=pthread_setspecific(TLS_keys[idx], value);
963 if(ret!=0) {
964 #ifdef TLS_DEBUG
965 g_message ("%s: pthread_setspecific error: %s", __func__,
966 strerror (ret));
967 #endif
969 MONO_SPIN_UNLOCK (TLS_spinlock);
971 return(FALSE);
974 MONO_SPIN_UNLOCK (TLS_spinlock);
976 return(TRUE);
980 * SleepEx:
981 * @ms: The time in milliseconds to suspend for
982 * @alertable: if TRUE, the wait can be interrupted by an APC call
984 * Suspends execution of the current thread for @ms milliseconds. A
985 * value of zero causes the thread to relinquish its time slice. A
986 * value of %INFINITE causes an infinite delay.
988 guint32 SleepEx(guint32 ms, gboolean alertable)
990 struct timespec req, rem;
991 int ms_quot, ms_rem;
992 int ret;
993 gpointer current_thread = NULL;
995 #ifdef DEBUG
996 g_message("%s: Sleeping for %d ms", __func__, ms);
997 #endif
999 if (alertable) {
1000 current_thread = _wapi_thread_handle_from_id (pthread_self ());
1001 if (current_thread == NULL) {
1002 SetLastError (ERROR_INVALID_HANDLE);
1003 return(WAIT_FAILED);
1006 if (_wapi_thread_apc_pending (current_thread)) {
1007 _wapi_thread_dispatch_apc_queue (current_thread);
1008 return WAIT_IO_COMPLETION;
1012 if(ms==0) {
1013 sched_yield();
1014 return 0;
1017 /* FIXME: check for INFINITE and sleep forever */
1018 ms_quot = ms / 1000;
1019 ms_rem = ms % 1000;
1021 req.tv_sec=ms_quot;
1022 req.tv_nsec=ms_rem*1000000;
1024 again:
1025 ret=nanosleep(&req, &rem);
1027 if (alertable && _wapi_thread_apc_pending (current_thread)) {
1028 _wapi_thread_dispatch_apc_queue (current_thread);
1029 return WAIT_IO_COMPLETION;
1032 if(ret==-1) {
1033 /* Sleep interrupted with rem time remaining */
1034 #ifdef DEBUG
1035 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
1037 g_message("%s: Still got %d ms to go", __func__, rems);
1038 #endif
1039 req=rem;
1040 goto again;
1043 return 0;
1046 void Sleep(guint32 ms)
1048 SleepEx(ms, FALSE);
1051 gboolean _wapi_thread_cur_apc_pending (void)
1053 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
1055 if (thread == NULL) {
1056 SetLastError (ERROR_INVALID_HANDLE);
1057 return(FALSE);
1060 return(_wapi_thread_apc_pending (thread));
1063 gboolean _wapi_thread_apc_pending (gpointer handle)
1065 struct _WapiHandle_thread *thread;
1066 gboolean ok;
1068 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1069 (gpointer *)&thread);
1070 if (ok == FALSE) {
1071 #ifdef DEBUG
1072 /* This might happen at process shutdown, as all
1073 * thread handles are forcibly closed. If a thread
1074 * still has an alertable wait the final
1075 * _wapi_thread_apc_pending check will probably fail
1076 * to find the handle
1078 g_warning ("%s: error looking up thread handle %p", __func__,
1079 handle);
1080 #endif
1081 return (FALSE);
1084 return(thread->has_apc || thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE);
1087 gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
1089 /* We don't support calling APC functions */
1090 struct _WapiHandle_thread *thread;
1091 gboolean ok;
1093 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1094 (gpointer *)&thread);
1095 g_assert (ok);
1097 thread->has_apc = FALSE;
1099 return(TRUE);
1103 * In this implementation, APC_CALLBACK is ignored.
1104 * if HANDLE refers to the current thread, the only effect this function has
1105 * that if called from a signal handler, and the thread was waiting when receiving
1106 * the signal, the wait will be broken after the signal handler returns.
1107 * In this case, this function is async-signal-safe.
1109 guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer handle,
1110 gpointer param)
1112 struct _WapiHandle_thread *thread_handle;
1113 gboolean ok;
1115 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1116 (gpointer *)&thread_handle);
1117 if (ok == FALSE) {
1118 g_warning ("%s: error looking up thread handle %p", __func__,
1119 handle);
1120 return (0);
1123 g_assert (thread_handle->id == GetCurrentThreadId ());
1124 /* No locking/memory barriers are needed here */
1125 thread_handle->has_apc = TRUE;
1126 return(1);
1130 * wapi_interrupt_thread:
1132 * This is not part of the WIN32 API.
1133 * The state of the thread handle HANDLE is set to 'interrupted' which means that
1134 * if the thread calls one of the WaitFor functions, the function will return with
1135 * WAIT_IO_COMPLETION instead of waiting. Also, if the thread was waiting when
1136 * this function was called, the wait will be broken.
1137 * It is possible that the wait functions return WAIT_IO_COMPLETION, but the
1138 * target thread didn't receive the interrupt signal yet, in this case it should
1139 * call the wait function again. This essentially means that the target thread will
1140 * busy wait until it is ready to process the interruption.
1141 * FIXME: get rid of QueueUserAPC and thread->has_apc, SleepEx seems to require it.
1143 void wapi_interrupt_thread (gpointer thread_handle)
1145 struct _WapiHandle_thread *thread;
1146 gboolean ok;
1147 gpointer prev_handle, wait_handle;
1148 guint32 idx;
1149 pthread_cond_t *cond;
1150 mono_mutex_t *mutex;
1152 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1153 (gpointer *)&thread);
1154 g_assert (ok);
1156 while (TRUE) {
1157 wait_handle = thread->wait_handle;
1160 * Atomically obtain the handle the thread is waiting on, and
1161 * change it to a flag value.
1163 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1164 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1165 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1166 /* Already interrupted */
1167 return;
1168 if (prev_handle == wait_handle)
1169 break;
1171 /* Try again */
1174 WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread_handle->id););
1176 if (!wait_handle)
1177 /* Not waiting */
1178 return;
1180 /* If we reach here, then wait_handle is set to the flag value,
1181 * which means that the target thread is either
1182 * - before the first CAS in timedwait, which means it won't enter the
1183 * wait.
1184 * - it is after the first CAS, so it is already waiting, or it will
1185 * enter the wait, and it will be interrupted by the broadcast.
1187 idx = GPOINTER_TO_UINT(wait_handle);
1188 cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
1189 mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
1191 mono_mutex_lock (mutex);
1192 mono_cond_broadcast (cond);
1193 mono_mutex_unlock (mutex);
1195 /* ref added by set_wait_handle */
1196 _wapi_handle_unref (wait_handle);
1200 * wapi_clear_interruption:
1202 * This is not part of the WIN32 API.
1203 * Clear the 'interrupted' state of the calling thread.
1205 void wapi_clear_interruption (void)
1207 struct _WapiHandle_thread *thread;
1208 gboolean ok;
1209 gpointer prev_handle;
1210 gpointer thread_handle;
1212 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1213 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1214 (gpointer *)&thread);
1215 g_assert (ok);
1217 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1218 NULL, INTERRUPTION_REQUESTED_HANDLE);
1219 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1220 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1222 _wapi_handle_unref (thread_handle);
1225 char* wapi_current_thread_desc ()
1227 struct _WapiHandle_thread *thread;
1228 int i;
1229 gboolean ok;
1230 gpointer handle;
1231 gpointer thread_handle;
1232 GString* text;
1233 char *res;
1235 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1236 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1237 (gpointer *)&thread);
1238 if (!ok)
1239 return g_strdup_printf ("thread handle %p state : lookup failure", thread_handle);
1241 handle = thread->wait_handle;
1242 text = g_string_new (0);
1243 g_string_append_printf (text, "thread handle %p state : ", thread_handle);
1245 if (!handle)
1246 g_string_append_printf (text, "not waiting");
1247 else if (handle == INTERRUPTION_REQUESTED_HANDLE)
1248 g_string_append_printf (text, "interrupted state");
1249 else
1250 g_string_append_printf (text, "waiting on %p : %s ", handle, _wapi_handle_typename[_wapi_handle_type (handle)]);
1251 g_string_append_printf (text, " owns (");
1252 for (i = 0; i < thread->owned_mutexes->len; i++) {
1253 gpointer mutex = g_ptr_array_index (thread->owned_mutexes, i);
1254 if (i > 0)
1255 g_string_append_printf (text, ", %p", mutex);
1256 else
1257 g_string_append_printf (text, "%p", mutex);
1259 g_string_append_printf (text, ")");
1261 res = text->str;
1262 g_string_free (text, FALSE);
1263 return res;
1267 * wapi_thread_set_wait_handle:
1269 * Set the wait handle for the current thread to HANDLE. Return TRUE on success, FALSE
1270 * if the thread is in interrupted state, and cannot start waiting.
1272 gboolean wapi_thread_set_wait_handle (gpointer handle)
1274 struct _WapiHandle_thread *thread;
1275 gboolean ok;
1276 gpointer prev_handle;
1277 gpointer thread_handle;
1279 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1280 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1281 (gpointer *)&thread);
1282 g_assert (ok);
1284 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1285 handle, NULL);
1286 _wapi_handle_unref (thread_handle);
1288 if (prev_handle == NULL) {
1289 /* thread->wait_handle acts as an additional reference to the handle */
1290 _wapi_handle_ref (handle);
1292 WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
1293 } else {
1294 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
1295 WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
1298 return prev_handle == NULL;
1302 * wapi_thread_clear_wait_handle:
1304 * Clear the wait handle of the current thread.
1306 void wapi_thread_clear_wait_handle (gpointer handle)
1308 struct _WapiHandle_thread *thread;
1309 gboolean ok;
1310 gpointer prev_handle;
1311 gpointer thread_handle;
1313 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1314 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1315 (gpointer *)&thread);
1316 g_assert (ok);
1318 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1319 NULL, handle);
1321 if (prev_handle == handle) {
1322 _wapi_handle_unref (handle);
1323 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1324 } else {
1325 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
1326 WAIT_DEBUG (printf ("%p: finished waiting.\n", GetCurrentThreadId ()););
1329 _wapi_handle_unref (thread_handle);
1332 void _wapi_thread_own_mutex (gpointer mutex)
1334 struct _WapiHandle_thread *thread_handle;
1335 gboolean ok;
1336 gpointer thread;
1338 thread = _wapi_thread_handle_from_id (pthread_self ());
1339 if (thread == NULL) {
1340 g_warning ("%s: error looking up thread by ID", __func__);
1341 return;
1344 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1345 (gpointer *)&thread_handle);
1346 if (ok == FALSE) {
1347 g_warning ("%s: error looking up thread handle %p", __func__,
1348 thread);
1349 return;
1352 _wapi_handle_ref (mutex);
1354 g_ptr_array_add (thread_handle->owned_mutexes, mutex);
1357 void _wapi_thread_disown_mutex (gpointer mutex)
1359 struct _WapiHandle_thread *thread_handle;
1360 gboolean ok;
1361 gpointer thread;
1363 thread = _wapi_thread_handle_from_id (pthread_self ());
1364 if (thread == NULL) {
1365 g_warning ("%s: error looking up thread by ID", __func__);
1366 return;
1369 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1370 (gpointer *)&thread_handle);
1371 if (ok == FALSE) {
1372 g_warning ("%s: error looking up thread handle %p", __func__,
1373 thread);
1374 return;
1377 _wapi_handle_unref (mutex);
1379 g_ptr_array_remove (thread_handle->owned_mutexes, mutex);