[runtime] Get rid of ResumeThread(), use mono_thread_info_resume () instead.
[mono.git] / mono / io-layer / wthreads.c
1 /*
2  * threads.c:  Thread handles
3  *
4  * Author:
5  *      Dick Porter (dick@ximian.com)
6  *
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)
10  */
11
12 #include <config.h>
13 #include <stdio.h>
14 #include <glib.h>
15 #include <string.h>
16 #include <pthread.h>
17 #include <signal.h>
18 #include <sched.h>
19 #include <sys/time.h>
20 #include <errno.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23
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>
30
31 #include <mono/utils/mono-threads.h>
32 #include <mono/utils/gc_wrapper.h>
33 #include <mono/utils/atomic.h>
34 #include <mono/utils/mono-mutex.h>
35
36 #ifdef HAVE_VALGRIND_MEMCHECK_H
37 #include <valgrind/memcheck.h>
38 #endif
39
40 #if 0
41 #define DEBUG(...) g_message(__VA_ARGS__)
42 #else
43 #define DEBUG(...)
44 #endif
45
46 #if 0
47 #define WAIT_DEBUG(code) do { code } while (0)
48 #else
49 #define WAIT_DEBUG(code) do { } while (0)
50 #endif
51
52 /* Hash threads with tids. I thought of using TLS for this, but that
53  * would have to set the data in the new thread, which is more hassle
54  */
55 static mono_once_t thread_hash_once = MONO_ONCE_INIT;
56 static pthread_key_t thread_hash_key;
57
58 /* This key is used with attached threads and a destructor to signal
59  * when attached threads exit, as they don't have the thread_exit()
60  * infrastructure
61  */
62 static pthread_key_t thread_attached_key;
63
64 struct _WapiHandleOps _wapi_thread_ops = {
65         NULL,                           /* close */
66         NULL,                           /* signal */
67         NULL,                           /* own */
68         NULL,                           /* is_owned */
69         NULL,                           /* special_wait */
70         NULL                            /* prewait */
71 };
72
73 static mono_once_t thread_ops_once=MONO_ONCE_INIT;
74
75 static void thread_ops_init (void)
76 {
77         _wapi_handle_register_capabilities (WAPI_HANDLE_THREAD,
78                                             WAPI_HANDLE_CAP_WAIT);
79 }
80
81 void _wapi_thread_cleanup (void)
82 {
83         int ret;
84         
85         ret = pthread_key_delete (thread_hash_key);
86         g_assert (ret == 0);
87         
88         ret = pthread_key_delete (thread_attached_key);
89         g_assert (ret == 0);
90 }
91
92 /* Called by thread_exit(), but maybe indirectly by
93  * mono_thread_manage() via mono_thread_signal_self() too
94  */
95 static void _wapi_thread_abandon_mutexes (gpointer handle)
96 {
97         struct _WapiHandle_thread *thread_handle;
98         gboolean ok;
99         int i;
100         pid_t pid = _wapi_getpid ();
101         pthread_t tid = pthread_self ();
102         
103         DEBUG ("%s: Thread %p abandoning held mutexes", __func__, handle);
104
105         if (handle == NULL) {
106                 handle = _wapi_thread_handle_from_id (pthread_self ());
107                 if (handle == NULL) {
108                         /* Something gone badly wrong... */
109                         return;
110                 }
111         }
112         
113         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
114                                   (gpointer *)&thread_handle);
115         if (ok == FALSE) {
116                 g_warning ("%s: error looking up thread handle %p", __func__,
117                            handle);
118                 return;
119         }
120         
121         if (!pthread_equal (thread_handle->id, tid)) {
122                 return;
123         }
124         
125         for (i = 0; i < thread_handle->owned_mutexes->len; i++) {
126                 gpointer mutex = g_ptr_array_index (thread_handle->owned_mutexes, i);
127                 
128                 _wapi_mutex_abandon (mutex, pid, tid);
129                 _wapi_thread_disown_mutex (mutex);
130         }
131 }
132
133 void _wapi_thread_set_termination_details (gpointer handle,
134                                            guint32 exitstatus)
135 {
136         struct _WapiHandle_thread *thread_handle;
137         gboolean ok;
138         int thr_ret;
139         
140         if (_wapi_handle_issignalled (handle) ||
141             _wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) {
142                 /* We must have already deliberately finished with
143                  * this thread, so don't do any more now
144                  */
145                 return;
146         }
147
148         DEBUG ("%s: Thread %p terminating", __func__, handle);
149
150         _wapi_thread_abandon_mutexes (handle);
151         
152         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
153                                   (gpointer *)&thread_handle);
154         if (ok == FALSE) {
155                 g_warning ("%s: error looking up thread handle %p", __func__,
156                            handle);
157
158                 return;
159         }
160         
161         pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
162                               handle);
163         thr_ret = _wapi_handle_lock_handle (handle);
164         g_assert (thr_ret == 0);
165         
166         thread_handle->exitstatus = exitstatus;
167         thread_handle->state = THREAD_STATE_EXITED;
168         g_ptr_array_free (thread_handle->owned_mutexes, TRUE);
169
170         _wapi_handle_set_signal_state (handle, TRUE, TRUE);
171
172         thr_ret = _wapi_handle_unlock_handle (handle);
173         g_assert (thr_ret == 0);
174         pthread_cleanup_pop (0);
175         
176         DEBUG("%s: Recording thread handle %p id %ld status as %d",
177                   __func__, handle, thread_handle->id, exitstatus);
178         
179         /* The thread is no longer active, so unref it */
180         _wapi_handle_unref (handle);
181 }
182
183 void _wapi_thread_signal_self (guint32 exitstatus)
184 {
185         gpointer handle;
186         
187         handle = _wapi_thread_handle_from_id (pthread_self ());
188         if (handle == NULL) {
189                 /* Something gone badly wrong... */
190                 return;
191         }
192         
193         _wapi_thread_set_termination_details (handle, exitstatus);
194 }
195
196 /* Called by the thread creation code as a thread is finishing up, and
197  * by ExitThread()
198 */
199 static void thread_exit (guint32 exitstatus, gpointer handle) G_GNUC_NORETURN;
200 #if defined(__native_client__)
201 void nacl_shutdown_gc_thread(void);
202 #endif
203 static void thread_exit (guint32 exitstatus, gpointer handle)
204 {
205 #if defined(__native_client__)
206         nacl_shutdown_gc_thread();
207 #endif
208         _wapi_thread_set_termination_details (handle, exitstatus);
209         
210         /* Call pthread_exit() to call destructors and really exit the
211          * thread
212          */
213         mono_gc_pthread_exit (NULL);
214 }
215
216 void
217 wapi_thread_set_exit_code (guint32 exitstatus, gpointer handle)
218 {
219         _wapi_thread_set_termination_details (handle, exitstatus);
220 }
221
222 static void thread_attached_exit (gpointer handle)
223 {
224         /* Drop the extra reference we take in thread_attach, now this
225          * thread is dead
226          */
227         
228         _wapi_thread_set_termination_details (handle, 0);
229 }
230
231 static void thread_hash_init(void)
232 {
233         int thr_ret;
234         
235         thr_ret = pthread_key_create (&thread_hash_key, NULL);
236         g_assert (thr_ret == 0);
237
238         thr_ret = pthread_key_create (&thread_attached_key,
239                                       thread_attached_exit);
240         g_assert (thr_ret == 0);
241 }
242
243 /*
244  * wapi_create_thread_handle:
245  *
246  *   Create a thread handle for the current thread.
247  */
248 gpointer
249 wapi_create_thread_handle (void)
250 {
251         struct _WapiHandle_thread thread_handle = {0}, *thread;
252         gpointer handle;
253         int res;
254
255         mono_once (&thread_hash_once, thread_hash_init);
256         mono_once (&thread_ops_once, thread_ops_init);
257
258         thread_handle.state = THREAD_STATE_START;
259         thread_handle.owned_mutexes = g_ptr_array_new ();
260
261         handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
262         if (handle == _WAPI_HANDLE_INVALID) {
263                 g_warning ("%s: error creating thread handle", __func__);
264                 SetLastError (ERROR_GEN_FAILURE);
265                 
266                 return NULL;
267         }
268
269         res = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
270                                                            (gpointer *)&thread);
271         g_assert (res);
272
273         res = pthread_setspecific (thread_hash_key, handle);
274         if (res)
275                 mono_gc_pthread_exit (NULL);
276
277         thread->id = pthread_self ();
278
279         /*
280          * Hold a reference while the thread is active, because we use
281          * the handle to store thread exit information
282          */
283         _wapi_handle_ref (handle);
284
285         DEBUG ("%s: started thread id %ld", __func__, thread->id);
286         
287         return handle;
288 }
289
290 /* The only time this function is called when tid != pthread_self ()
291  * is from OpenThread (), so we can fast-path most cases by just
292  * looking up the handle in TLS.  OpenThread () must cope with a NULL
293  * return and do a handle search in that case.
294  */
295 gpointer _wapi_thread_handle_from_id (pthread_t tid)
296 {
297         gpointer ret;
298
299         if (pthread_equal (tid, pthread_self ()) &&
300             (ret = pthread_getspecific (thread_hash_key)) != NULL) {
301                 /* We know the handle */
302
303                 DEBUG ("%s: Returning %p for self thread %ld from TLS",
304                            __func__, ret, tid);
305                 
306                 return(ret);
307         }
308         
309         DEBUG ("%s: Returning NULL for unknown or non-self thread %ld",
310                    __func__, tid);
311                 
312
313         return(NULL);
314 }
315
316 static gboolean find_thread_by_id (gpointer handle, gpointer user_data)
317 {
318         pthread_t tid = (pthread_t)user_data;
319         struct _WapiHandle_thread *thread_handle;
320         gboolean ok;
321         
322         /* Ignore threads that have already exited (ie they are signalled) */
323         if (_wapi_handle_issignalled (handle) == FALSE) {
324                 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
325                                           (gpointer *)&thread_handle);
326                 if (ok == FALSE) {
327                         /* It's possible that the handle has vanished
328                          * during the _wapi_search_handle before it
329                          * gets here, so don't spam the console with
330                          * warnings.
331                          */
332                         return(FALSE);
333                 }
334                 
335                 DEBUG ("%s: looking at thread %ld from process %d", __func__, thread_handle->id, 0);
336
337                 if (pthread_equal (thread_handle->id, tid)) {
338                         DEBUG ("%s: found the thread we are looking for",
339                                    __func__);
340                         return(TRUE);
341                 }
342         }
343         
344         DEBUG ("%s: not found %ld, returning FALSE", __func__, tid);
345         
346         return(FALSE);
347 }
348
349 /* NB tid is 32bit in MS API, but we need 64bit on amd64 and s390x
350  * (and probably others)
351  */
352 gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, gsize tid)
353 {
354         gpointer ret=NULL;
355         
356         mono_once (&thread_hash_once, thread_hash_init);
357         mono_once (&thread_ops_once, thread_ops_init);
358         
359         DEBUG ("%s: looking up thread %"G_GSIZE_FORMAT, __func__, tid);
360
361         ret = _wapi_thread_handle_from_id ((pthread_t)tid);
362         if (ret == NULL) {
363                 /* We need to search for this thread */
364                 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 */
365         } else {
366                 /* if _wapi_search_handle() returns a found handle, it
367                  * refs it itself
368                  */
369                 _wapi_handle_ref (ret);
370         }
371         
372         DEBUG ("%s: returning thread handle %p", __func__, ret);
373         
374         return(ret);
375 }
376
377 /**
378  * ExitThread:
379  * @exitcode: Sets the thread's exit code, which can be read from
380  * another thread with GetExitCodeThread().
381  *
382  * Terminates the calling thread.  A thread can also exit by returning
383  * from its start function. When the last thread in a process
384  * terminates, the process itself terminates.
385  */
386 void ExitThread(guint32 exitcode)
387 {
388         gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
389         
390         if (thread != NULL) {
391                 thread_exit(exitcode, thread);
392         } else {
393                 /* Just blow this thread away */
394                 mono_gc_pthread_exit (NULL);
395         }
396 }
397
398 /**
399  * GetExitCodeThread:
400  * @handle: The thread handle to query
401  * @exitcode: The thread @handle exit code is stored here
402  *
403  * Finds the exit code of @handle, and stores it in @exitcode.  If the
404  * thread @handle is still running, the value stored is %STILL_ACTIVE.
405  *
406  * Return value: %TRUE, or %FALSE on error.
407  */
408 gboolean GetExitCodeThread(gpointer handle, guint32 *exitcode)
409 {
410         struct _WapiHandle_thread *thread_handle;
411         gboolean ok;
412         
413         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
414                                   (gpointer *)&thread_handle);
415         if (ok == FALSE) {
416                 g_warning ("%s: error looking up thread handle %p", __func__,
417                            handle);
418                 return (FALSE);
419         }
420         
421         DEBUG ("%s: Finding exit status for thread handle %p id %ld",
422                    __func__, handle, thread_handle->id);
423
424         if (exitcode == NULL) {
425                 DEBUG ("%s: Nowhere to store exit code", __func__);
426                 return(FALSE);
427         }
428         
429         if (thread_handle->state != THREAD_STATE_EXITED) {
430                 DEBUG ("%s: Thread still active (state %d, exited is %d)",
431                            __func__, thread_handle->state,
432                            THREAD_STATE_EXITED);
433                 *exitcode = STILL_ACTIVE;
434                 return(TRUE);
435         }
436         
437         *exitcode = thread_handle->exitstatus;
438         
439         return(TRUE);
440 }
441
442 /**
443  * GetCurrentThreadId:
444  *
445  * Looks up the thread ID of the current thread.  This ID can be
446  * passed to OpenThread() to create a new handle on this thread.
447  *
448  * Return value: the thread ID.  NB this is defined as DWORD (ie 32
449  * bit) in the MS API, but we need to cope with 64 bit IDs for s390x
450  * and amd64.  This doesn't really break the API, it just embraces and
451  * extends it on 64bit platforms :)
452  */
453 gsize GetCurrentThreadId(void)
454 {
455         pthread_t tid = pthread_self();
456         
457 #ifdef PTHREAD_POINTER_ID
458         /* Don't use GPOINTER_TO_UINT here, it can't cope with
459          * sizeof(void *) > sizeof(uint) when a cast to uint would
460          * overflow
461          */
462         return((gsize)tid);
463 #else
464         return(tid);
465 #endif
466 }
467
468 static gpointer thread_attach(gsize *tid)
469 {
470         struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
471         gpointer handle;
472         gboolean ok;
473         int thr_ret;
474         
475         mono_once (&thread_hash_once, thread_hash_init);
476         mono_once (&thread_ops_once, thread_ops_init);
477
478         thread_handle.state = THREAD_STATE_START;
479         thread_handle.owned_mutexes = g_ptr_array_new ();
480
481         handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
482         if (handle == _WAPI_HANDLE_INVALID) {
483                 g_warning ("%s: error creating thread handle", __func__);
484                 
485                 SetLastError (ERROR_GEN_FAILURE);
486                 return (NULL);
487         }
488
489         pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
490                               handle);
491         thr_ret = _wapi_handle_lock_handle (handle);
492         g_assert (thr_ret == 0);
493         
494         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
495                                   (gpointer *)&thread_handle_p);
496         if (ok == FALSE) {
497                 g_warning ("%s: error looking up thread handle %p", __func__,
498                            handle);
499                 
500                 SetLastError (ERROR_GEN_FAILURE);
501                 goto cleanup;
502         }
503
504         /* Hold a reference while the thread is active, because we use
505          * the handle to store thread exit information
506          */
507         _wapi_handle_ref (handle);
508
509         thread_handle_p->handle = handle;
510         thread_handle_p->id = pthread_self ();
511
512         thr_ret = pthread_setspecific (thread_hash_key, (void *)handle);
513         g_assert (thr_ret == 0);
514
515         thr_ret = pthread_setspecific (thread_attached_key, (void *)handle);
516         g_assert (thr_ret == 0);
517         
518         DEBUG("%s: Attached thread handle %p ID %ld", __func__, handle,
519                   thread_handle_p->id);
520
521         if (tid != NULL) {
522 #ifdef PTHREAD_POINTER_ID
523                 /* Don't use GPOINTER_TO_UINT here, it can't cope with
524                  * sizeof(void *) > sizeof(uint) when a cast to uint
525                  * would overflow
526                  */
527                 *tid = (gsize)(thread_handle_p->id);
528 #else
529                 *tid = thread_handle_p->id;
530 #endif
531         }
532
533 cleanup:
534         thr_ret = _wapi_handle_unlock_handle (handle);
535         g_assert (thr_ret == 0);
536         pthread_cleanup_pop (0);
537         
538         return(handle);
539 }
540
541 gpointer _wapi_thread_duplicate ()
542 {
543         gpointer ret = NULL;
544         
545         mono_once (&thread_hash_once, thread_hash_init);
546         mono_once (&thread_ops_once, thread_ops_init);
547         
548         ret = _wapi_thread_handle_from_id (pthread_self ());
549         if (!ret) {
550                 ret = thread_attach (NULL);
551         } else {
552                 _wapi_handle_ref (ret);
553         }
554         
555         return(ret);
556 }
557
558 /**
559  * GetCurrentThread:
560  *
561  * Looks up the handle associated with the current thread.  Under
562  * Windows this is a pseudohandle, and must be duplicated with
563  * DuplicateHandle() for some operations.
564  *
565  * Return value: The current thread handle, or %NULL on failure.
566  * (Unknown whether Windows has a possible failure here.  It may be
567  * necessary to implement the pseudohandle-constant behaviour).
568  */
569 gpointer GetCurrentThread(void)
570 {
571         mono_once(&thread_hash_once, thread_hash_init);
572         mono_once (&thread_ops_once, thread_ops_init);
573         
574         return(_WAPI_THREAD_CURRENT);
575 }
576
577 /**
578  * SleepEx:
579  * @ms: The time in milliseconds to suspend for
580  * @alertable: if TRUE, the wait can be interrupted by an APC call
581  *
582  * Suspends execution of the current thread for @ms milliseconds.  A
583  * value of zero causes the thread to relinquish its time slice.  A
584  * value of %INFINITE causes an infinite delay.
585  */
586 guint32 SleepEx(guint32 ms, gboolean alertable)
587 {
588         struct timespec req, rem;
589         int ms_quot, ms_rem;
590         int ret;
591         gpointer current_thread = NULL;
592         
593         DEBUG("%s: Sleeping for %d ms", __func__, ms);
594
595         if (alertable) {
596                 current_thread = _wapi_thread_handle_from_id (pthread_self ());
597                 if (current_thread == NULL) {
598                         SetLastError (ERROR_INVALID_HANDLE);
599                         return(WAIT_FAILED);
600                 }
601                 
602                 if (_wapi_thread_apc_pending (current_thread)) {
603                         _wapi_thread_dispatch_apc_queue (current_thread);
604                         return WAIT_IO_COMPLETION;
605                 }
606         }
607         
608         if(ms==0) {
609                 sched_yield();
610                 return 0;
611         }
612         
613         /* FIXME: check for INFINITE and sleep forever */
614         ms_quot = ms / 1000;
615         ms_rem = ms % 1000;
616         
617         req.tv_sec=ms_quot;
618         req.tv_nsec=ms_rem*1000000;
619         
620 again:
621         memset (&rem, 0, sizeof (rem));
622         ret=nanosleep(&req, &rem);
623
624         if (alertable && _wapi_thread_apc_pending (current_thread)) {
625                 _wapi_thread_dispatch_apc_queue (current_thread);
626                 return WAIT_IO_COMPLETION;
627         }
628         
629         if(ret==-1) {
630                 /* Sleep interrupted with rem time remaining */
631 #ifdef DEBUG_ENABLED
632                 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
633                 
634                 g_message("%s: Still got %d ms to go", __func__, rems);
635 #endif
636                 req=rem;
637                 goto again;
638         }
639
640         return 0;
641 }
642
643 void Sleep(guint32 ms)
644 {
645         SleepEx(ms, FALSE);
646 }
647
648 gboolean _wapi_thread_cur_apc_pending (void)
649 {
650         gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
651         
652         if (thread == NULL) {
653                 SetLastError (ERROR_INVALID_HANDLE);
654                 return(FALSE);
655         }
656         
657         return(_wapi_thread_apc_pending (thread));
658 }
659
660 gboolean _wapi_thread_apc_pending (gpointer handle)
661 {
662         struct _WapiHandle_thread *thread;
663         gboolean ok;
664         
665         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
666                                   (gpointer *)&thread);
667         if (ok == FALSE) {
668                 /* This might happen at process shutdown, as all
669                  * thread handles are forcibly closed.  If a thread
670                  * still has an alertable wait the final
671                  * _wapi_thread_apc_pending check will probably fail
672                  * to find the handle
673                  */
674                 DEBUG ("%s: error looking up thread handle %p", __func__,
675                            handle);
676                 return (FALSE);
677         }
678         
679         return(thread->has_apc || thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE);
680 }
681
682 gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
683 {
684         /* We don't support calling APC functions */
685         struct _WapiHandle_thread *thread;
686         gboolean ok;
687         
688         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
689                                   (gpointer *)&thread);
690         g_assert (ok);
691
692         thread->has_apc = FALSE;
693
694         return(TRUE);
695 }
696
697 /*
698  * In this implementation, APC_CALLBACK is ignored.
699  * if HANDLE refers to the current thread, the only effect this function has 
700  * that if called from a signal handler, and the thread was waiting when receiving 
701  * the signal, the wait will be broken after the signal handler returns.
702  * In this case, this function is async-signal-safe.
703  */
704 guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer handle, 
705                       gpointer param)
706 {
707         struct _WapiHandle_thread *thread_handle;
708         gboolean ok;
709         
710         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
711                                   (gpointer *)&thread_handle);
712         if (ok == FALSE) {
713                 g_warning ("%s: error looking up thread handle %p", __func__,
714                            handle);
715                 return (0);
716         }
717
718         g_assert (thread_handle->id == (pthread_t)GetCurrentThreadId ());
719         /* No locking/memory barriers are needed here */
720         thread_handle->has_apc = TRUE;
721         return(1);
722 }
723
724 /*
725  * wapi_interrupt_thread:
726  *
727  *   This is not part of the WIN32 API.
728  * The state of the thread handle HANDLE is set to 'interrupted' which means that
729  * if the thread calls one of the WaitFor functions, the function will return with 
730  * WAIT_IO_COMPLETION instead of waiting. Also, if the thread was waiting when
731  * this function was called, the wait will be broken.
732  * It is possible that the wait functions return WAIT_IO_COMPLETION, but the
733  * target thread didn't receive the interrupt signal yet, in this case it should
734  * call the wait function again. This essentially means that the target thread will
735  * busy wait until it is ready to process the interruption.
736  * FIXME: get rid of QueueUserAPC and thread->has_apc, SleepEx seems to require it.
737  */
738 void wapi_interrupt_thread (gpointer thread_handle)
739 {
740         struct _WapiHandle_thread *thread;
741         gboolean ok;
742         gpointer prev_handle, wait_handle;
743         guint32 idx;
744         pthread_cond_t *cond;
745         mono_mutex_t *mutex;
746         
747         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
748                                   (gpointer *)&thread);
749         g_assert (ok);
750
751         while (TRUE) {
752                 wait_handle = thread->wait_handle;
753
754                 /* 
755                  * Atomically obtain the handle the thread is waiting on, and
756                  * change it to a flag value.
757                  */
758                 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
759                                                                                                                  INTERRUPTION_REQUESTED_HANDLE, wait_handle);
760                 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
761                         /* Already interrupted */
762                         return;
763                 if (prev_handle == wait_handle)
764                         break;
765
766                 /* Try again */
767         }
768
769         WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread->id););
770
771         if (!wait_handle)
772                 /* Not waiting */
773                 return;
774
775         /* If we reach here, then wait_handle is set to the flag value, 
776          * which means that the target thread is either
777          * - before the first CAS in timedwait, which means it won't enter the
778          * wait.
779          * - it is after the first CAS, so it is already waiting, or it will 
780          * enter the wait, and it will be interrupted by the broadcast.
781          */
782         idx = GPOINTER_TO_UINT(wait_handle);
783         cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
784         mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
785
786         mono_mutex_lock (mutex);
787         mono_cond_broadcast (cond);
788         mono_mutex_unlock (mutex);
789
790         /* ref added by set_wait_handle */
791         _wapi_handle_unref (wait_handle);
792 }
793
794
795 gpointer wapi_prepare_interrupt_thread (gpointer thread_handle)
796 {
797         struct _WapiHandle_thread *thread;
798         gboolean ok;
799         gpointer prev_handle, wait_handle;
800         
801         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
802                                   (gpointer *)&thread);
803         g_assert (ok);
804
805         while (TRUE) {
806                 wait_handle = thread->wait_handle;
807
808                 /* 
809                  * Atomically obtain the handle the thread is waiting on, and
810                  * change it to a flag value.
811                  */
812                 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
813                                                                                                                  INTERRUPTION_REQUESTED_HANDLE, wait_handle);
814                 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
815                         /* Already interrupted */
816                         return 0;
817                 if (prev_handle == wait_handle)
818                         break;
819
820                 /* Try again */
821         }
822
823         WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread->id););
824
825         return wait_handle;
826 }
827
828 void wapi_finish_interrupt_thread (gpointer wait_handle)
829 {
830         pthread_cond_t *cond;
831         mono_mutex_t *mutex;
832         guint32 idx;
833
834         if (!wait_handle)
835                 /* Not waiting */
836                 return;
837
838         /* If we reach here, then wait_handle is set to the flag value, 
839          * which means that the target thread is either
840          * - before the first CAS in timedwait, which means it won't enter the
841          * wait.
842          * - it is after the first CAS, so it is already waiting, or it will 
843          * enter the wait, and it will be interrupted by the broadcast.
844          */
845         idx = GPOINTER_TO_UINT(wait_handle);
846         cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
847         mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
848
849         mono_mutex_lock (mutex);
850         mono_cond_broadcast (cond);
851         mono_mutex_unlock (mutex);
852
853         /* ref added by set_wait_handle */
854         _wapi_handle_unref (wait_handle);
855 }
856
857
858 /*
859  * wapi_self_interrupt:
860  *
861  *   This is not part of the WIN32 API.
862  * Set the 'interrupted' state of the calling thread if it's NULL.
863  */
864 void wapi_self_interrupt (void)
865 {
866         struct _WapiHandle_thread *thread;
867         gboolean ok;
868         gpointer prev_handle, wait_handle;
869         gpointer thread_handle;
870
871
872         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
873         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
874                                                           (gpointer *)&thread);
875         g_assert (ok);
876
877         while (TRUE) {
878                 wait_handle = thread->wait_handle;
879
880                 /*
881                  * Atomically obtain the handle the thread is waiting on, and
882                  * change it to a flag value.
883                  */
884                 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
885                                                                                                                  INTERRUPTION_REQUESTED_HANDLE, wait_handle);
886                 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
887                         /* Already interrupted */
888                         goto cleanup;
889                 /*We did not get interrupted*/
890                 if (prev_handle == wait_handle)
891                         break;
892
893                 /* Try again */
894         }
895
896         if (wait_handle) {
897                 /* ref added by set_wait_handle */
898                 _wapi_handle_unref (wait_handle);
899         }
900
901 cleanup:
902         _wapi_handle_unref (thread_handle);
903 }
904
905 /*
906  * wapi_clear_interruption:
907  *
908  *   This is not part of the WIN32 API. 
909  * Clear the 'interrupted' state of the calling thread.
910  * This function is signal safe
911  */
912 void wapi_clear_interruption (void)
913 {
914         struct _WapiHandle_thread *thread;
915         gboolean ok;
916         gpointer prev_handle;
917         gpointer thread_handle;
918
919         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
920         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
921                                                           (gpointer *)&thread);
922         g_assert (ok);
923
924         prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
925                                                                                                          NULL, INTERRUPTION_REQUESTED_HANDLE);
926         if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
927                 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
928
929         _wapi_handle_unref (thread_handle);
930 }
931
932 char* wapi_current_thread_desc ()
933 {
934         struct _WapiHandle_thread *thread;
935         int i;
936         gboolean ok;
937         gpointer handle;
938         gpointer thread_handle;
939         GString* text;
940         char *res;
941
942         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
943         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
944                                                           (gpointer *)&thread);
945         if (!ok)
946                 return g_strdup_printf ("thread handle %p state : lookup failure", thread_handle);
947
948         handle = thread->wait_handle;
949         text = g_string_new (0);
950         g_string_append_printf (text, "thread handle %p state : ", thread_handle);
951
952         if (!handle)
953                 g_string_append_printf (text, "not waiting");
954         else if (handle == INTERRUPTION_REQUESTED_HANDLE)
955                 g_string_append_printf (text, "interrupted state");
956         else
957                 g_string_append_printf (text, "waiting on %p : %s ", handle, _wapi_handle_typename[_wapi_handle_type (handle)]);
958         g_string_append_printf (text, " owns (");
959         for (i = 0; i < thread->owned_mutexes->len; i++) {
960                 gpointer mutex = g_ptr_array_index (thread->owned_mutexes, i);
961                 if (i > 0)
962                         g_string_append_printf (text, ", %p", mutex);
963                 else
964                         g_string_append_printf (text, "%p", mutex);
965         }
966         g_string_append_printf (text, ")");
967
968         res = text->str;
969         g_string_free (text, FALSE);
970         return res;
971 }
972
973 /**
974  * wapi_thread_set_wait_handle:
975  *
976  *   Set the wait handle for the current thread to HANDLE. Return TRUE on success, FALSE
977  * if the thread is in interrupted state, and cannot start waiting.
978  */
979 gboolean wapi_thread_set_wait_handle (gpointer handle)
980 {
981         struct _WapiHandle_thread *thread;
982         gboolean ok;
983         gpointer prev_handle;
984         gpointer thread_handle;
985
986         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
987         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
988                                                           (gpointer *)&thread);
989         g_assert (ok);
990
991         prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
992                                                                                                          handle, NULL);
993         _wapi_handle_unref (thread_handle);
994
995         if (prev_handle == NULL) {
996                 /* thread->wait_handle acts as an additional reference to the handle */
997                 _wapi_handle_ref (handle);
998
999                 WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
1000         } else {
1001                 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
1002                 WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
1003         }
1004
1005         return prev_handle == NULL;
1006 }
1007
1008 /**
1009  * wapi_thread_clear_wait_handle:
1010  *
1011  *   Clear the wait handle of the current thread.
1012  */
1013 void wapi_thread_clear_wait_handle (gpointer handle)
1014 {
1015         struct _WapiHandle_thread *thread;
1016         gboolean ok;
1017         gpointer prev_handle;
1018         gpointer thread_handle;
1019
1020         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1021         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1022                                                           (gpointer *)&thread);
1023         g_assert (ok);
1024
1025         prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1026                                                                                                          NULL, handle);
1027
1028         if (prev_handle == handle) {
1029                 _wapi_handle_unref (handle);
1030                 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1031         } else {
1032                 /*It can be NULL if it was asynchronously cleared*/
1033                 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE || prev_handle == NULL);
1034                 WAIT_DEBUG (printf ("%p: finished waiting.\n", GetCurrentThreadId ()););
1035         }
1036
1037         _wapi_handle_unref (thread_handle);
1038 }
1039
1040 void _wapi_thread_own_mutex (gpointer mutex)
1041 {
1042         struct _WapiHandle_thread *thread_handle;
1043         gboolean ok;
1044         gpointer thread;
1045         
1046         thread = _wapi_thread_handle_from_id (pthread_self ());
1047         if (thread == NULL) {
1048                 g_warning ("%s: error looking up thread by ID", __func__);
1049                 return;
1050         }
1051
1052         ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1053                                   (gpointer *)&thread_handle);
1054         if (ok == FALSE) {
1055                 g_warning ("%s: error looking up thread handle %p", __func__,
1056                            thread);
1057                 return;
1058         }
1059
1060         _wapi_handle_ref (mutex);
1061         
1062         g_ptr_array_add (thread_handle->owned_mutexes, mutex);
1063 }
1064
1065 void _wapi_thread_disown_mutex (gpointer mutex)
1066 {
1067         struct _WapiHandle_thread *thread_handle;
1068         gboolean ok;
1069         gpointer thread;
1070
1071         thread = _wapi_thread_handle_from_id (pthread_self ());
1072         if (thread == NULL) {
1073                 g_warning ("%s: error looking up thread by ID", __func__);
1074                 return;
1075         }
1076
1077         ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1078                                   (gpointer *)&thread_handle);
1079         if (ok == FALSE) {
1080                 g_warning ("%s: error looking up thread handle %p", __func__,
1081                            thread);
1082                 return;
1083         }
1084
1085         _wapi_handle_unref (mutex);
1086         
1087         g_ptr_array_remove (thread_handle->owned_mutexes, mutex);
1088 }