2 * threads.c: Thread handles
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002-2006 Ximian, Inc.
14 #include <mono/os/gc_wrapper.h>
20 #include <sys/types.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>
32 #ifdef HAVE_VALGRIND_MEMCHECK_H
33 #include <valgrind/memcheck.h>
39 /* Hash threads with tids. I thought of using TLS for this, but that
40 * would have to set the data in the new thread, which is more hassle
42 static mono_once_t thread_hash_once = MONO_ONCE_INIT;
43 static pthread_key_t thread_hash_key;
45 /* This key is used with attached threads and a destructor to signal
46 * when attached threads exit, as they don't have the thread_exit()
49 static pthread_key_t thread_attached_key;
51 struct _WapiHandleOps _wapi_thread_ops = {
56 NULL, /* special_wait */
60 static mono_once_t thread_ops_once=MONO_ONCE_INIT;
62 static void thread_ops_init (void)
64 _wapi_handle_register_capabilities (WAPI_HANDLE_THREAD,
65 WAPI_HANDLE_CAP_WAIT);
68 void _wapi_thread_cleanup (void)
72 ret = pthread_key_delete (thread_hash_key);
75 ret = pthread_key_delete (thread_attached_key);
79 /* Called by thread_exit(), but maybe indirectly by
80 * mono_thread_manage() via mono_thread_signal_self() too
82 static void _wapi_thread_abandon_mutexes (gpointer handle)
84 struct _WapiHandle_thread *thread_handle;
87 pid_t pid = _wapi_getpid ();
88 pthread_t tid = pthread_self ();
91 g_message ("%s: Thread %p abandoning held mutexes", __func__, handle);
95 handle = _wapi_thread_handle_from_id (pthread_self ());
97 /* Something gone badly wrong... */
102 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
103 (gpointer *)&thread_handle);
105 g_warning ("%s: error looking up thread handle %p", __func__,
110 if (!pthread_equal (thread_handle->id, tid)) {
114 for (i = 0; i < thread_handle->owned_mutexes->len; i++) {
115 gpointer mutex = g_ptr_array_index (thread_handle->owned_mutexes, i);
117 _wapi_mutex_abandon (mutex, pid, tid);
118 _wapi_thread_disown_mutex (mutex);
122 void _wapi_thread_set_termination_details (gpointer handle,
125 struct _WapiHandle_thread *thread_handle;
129 if (_wapi_handle_issignalled (handle) ||
130 _wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) {
131 /* We must have already deliberately finished with
132 * this thread, so don't do any more now
138 g_message ("%s: Thread %p terminating", __func__, handle);
141 _wapi_thread_abandon_mutexes (handle);
143 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
144 (gpointer *)&thread_handle);
146 g_warning ("%s: error looking up thread handle %p", __func__,
152 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
154 thr_ret = _wapi_handle_lock_handle (handle);
155 g_assert (thr_ret == 0);
157 thread_handle->exitstatus = exitstatus;
158 thread_handle->state = THREAD_STATE_EXITED;
159 MONO_SEM_DESTROY (&thread_handle->suspend_sem);
160 g_ptr_array_free (thread_handle->owned_mutexes, TRUE);
162 _wapi_handle_set_signal_state (handle, TRUE, TRUE);
164 thr_ret = _wapi_handle_unlock_handle (handle);
165 g_assert (thr_ret == 0);
166 pthread_cleanup_pop (0);
169 g_message("%s: Recording thread handle %p id %ld status as %d",
170 __func__, handle, thread_handle->id, exitstatus);
173 /* The thread is no longer active, so unref it */
174 _wapi_handle_unref (handle);
177 void _wapi_thread_signal_self (guint32 exitstatus)
181 handle = _wapi_thread_handle_from_id (pthread_self ());
182 if (handle == NULL) {
183 /* Something gone badly wrong... */
187 _wapi_thread_set_termination_details (handle, exitstatus);
190 /* Called by the thread creation code as a thread is finishing up, and
193 static void thread_exit (guint32 exitstatus, gpointer handle) G_GNUC_NORETURN;
194 static void thread_exit (guint32 exitstatus, gpointer handle)
196 _wapi_thread_set_termination_details (handle, exitstatus);
198 /* Call pthread_exit() to call destructors and really exit the
204 static void thread_attached_exit (gpointer handle)
206 /* Drop the extra reference we take in thread_attach, now this
210 _wapi_thread_set_termination_details (handle, 0);
213 static void thread_hash_init(void)
217 thr_ret = pthread_key_create (&thread_hash_key, NULL);
218 g_assert (thr_ret == 0);
220 thr_ret = pthread_key_create (&thread_attached_key,
221 thread_attached_exit);
222 g_assert (thr_ret == 0);
225 static void _wapi_thread_suspend (struct _WapiHandle_thread *thread)
227 g_assert (pthread_equal (thread->id, pthread_self ()));
229 while (MONO_SEM_WAIT (&thread->suspend_sem) != 0 &&
233 static void _wapi_thread_resume (struct _WapiHandle_thread *thread)
235 MONO_SEM_POST (&thread->suspend_sem);
238 static void *thread_start_routine (gpointer args) G_GNUC_NORETURN;
239 static void *thread_start_routine (gpointer args)
241 struct _WapiHandle_thread *thread = (struct _WapiHandle_thread *)args;
244 thr_ret = pthread_detach (pthread_self ());
245 g_assert (thr_ret == 0);
247 thr_ret = pthread_setspecific (thread_hash_key,
248 (void *)thread->handle);
250 /* This is only supposed to happen when Mono is
251 shutting down. We cannot assert on it, though,
252 because we must not depend on metadata, which is
253 where the shutdown code is.
255 This is a race condition which arises because
256 pthreads don't allow creation of suspended threads.
257 Once Mono is set to shut down no new thread is
258 allowed to start, even though threads may still be
259 created. We emulate suspended threads in this
260 function by calling _wapi_thread_suspend() below.
262 So it can happen that even though Mono is already
263 shutting down we still end up here, and at this
264 point the thread_hash_key might already be
269 thread->id = pthread_self();
272 g_message ("%s: started thread id %ld", __func__, thread->id);
275 if (thread->create_flags & CREATE_SUSPENDED) {
276 _wapi_thread_suspend (thread);
279 thread_exit (thread->start_routine (thread->start_arg),
283 /* Even though we tell gcc that this function doesn't return,
284 * other compilers won't see that.
292 * @security: Ignored for now.
293 * @stacksize: the size in bytes of the new thread's stack. Use 0 to
294 * default to the normal stack size. (Ignored for now).
295 * @start: The function that the new thread should start with
296 * @param: The parameter to give to @start.
297 * @create: If 0, the new thread is ready to run immediately. If
298 * %CREATE_SUSPENDED, the new thread will be in the suspended state,
299 * requiring a ResumeThread() call to continue running.
300 * @tid: If non-NULL, the ID of the new thread is stored here. NB
301 * this is defined as a DWORD (ie 32bit) in the MS API, but we need to
302 * cope with 64 bit IDs for s390x and amd64.
304 * Creates a new threading handle.
306 * Return value: a new handle, or NULL
308 gpointer CreateThread(WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 stacksize,
309 WapiThreadStart start, gpointer param, guint32 create,
312 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
319 gpointer ct_ret = NULL;
321 mono_once (&thread_hash_once, thread_hash_init);
322 mono_once (&thread_ops_once, thread_ops_init);
328 thread_handle.state = THREAD_STATE_START;
329 thread_handle.owned_mutexes = g_ptr_array_new ();
330 thread_handle.create_flags = create;
331 thread_handle.start_routine = start;
332 thread_handle.start_arg = param;
334 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
335 if (handle == _WAPI_HANDLE_INVALID) {
336 g_warning ("%s: error creating thread handle", __func__);
337 SetLastError (ERROR_GEN_FAILURE);
342 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
344 thr_ret = _wapi_handle_lock_handle (handle);
345 g_assert (thr_ret == 0);
347 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
348 (gpointer *)&thread_handle_p);
350 g_warning ("%s: error looking up thread handle %p", __func__,
352 SetLastError (ERROR_GEN_FAILURE);
357 /* Hold a reference while the thread is active, because we use
358 * the handle to store thread exit information
360 _wapi_handle_ref (handle);
362 /* Set a 2M stack size. This is the default on Linux, but BSD
363 * needs it. (The original bug report from Martin Dvorak <md@9ll.cz>
364 * set the size to 2M-4k. I don't know why it's short by 4k, so
365 * I'm leaving it as 2M until I'm told differently.)
367 thr_ret = pthread_attr_init(&attr);
368 g_assert (thr_ret == 0);
370 /* defaults of 2Mb for 32bits and 4Mb for 64bits */
371 /* temporarily changed to use 1 MB: this allows more threads
372 * to be used, as well as using less virtual memory and so
373 * more is available for the GC heap.
376 #if HAVE_VALGRIND_MEMCHECK_H
377 if (RUNNING_ON_VALGRIND) {
380 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
383 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
387 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
388 thr_ret = pthread_attr_setstacksize(&attr, stacksize);
389 g_assert (thr_ret == 0);
392 MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
393 thread_handle_p->handle = handle;
395 ret = pthread_create (&thread_handle_p->id, &attr,
396 thread_start_routine, (void *)thread_handle_p);
399 g_message ("%s: Thread create error: %s", __func__,
403 /* Two, because of the reference we took above */
411 g_message("%s: Started thread handle %p ID %ld", __func__, handle,
412 thread_handle_p->id);
416 #ifdef PTHREAD_POINTER_ID
417 /* Don't use GPOINTER_TO_UINT here, it can't cope with
418 * sizeof(void *) > sizeof(uint) when a cast to uint
421 *tid = (gsize)(thread_handle_p->id);
423 *tid = thread_handle_p->id;
428 thr_ret = _wapi_handle_unlock_handle (handle);
429 g_assert (thr_ret == 0);
430 pthread_cleanup_pop (0);
432 /* Must not call _wapi_handle_unref() with the shared handles
435 for (i = 0; i < unrefs; i++) {
436 _wapi_handle_unref (handle);
442 /* The only time this function is called when tid != pthread_self ()
443 * is from OpenThread (), so we can fast-path most cases by just
444 * looking up the handle in TLS. OpenThread () must cope with a NULL
445 * return and do a handle search in that case.
447 gpointer _wapi_thread_handle_from_id (pthread_t tid)
451 if (pthread_equal (tid, pthread_self ()) &&
452 (ret = pthread_getspecific (thread_hash_key)) != NULL) {
453 /* We know the handle */
456 g_message ("%s: Returning %p for self thread %ld from TLS",
464 g_message ("%s: Returning NULL for unknown or non-self thread %ld",
472 static gboolean find_thread_by_id (gpointer handle, gpointer user_data)
474 pthread_t tid = (pthread_t)user_data;
475 struct _WapiHandle_thread *thread_handle;
478 /* Ignore threads that have already exited (ie they are signalled) */
479 if (_wapi_handle_issignalled (handle) == FALSE) {
480 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
481 (gpointer *)&thread_handle);
483 /* It's possible that the handle has vanished
484 * during the _wapi_search_handle before it
485 * gets here, so don't spam the console with
492 g_message ("%s: looking at thread %ld from process %d", __func__, thread_handle->id, 0);
495 if (pthread_equal (thread_handle->id, tid)) {
497 g_message ("%s: found the thread we are looking for",
505 g_message ("%s: not found %ld, returning FALSE", __func__, tid);
511 /* NB tid is 32bit in MS API, but we need 64bit on amd64 and s390x
512 * (and probably others)
514 gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, gsize tid)
518 mono_once (&thread_hash_once, thread_hash_init);
519 mono_once (&thread_ops_once, thread_ops_init);
522 g_message ("%s: looking up thread %"G_GSIZE_FORMAT, __func__, tid);
525 ret = _wapi_thread_handle_from_id ((pthread_t)tid);
527 /* We need to search for this thread */
528 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 */
530 /* if _wapi_search_handle() returns a found handle, it
533 _wapi_handle_ref (ret);
537 g_message ("%s: returning thread handle %p", __func__, ret);
545 * @exitcode: Sets the thread's exit code, which can be read from
546 * another thread with GetExitCodeThread().
548 * Terminates the calling thread. A thread can also exit by returning
549 * from its start function. When the last thread in a process
550 * terminates, the process itself terminates.
552 void ExitThread(guint32 exitcode)
554 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
556 if (thread != NULL) {
557 thread_exit(exitcode, thread);
559 /* Just blow this thread away */
566 * @handle: The thread handle to query
567 * @exitcode: The thread @handle exit code is stored here
569 * Finds the exit code of @handle, and stores it in @exitcode. If the
570 * thread @handle is still running, the value stored is %STILL_ACTIVE.
572 * Return value: %TRUE, or %FALSE on error.
574 gboolean GetExitCodeThread(gpointer handle, guint32 *exitcode)
576 struct _WapiHandle_thread *thread_handle;
579 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
580 (gpointer *)&thread_handle);
582 g_warning ("%s: error looking up thread handle %p", __func__,
588 g_message ("%s: Finding exit status for thread handle %p id %ld",
589 __func__, handle, thread_handle->id);
592 if (exitcode == NULL) {
594 g_message ("%s: Nowhere to store exit code", __func__);
599 if (thread_handle->state != THREAD_STATE_EXITED) {
601 g_message ("%s: Thread still active (state %d, exited is %d)",
602 __func__, thread_handle->state,
603 THREAD_STATE_EXITED);
605 *exitcode = STILL_ACTIVE;
609 *exitcode = thread_handle->exitstatus;
615 * GetCurrentThreadId:
617 * Looks up the thread ID of the current thread. This ID can be
618 * passed to OpenThread() to create a new handle on this thread.
620 * Return value: the thread ID. NB this is defined as DWORD (ie 32
621 * bit) in the MS API, but we need to cope with 64 bit IDs for s390x
622 * and amd64. This doesn't really break the API, it just embraces and
623 * extends it on 64bit platforms :)
625 gsize GetCurrentThreadId(void)
627 pthread_t tid = pthread_self();
629 #ifdef PTHREAD_POINTER_ID
630 /* Don't use GPOINTER_TO_UINT here, it can't cope with
631 * sizeof(void *) > sizeof(uint) when a cast to uint would
640 static gpointer thread_attach(gsize *tid)
642 struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
647 mono_once (&thread_hash_once, thread_hash_init);
648 mono_once (&thread_ops_once, thread_ops_init);
650 thread_handle.state = THREAD_STATE_START;
651 thread_handle.owned_mutexes = g_ptr_array_new ();
653 handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
654 if (handle == _WAPI_HANDLE_INVALID) {
655 g_warning ("%s: error creating thread handle", __func__);
657 SetLastError (ERROR_GEN_FAILURE);
661 pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
663 thr_ret = _wapi_handle_lock_handle (handle);
664 g_assert (thr_ret == 0);
666 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
667 (gpointer *)&thread_handle_p);
669 g_warning ("%s: error looking up thread handle %p", __func__,
672 SetLastError (ERROR_GEN_FAILURE);
676 /* Hold a reference while the thread is active, because we use
677 * the handle to store thread exit information
679 _wapi_handle_ref (handle);
681 /* suspend_sem is not used for attached threads, but
682 * thread_exit() might try to destroy it
684 MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
685 thread_handle_p->handle = handle;
686 thread_handle_p->id = pthread_self ();
688 thr_ret = pthread_setspecific (thread_hash_key, (void *)handle);
689 g_assert (thr_ret == 0);
691 thr_ret = pthread_setspecific (thread_attached_key, (void *)handle);
692 g_assert (thr_ret == 0);
695 g_message("%s: Attached thread handle %p ID %ld", __func__, handle,
696 thread_handle_p->id);
700 #ifdef PTHREAD_POINTER_ID
701 /* Don't use GPOINTER_TO_UINT here, it can't cope with
702 * sizeof(void *) > sizeof(uint) when a cast to uint
705 *tid = (gsize)(thread_handle_p->id);
707 *tid = thread_handle_p->id;
712 thr_ret = _wapi_handle_unlock_handle (handle);
713 g_assert (thr_ret == 0);
714 pthread_cleanup_pop (0);
719 gpointer _wapi_thread_duplicate ()
723 mono_once (&thread_hash_once, thread_hash_init);
724 mono_once (&thread_ops_once, thread_ops_init);
726 ret = _wapi_thread_handle_from_id (pthread_self ());
728 ret = thread_attach (NULL);
730 _wapi_handle_ref (ret);
739 * Looks up the handle associated with the current thread. Under
740 * Windows this is a pseudohandle, and must be duplicated with
741 * DuplicateHandle() for some operations.
743 * Return value: The current thread handle, or %NULL on failure.
744 * (Unknown whether Windows has a possible failure here. It may be
745 * necessary to implement the pseudohandle-constant behaviour).
747 gpointer GetCurrentThread(void)
749 mono_once(&thread_hash_once, thread_hash_init);
750 mono_once (&thread_ops_once, thread_ops_init);
752 return(_WAPI_THREAD_CURRENT);
757 * @handle: the thread handle to resume
759 * Decrements the suspend count of thread @handle. A thread can only
760 * run if its suspend count is zero.
762 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
764 guint32 ResumeThread(gpointer handle)
766 struct _WapiHandle_thread *thread_handle;
769 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
770 (gpointer *)&thread_handle);
772 g_warning ("%s: error looking up thread handle %p", __func__,
778 /* This is still a kludge that only copes with starting a
779 * thread that was suspended on create, so don't bother with
780 * the suspend count crap yet
782 _wapi_thread_resume (thread_handle);
788 * @handle: the thread handle to suspend
790 * Increments the suspend count of thread @handle. A thread can only
791 * run if its suspend count is zero.
793 * Return value: the previous suspend count, or 0xFFFFFFFF on error.
795 guint32 SuspendThread(gpointer handle)
801 * We assume here that TLS_MINIMUM_AVAILABLE is less than
802 * PTHREAD_KEYS_MAX, allowing enough overhead for a few TLS keys for
805 * Currently TLS_MINIMUM_AVAILABLE is 64 and _POSIX_THREAD_KEYS_MAX
806 * (the minimum value for PTHREAD_KEYS_MAX) is 128, so we should be
810 static pthread_key_t TLS_keys[TLS_MINIMUM_AVAILABLE];
811 static gboolean TLS_used[TLS_MINIMUM_AVAILABLE]={FALSE};
812 static guint32 TLS_spinlock=0;
815 mono_pthread_key_for_tls (guint32 idx)
817 return (guint32)TLS_keys [idx];
823 * Allocates a Thread Local Storage (TLS) index. Any thread in the
824 * same process can use this index to store and retrieve values that
825 * are local to that thread.
827 * Return value: The index value, or %TLS_OUT_OF_INDEXES if no index
830 guint32 TlsAlloc(void)
835 MONO_SPIN_LOCK (TLS_spinlock);
837 for(i=0; i<TLS_MINIMUM_AVAILABLE; i++) {
838 if(TLS_used[i]==FALSE) {
840 thr_ret = pthread_key_create(&TLS_keys[i], NULL);
841 g_assert (thr_ret == 0);
843 MONO_SPIN_UNLOCK (TLS_spinlock);
846 g_message ("%s: returning key %d", __func__, i);
853 MONO_SPIN_UNLOCK (TLS_spinlock);
856 g_message ("%s: out of indices", __func__);
860 return(TLS_OUT_OF_INDEXES);
863 #define MAKE_GC_ID(idx) (GUINT_TO_POINTER((idx)|(GetCurrentThreadId()<<8)))
867 * @idx: The TLS index to free
869 * Releases a TLS index, making it available for reuse. This call
870 * will delete any TLS data stored under index @idx in all threads.
872 * Return value: %TRUE on success, %FALSE otherwise.
874 gboolean TlsFree(guint32 idx)
879 g_message ("%s: freeing key %d", __func__, idx);
882 MONO_SPIN_LOCK (TLS_spinlock);
884 if(TLS_used[idx]==FALSE) {
885 MONO_SPIN_UNLOCK (TLS_spinlock);
891 thr_ret = pthread_key_delete(TLS_keys[idx]);
892 g_assert (thr_ret == 0);
894 MONO_SPIN_UNLOCK (TLS_spinlock);
901 * @idx: The TLS index to retrieve
903 * Retrieves the TLS data stored under index @idx.
905 * Return value: The value stored in the TLS index @idx in the current
906 * thread, or %NULL on error. As %NULL can be a valid return value,
907 * in this case GetLastError() returns %ERROR_SUCCESS.
909 gpointer TlsGetValue(guint32 idx)
914 g_message ("%s: looking up key %d", __func__, idx);
917 ret=pthread_getspecific(TLS_keys[idx]);
920 g_message ("%s: returning %p", __func__, ret);
928 * @idx: The TLS index to store
929 * @value: The value to store under index @idx
931 * Stores @value at TLS index @idx.
933 * Return value: %TRUE on success, %FALSE otherwise.
935 gboolean TlsSetValue(guint32 idx, gpointer value)
940 g_message ("%s: setting key %d to %p", __func__, idx, value);
943 MONO_SPIN_LOCK (TLS_spinlock);
945 if(TLS_used[idx]==FALSE) {
947 g_message ("%s: key %d unused", __func__, idx);
950 MONO_SPIN_UNLOCK (TLS_spinlock);
955 ret=pthread_setspecific(TLS_keys[idx], value);
958 g_message ("%s: pthread_setspecific error: %s", __func__,
962 MONO_SPIN_UNLOCK (TLS_spinlock);
967 MONO_SPIN_UNLOCK (TLS_spinlock);
974 * @ms: The time in milliseconds to suspend for
975 * @alertable: if TRUE, the wait can be interrupted by an APC call
977 * Suspends execution of the current thread for @ms milliseconds. A
978 * value of zero causes the thread to relinquish its time slice. A
979 * value of %INFINITE causes an infinite delay.
981 guint32 SleepEx(guint32 ms, gboolean alertable)
983 struct timespec req, rem;
986 gpointer current_thread = NULL;
989 g_message("%s: Sleeping for %d ms", __func__, ms);
993 current_thread = _wapi_thread_handle_from_id (pthread_self ());
994 if (current_thread == NULL) {
995 SetLastError (ERROR_INVALID_HANDLE);
999 if (_wapi_thread_apc_pending (current_thread)) {
1000 _wapi_thread_dispatch_apc_queue (current_thread);
1001 return WAIT_IO_COMPLETION;
1010 /* FIXME: check for INFINITE and sleep forever */
1011 ms_quot = ms / 1000;
1015 req.tv_nsec=ms_rem*1000000;
1018 ret=nanosleep(&req, &rem);
1020 if (alertable && _wapi_thread_apc_pending (current_thread)) {
1021 _wapi_thread_dispatch_apc_queue (current_thread);
1022 return WAIT_IO_COMPLETION;
1026 /* Sleep interrupted with rem time remaining */
1028 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
1030 g_message("%s: Still got %d ms to go", __func__, rems);
1039 void Sleep(guint32 ms)
1044 gboolean _wapi_thread_cur_apc_pending (void)
1046 gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
1048 if (thread == NULL) {
1049 SetLastError (ERROR_INVALID_HANDLE);
1053 return(_wapi_thread_apc_pending (thread));
1056 gboolean _wapi_thread_apc_pending (gpointer handle)
1058 struct _WapiHandle_thread *thread;
1061 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1062 (gpointer *)&thread);
1065 /* This might happen at process shutdown, as all
1066 * thread handles are forcibly closed. If a thread
1067 * still has an alertable wait the final
1068 * _wapi_thread_apc_pending check will probably fail
1069 * to find the handle
1071 g_warning ("%s: error looking up thread handle %p", __func__,
1077 return(thread->has_apc);
1080 gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
1082 /* We don't support calling APC functions */
1083 struct _WapiHandle_thread *thread;
1086 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1087 (gpointer *)&thread);
1090 thread->has_apc = FALSE;
1096 * In this implementation, APC_CALLBACK is ignored, HANDLE can only refer to the current
1097 * thread, and the only effect this function has that if called from a signal handler,
1098 * and the thread was waiting when receiving the signal, the wait will be broken after
1099 * the signal handler returns.
1100 * These limitations are not a problem as the runtime only uses this functionality.
1101 * This function is async-signal-safe.
1103 guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer handle,
1106 struct _WapiHandle_thread *thread_handle;
1109 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
1110 (gpointer *)&thread_handle);
1112 g_warning ("%s: error looking up thread handle %p", __func__,
1117 g_assert (thread_handle->id == GetCurrentThreadId ());
1119 /* No locking/memory barriers are needed here */
1120 thread_handle->has_apc = TRUE;
1125 void _wapi_thread_own_mutex (gpointer mutex)
1127 struct _WapiHandle_thread *thread_handle;
1131 thread = _wapi_thread_handle_from_id (pthread_self ());
1132 if (thread == NULL) {
1133 g_warning ("%s: error looking up thread by ID", __func__);
1137 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1138 (gpointer *)&thread_handle);
1140 g_warning ("%s: error looking up thread handle %p", __func__,
1145 _wapi_handle_ref (mutex);
1147 g_ptr_array_add (thread_handle->owned_mutexes, mutex);
1150 void _wapi_thread_disown_mutex (gpointer mutex)
1152 struct _WapiHandle_thread *thread_handle;
1156 thread = _wapi_thread_handle_from_id (pthread_self ());
1157 if (thread == NULL) {
1158 g_warning ("%s: error looking up thread by ID", __func__);
1162 ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1163 (gpointer *)&thread_handle);
1165 g_warning ("%s: error looking up thread handle %p", __func__,
1170 _wapi_handle_unref (mutex);
1172 g_ptr_array_remove (thread_handle->owned_mutexes, mutex);