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