Merge branch 'msbuilddll2'
[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         thread->handle = handle;
274
275         res = pthread_setspecific (thread_hash_key, handle);
276         if (res)
277                 mono_gc_pthread_exit (NULL);
278
279         thread->id = pthread_self ();
280
281         /*
282          * Hold a reference while the thread is active, because we use
283          * the handle to store thread exit information
284          */
285         _wapi_handle_ref (handle);
286
287         DEBUG ("%s: started thread id %ld", __func__, thread->id);
288         
289         return handle;
290 }
291
292 /* The only time this function is called when tid != pthread_self ()
293  * is from OpenThread (), so we can fast-path most cases by just
294  * looking up the handle in TLS.  OpenThread () must cope with a NULL
295  * return and do a handle search in that case.
296  */
297 gpointer _wapi_thread_handle_from_id (pthread_t tid)
298 {
299         gpointer ret;
300
301         if (pthread_equal (tid, pthread_self ()) &&
302             (ret = pthread_getspecific (thread_hash_key)) != NULL) {
303                 /* We know the handle */
304
305                 DEBUG ("%s: Returning %p for self thread %ld from TLS",
306                            __func__, ret, tid);
307                 
308                 return(ret);
309         }
310         
311         DEBUG ("%s: Returning NULL for unknown or non-self thread %ld",
312                    __func__, tid);
313                 
314
315         return(NULL);
316 }
317
318 static gboolean find_thread_by_id (gpointer handle, gpointer user_data)
319 {
320         pthread_t tid = (pthread_t)user_data;
321         struct _WapiHandle_thread *thread_handle;
322         gboolean ok;
323         
324         /* Ignore threads that have already exited (ie they are signalled) */
325         if (_wapi_handle_issignalled (handle) == FALSE) {
326                 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
327                                           (gpointer *)&thread_handle);
328                 if (ok == FALSE) {
329                         /* It's possible that the handle has vanished
330                          * during the _wapi_search_handle before it
331                          * gets here, so don't spam the console with
332                          * warnings.
333                          */
334                         return(FALSE);
335                 }
336                 
337                 DEBUG ("%s: looking at thread %ld from process %d", __func__, thread_handle->id, 0);
338
339                 if (pthread_equal (thread_handle->id, tid)) {
340                         DEBUG ("%s: found the thread we are looking for",
341                                    __func__);
342                         return(TRUE);
343                 }
344         }
345         
346         DEBUG ("%s: not found %ld, returning FALSE", __func__, tid);
347         
348         return(FALSE);
349 }
350
351 /* NB tid is 32bit in MS API, but we need 64bit on amd64 and s390x
352  * (and probably others)
353  */
354 gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, gsize tid)
355 {
356         gpointer ret=NULL;
357         
358         mono_once (&thread_hash_once, thread_hash_init);
359         mono_once (&thread_ops_once, thread_ops_init);
360         
361         DEBUG ("%s: looking up thread %"G_GSIZE_FORMAT, __func__, tid);
362
363         ret = _wapi_thread_handle_from_id ((pthread_t)tid);
364         if (ret == NULL) {
365                 /* We need to search for this thread */
366                 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 */
367         } else {
368                 /* if _wapi_search_handle() returns a found handle, it
369                  * refs it itself
370                  */
371                 _wapi_handle_ref (ret);
372         }
373         
374         DEBUG ("%s: returning thread handle %p", __func__, ret);
375         
376         return(ret);
377 }
378
379 /**
380  * ExitThread:
381  * @exitcode: Sets the thread's exit code, which can be read from
382  * another thread with GetExitCodeThread().
383  *
384  * Terminates the calling thread.  A thread can also exit by returning
385  * from its start function. When the last thread in a process
386  * terminates, the process itself terminates.
387  */
388 void ExitThread(guint32 exitcode)
389 {
390         gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
391         
392         if (thread != NULL) {
393                 thread_exit(exitcode, thread);
394         } else {
395                 /* Just blow this thread away */
396                 mono_gc_pthread_exit (NULL);
397         }
398 }
399
400 /**
401  * GetExitCodeThread:
402  * @handle: The thread handle to query
403  * @exitcode: The thread @handle exit code is stored here
404  *
405  * Finds the exit code of @handle, and stores it in @exitcode.  If the
406  * thread @handle is still running, the value stored is %STILL_ACTIVE.
407  *
408  * Return value: %TRUE, or %FALSE on error.
409  */
410 gboolean GetExitCodeThread(gpointer handle, guint32 *exitcode)
411 {
412         struct _WapiHandle_thread *thread_handle;
413         gboolean ok;
414         
415         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
416                                   (gpointer *)&thread_handle);
417         if (ok == FALSE) {
418                 g_warning ("%s: error looking up thread handle %p", __func__,
419                            handle);
420                 return (FALSE);
421         }
422         
423         DEBUG ("%s: Finding exit status for thread handle %p id %ld",
424                    __func__, handle, thread_handle->id);
425
426         if (exitcode == NULL) {
427                 DEBUG ("%s: Nowhere to store exit code", __func__);
428                 return(FALSE);
429         }
430         
431         if (thread_handle->state != THREAD_STATE_EXITED) {
432                 DEBUG ("%s: Thread still active (state %d, exited is %d)",
433                            __func__, thread_handle->state,
434                            THREAD_STATE_EXITED);
435                 *exitcode = STILL_ACTIVE;
436                 return(TRUE);
437         }
438         
439         *exitcode = thread_handle->exitstatus;
440         
441         return(TRUE);
442 }
443
444 /**
445  * GetCurrentThreadId:
446  *
447  * Looks up the thread ID of the current thread.  This ID can be
448  * passed to OpenThread() to create a new handle on this thread.
449  *
450  * Return value: the thread ID.  NB this is defined as DWORD (ie 32
451  * bit) in the MS API, but we need to cope with 64 bit IDs for s390x
452  * and amd64.  This doesn't really break the API, it just embraces and
453  * extends it on 64bit platforms :)
454  */
455 gsize GetCurrentThreadId(void)
456 {
457         pthread_t tid = pthread_self();
458         
459 #ifdef PTHREAD_POINTER_ID
460         /* Don't use GPOINTER_TO_UINT here, it can't cope with
461          * sizeof(void *) > sizeof(uint) when a cast to uint would
462          * overflow
463          */
464         return((gsize)tid);
465 #else
466         return(tid);
467 #endif
468 }
469
470 static gpointer thread_attach(gsize *tid)
471 {
472         struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
473         gpointer handle;
474         gboolean ok;
475         int thr_ret;
476         
477         mono_once (&thread_hash_once, thread_hash_init);
478         mono_once (&thread_ops_once, thread_ops_init);
479
480         thread_handle.state = THREAD_STATE_START;
481         thread_handle.owned_mutexes = g_ptr_array_new ();
482
483         handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
484         if (handle == _WAPI_HANDLE_INVALID) {
485                 g_warning ("%s: error creating thread handle", __func__);
486                 
487                 SetLastError (ERROR_GEN_FAILURE);
488                 return (NULL);
489         }
490
491         pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
492                               handle);
493         thr_ret = _wapi_handle_lock_handle (handle);
494         g_assert (thr_ret == 0);
495         
496         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
497                                   (gpointer *)&thread_handle_p);
498         if (ok == FALSE) {
499                 g_warning ("%s: error looking up thread handle %p", __func__,
500                            handle);
501                 
502                 SetLastError (ERROR_GEN_FAILURE);
503                 goto cleanup;
504         }
505
506         /* Hold a reference while the thread is active, because we use
507          * the handle to store thread exit information
508          */
509         _wapi_handle_ref (handle);
510
511         thread_handle_p->handle = handle;
512         thread_handle_p->id = pthread_self ();
513
514         thr_ret = pthread_setspecific (thread_hash_key, (void *)handle);
515         g_assert (thr_ret == 0);
516
517         thr_ret = pthread_setspecific (thread_attached_key, (void *)handle);
518         g_assert (thr_ret == 0);
519         
520         DEBUG("%s: Attached thread handle %p ID %ld", __func__, handle,
521                   thread_handle_p->id);
522
523         if (tid != NULL) {
524 #ifdef PTHREAD_POINTER_ID
525                 /* Don't use GPOINTER_TO_UINT here, it can't cope with
526                  * sizeof(void *) > sizeof(uint) when a cast to uint
527                  * would overflow
528                  */
529                 *tid = (gsize)(thread_handle_p->id);
530 #else
531                 *tid = thread_handle_p->id;
532 #endif
533         }
534
535 cleanup:
536         thr_ret = _wapi_handle_unlock_handle (handle);
537         g_assert (thr_ret == 0);
538         pthread_cleanup_pop (0);
539         
540         return(handle);
541 }
542
543 gpointer _wapi_thread_duplicate ()
544 {
545         gpointer ret = NULL;
546         
547         mono_once (&thread_hash_once, thread_hash_init);
548         mono_once (&thread_ops_once, thread_ops_init);
549         
550         ret = _wapi_thread_handle_from_id (pthread_self ());
551         if (!ret) {
552                 ret = thread_attach (NULL);
553         } else {
554                 _wapi_handle_ref (ret);
555         }
556         
557         return(ret);
558 }
559
560 /**
561  * GetCurrentThread:
562  *
563  * Looks up the handle associated with the current thread.  Under
564  * Windows this is a pseudohandle, and must be duplicated with
565  * DuplicateHandle() for some operations.
566  *
567  * Return value: The current thread handle, or %NULL on failure.
568  * (Unknown whether Windows has a possible failure here.  It may be
569  * necessary to implement the pseudohandle-constant behaviour).
570  */
571 gpointer GetCurrentThread(void)
572 {
573         mono_once(&thread_hash_once, thread_hash_init);
574         mono_once (&thread_ops_once, thread_ops_init);
575         
576         return(_WAPI_THREAD_CURRENT);
577 }
578
579 /**
580  * SleepEx:
581  * @ms: The time in milliseconds to suspend for
582  * @alertable: if TRUE, the wait can be interrupted by an APC call
583  *
584  * Suspends execution of the current thread for @ms milliseconds.  A
585  * value of zero causes the thread to relinquish its time slice.  A
586  * value of %INFINITE causes an infinite delay.
587  */
588 guint32 SleepEx(guint32 ms, gboolean alertable)
589 {
590         struct timespec req, rem;
591         int ms_quot, ms_rem;
592         int ret;
593         gpointer current_thread = NULL;
594         
595         DEBUG("%s: Sleeping for %d ms", __func__, ms);
596
597         if (alertable) {
598                 current_thread = _wapi_thread_handle_from_id (pthread_self ());
599                 if (current_thread == NULL) {
600                         SetLastError (ERROR_INVALID_HANDLE);
601                         return(WAIT_FAILED);
602                 }
603                 
604                 if (_wapi_thread_apc_pending (current_thread)) {
605                         _wapi_thread_dispatch_apc_queue (current_thread);
606                         return WAIT_IO_COMPLETION;
607                 }
608         }
609         
610         if(ms==0) {
611                 sched_yield();
612                 return 0;
613         }
614         
615         /* FIXME: check for INFINITE and sleep forever */
616         ms_quot = ms / 1000;
617         ms_rem = ms % 1000;
618         
619         req.tv_sec=ms_quot;
620         req.tv_nsec=ms_rem*1000000;
621         
622 again:
623         memset (&rem, 0, sizeof (rem));
624         ret=nanosleep(&req, &rem);
625
626         if (alertable && _wapi_thread_apc_pending (current_thread)) {
627                 _wapi_thread_dispatch_apc_queue (current_thread);
628                 return WAIT_IO_COMPLETION;
629         }
630         
631         if(ret==-1) {
632                 /* Sleep interrupted with rem time remaining */
633 #ifdef DEBUG_ENABLED
634                 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
635                 
636                 g_message("%s: Still got %d ms to go", __func__, rems);
637 #endif
638                 req=rem;
639                 goto again;
640         }
641
642         return 0;
643 }
644
645 void Sleep(guint32 ms)
646 {
647         SleepEx(ms, FALSE);
648 }
649
650 gboolean _wapi_thread_cur_apc_pending (void)
651 {
652         gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
653         
654         if (thread == NULL) {
655                 SetLastError (ERROR_INVALID_HANDLE);
656                 return(FALSE);
657         }
658         
659         return(_wapi_thread_apc_pending (thread));
660 }
661
662 gboolean _wapi_thread_apc_pending (gpointer handle)
663 {
664         struct _WapiHandle_thread *thread;
665         gboolean ok;
666         
667         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
668                                   (gpointer *)&thread);
669         if (ok == FALSE) {
670                 /* This might happen at process shutdown, as all
671                  * thread handles are forcibly closed.  If a thread
672                  * still has an alertable wait the final
673                  * _wapi_thread_apc_pending check will probably fail
674                  * to find the handle
675                  */
676                 DEBUG ("%s: error looking up thread handle %p", __func__,
677                            handle);
678                 return (FALSE);
679         }
680         
681         return(thread->has_apc || thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE);
682 }
683
684 gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
685 {
686         /* We don't support calling APC functions */
687         struct _WapiHandle_thread *thread;
688         gboolean ok;
689         
690         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
691                                   (gpointer *)&thread);
692         g_assert (ok);
693
694         thread->has_apc = FALSE;
695
696         return(TRUE);
697 }
698
699 /*
700  * wapi_interrupt_self:
701  *
702  * If this function called from a signal handler, and the thread was waiting when receiving
703  * the signal, the wait will be broken after the signal handler returns.
704  * This function is async-signal-safe.
705  */
706 void
707 wapi_thread_interrupt_self (void)
708 {
709         HANDLE handle;
710         struct _WapiHandle_thread *thread_handle;
711         gboolean ok;
712         
713         handle = _wapi_thread_handle_from_id (pthread_self ());
714         g_assert (handle);
715
716         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
717                                   (gpointer *)&thread_handle);
718         if (ok == FALSE) {
719                 g_warning ("%s: error looking up thread handle %p", __func__,
720                            handle);
721                 return;
722         }
723
724         /* No locking/memory barriers are needed here */
725         thread_handle->has_apc = TRUE;
726 }
727
728 /*
729  * wapi_interrupt_thread:
730  *
731  *   This is not part of the WIN32 API.
732  * The state of the thread handle HANDLE is set to 'interrupted' which means that
733  * if the thread calls one of the WaitFor functions, the function will return with 
734  * WAIT_IO_COMPLETION instead of waiting. Also, if the thread was waiting when
735  * this function was called, the wait will be broken.
736  * It is possible that the wait functions return WAIT_IO_COMPLETION, but the
737  * target thread didn't receive the interrupt signal yet, in this case it should
738  * call the wait function again. This essentially means that the target thread will
739  * busy wait until it is ready to process the interruption.
740  * FIXME: get rid of QueueUserAPC and thread->has_apc, SleepEx seems to require it.
741  */
742 void wapi_interrupt_thread (gpointer thread_handle)
743 {
744         struct _WapiHandle_thread *thread;
745         gboolean ok;
746         gpointer prev_handle, wait_handle;
747         guint32 idx;
748         pthread_cond_t *cond;
749         mono_mutex_t *mutex;
750         
751         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
752                                   (gpointer *)&thread);
753         g_assert (ok);
754
755         while (TRUE) {
756                 wait_handle = thread->wait_handle;
757
758                 /* 
759                  * Atomically obtain the handle the thread is waiting on, and
760                  * change it to a flag value.
761                  */
762                 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
763                                                                                                                  INTERRUPTION_REQUESTED_HANDLE, wait_handle);
764                 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
765                         /* Already interrupted */
766                         return;
767                 if (prev_handle == wait_handle)
768                         break;
769
770                 /* Try again */
771         }
772
773         WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread->id););
774
775         if (!wait_handle)
776                 /* Not waiting */
777                 return;
778
779         /* If we reach here, then wait_handle is set to the flag value, 
780          * which means that the target thread is either
781          * - before the first CAS in timedwait, which means it won't enter the
782          * wait.
783          * - it is after the first CAS, so it is already waiting, or it will 
784          * enter the wait, and it will be interrupted by the broadcast.
785          */
786         idx = GPOINTER_TO_UINT(wait_handle);
787         cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
788         mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
789
790         mono_mutex_lock (mutex);
791         mono_cond_broadcast (cond);
792         mono_mutex_unlock (mutex);
793
794         /* ref added by set_wait_handle */
795         _wapi_handle_unref (wait_handle);
796 }
797
798
799 gpointer wapi_prepare_interrupt_thread (gpointer thread_handle)
800 {
801         struct _WapiHandle_thread *thread;
802         gboolean ok;
803         gpointer prev_handle, wait_handle;
804         
805         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
806                                   (gpointer *)&thread);
807         g_assert (ok);
808
809         while (TRUE) {
810                 wait_handle = thread->wait_handle;
811
812                 /* 
813                  * Atomically obtain the handle the thread is waiting on, and
814                  * change it to a flag value.
815                  */
816                 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
817                                                                                                                  INTERRUPTION_REQUESTED_HANDLE, wait_handle);
818                 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
819                         /* Already interrupted */
820                         return 0;
821                 if (prev_handle == wait_handle)
822                         break;
823
824                 /* Try again */
825         }
826
827         WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread->id););
828
829         return wait_handle;
830 }
831
832 void wapi_finish_interrupt_thread (gpointer wait_handle)
833 {
834         pthread_cond_t *cond;
835         mono_mutex_t *mutex;
836         guint32 idx;
837
838         if (!wait_handle)
839                 /* Not waiting */
840                 return;
841
842         /* If we reach here, then wait_handle is set to the flag value, 
843          * which means that the target thread is either
844          * - before the first CAS in timedwait, which means it won't enter the
845          * wait.
846          * - it is after the first CAS, so it is already waiting, or it will 
847          * enter the wait, and it will be interrupted by the broadcast.
848          */
849         idx = GPOINTER_TO_UINT(wait_handle);
850         cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
851         mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
852
853         mono_mutex_lock (mutex);
854         mono_cond_broadcast (cond);
855         mono_mutex_unlock (mutex);
856
857         /* ref added by set_wait_handle */
858         _wapi_handle_unref (wait_handle);
859 }
860
861
862 /*
863  * wapi_self_interrupt:
864  *
865  *   This is not part of the WIN32 API.
866  * Set the 'interrupted' state of the calling thread if it's NULL.
867  */
868 void wapi_self_interrupt (void)
869 {
870         struct _WapiHandle_thread *thread;
871         gboolean ok;
872         gpointer prev_handle, wait_handle;
873         gpointer thread_handle;
874
875
876         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
877         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
878                                                           (gpointer *)&thread);
879         g_assert (ok);
880
881         while (TRUE) {
882                 wait_handle = thread->wait_handle;
883
884                 /*
885                  * Atomically obtain the handle the thread is waiting on, and
886                  * change it to a flag value.
887                  */
888                 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
889                                                                                                                  INTERRUPTION_REQUESTED_HANDLE, wait_handle);
890                 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
891                         /* Already interrupted */
892                         goto cleanup;
893                 /*We did not get interrupted*/
894                 if (prev_handle == wait_handle)
895                         break;
896
897                 /* Try again */
898         }
899
900         if (wait_handle) {
901                 /* ref added by set_wait_handle */
902                 _wapi_handle_unref (wait_handle);
903         }
904
905 cleanup:
906         _wapi_handle_unref (thread_handle);
907 }
908
909 /*
910  * wapi_clear_interruption:
911  *
912  *   This is not part of the WIN32 API. 
913  * Clear the 'interrupted' state of the calling thread.
914  * This function is signal safe
915  */
916 void wapi_clear_interruption (void)
917 {
918         struct _WapiHandle_thread *thread;
919         gboolean ok;
920         gpointer prev_handle;
921         gpointer thread_handle;
922
923         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
924         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
925                                                           (gpointer *)&thread);
926         g_assert (ok);
927
928         prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
929                                                                                                          NULL, INTERRUPTION_REQUESTED_HANDLE);
930         if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
931                 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
932
933         _wapi_handle_unref (thread_handle);
934 }
935
936 char* wapi_current_thread_desc ()
937 {
938         struct _WapiHandle_thread *thread;
939         int i;
940         gboolean ok;
941         gpointer handle;
942         gpointer thread_handle;
943         GString* text;
944         char *res;
945
946         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
947         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
948                                                           (gpointer *)&thread);
949         if (!ok)
950                 return g_strdup_printf ("thread handle %p state : lookup failure", thread_handle);
951
952         handle = thread->wait_handle;
953         text = g_string_new (0);
954         g_string_append_printf (text, "thread handle %p state : ", thread_handle);
955
956         if (!handle)
957                 g_string_append_printf (text, "not waiting");
958         else if (handle == INTERRUPTION_REQUESTED_HANDLE)
959                 g_string_append_printf (text, "interrupted state");
960         else
961                 g_string_append_printf (text, "waiting on %p : %s ", handle, _wapi_handle_typename[_wapi_handle_type (handle)]);
962         g_string_append_printf (text, " owns (");
963         for (i = 0; i < thread->owned_mutexes->len; i++) {
964                 gpointer mutex = g_ptr_array_index (thread->owned_mutexes, i);
965                 if (i > 0)
966                         g_string_append_printf (text, ", %p", mutex);
967                 else
968                         g_string_append_printf (text, "%p", mutex);
969         }
970         g_string_append_printf (text, ")");
971
972         res = text->str;
973         g_string_free (text, FALSE);
974         return res;
975 }
976
977 /**
978  * wapi_thread_set_wait_handle:
979  *
980  *   Set the wait handle for the current thread to HANDLE. Return TRUE on success, FALSE
981  * if the thread is in interrupted state, and cannot start waiting.
982  */
983 gboolean wapi_thread_set_wait_handle (gpointer handle)
984 {
985         struct _WapiHandle_thread *thread;
986         gboolean ok;
987         gpointer prev_handle;
988         gpointer thread_handle;
989
990         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
991         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
992                                                           (gpointer *)&thread);
993         g_assert (ok);
994
995         prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
996                                                                                                          handle, NULL);
997         _wapi_handle_unref (thread_handle);
998
999         if (prev_handle == NULL) {
1000                 /* thread->wait_handle acts as an additional reference to the handle */
1001                 _wapi_handle_ref (handle);
1002
1003                 WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
1004         } else {
1005                 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
1006                 WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
1007         }
1008
1009         return prev_handle == NULL;
1010 }
1011
1012 /**
1013  * wapi_thread_clear_wait_handle:
1014  *
1015  *   Clear the wait handle of the current thread.
1016  */
1017 void wapi_thread_clear_wait_handle (gpointer handle)
1018 {
1019         struct _WapiHandle_thread *thread;
1020         gboolean ok;
1021         gpointer prev_handle;
1022         gpointer thread_handle;
1023
1024         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1025         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1026                                                           (gpointer *)&thread);
1027         g_assert (ok);
1028
1029         prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1030                                                                                                          NULL, handle);
1031
1032         if (prev_handle == handle) {
1033                 _wapi_handle_unref (handle);
1034                 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1035         } else {
1036                 /*It can be NULL if it was asynchronously cleared*/
1037                 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE || prev_handle == NULL);
1038                 WAIT_DEBUG (printf ("%p: finished waiting.\n", GetCurrentThreadId ()););
1039         }
1040
1041         _wapi_handle_unref (thread_handle);
1042 }
1043
1044 void _wapi_thread_own_mutex (gpointer mutex)
1045 {
1046         struct _WapiHandle_thread *thread_handle;
1047         gboolean ok;
1048         gpointer thread;
1049         
1050         thread = _wapi_thread_handle_from_id (pthread_self ());
1051         if (thread == NULL) {
1052                 g_warning ("%s: error looking up thread by ID", __func__);
1053                 return;
1054         }
1055
1056         ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1057                                   (gpointer *)&thread_handle);
1058         if (ok == FALSE) {
1059                 g_warning ("%s: error looking up thread handle %p", __func__,
1060                            thread);
1061                 return;
1062         }
1063
1064         _wapi_handle_ref (mutex);
1065         
1066         g_ptr_array_add (thread_handle->owned_mutexes, mutex);
1067 }
1068
1069 void _wapi_thread_disown_mutex (gpointer mutex)
1070 {
1071         struct _WapiHandle_thread *thread_handle;
1072         gboolean ok;
1073         gpointer thread;
1074
1075         thread = _wapi_thread_handle_from_id (pthread_self ());
1076         if (thread == NULL) {
1077                 g_warning ("%s: error looking up thread by ID", __func__);
1078                 return;
1079         }
1080
1081         ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1082                                   (gpointer *)&thread_handle);
1083         if (ok == FALSE) {
1084                 g_warning ("%s: error looking up thread handle %p", __func__,
1085                            thread);
1086                 return;
1087         }
1088
1089         _wapi_handle_unref (mutex);
1090         
1091         g_ptr_array_remove (thread_handle->owned_mutexes, mutex);
1092 }