2 * threads.c: Thread handles
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002-2006 Ximian, Inc.
8 * Copyright 2003-2011 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
21 #include <sys/types.h>
24 #include <mono/io-layer/wapi.h>
25 #include <mono/io-layer/wapi-private.h>
26 #include <mono/io-layer/handles-private.h>
27 #include <mono/io-layer/misc-private.h>
28 #include <mono/io-layer/thread-private.h>
29 #include <mono/io-layer/mutex-private.h>
31 #include <mono/utils/mono-threads.h>
32 #include <mono/utils/atomic.h>
33 #include <mono/utils/mono-mutex.h>
35 #ifdef HAVE_VALGRIND_MEMCHECK_H
36 #include <valgrind/memcheck.h>
40 #define DEBUG(...) g_message(__VA_ARGS__)
46 #define WAIT_DEBUG(code) do { code } while (0)
48 #define WAIT_DEBUG(code) do { } while (0)
51 struct _WapiHandleOps _wapi_thread_ops = {
56 NULL, /* special_wait */
60 static mono_once_t thread_ops_once = MONO_ONCE_INIT;
63 thread_ops_init (void)
65 _wapi_handle_register_capabilities (WAPI_HANDLE_THREAD,
66 WAPI_HANDLE_CAP_WAIT);
70 _wapi_thread_cleanup (void)
75 get_current_thread_handle (void)
79 info = mono_thread_info_current ();
81 g_assert (info->handle);
85 static WapiHandle_thread*
86 lookup_thread (HANDLE handle)
88 WapiHandle_thread *thread;
91 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
97 static WapiHandle_thread*
98 get_current_thread (void)
102 handle = get_current_thread_handle ();
103 return lookup_thread (handle);
107 wapi_thread_handle_set_exited (gpointer handle, guint32 exitstatus)
109 WapiHandle_thread *thread_handle;
111 pid_t pid = _wapi_getpid ();
112 pthread_t tid = pthread_self ();
114 if (_wapi_handle_issignalled (handle) ||
115 _wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) {
116 /* We must have already deliberately finished with
117 * this thread, so don't do any more now
122 DEBUG ("%s: Thread %p terminating", __func__, handle);
124 thread_handle = lookup_thread (handle);
126 DEBUG ("%s: Thread %p abandoning held mutexes", __func__, handle);
128 for (i = 0; i < thread_handle->owned_mutexes->len; i++) {
129 gpointer mutex = g_ptr_array_index (thread_handle->owned_mutexes, i);
131 _wapi_mutex_abandon (mutex, pid, tid);
132 _wapi_thread_disown_mutex (mutex);
134 g_ptr_array_free (thread_handle->owned_mutexes, TRUE);
136 thr_ret = _wapi_handle_lock_handle (handle);
137 g_assert (thr_ret == 0);
139 _wapi_handle_set_signal_state (handle, TRUE, TRUE);
141 thr_ret = _wapi_handle_unlock_handle (handle);
142 g_assert (thr_ret == 0);
144 DEBUG("%s: Recording thread handle %p id %ld status as %d",
145 __func__, handle, thread_handle->id, exitstatus);
147 /* The thread is no longer active, so unref it */
148 _wapi_handle_unref (handle);
152 * wapi_create_thread_handle:
154 * Create a thread handle for the current thread.
157 wapi_create_thread_handle (void)
159 WapiHandle_thread thread_handle = {0}, *thread;
162 mono_once (&thread_ops_once, thread_ops_init);
164 thread_handle.owned_mutexes = g_ptr_array_new ();
166 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
167 if (handle == _WAPI_HANDLE_INVALID) {
168 g_warning ("%s: error creating thread handle", __func__);
169 SetLastError (ERROR_GEN_FAILURE);
174 thread = lookup_thread (handle);
176 thread->id = pthread_self ();
179 * Hold a reference while the thread is active, because we use
180 * the handle to store thread exit information
182 _wapi_handle_ref (handle);
184 DEBUG ("%s: started thread id %ld", __func__, thread->id);
190 wapi_ref_thread_handle (gpointer handle)
192 _wapi_handle_ref (handle);
196 wapi_get_current_thread_handle (void)
198 return get_current_thread_handle ();
202 * GetCurrentThreadId:
204 * Looks up the thread ID of the current thread. This ID can be
205 * passed to OpenThread() to create a new handle on this thread.
207 * Return value: the thread ID. NB this is defined as DWORD (ie 32
208 * bit) in the MS API, but we need to cope with 64 bit IDs for s390x
209 * and amd64. This doesn't really break the API, it just embraces and
210 * extends it on 64bit platforms :)
213 GetCurrentThreadId (void)
215 MonoNativeThreadId id;
217 id = mono_native_thread_id_get ();
218 return MONO_NATIVE_THREAD_ID_TO_UINT (id);
223 * @ms: The time in milliseconds to suspend for
224 * @alertable: if TRUE, the wait can be interrupted by an APC call
226 * Suspends execution of the current thread for @ms milliseconds. A
227 * value of zero causes the thread to relinquish its time slice. A
228 * value of %INFINITE causes an infinite delay.
231 SleepEx (guint32 ms, gboolean alertable)
236 gpointer current_thread = NULL;
238 struct timespec start, target;
243 DEBUG("%s: Sleeping for %d ms", __func__, ms);
246 current_thread = get_current_thread_handle ();
248 if (_wapi_thread_apc_pending (current_thread))
249 return WAIT_IO_COMPLETION;
257 /* FIXME: check for INFINITE and sleep forever */
262 req.tv_nsec=ms_rem*1000000;
265 /* Use clock_nanosleep () to prevent time drifting problems when nanosleep () is interrupted by signals */
266 ret = clock_gettime (CLOCK_MONOTONIC, &start);
269 target.tv_sec += ms_quot;
270 target.tv_nsec += ms_rem * 1000000;
271 if (target.tv_nsec > 999999999) {
272 target.tv_nsec -= 999999999;
277 ret = clock_nanosleep (CLOCK_MONOTONIC, TIMER_ABSTIME, &target, NULL);
279 if (alertable && _wapi_thread_apc_pending (current_thread))
280 return WAIT_IO_COMPLETION;
289 memset (&rem, 0, sizeof (rem));
290 ret=nanosleep(&req, &rem);
292 if (alertable && _wapi_thread_apc_pending (current_thread))
293 return WAIT_IO_COMPLETION;
296 /* Sleep interrupted with rem time remaining */
298 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
300 g_message("%s: Still got %d ms to go", __func__, rems);
306 #endif /* __linux__ */
318 _wapi_thread_cur_apc_pending (void)
320 return _wapi_thread_apc_pending (get_current_thread_handle ());
324 _wapi_thread_apc_pending (gpointer handle)
326 WapiHandle_thread *thread;
328 thread = lookup_thread (handle);
330 return thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE;
334 * wapi_interrupt_thread:
336 * The state of the thread handle HANDLE is set to 'interrupted' which means that
337 * if the thread calls one of the WaitFor functions, the function will return with
338 * WAIT_IO_COMPLETION instead of waiting. Also, if the thread was waiting when
339 * this function was called, the wait will be broken.
340 * It is possible that the wait functions return WAIT_IO_COMPLETION, but the
341 * target thread didn't receive the interrupt signal yet, in this case it should
342 * call the wait function again. This essentially means that the target thread will
343 * busy wait until it is ready to process the interruption.
346 wapi_interrupt_thread (gpointer thread_handle)
348 gpointer wait_handle;
350 wait_handle = wapi_prepare_interrupt_thread (thread_handle);
351 wapi_finish_interrupt_thread (wait_handle);
355 wapi_prepare_interrupt_thread (gpointer thread_handle)
357 WapiHandle_thread *thread;
358 gpointer prev_handle, wait_handle;
360 thread = lookup_thread (thread_handle);
363 wait_handle = thread->wait_handle;
366 * Atomically obtain the handle the thread is waiting on, and
367 * change it to a flag value.
369 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
370 INTERRUPTION_REQUESTED_HANDLE, wait_handle);
371 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
372 /* Already interrupted */
374 if (prev_handle == wait_handle)
380 WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread->id););
386 wapi_finish_interrupt_thread (gpointer wait_handle)
388 pthread_cond_t *cond;
396 /* If we reach here, then wait_handle is set to the flag value,
397 * which means that the target thread is either
398 * - before the first CAS in timedwait, which means it won't enter the
400 * - it is after the first CAS, so it is already waiting, or it will
401 * enter the wait, and it will be interrupted by the broadcast.
403 idx = GPOINTER_TO_UINT(wait_handle);
404 cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
405 mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
407 mono_mutex_lock (mutex);
408 mono_cond_broadcast (cond);
409 mono_mutex_unlock (mutex);
411 /* ref added by set_wait_handle */
412 _wapi_handle_unref (wait_handle);
416 * wapi_self_interrupt:
418 * This is not part of the WIN32 API.
419 * Set the 'interrupted' state of the calling thread if it's NULL.
422 wapi_self_interrupt (void)
424 gpointer wait_handle;
426 wait_handle = wapi_prepare_interrupt_thread (get_current_thread_handle ());
428 /* ref added by set_wait_handle */
429 _wapi_handle_unref (wait_handle);
433 * wapi_clear_interruption:
435 * This is not part of the WIN32 API.
436 * Clear the 'interrupted' state of the calling thread.
437 * This function is signal safe
440 wapi_clear_interruption (void)
442 WapiHandle_thread *thread;
443 gpointer prev_handle;
445 thread = get_current_thread ();
447 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
448 NULL, INTERRUPTION_REQUESTED_HANDLE);
449 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
450 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
454 * wapi_thread_set_wait_handle:
456 * Set the wait handle for the current thread to HANDLE. Return TRUE on success, FALSE
457 * if the thread is in interrupted state, and cannot start waiting.
460 wapi_thread_set_wait_handle (gpointer handle)
462 WapiHandle_thread *thread;
463 gpointer prev_handle;
465 thread = get_current_thread ();
467 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
469 if (prev_handle == NULL) {
470 /* thread->wait_handle acts as an additional reference to the handle */
471 _wapi_handle_ref (handle);
473 WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
475 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
476 WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
479 return prev_handle == NULL;
483 * wapi_thread_clear_wait_handle:
485 * Clear the wait handle of the current thread.
488 wapi_thread_clear_wait_handle (gpointer handle)
490 WapiHandle_thread *thread;
491 gpointer prev_handle;
493 thread = get_current_thread ();
495 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
497 if (prev_handle == handle) {
498 _wapi_handle_unref (handle);
499 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
501 /*It can be NULL if it was asynchronously cleared*/
502 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE || prev_handle == NULL);
503 WAIT_DEBUG (printf ("%p: finished waiting.\n", GetCurrentThreadId ()););
508 _wapi_thread_own_mutex (gpointer mutex)
510 WapiHandle_thread *thread;
512 thread = get_current_thread ();
514 _wapi_handle_ref (mutex);
516 g_ptr_array_add (thread->owned_mutexes, mutex);
520 _wapi_thread_disown_mutex (gpointer mutex)
522 WapiHandle_thread *thread;
524 thread = get_current_thread ();
526 _wapi_handle_unref (mutex);
528 g_ptr_array_remove (thread->owned_mutexes, mutex);
532 wapi_current_thread_desc (void)
534 WapiHandle_thread *thread;
535 gpointer thread_handle;
541 thread_handle = get_current_thread_handle ();
542 thread = lookup_thread (thread_handle);
544 handle = thread->wait_handle;
545 text = g_string_new (0);
546 g_string_append_printf (text, "thread handle %p state : ", thread_handle);
549 g_string_append_printf (text, "not waiting");
550 else if (handle == INTERRUPTION_REQUESTED_HANDLE)
551 g_string_append_printf (text, "interrupted state");
553 g_string_append_printf (text, "waiting on %p : %s ", handle, _wapi_handle_typename[_wapi_handle_type (handle)]);
554 g_string_append_printf (text, " owns (");
555 for (i = 0; i < thread->owned_mutexes->len; i++) {
556 gpointer mutex = g_ptr_array_index (thread->owned_mutexes, i);
558 g_string_append_printf (text, ", %p", mutex);
560 g_string_append_printf (text, "%p", mutex);
562 g_string_append_printf (text, ")");
565 g_string_free (text, FALSE);