Merge branch 'master' of github.com:mono/mono
[mono-project/dkf.git] / mono / io-layer / wthreads.c
blob6f84bf12b337a07f7ac8820191d3fac5d256a33b
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 = mono_gc_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 #ifdef DEBUG
276 g_message ("%s: started thread id %ld", __func__, thread->id);
277 #endif
279 /* We set it again here since passing &thread->id to pthread_create is racy
280 as the thread can start running before the value is set.*/
281 thread->id = pthread_self ();
283 if (thread->create_flags & CREATE_SUSPENDED) {
284 _wapi_thread_suspend (thread);
287 thread_exit (thread->start_routine (thread->start_arg),
288 thread->handle);
290 #ifndef __GNUC__
291 /* Even though we tell gcc that this function doesn't return,
292 * other compilers won't see that.
294 return(NULL);
295 #endif
299 * CreateThread:
300 * @security: Ignored for now.
301 * @stacksize: the size in bytes of the new thread's stack. Use 0 to
302 * default to the normal stack size. (Ignored for now).
303 * @start: The function that the new thread should start with
304 * @param: The parameter to give to @start.
305 * @create: If 0, the new thread is ready to run immediately. If
306 * %CREATE_SUSPENDED, the new thread will be in the suspended state,
307 * requiring a ResumeThread() call to continue running.
308 * @tid: If non-NULL, the ID of the new thread is stored here. NB
309 * this is defined as a DWORD (ie 32bit) in the MS API, but we need to
310 * cope with 64 bit IDs for s390x and amd64.
312 * Creates a new threading handle.
314 * Return value: a new handle, or NULL
316 gpointer CreateThread(WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 stacksize,
317 WapiThreadStart start, gpointer param, guint32 create,
318 gsize *tid)
320 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
321 pthread_attr_t attr;
322 gpointer handle;
323 gboolean ok;
324 int ret;
325 int thr_ret;
326 int i, unrefs = 0;
327 gpointer ct_ret = NULL;
329 mono_once (&thread_hash_once, thread_hash_init);
330 mono_once (&thread_ops_once, thread_ops_init);
332 if (start == NULL) {
333 return(NULL);
336 thread_handle.state = THREAD_STATE_START;
337 thread_handle.owned_mutexes = g_ptr_array_new ();
338 thread_handle.create_flags = create;
339 thread_handle.start_routine = start;
340 thread_handle.start_arg = param;
342 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
343 if (handle == _WAPI_HANDLE_INVALID) {
344 g_warning ("%s: error creating thread handle", __func__);
345 SetLastError (ERROR_GEN_FAILURE);
347 return (NULL);
350 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
351 handle);
352 thr_ret = _wapi_handle_lock_handle (handle);
353 g_assert (thr_ret == 0);
355 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
356 (gpointer *)&thread_handle_p);
357 if (ok == FALSE) {
358 g_warning ("%s: error looking up thread handle %p", __func__,
359 handle);
360 SetLastError (ERROR_GEN_FAILURE);
362 goto cleanup;
365 /* Hold a reference while the thread is active, because we use
366 * the handle to store thread exit information
368 _wapi_handle_ref (handle);
370 /* Set a 2M stack size. This is the default on Linux, but BSD
371 * needs it. (The original bug report from Martin Dvorak <md@9ll.cz>
372 * set the size to 2M-4k. I don't know why it's short by 4k, so
373 * I'm leaving it as 2M until I'm told differently.)
375 thr_ret = pthread_attr_init(&attr);
376 g_assert (thr_ret == 0);
378 /* defaults of 2Mb for 32bits and 4Mb for 64bits */
379 /* temporarily changed to use 1 MB: this allows more threads
380 * to be used, as well as using less virtual memory and so
381 * more is available for the GC heap.
383 if (stacksize == 0){
384 #if HAVE_VALGRIND_MEMCHECK_H
385 if (RUNNING_ON_VALGRIND) {
386 stacksize = 1 << 20;
387 } else {
388 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
390 #else
391 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
392 #endif
395 #ifdef PTHREAD_STACK_MIN
396 if (stacksize < PTHREAD_STACK_MIN)
397 stacksize = PTHREAD_STACK_MIN;
398 #endif
400 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
401 thr_ret = pthread_attr_setstacksize(&attr, stacksize);
402 g_assert (thr_ret == 0);
403 #endif
405 MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
406 thread_handle_p->handle = handle;
409 ret = mono_gc_pthread_create (&thread_handle_p->id, &attr,
410 thread_start_routine, (void *)thread_handle_p);
412 if (ret != 0) {
413 #ifdef DEBUG
414 g_message ("%s: Thread create error: %s", __func__,
415 strerror(ret));
416 #endif
418 /* Two, because of the reference we took above */
419 unrefs = 2;
421 goto cleanup;
423 ct_ret = handle;
425 #ifdef DEBUG
426 g_message("%s: Started thread handle %p ID %ld", __func__, handle,
427 thread_handle_p->id);
428 #endif
430 if (tid != NULL) {
431 #ifdef PTHREAD_POINTER_ID
432 /* Don't use GPOINTER_TO_UINT here, it can't cope with
433 * sizeof(void *) > sizeof(uint) when a cast to uint
434 * would overflow
436 *tid = (gsize)(thread_handle_p->id);
437 #else
438 *tid = thread_handle_p->id;
439 #endif
442 cleanup:
443 thr_ret = _wapi_handle_unlock_handle (handle);
444 g_assert (thr_ret == 0);
445 pthread_cleanup_pop (0);
447 /* Must not call _wapi_handle_unref() with the shared handles
448 * already locked
450 for (i = 0; i < unrefs; i++) {
451 _wapi_handle_unref (handle);
454 return(ct_ret);
457 /* The only time this function is called when tid != pthread_self ()
458 * is from OpenThread (), so we can fast-path most cases by just
459 * looking up the handle in TLS. OpenThread () must cope with a NULL
460 * return and do a handle search in that case.
462 gpointer _wapi_thread_handle_from_id (pthread_t tid)
464 gpointer ret;
466 if (pthread_equal (tid, pthread_self ()) &&
467 (ret = pthread_getspecific (thread_hash_key)) != NULL) {
468 /* We know the handle */
470 #ifdef DEBUG
471 g_message ("%s: Returning %p for self thread %ld from TLS",
472 __func__, ret, tid);
473 #endif
475 return(ret);
478 #ifdef DEBUG
479 g_message ("%s: Returning NULL for unknown or non-self thread %ld",
480 __func__, tid);
481 #endif
484 return(NULL);
487 static gboolean find_thread_by_id (gpointer handle, gpointer user_data)
489 pthread_t tid = (pthread_t)user_data;
490 struct _WapiHandle_thread *thread_handle;
491 gboolean ok;
493 /* Ignore threads that have already exited (ie they are signalled) */
494 if (_wapi_handle_issignalled (handle) == FALSE) {
495 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
496 (gpointer *)&thread_handle);
497 if (ok == FALSE) {
498 /* It's possible that the handle has vanished
499 * during the _wapi_search_handle before it
500 * gets here, so don't spam the console with
501 * warnings.
503 return(FALSE);
506 #ifdef DEBUG
507 g_message ("%s: looking at thread %ld from process %d", __func__, thread_handle->id, 0);
508 #endif
510 if (pthread_equal (thread_handle->id, tid)) {
511 #ifdef DEBUG
512 g_message ("%s: found the thread we are looking for",
513 __func__);
514 #endif
515 return(TRUE);
519 #ifdef DEBUG
520 g_message ("%s: not found %ld, returning FALSE", __func__, tid);
521 #endif
523 return(FALSE);
526 /* NB tid is 32bit in MS API, but we need 64bit on amd64 and s390x
527 * (and probably others)
529 gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, gsize tid)
531 gpointer ret=NULL;
533 mono_once (&thread_hash_once, thread_hash_init);
534 mono_once (&thread_ops_once, thread_ops_init);
536 #ifdef DEBUG
537 g_message ("%s: looking up thread %"G_GSIZE_FORMAT, __func__, tid);
538 #endif
540 ret = _wapi_thread_handle_from_id ((pthread_t)tid);
541 if (ret == NULL) {
542 /* We need to search for this thread */
543 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 */
544 } else {
545 /* if _wapi_search_handle() returns a found handle, it
546 * refs it itself
548 _wapi_handle_ref (ret);
551 #ifdef DEBUG
552 g_message ("%s: returning thread handle %p", __func__, ret);
553 #endif
555 return(ret);
559 * ExitThread:
560 * @exitcode: Sets the thread's exit code, which can be read from
561 * another thread with GetExitCodeThread().
563 * Terminates the calling thread. A thread can also exit by returning
564 * from its start function. When the last thread in a process
565 * terminates, the process itself terminates.
567 void ExitThread(guint32 exitcode)
569 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
571 if (thread != NULL) {
572 thread_exit(exitcode, thread);
573 } else {
574 /* Just blow this thread away */
575 pthread_exit (NULL);
580 * GetExitCodeThread:
581 * @handle: The thread handle to query
582 * @exitcode: The thread @handle exit code is stored here
584 * Finds the exit code of @handle, and stores it in @exitcode. If the
585 * thread @handle is still running, the value stored is %STILL_ACTIVE.
587 * Return value: %TRUE, or %FALSE on error.
589 gboolean GetExitCodeThread(gpointer handle, guint32 *exitcode)
591 struct _WapiHandle_thread *thread_handle;
592 gboolean ok;
594 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
595 (gpointer *)&thread_handle);
596 if (ok == FALSE) {
597 g_warning ("%s: error looking up thread handle %p", __func__,
598 handle);
599 return (FALSE);
602 #ifdef DEBUG
603 g_message ("%s: Finding exit status for thread handle %p id %ld",
604 __func__, handle, thread_handle->id);
605 #endif
607 if (exitcode == NULL) {
608 #ifdef DEBUG
609 g_message ("%s: Nowhere to store exit code", __func__);
610 #endif
611 return(FALSE);
614 if (thread_handle->state != THREAD_STATE_EXITED) {
615 #ifdef DEBUG
616 g_message ("%s: Thread still active (state %d, exited is %d)",
617 __func__, thread_handle->state,
618 THREAD_STATE_EXITED);
619 #endif
620 *exitcode = STILL_ACTIVE;
621 return(TRUE);
624 *exitcode = thread_handle->exitstatus;
626 return(TRUE);
630 * GetCurrentThreadId:
632 * Looks up the thread ID of the current thread. This ID can be
633 * passed to OpenThread() to create a new handle on this thread.
635 * Return value: the thread ID. NB this is defined as DWORD (ie 32
636 * bit) in the MS API, but we need to cope with 64 bit IDs for s390x
637 * and amd64. This doesn't really break the API, it just embraces and
638 * extends it on 64bit platforms :)
640 gsize GetCurrentThreadId(void)
642 pthread_t tid = pthread_self();
644 #ifdef PTHREAD_POINTER_ID
645 /* Don't use GPOINTER_TO_UINT here, it can't cope with
646 * sizeof(void *) > sizeof(uint) when a cast to uint would
647 * overflow
649 return((gsize)tid);
650 #else
651 return(tid);
652 #endif
655 static gpointer thread_attach(gsize *tid)
657 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
658 gpointer handle;
659 gboolean ok;
660 int thr_ret;
662 mono_once (&thread_hash_once, thread_hash_init);
663 mono_once (&thread_ops_once, thread_ops_init);
665 thread_handle.state = THREAD_STATE_START;
666 thread_handle.owned_mutexes = g_ptr_array_new ();
668 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
669 if (handle == _WAPI_HANDLE_INVALID) {
670 g_warning ("%s: error creating thread handle", __func__);
672 SetLastError (ERROR_GEN_FAILURE);
673 return (NULL);
676 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
677 handle);
678 thr_ret = _wapi_handle_lock_handle (handle);
679 g_assert (thr_ret == 0);
681 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
682 (gpointer *)&thread_handle_p);
683 if (ok == FALSE) {
684 g_warning ("%s: error looking up thread handle %p", __func__,
685 handle);
687 SetLastError (ERROR_GEN_FAILURE);
688 goto cleanup;
691 /* Hold a reference while the thread is active, because we use
692 * the handle to store thread exit information
694 _wapi_handle_ref (handle);
696 /* suspend_sem is not used for attached threads, but
697 * thread_exit() might try to destroy it
699 MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
700 thread_handle_p->handle = handle;
701 thread_handle_p->id = pthread_self ();
703 thr_ret = pthread_setspecific (thread_hash_key, (void *)handle);
704 g_assert (thr_ret == 0);
706 thr_ret = pthread_setspecific (thread_attached_key, (void *)handle);
707 g_assert (thr_ret == 0);
709 #ifdef DEBUG
710 g_message("%s: Attached thread handle %p ID %ld", __func__, handle,
711 thread_handle_p->id);
712 #endif
714 if (tid != NULL) {
715 #ifdef PTHREAD_POINTER_ID
716 /* Don't use GPOINTER_TO_UINT here, it can't cope with
717 * sizeof(void *) > sizeof(uint) when a cast to uint
718 * would overflow
720 *tid = (gsize)(thread_handle_p->id);
721 #else
722 *tid = thread_handle_p->id;
723 #endif
726 cleanup:
727 thr_ret = _wapi_handle_unlock_handle (handle);
728 g_assert (thr_ret == 0);
729 pthread_cleanup_pop (0);
731 return(handle);
734 gpointer _wapi_thread_duplicate ()
736 gpointer ret = NULL;
738 mono_once (&thread_hash_once, thread_hash_init);
739 mono_once (&thread_ops_once, thread_ops_init);
741 ret = _wapi_thread_handle_from_id (pthread_self ());
742 if (!ret) {
743 ret = thread_attach (NULL);
744 } else {
745 _wapi_handle_ref (ret);
748 return(ret);
752 * GetCurrentThread:
754 * Looks up the handle associated with the current thread. Under
755 * Windows this is a pseudohandle, and must be duplicated with
756 * DuplicateHandle() for some operations.
758 * Return value: The current thread handle, or %NULL on failure.
759 * (Unknown whether Windows has a possible failure here. It may be
760 * necessary to implement the pseudohandle-constant behaviour).
762 gpointer GetCurrentThread(void)
764 mono_once(&thread_hash_once, thread_hash_init);
765 mono_once (&thread_ops_once, thread_ops_init);
767 return(_WAPI_THREAD_CURRENT);
771 * ResumeThread:
772 * @handle: the thread handle to resume
774 * Decrements the suspend count of thread @handle. A thread can only
775 * run if its suspend count is zero.
777 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
779 guint32 ResumeThread(gpointer handle)
781 struct _WapiHandle_thread *thread_handle;
782 gboolean ok;
784 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
785 (gpointer *)&thread_handle);
786 if (ok == FALSE) {
787 g_warning ("%s: error looking up thread handle %p", __func__,
788 handle);
790 return (0xFFFFFFFF);
793 /* This is still a kludge that only copes with starting a
794 * thread that was suspended on create, so don't bother with
795 * the suspend count crap yet
797 _wapi_thread_resume (thread_handle);
798 return(0xFFFFFFFF);
802 * SuspendThread:
803 * @handle: the thread handle to suspend
805 * Increments the suspend count of thread @handle. A thread can only
806 * run if its suspend count is zero.
808 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
810 guint32 SuspendThread(gpointer handle)
812 return(0xFFFFFFFF);
816 * We assume here that TLS_MINIMUM_AVAILABLE is less than
817 * PTHREAD_KEYS_MAX, allowing enough overhead for a few TLS keys for
818 * library usage.
820 * Currently TLS_MINIMUM_AVAILABLE is 64 and _POSIX_THREAD_KEYS_MAX
821 * (the minimum value for PTHREAD_KEYS_MAX) is 128, so we should be
822 * fine.
825 static pthread_key_t TLS_keys[TLS_MINIMUM_AVAILABLE];
826 static gboolean TLS_used[TLS_MINIMUM_AVAILABLE]={FALSE};
827 static pthread_mutex_t TLS_mutex = PTHREAD_MUTEX_INITIALIZER;
829 guint32
830 mono_pthread_key_for_tls (guint32 idx)
832 return (guint32)TLS_keys [idx];
836 * TlsAlloc:
838 * Allocates a Thread Local Storage (TLS) index. Any thread in the
839 * same process can use this index to store and retrieve values that
840 * are local to that thread.
842 * Return value: The index value, or %TLS_OUT_OF_INDEXES if no index
843 * is available.
845 guint32 TlsAlloc(void)
847 guint32 i;
848 int thr_ret;
850 pthread_mutex_lock (&TLS_mutex);
852 for(i=0; i<TLS_MINIMUM_AVAILABLE; i++) {
853 if(TLS_used[i]==FALSE) {
854 TLS_used[i]=TRUE;
855 thr_ret = pthread_key_create(&TLS_keys[i], NULL);
856 g_assert (thr_ret == 0);
858 pthread_mutex_unlock (&TLS_mutex);
860 #ifdef TLS_DEBUG
861 g_message ("%s: returning key %d", __func__, i);
862 #endif
864 return(i);
868 pthread_mutex_unlock (&TLS_mutex);
870 #ifdef TLS_DEBUG
871 g_message ("%s: out of indices", __func__);
872 #endif
875 return(TLS_OUT_OF_INDEXES);
878 #define MAKE_GC_ID(idx) (GUINT_TO_POINTER((idx)|(GetCurrentThreadId()<<8)))
881 * TlsFree:
882 * @idx: The TLS index to free
884 * Releases a TLS index, making it available for reuse. This call
885 * will delete any TLS data stored under index @idx in all threads.
887 * Return value: %TRUE on success, %FALSE otherwise.
889 gboolean TlsFree(guint32 idx)
891 int thr_ret;
893 #ifdef TLS_DEBUG
894 g_message ("%s: freeing key %d", __func__, idx);
895 #endif
897 if (idx >= TLS_MINIMUM_AVAILABLE) {
898 SetLastError (ERROR_INVALID_PARAMETER);
899 return FALSE;
902 pthread_mutex_lock (&TLS_mutex);
904 if(TLS_used[idx]==FALSE) {
905 pthread_mutex_unlock (&TLS_mutex);
906 SetLastError (ERROR_INVALID_PARAMETER);
907 return(FALSE);
910 TLS_used[idx]=FALSE;
911 thr_ret = pthread_key_delete(TLS_keys[idx]);
912 g_assert (thr_ret == 0);
914 pthread_mutex_unlock (&TLS_mutex);
916 return(TRUE);
920 * TlsGetValue:
921 * @idx: The TLS index to retrieve
923 * Retrieves the TLS data stored under index @idx.
925 * Return value: The value stored in the TLS index @idx in the current
926 * thread, or %NULL on error. As %NULL can be a valid return value,
927 * in this case GetLastError() returns %ERROR_SUCCESS.
929 gpointer TlsGetValue(guint32 idx)
931 gpointer ret;
933 #ifdef TLS_DEBUG
934 g_message ("%s: looking up key %d", __func__, idx);
935 #endif
936 if (idx >= TLS_MINIMUM_AVAILABLE) {
937 SetLastError (ERROR_INVALID_PARAMETER);
938 return NULL;
940 ret=pthread_getspecific(TLS_keys[idx]);
942 #ifdef TLS_DEBUG
943 g_message ("%s: returning %p", __func__, ret);
944 #endif
946 SetLastError (ERROR_SUCCESS);
947 return(ret);
951 * TlsSetValue:
952 * @idx: The TLS index to store
953 * @value: The value to store under index @idx
955 * Stores @value at TLS index @idx.
957 * Return value: %TRUE on success, %FALSE otherwise.
959 gboolean TlsSetValue(guint32 idx, gpointer value)
961 int ret;
963 #ifdef TLS_DEBUG
964 g_message ("%s: setting key %d to %p", __func__, idx, value);
965 #endif
966 if (idx >= TLS_MINIMUM_AVAILABLE) {
967 SetLastError (ERROR_INVALID_PARAMETER);
968 return FALSE;
971 ret=pthread_setspecific(TLS_keys[idx], value);
972 #ifdef TLS_DEBUG
973 if(ret!=0)
974 g_message ("%s: pthread_setspecific error: %s", __func__,
975 strerror (ret));
976 #endif
978 return(ret == 0);
982 * SleepEx:
983 * @ms: The time in milliseconds to suspend for
984 * @alertable: if TRUE, the wait can be interrupted by an APC call
986 * Suspends execution of the current thread for @ms milliseconds. A
987 * value of zero causes the thread to relinquish its time slice. A
988 * value of %INFINITE causes an infinite delay.
990 guint32 SleepEx(guint32 ms, gboolean alertable)
992 struct timespec req, rem;
993 int ms_quot, ms_rem;
994 int ret;
995 gpointer current_thread = NULL;
997 #ifdef DEBUG
998 g_message("%s: Sleeping for %d ms", __func__, ms);
999 #endif
1001 if (alertable) {
1002 current_thread = _wapi_thread_handle_from_id (pthread_self ());
1003 if (current_thread == NULL) {
1004 SetLastError (ERROR_INVALID_HANDLE);
1005 return(WAIT_FAILED);
1008 if (_wapi_thread_apc_pending (current_thread)) {
1009 _wapi_thread_dispatch_apc_queue (current_thread);
1010 return WAIT_IO_COMPLETION;
1014 if(ms==0) {
1015 sched_yield();
1016 return 0;
1019 /* FIXME: check for INFINITE and sleep forever */
1020 ms_quot = ms / 1000;
1021 ms_rem = ms % 1000;
1023 req.tv_sec=ms_quot;
1024 req.tv_nsec=ms_rem*1000000;
1026 again:
1027 memset (&rem, 0, sizeof (rem));
1028 ret=nanosleep(&req, &rem);
1030 if (alertable && _wapi_thread_apc_pending (current_thread)) {
1031 _wapi_thread_dispatch_apc_queue (current_thread);
1032 return WAIT_IO_COMPLETION;
1035 if(ret==-1) {
1036 /* Sleep interrupted with rem time remaining */
1037 #ifdef DEBUG
1038 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
1040 g_message("%s: Still got %d ms to go", __func__, rems);
1041 #endif
1042 req=rem;
1043 goto again;
1046 return 0;
1049 void Sleep(guint32 ms)
1051 SleepEx(ms, FALSE);
1054 gboolean _wapi_thread_cur_apc_pending (void)
1056 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
1058 if (thread == NULL) {
1059 SetLastError (ERROR_INVALID_HANDLE);
1060 return(FALSE);
1063 return(_wapi_thread_apc_pending (thread));
1066 gboolean _wapi_thread_apc_pending (gpointer handle)
1068 struct _WapiHandle_thread *thread;
1069 gboolean ok;
1071 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1072 (gpointer *)&thread);
1073 if (ok == FALSE) {
1074 #ifdef DEBUG
1075 /* This might happen at process shutdown, as all
1076 * thread handles are forcibly closed. If a thread
1077 * still has an alertable wait the final
1078 * _wapi_thread_apc_pending check will probably fail
1079 * to find the handle
1081 g_warning ("%s: error looking up thread handle %p", __func__,
1082 handle);
1083 #endif
1084 return (FALSE);
1087 return(thread->has_apc || thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE);
1090 gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
1092 /* We don't support calling APC functions */
1093 struct _WapiHandle_thread *thread;
1094 gboolean ok;
1096 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1097 (gpointer *)&thread);
1098 g_assert (ok);
1100 thread->has_apc = FALSE;
1102 return(TRUE);
1106 * In this implementation, APC_CALLBACK is ignored.
1107 * if HANDLE refers to the current thread, the only effect this function has
1108 * that if called from a signal handler, and the thread was waiting when receiving
1109 * the signal, the wait will be broken after the signal handler returns.
1110 * In this case, this function is async-signal-safe.
1112 guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer handle,
1113 gpointer param)
1115 struct _WapiHandle_thread *thread_handle;
1116 gboolean ok;
1118 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1119 (gpointer *)&thread_handle);
1120 if (ok == FALSE) {
1121 g_warning ("%s: error looking up thread handle %p", __func__,
1122 handle);
1123 return (0);
1126 g_assert (thread_handle->id == GetCurrentThreadId ());
1127 /* No locking/memory barriers are needed here */
1128 thread_handle->has_apc = TRUE;
1129 return(1);
1133 * wapi_interrupt_thread:
1135 * This is not part of the WIN32 API.
1136 * The state of the thread handle HANDLE is set to 'interrupted' which means that
1137 * if the thread calls one of the WaitFor functions, the function will return with
1138 * WAIT_IO_COMPLETION instead of waiting. Also, if the thread was waiting when
1139 * this function was called, the wait will be broken.
1140 * It is possible that the wait functions return WAIT_IO_COMPLETION, but the
1141 * target thread didn't receive the interrupt signal yet, in this case it should
1142 * call the wait function again. This essentially means that the target thread will
1143 * busy wait until it is ready to process the interruption.
1144 * FIXME: get rid of QueueUserAPC and thread->has_apc, SleepEx seems to require it.
1146 void wapi_interrupt_thread (gpointer thread_handle)
1148 struct _WapiHandle_thread *thread;
1149 gboolean ok;
1150 gpointer prev_handle, wait_handle;
1151 guint32 idx;
1152 pthread_cond_t *cond;
1153 mono_mutex_t *mutex;
1155 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1156 (gpointer *)&thread);
1157 g_assert (ok);
1159 while (TRUE) {
1160 wait_handle = thread->wait_handle;
1163 * Atomically obtain the handle the thread is waiting on, and
1164 * change it to a flag value.
1166 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1167 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1168 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1169 /* Already interrupted */
1170 return;
1171 if (prev_handle == wait_handle)
1172 break;
1174 /* Try again */
1177 WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread_handle->id););
1179 if (!wait_handle)
1180 /* Not waiting */
1181 return;
1183 /* If we reach here, then wait_handle is set to the flag value,
1184 * which means that the target thread is either
1185 * - before the first CAS in timedwait, which means it won't enter the
1186 * wait.
1187 * - it is after the first CAS, so it is already waiting, or it will
1188 * enter the wait, and it will be interrupted by the broadcast.
1190 idx = GPOINTER_TO_UINT(wait_handle);
1191 cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
1192 mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
1194 mono_mutex_lock (mutex);
1195 mono_cond_broadcast (cond);
1196 mono_mutex_unlock (mutex);
1198 /* ref added by set_wait_handle */
1199 _wapi_handle_unref (wait_handle);
1203 * wapi_self_interrupt:
1205 * This is not part of the WIN32 API.
1206 * Set the 'interrupted' state of the calling thread if it's NULL.
1208 void wapi_self_interrupt (void)
1210 struct _WapiHandle_thread *thread;
1211 gboolean ok;
1212 gpointer prev_handle, wait_handle;
1213 gpointer thread_handle;
1216 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1217 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1218 (gpointer *)&thread);
1219 g_assert (ok);
1221 while (TRUE) {
1222 wait_handle = thread->wait_handle;
1225 * Atomically obtain the handle the thread is waiting on, and
1226 * change it to a flag value.
1228 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1229 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1230 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1231 /* Already interrupted */
1232 goto cleanup;
1233 /*We did not get interrupted*/
1234 if (prev_handle == wait_handle)
1235 break;
1237 /* Try again */
1240 if (wait_handle) {
1241 /* ref added by set_wait_handle */
1242 _wapi_handle_unref (wait_handle);
1245 cleanup:
1246 _wapi_handle_unref (thread_handle);
1250 * wapi_clear_interruption:
1252 * This is not part of the WIN32 API.
1253 * Clear the 'interrupted' state of the calling thread.
1254 * This function is signal safe
1256 void wapi_clear_interruption (void)
1258 struct _WapiHandle_thread *thread;
1259 gboolean ok;
1260 gpointer prev_handle;
1261 gpointer thread_handle;
1263 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1264 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1265 (gpointer *)&thread);
1266 g_assert (ok);
1268 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1269 NULL, INTERRUPTION_REQUESTED_HANDLE);
1270 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1271 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1273 _wapi_handle_unref (thread_handle);
1276 char* wapi_current_thread_desc ()
1278 struct _WapiHandle_thread *thread;
1279 int i;
1280 gboolean ok;
1281 gpointer handle;
1282 gpointer thread_handle;
1283 GString* text;
1284 char *res;
1286 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1287 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1288 (gpointer *)&thread);
1289 if (!ok)
1290 return g_strdup_printf ("thread handle %p state : lookup failure", thread_handle);
1292 handle = thread->wait_handle;
1293 text = g_string_new (0);
1294 g_string_append_printf (text, "thread handle %p state : ", thread_handle);
1296 if (!handle)
1297 g_string_append_printf (text, "not waiting");
1298 else if (handle == INTERRUPTION_REQUESTED_HANDLE)
1299 g_string_append_printf (text, "interrupted state");
1300 else
1301 g_string_append_printf (text, "waiting on %p : %s ", handle, _wapi_handle_typename[_wapi_handle_type (handle)]);
1302 g_string_append_printf (text, " owns (");
1303 for (i = 0; i < thread->owned_mutexes->len; i++) {
1304 gpointer mutex = g_ptr_array_index (thread->owned_mutexes, i);
1305 if (i > 0)
1306 g_string_append_printf (text, ", %p", mutex);
1307 else
1308 g_string_append_printf (text, "%p", mutex);
1310 g_string_append_printf (text, ")");
1312 res = text->str;
1313 g_string_free (text, FALSE);
1314 return res;
1318 * wapi_thread_set_wait_handle:
1320 * Set the wait handle for the current thread to HANDLE. Return TRUE on success, FALSE
1321 * if the thread is in interrupted state, and cannot start waiting.
1323 gboolean wapi_thread_set_wait_handle (gpointer handle)
1325 struct _WapiHandle_thread *thread;
1326 gboolean ok;
1327 gpointer prev_handle;
1328 gpointer thread_handle;
1330 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1331 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1332 (gpointer *)&thread);
1333 g_assert (ok);
1335 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1336 handle, NULL);
1337 _wapi_handle_unref (thread_handle);
1339 if (prev_handle == NULL) {
1340 /* thread->wait_handle acts as an additional reference to the handle */
1341 _wapi_handle_ref (handle);
1343 WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
1344 } else {
1345 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
1346 WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
1349 return prev_handle == NULL;
1353 * wapi_thread_clear_wait_handle:
1355 * Clear the wait handle of the current thread.
1357 void wapi_thread_clear_wait_handle (gpointer handle)
1359 struct _WapiHandle_thread *thread;
1360 gboolean ok;
1361 gpointer prev_handle;
1362 gpointer thread_handle;
1364 thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1365 ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1366 (gpointer *)&thread);
1367 g_assert (ok);
1369 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1370 NULL, handle);
1372 if (prev_handle == handle) {
1373 _wapi_handle_unref (handle);
1374 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1375 } else {
1376 /*It can be NULL if it was asynchronously cleared*/
1377 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE || prev_handle == NULL);
1378 WAIT_DEBUG (printf ("%p: finished waiting.\n", GetCurrentThreadId ()););
1381 _wapi_handle_unref (thread_handle);
1384 void _wapi_thread_own_mutex (gpointer mutex)
1386 struct _WapiHandle_thread *thread_handle;
1387 gboolean ok;
1388 gpointer thread;
1390 thread = _wapi_thread_handle_from_id (pthread_self ());
1391 if (thread == NULL) {
1392 g_warning ("%s: error looking up thread by ID", __func__);
1393 return;
1396 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1397 (gpointer *)&thread_handle);
1398 if (ok == FALSE) {
1399 g_warning ("%s: error looking up thread handle %p", __func__,
1400 thread);
1401 return;
1404 _wapi_handle_ref (mutex);
1406 g_ptr_array_add (thread_handle->owned_mutexes, mutex);
1409 void _wapi_thread_disown_mutex (gpointer mutex)
1411 struct _WapiHandle_thread *thread_handle;
1412 gboolean ok;
1413 gpointer thread;
1415 thread = _wapi_thread_handle_from_id (pthread_self ());
1416 if (thread == NULL) {
1417 g_warning ("%s: error looking up thread by ID", __func__);
1418 return;
1421 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1422 (gpointer *)&thread_handle);
1423 if (ok == FALSE) {
1424 g_warning ("%s: error looking up thread handle %p", __func__,
1425 thread);
1426 return;
1429 _wapi_handle_unref (mutex);
1431 g_ptr_array_remove (thread_handle->owned_mutexes, mutex);