Add unit test for AggregateException.GetBaseException that works on .net but is broke...
[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         MONO_SEM_DESTROY (&thread_handle->suspend_sem);
169         g_ptr_array_free (thread_handle->owned_mutexes, TRUE);
170
171         _wapi_handle_set_signal_state (handle, TRUE, TRUE);
172
173         thr_ret = _wapi_handle_unlock_handle (handle);
174         g_assert (thr_ret == 0);
175         pthread_cleanup_pop (0);
176         
177         DEBUG("%s: Recording thread handle %p id %ld status as %d",
178                   __func__, handle, thread_handle->id, exitstatus);
179         
180         /* The thread is no longer active, so unref it */
181         _wapi_handle_unref (handle);
182 }
183
184 void _wapi_thread_signal_self (guint32 exitstatus)
185 {
186         gpointer handle;
187         
188         handle = _wapi_thread_handle_from_id (pthread_self ());
189         if (handle == NULL) {
190                 /* Something gone badly wrong... */
191                 return;
192         }
193         
194         _wapi_thread_set_termination_details (handle, exitstatus);
195 }
196
197 /* Called by the thread creation code as a thread is finishing up, and
198  * by ExitThread()
199 */
200 static void thread_exit (guint32 exitstatus, gpointer handle) G_GNUC_NORETURN;
201 #if defined(__native_client__)
202 void nacl_shutdown_gc_thread(void);
203 #endif
204 static void thread_exit (guint32 exitstatus, gpointer handle)
205 {
206 #if defined(__native_client__)
207         nacl_shutdown_gc_thread();
208 #endif
209         _wapi_thread_set_termination_details (handle, exitstatus);
210         
211         /* Call pthread_exit() to call destructors and really exit the
212          * thread
213          */
214         mono_gc_pthread_exit (NULL);
215 }
216
217 static void thread_attached_exit (gpointer handle)
218 {
219         /* Drop the extra reference we take in thread_attach, now this
220          * thread is dead
221          */
222         
223         _wapi_thread_set_termination_details (handle, 0);
224 }
225
226 static void thread_hash_init(void)
227 {
228         int thr_ret;
229         
230         thr_ret = pthread_key_create (&thread_hash_key, NULL);
231         g_assert (thr_ret == 0);
232
233         thr_ret = pthread_key_create (&thread_attached_key,
234                                       thread_attached_exit);
235         g_assert (thr_ret == 0);
236 }
237
238 static void _wapi_thread_suspend (struct _WapiHandle_thread *thread)
239 {
240         g_assert (pthread_equal (thread->id, pthread_self ()));
241         
242         while (MONO_SEM_WAIT (&thread->suspend_sem) != 0 &&
243                errno == EINTR);
244 }
245
246 static void _wapi_thread_resume (struct _WapiHandle_thread *thread)
247 {
248         MONO_SEM_POST (&thread->suspend_sem);
249 }
250
251 static void *thread_start_routine (gpointer args) G_GNUC_NORETURN;
252 static void *thread_start_routine (gpointer args)
253 {
254         struct _WapiHandle_thread *thread = (struct _WapiHandle_thread *)args;
255         int thr_ret;
256
257         if (!(thread->create_flags & CREATE_NO_DETACH)) {
258                 thr_ret = mono_gc_pthread_detach (pthread_self ());
259                 g_assert (thr_ret == 0);
260         }
261
262         thr_ret = pthread_setspecific (thread_hash_key,
263                                        (void *)thread->handle);
264         if (thr_ret != 0) {
265                 /* This is only supposed to happen when Mono is
266                    shutting down.  We cannot assert on it, though,
267                    because we must not depend on metadata, which is
268                    where the shutdown code is.
269
270                    This is a race condition which arises because
271                    pthreads don't allow creation of suspended threads.
272                    Once Mono is set to shut down no new thread is
273                    allowed to start, even though threads may still be
274                    created.  We emulate suspended threads in this
275                    function by calling _wapi_thread_suspend() below.
276
277                    So it can happen that even though Mono is already
278                    shutting down we still end up here, and at this
279                    point the thread_hash_key might already be
280                    destroyed. */
281                 mono_gc_pthread_exit (NULL);
282         }
283
284         DEBUG ("%s: started thread id %ld", __func__, thread->id);
285
286         /* We set it again here since passing &thread->id to pthread_create is racy
287            as the thread can start running before the value is set.*/
288         thread->id = pthread_self ();
289
290         if (thread->create_flags & CREATE_SUSPENDED) {
291                 _wapi_thread_suspend (thread);
292         }
293         
294         thread_exit (thread->start_routine (thread->start_arg),
295                      thread->handle);
296
297 #ifndef __GNUC__
298         /* Even though we tell gcc that this function doesn't return,
299          * other compilers won't see that.
300          */
301         return(NULL);
302 #endif
303 }
304
305 /**
306  * CreateThread:
307  * @security: Ignored for now.
308  * @stacksize: the size in bytes of the new thread's stack. Use 0 to
309  * default to the normal stack size. (Ignored for now).
310  * @start: The function that the new thread should start with
311  * @param: The parameter to give to @start.
312  * @create: If 0, the new thread is ready to run immediately.  If
313  * %CREATE_SUSPENDED, the new thread will be in the suspended state,
314  * requiring a ResumeThread() call to continue running.
315  * @tid: If non-NULL, the ID of the new thread is stored here.  NB
316  * this is defined as a DWORD (ie 32bit) in the MS API, but we need to
317  * cope with 64 bit IDs for s390x and amd64.
318  *
319  * Creates a new threading handle.
320  *
321  * Return value: a new handle, or NULL
322  */
323 gpointer CreateThread(WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 stacksize,
324                       WapiThreadStart start, gpointer param, guint32 create,
325                       gsize *tid) 
326 {
327         struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
328         pthread_attr_t attr;
329         gpointer handle;
330         gboolean ok;
331         int ret;
332         int thr_ret;
333         int i, unrefs = 0;
334         gpointer ct_ret = NULL;
335         
336         mono_once (&thread_hash_once, thread_hash_init);
337         mono_once (&thread_ops_once, thread_ops_init);
338         
339         if (start == NULL) {
340                 return(NULL);
341         }
342
343         thread_handle.state = THREAD_STATE_START;
344         thread_handle.owned_mutexes = g_ptr_array_new ();
345         thread_handle.create_flags = create;
346         thread_handle.start_routine = start;
347         thread_handle.start_arg = param;
348         
349         handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
350         if (handle == _WAPI_HANDLE_INVALID) {
351                 g_warning ("%s: error creating thread handle", __func__);
352                 SetLastError (ERROR_GEN_FAILURE);
353                 
354                 return (NULL);
355         }
356
357         pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
358                               handle);
359         thr_ret = _wapi_handle_lock_handle (handle);
360         g_assert (thr_ret == 0);
361         
362         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
363                                   (gpointer *)&thread_handle_p);
364         if (ok == FALSE) {
365                 g_warning ("%s: error looking up thread handle %p", __func__,
366                            handle);
367                 SetLastError (ERROR_GEN_FAILURE);
368                 
369                 goto cleanup;
370         }
371
372         /* Hold a reference while the thread is active, because we use
373          * the handle to store thread exit information
374          */
375         _wapi_handle_ref (handle);
376         
377         /* Set a 2M stack size.  This is the default on Linux, but BSD
378          * needs it.  (The original bug report from Martin Dvorak <md@9ll.cz>
379          * set the size to 2M-4k.  I don't know why it's short by 4k, so
380          * I'm leaving it as 2M until I'm told differently.)
381          */
382         thr_ret = pthread_attr_init(&attr);
383         g_assert (thr_ret == 0);
384         
385         /* defaults of 2Mb for 32bits and 4Mb for 64bits */
386         /* temporarily changed to use 1 MB: this allows more threads
387          * to be used, as well as using less virtual memory and so
388          * more is available for the GC heap.
389          */
390         if (stacksize == 0){
391 #if HAVE_VALGRIND_MEMCHECK_H
392                 if (RUNNING_ON_VALGRIND) {
393                         stacksize = 1 << 20;
394                 } else {
395                         stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
396                 }
397 #else
398                 stacksize = (SIZEOF_VOID_P / 4) * 1024 * 1024;
399 #endif
400         }
401
402 #ifdef PTHREAD_STACK_MIN
403         if (stacksize < PTHREAD_STACK_MIN)
404                 stacksize = PTHREAD_STACK_MIN;
405 #endif
406
407 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
408         thr_ret = pthread_attr_setstacksize(&attr, stacksize);
409         g_assert (thr_ret == 0);
410 #endif
411
412         MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
413         thread_handle_p->handle = handle;
414         
415
416         ret = mono_threads_pthread_create (&thread_handle_p->id, &attr,
417                                                                            thread_start_routine, (void *)thread_handle_p);
418
419         if (ret != 0) {
420                 g_warning ("%s: Error creating native thread handle %s (%d)", __func__,
421                            strerror (ret), ret);
422                 SetLastError (ERROR_GEN_FAILURE);
423
424                 /* Two, because of the reference we took above */
425                 unrefs = 2;
426                 
427                 goto cleanup;
428         }
429         ct_ret = handle;
430         
431         DEBUG("%s: Started thread handle %p ID %ld", __func__, handle,
432                   thread_handle_p->id);
433         
434         if (tid != NULL) {
435 #ifdef PTHREAD_POINTER_ID
436                 /* Don't use GPOINTER_TO_UINT here, it can't cope with
437                  * sizeof(void *) > sizeof(uint) when a cast to uint
438                  * would overflow
439                  */
440                 *tid = (gsize)(thread_handle_p->id);
441 #else
442                 *tid = thread_handle_p->id;
443 #endif
444         }
445
446 cleanup:
447         thr_ret = _wapi_handle_unlock_handle (handle);
448         g_assert (thr_ret == 0);
449         pthread_cleanup_pop (0);
450         
451         /* Must not call _wapi_handle_unref() with the shared handles
452          * already locked
453          */
454         for (i = 0; i < unrefs; i++) {
455                 _wapi_handle_unref (handle);
456         }
457         
458         return(ct_ret);
459 }
460
461 /* The only time this function is called when tid != pthread_self ()
462  * is from OpenThread (), so we can fast-path most cases by just
463  * looking up the handle in TLS.  OpenThread () must cope with a NULL
464  * return and do a handle search in that case.
465  */
466 gpointer _wapi_thread_handle_from_id (pthread_t tid)
467 {
468         gpointer ret;
469
470         if (pthread_equal (tid, pthread_self ()) &&
471             (ret = pthread_getspecific (thread_hash_key)) != NULL) {
472                 /* We know the handle */
473
474                 DEBUG ("%s: Returning %p for self thread %ld from TLS",
475                            __func__, ret, tid);
476                 
477                 return(ret);
478         }
479         
480         DEBUG ("%s: Returning NULL for unknown or non-self thread %ld",
481                    __func__, tid);
482                 
483
484         return(NULL);
485 }
486
487 static gboolean find_thread_by_id (gpointer handle, gpointer user_data)
488 {
489         pthread_t tid = (pthread_t)user_data;
490         struct _WapiHandle_thread *thread_handle;
491         gboolean ok;
492         
493         /* Ignore threads that have already exited (ie they are signalled) */
494         if (_wapi_handle_issignalled (handle) == FALSE) {
495                 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
496                                           (gpointer *)&thread_handle);
497                 if (ok == FALSE) {
498                         /* It's possible that the handle has vanished
499                          * during the _wapi_search_handle before it
500                          * gets here, so don't spam the console with
501                          * warnings.
502                          */
503                         return(FALSE);
504                 }
505                 
506                 DEBUG ("%s: looking at thread %ld from process %d", __func__, thread_handle->id, 0);
507
508                 if (pthread_equal (thread_handle->id, tid)) {
509                         DEBUG ("%s: found the thread we are looking for",
510                                    __func__);
511                         return(TRUE);
512                 }
513         }
514         
515         DEBUG ("%s: not found %ld, returning FALSE", __func__, tid);
516         
517         return(FALSE);
518 }
519
520 /* NB tid is 32bit in MS API, but we need 64bit on amd64 and s390x
521  * (and probably others)
522  */
523 gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, gsize tid)
524 {
525         gpointer ret=NULL;
526         
527         mono_once (&thread_hash_once, thread_hash_init);
528         mono_once (&thread_ops_once, thread_ops_init);
529         
530         DEBUG ("%s: looking up thread %"G_GSIZE_FORMAT, __func__, tid);
531
532         ret = _wapi_thread_handle_from_id ((pthread_t)tid);
533         if (ret == NULL) {
534                 /* We need to search for this thread */
535                 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 */
536         } else {
537                 /* if _wapi_search_handle() returns a found handle, it
538                  * refs it itself
539                  */
540                 _wapi_handle_ref (ret);
541         }
542         
543         DEBUG ("%s: returning thread handle %p", __func__, ret);
544         
545         return(ret);
546 }
547
548 /**
549  * ExitThread:
550  * @exitcode: Sets the thread's exit code, which can be read from
551  * another thread with GetExitCodeThread().
552  *
553  * Terminates the calling thread.  A thread can also exit by returning
554  * from its start function. When the last thread in a process
555  * terminates, the process itself terminates.
556  */
557 void ExitThread(guint32 exitcode)
558 {
559         gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
560         
561         if (thread != NULL) {
562                 thread_exit(exitcode, thread);
563         } else {
564                 /* Just blow this thread away */
565                 mono_gc_pthread_exit (NULL);
566         }
567 }
568
569 /**
570  * GetExitCodeThread:
571  * @handle: The thread handle to query
572  * @exitcode: The thread @handle exit code is stored here
573  *
574  * Finds the exit code of @handle, and stores it in @exitcode.  If the
575  * thread @handle is still running, the value stored is %STILL_ACTIVE.
576  *
577  * Return value: %TRUE, or %FALSE on error.
578  */
579 gboolean GetExitCodeThread(gpointer handle, guint32 *exitcode)
580 {
581         struct _WapiHandle_thread *thread_handle;
582         gboolean ok;
583         
584         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
585                                   (gpointer *)&thread_handle);
586         if (ok == FALSE) {
587                 g_warning ("%s: error looking up thread handle %p", __func__,
588                            handle);
589                 return (FALSE);
590         }
591         
592         DEBUG ("%s: Finding exit status for thread handle %p id %ld",
593                    __func__, handle, thread_handle->id);
594
595         if (exitcode == NULL) {
596                 DEBUG ("%s: Nowhere to store exit code", __func__);
597                 return(FALSE);
598         }
599         
600         if (thread_handle->state != THREAD_STATE_EXITED) {
601                 DEBUG ("%s: Thread still active (state %d, exited is %d)",
602                            __func__, thread_handle->state,
603                            THREAD_STATE_EXITED);
604                 *exitcode = STILL_ACTIVE;
605                 return(TRUE);
606         }
607         
608         *exitcode = thread_handle->exitstatus;
609         
610         return(TRUE);
611 }
612
613 /**
614  * GetCurrentThreadId:
615  *
616  * Looks up the thread ID of the current thread.  This ID can be
617  * passed to OpenThread() to create a new handle on this thread.
618  *
619  * Return value: the thread ID.  NB this is defined as DWORD (ie 32
620  * bit) in the MS API, but we need to cope with 64 bit IDs for s390x
621  * and amd64.  This doesn't really break the API, it just embraces and
622  * extends it on 64bit platforms :)
623  */
624 gsize GetCurrentThreadId(void)
625 {
626         pthread_t tid = pthread_self();
627         
628 #ifdef PTHREAD_POINTER_ID
629         /* Don't use GPOINTER_TO_UINT here, it can't cope with
630          * sizeof(void *) > sizeof(uint) when a cast to uint would
631          * overflow
632          */
633         return((gsize)tid);
634 #else
635         return(tid);
636 #endif
637 }
638
639 static gpointer thread_attach(gsize *tid)
640 {
641         struct _WapiHandle_thread thread_handle = {0}, *thread_handle_p;
642         gpointer handle;
643         gboolean ok;
644         int thr_ret;
645         
646         mono_once (&thread_hash_once, thread_hash_init);
647         mono_once (&thread_ops_once, thread_ops_init);
648
649         thread_handle.state = THREAD_STATE_START;
650         thread_handle.owned_mutexes = g_ptr_array_new ();
651
652         handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
653         if (handle == _WAPI_HANDLE_INVALID) {
654                 g_warning ("%s: error creating thread handle", __func__);
655                 
656                 SetLastError (ERROR_GEN_FAILURE);
657                 return (NULL);
658         }
659
660         pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
661                               handle);
662         thr_ret = _wapi_handle_lock_handle (handle);
663         g_assert (thr_ret == 0);
664         
665         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
666                                   (gpointer *)&thread_handle_p);
667         if (ok == FALSE) {
668                 g_warning ("%s: error looking up thread handle %p", __func__,
669                            handle);
670                 
671                 SetLastError (ERROR_GEN_FAILURE);
672                 goto cleanup;
673         }
674
675         /* Hold a reference while the thread is active, because we use
676          * the handle to store thread exit information
677          */
678         _wapi_handle_ref (handle);
679
680         /* suspend_sem is not used for attached threads, but
681          * thread_exit() might try to destroy it
682          */
683         MONO_SEM_INIT (&thread_handle_p->suspend_sem, 0);
684         thread_handle_p->handle = handle;
685         thread_handle_p->id = pthread_self ();
686
687         thr_ret = pthread_setspecific (thread_hash_key, (void *)handle);
688         g_assert (thr_ret == 0);
689
690         thr_ret = pthread_setspecific (thread_attached_key, (void *)handle);
691         g_assert (thr_ret == 0);
692         
693         DEBUG("%s: Attached thread handle %p ID %ld", __func__, handle,
694                   thread_handle_p->id);
695
696         if (tid != NULL) {
697 #ifdef PTHREAD_POINTER_ID
698                 /* Don't use GPOINTER_TO_UINT here, it can't cope with
699                  * sizeof(void *) > sizeof(uint) when a cast to uint
700                  * would overflow
701                  */
702                 *tid = (gsize)(thread_handle_p->id);
703 #else
704                 *tid = thread_handle_p->id;
705 #endif
706         }
707
708 cleanup:
709         thr_ret = _wapi_handle_unlock_handle (handle);
710         g_assert (thr_ret == 0);
711         pthread_cleanup_pop (0);
712         
713         return(handle);
714 }
715
716 gpointer _wapi_thread_duplicate ()
717 {
718         gpointer ret = NULL;
719         
720         mono_once (&thread_hash_once, thread_hash_init);
721         mono_once (&thread_ops_once, thread_ops_init);
722         
723         ret = _wapi_thread_handle_from_id (pthread_self ());
724         if (!ret) {
725                 ret = thread_attach (NULL);
726         } else {
727                 _wapi_handle_ref (ret);
728         }
729         
730         return(ret);
731 }
732
733 /**
734  * GetCurrentThread:
735  *
736  * Looks up the handle associated with the current thread.  Under
737  * Windows this is a pseudohandle, and must be duplicated with
738  * DuplicateHandle() for some operations.
739  *
740  * Return value: The current thread handle, or %NULL on failure.
741  * (Unknown whether Windows has a possible failure here.  It may be
742  * necessary to implement the pseudohandle-constant behaviour).
743  */
744 gpointer GetCurrentThread(void)
745 {
746         mono_once(&thread_hash_once, thread_hash_init);
747         mono_once (&thread_ops_once, thread_ops_init);
748         
749         return(_WAPI_THREAD_CURRENT);
750 }
751
752 /**
753  * ResumeThread:
754  * @handle: the thread handle to resume
755  *
756  * Decrements the suspend count of thread @handle. A thread can only
757  * run if its suspend count is zero.
758  *
759  * Return value: the previous suspend count, or 0xFFFFFFFF on error.
760  */
761 guint32 ResumeThread(gpointer handle)
762 {
763         struct _WapiHandle_thread *thread_handle;
764         gboolean ok;
765         
766         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
767                                   (gpointer *)&thread_handle);
768         if (ok == FALSE) {
769                 g_warning ("%s: error looking up thread handle %p", __func__,
770                            handle);
771                 
772                 return (0xFFFFFFFF);
773         }
774
775         /* This is still a kludge that only copes with starting a
776          * thread that was suspended on create, so don't bother with
777          * the suspend count crap yet
778          */
779         _wapi_thread_resume (thread_handle);
780         return(0xFFFFFFFF);
781 }
782
783 /**
784  * SuspendThread:
785  * @handle: the thread handle to suspend
786  *
787  * Increments the suspend count of thread @handle. A thread can only
788  * run if its suspend count is zero.
789  *
790  * Return value: the previous suspend count, or 0xFFFFFFFF on error.
791  */
792 guint32 SuspendThread(gpointer handle)
793 {
794         return(0xFFFFFFFF);
795 }
796
797 /**
798  * SleepEx:
799  * @ms: The time in milliseconds to suspend for
800  * @alertable: if TRUE, the wait can be interrupted by an APC call
801  *
802  * Suspends execution of the current thread for @ms milliseconds.  A
803  * value of zero causes the thread to relinquish its time slice.  A
804  * value of %INFINITE causes an infinite delay.
805  */
806 guint32 SleepEx(guint32 ms, gboolean alertable)
807 {
808         struct timespec req, rem;
809         int ms_quot, ms_rem;
810         int ret;
811         gpointer current_thread = NULL;
812         
813         DEBUG("%s: Sleeping for %d ms", __func__, ms);
814
815         if (alertable) {
816                 current_thread = _wapi_thread_handle_from_id (pthread_self ());
817                 if (current_thread == NULL) {
818                         SetLastError (ERROR_INVALID_HANDLE);
819                         return(WAIT_FAILED);
820                 }
821                 
822                 if (_wapi_thread_apc_pending (current_thread)) {
823                         _wapi_thread_dispatch_apc_queue (current_thread);
824                         return WAIT_IO_COMPLETION;
825                 }
826         }
827         
828         if(ms==0) {
829                 sched_yield();
830                 return 0;
831         }
832         
833         /* FIXME: check for INFINITE and sleep forever */
834         ms_quot = ms / 1000;
835         ms_rem = ms % 1000;
836         
837         req.tv_sec=ms_quot;
838         req.tv_nsec=ms_rem*1000000;
839         
840 again:
841         memset (&rem, 0, sizeof (rem));
842         ret=nanosleep(&req, &rem);
843
844         if (alertable && _wapi_thread_apc_pending (current_thread)) {
845                 _wapi_thread_dispatch_apc_queue (current_thread);
846                 return WAIT_IO_COMPLETION;
847         }
848         
849         if(ret==-1) {
850                 /* Sleep interrupted with rem time remaining */
851 #ifdef DEBUG_ENABLED
852                 guint32 rems=rem.tv_sec*1000 + rem.tv_nsec/1000000;
853                 
854                 g_message("%s: Still got %d ms to go", __func__, rems);
855 #endif
856                 req=rem;
857                 goto again;
858         }
859
860         return 0;
861 }
862
863 void Sleep(guint32 ms)
864 {
865         SleepEx(ms, FALSE);
866 }
867
868 gboolean _wapi_thread_cur_apc_pending (void)
869 {
870         gpointer thread = _wapi_thread_handle_from_id (pthread_self ());
871         
872         if (thread == NULL) {
873                 SetLastError (ERROR_INVALID_HANDLE);
874                 return(FALSE);
875         }
876         
877         return(_wapi_thread_apc_pending (thread));
878 }
879
880 gboolean _wapi_thread_apc_pending (gpointer handle)
881 {
882         struct _WapiHandle_thread *thread;
883         gboolean ok;
884         
885         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
886                                   (gpointer *)&thread);
887         if (ok == FALSE) {
888                 /* This might happen at process shutdown, as all
889                  * thread handles are forcibly closed.  If a thread
890                  * still has an alertable wait the final
891                  * _wapi_thread_apc_pending check will probably fail
892                  * to find the handle
893                  */
894                 DEBUG ("%s: error looking up thread handle %p", __func__,
895                            handle);
896                 return (FALSE);
897         }
898         
899         return(thread->has_apc || thread->wait_handle == INTERRUPTION_REQUESTED_HANDLE);
900 }
901
902 gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
903 {
904         /* We don't support calling APC functions */
905         struct _WapiHandle_thread *thread;
906         gboolean ok;
907         
908         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
909                                   (gpointer *)&thread);
910         g_assert (ok);
911
912         thread->has_apc = FALSE;
913
914         return(TRUE);
915 }
916
917 /*
918  * In this implementation, APC_CALLBACK is ignored.
919  * if HANDLE refers to the current thread, the only effect this function has 
920  * that if called from a signal handler, and the thread was waiting when receiving 
921  * the signal, the wait will be broken after the signal handler returns.
922  * In this case, this function is async-signal-safe.
923  */
924 guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer handle, 
925                       gpointer param)
926 {
927         struct _WapiHandle_thread *thread_handle;
928         gboolean ok;
929         
930         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
931                                   (gpointer *)&thread_handle);
932         if (ok == FALSE) {
933                 g_warning ("%s: error looking up thread handle %p", __func__,
934                            handle);
935                 return (0);
936         }
937
938         g_assert (thread_handle->id == (pthread_t)GetCurrentThreadId ());
939         /* No locking/memory barriers are needed here */
940         thread_handle->has_apc = TRUE;
941         return(1);
942 }
943
944 /*
945  * wapi_interrupt_thread:
946  *
947  *   This is not part of the WIN32 API.
948  * The state of the thread handle HANDLE is set to 'interrupted' which means that
949  * if the thread calls one of the WaitFor functions, the function will return with 
950  * WAIT_IO_COMPLETION instead of waiting. Also, if the thread was waiting when
951  * this function was called, the wait will be broken.
952  * It is possible that the wait functions return WAIT_IO_COMPLETION, but the
953  * target thread didn't receive the interrupt signal yet, in this case it should
954  * call the wait function again. This essentially means that the target thread will
955  * busy wait until it is ready to process the interruption.
956  * FIXME: get rid of QueueUserAPC and thread->has_apc, SleepEx seems to require it.
957  */
958 void wapi_interrupt_thread (gpointer thread_handle)
959 {
960         struct _WapiHandle_thread *thread;
961         gboolean ok;
962         gpointer prev_handle, wait_handle;
963         guint32 idx;
964         pthread_cond_t *cond;
965         mono_mutex_t *mutex;
966         
967         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
968                                   (gpointer *)&thread);
969         g_assert (ok);
970
971         while (TRUE) {
972                 wait_handle = thread->wait_handle;
973
974                 /* 
975                  * Atomically obtain the handle the thread is waiting on, and
976                  * change it to a flag value.
977                  */
978                 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
979                                                                                                                  INTERRUPTION_REQUESTED_HANDLE, wait_handle);
980                 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
981                         /* Already interrupted */
982                         return;
983                 if (prev_handle == wait_handle)
984                         break;
985
986                 /* Try again */
987         }
988
989         WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread->id););
990
991         if (!wait_handle)
992                 /* Not waiting */
993                 return;
994
995         /* If we reach here, then wait_handle is set to the flag value, 
996          * which means that the target thread is either
997          * - before the first CAS in timedwait, which means it won't enter the
998          * wait.
999          * - it is after the first CAS, so it is already waiting, or it will 
1000          * enter the wait, and it will be interrupted by the broadcast.
1001          */
1002         idx = GPOINTER_TO_UINT(wait_handle);
1003         cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
1004         mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
1005
1006         mono_mutex_lock (mutex);
1007         mono_cond_broadcast (cond);
1008         mono_mutex_unlock (mutex);
1009
1010         /* ref added by set_wait_handle */
1011         _wapi_handle_unref (wait_handle);
1012 }
1013
1014
1015 gpointer wapi_prepare_interrupt_thread (gpointer thread_handle)
1016 {
1017         struct _WapiHandle_thread *thread;
1018         gboolean ok;
1019         gpointer prev_handle, wait_handle;
1020         
1021         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1022                                   (gpointer *)&thread);
1023         g_assert (ok);
1024
1025         while (TRUE) {
1026                 wait_handle = thread->wait_handle;
1027
1028                 /* 
1029                  * Atomically obtain the handle the thread is waiting on, and
1030                  * change it to a flag value.
1031                  */
1032                 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1033                                                                                                                  INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1034                 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1035                         /* Already interrupted */
1036                         return 0;
1037                 if (prev_handle == wait_handle)
1038                         break;
1039
1040                 /* Try again */
1041         }
1042
1043         WAIT_DEBUG (printf ("%p: state -> INTERRUPTED.\n", thread->id););
1044
1045         return wait_handle;
1046 }
1047
1048 void wapi_finish_interrupt_thread (gpointer wait_handle)
1049 {
1050         pthread_cond_t *cond;
1051         mono_mutex_t *mutex;
1052         guint32 idx;
1053
1054         if (!wait_handle)
1055                 /* Not waiting */
1056                 return;
1057
1058         /* If we reach here, then wait_handle is set to the flag value, 
1059          * which means that the target thread is either
1060          * - before the first CAS in timedwait, which means it won't enter the
1061          * wait.
1062          * - it is after the first CAS, so it is already waiting, or it will 
1063          * enter the wait, and it will be interrupted by the broadcast.
1064          */
1065         idx = GPOINTER_TO_UINT(wait_handle);
1066         cond = &_WAPI_PRIVATE_HANDLES(idx).signal_cond;
1067         mutex = &_WAPI_PRIVATE_HANDLES(idx).signal_mutex;
1068
1069         mono_mutex_lock (mutex);
1070         mono_cond_broadcast (cond);
1071         mono_mutex_unlock (mutex);
1072
1073         /* ref added by set_wait_handle */
1074         _wapi_handle_unref (wait_handle);
1075 }
1076
1077
1078 /*
1079  * wapi_self_interrupt:
1080  *
1081  *   This is not part of the WIN32 API.
1082  * Set the 'interrupted' state of the calling thread if it's NULL.
1083  */
1084 void wapi_self_interrupt (void)
1085 {
1086         struct _WapiHandle_thread *thread;
1087         gboolean ok;
1088         gpointer prev_handle, wait_handle;
1089         gpointer thread_handle;
1090
1091
1092         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1093         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1094                                                           (gpointer *)&thread);
1095         g_assert (ok);
1096
1097         while (TRUE) {
1098                 wait_handle = thread->wait_handle;
1099
1100                 /*
1101                  * Atomically obtain the handle the thread is waiting on, and
1102                  * change it to a flag value.
1103                  */
1104                 prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1105                                                                                                                  INTERRUPTION_REQUESTED_HANDLE, wait_handle);
1106                 if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1107                         /* Already interrupted */
1108                         goto cleanup;
1109                 /*We did not get interrupted*/
1110                 if (prev_handle == wait_handle)
1111                         break;
1112
1113                 /* Try again */
1114         }
1115
1116         if (wait_handle) {
1117                 /* ref added by set_wait_handle */
1118                 _wapi_handle_unref (wait_handle);
1119         }
1120
1121 cleanup:
1122         _wapi_handle_unref (thread_handle);
1123 }
1124
1125 /*
1126  * wapi_clear_interruption:
1127  *
1128  *   This is not part of the WIN32 API. 
1129  * Clear the 'interrupted' state of the calling thread.
1130  * This function is signal safe
1131  */
1132 void wapi_clear_interruption (void)
1133 {
1134         struct _WapiHandle_thread *thread;
1135         gboolean ok;
1136         gpointer prev_handle;
1137         gpointer thread_handle;
1138
1139         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1140         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1141                                                           (gpointer *)&thread);
1142         g_assert (ok);
1143
1144         prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1145                                                                                                          NULL, INTERRUPTION_REQUESTED_HANDLE);
1146         if (prev_handle == INTERRUPTION_REQUESTED_HANDLE)
1147                 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1148
1149         _wapi_handle_unref (thread_handle);
1150 }
1151
1152 char* wapi_current_thread_desc ()
1153 {
1154         struct _WapiHandle_thread *thread;
1155         int i;
1156         gboolean ok;
1157         gpointer handle;
1158         gpointer thread_handle;
1159         GString* text;
1160         char *res;
1161
1162         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1163         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1164                                                           (gpointer *)&thread);
1165         if (!ok)
1166                 return g_strdup_printf ("thread handle %p state : lookup failure", thread_handle);
1167
1168         handle = thread->wait_handle;
1169         text = g_string_new (0);
1170         g_string_append_printf (text, "thread handle %p state : ", thread_handle);
1171
1172         if (!handle)
1173                 g_string_append_printf (text, "not waiting");
1174         else if (handle == INTERRUPTION_REQUESTED_HANDLE)
1175                 g_string_append_printf (text, "interrupted state");
1176         else
1177                 g_string_append_printf (text, "waiting on %p : %s ", handle, _wapi_handle_typename[_wapi_handle_type (handle)]);
1178         g_string_append_printf (text, " owns (");
1179         for (i = 0; i < thread->owned_mutexes->len; i++) {
1180                 gpointer mutex = g_ptr_array_index (thread->owned_mutexes, i);
1181                 if (i > 0)
1182                         g_string_append_printf (text, ", %p", mutex);
1183                 else
1184                         g_string_append_printf (text, "%p", mutex);
1185         }
1186         g_string_append_printf (text, ")");
1187
1188         res = text->str;
1189         g_string_free (text, FALSE);
1190         return res;
1191 }
1192
1193 /**
1194  * wapi_thread_set_wait_handle:
1195  *
1196  *   Set the wait handle for the current thread to HANDLE. Return TRUE on success, FALSE
1197  * if the thread is in interrupted state, and cannot start waiting.
1198  */
1199 gboolean wapi_thread_set_wait_handle (gpointer handle)
1200 {
1201         struct _WapiHandle_thread *thread;
1202         gboolean ok;
1203         gpointer prev_handle;
1204         gpointer thread_handle;
1205
1206         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1207         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1208                                                           (gpointer *)&thread);
1209         g_assert (ok);
1210
1211         prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1212                                                                                                          handle, NULL);
1213         _wapi_handle_unref (thread_handle);
1214
1215         if (prev_handle == NULL) {
1216                 /* thread->wait_handle acts as an additional reference to the handle */
1217                 _wapi_handle_ref (handle);
1218
1219                 WAIT_DEBUG (printf ("%p: state -> WAITING.\n", GetCurrentThreadId ()););
1220         } else {
1221                 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE);
1222                 WAIT_DEBUG (printf ("%p: unable to set state to WAITING.\n", GetCurrentThreadId ()););
1223         }
1224
1225         return prev_handle == NULL;
1226 }
1227
1228 /**
1229  * wapi_thread_clear_wait_handle:
1230  *
1231  *   Clear the wait handle of the current thread.
1232  */
1233 void wapi_thread_clear_wait_handle (gpointer handle)
1234 {
1235         struct _WapiHandle_thread *thread;
1236         gboolean ok;
1237         gpointer prev_handle;
1238         gpointer thread_handle;
1239
1240         thread_handle = OpenThread (0, 0, GetCurrentThreadId ());
1241         ok = _wapi_lookup_handle (thread_handle, WAPI_HANDLE_THREAD,
1242                                                           (gpointer *)&thread);
1243         g_assert (ok);
1244
1245         prev_handle = InterlockedCompareExchangePointer (&thread->wait_handle,
1246                                                                                                          NULL, handle);
1247
1248         if (prev_handle == handle) {
1249                 _wapi_handle_unref (handle);
1250                 WAIT_DEBUG (printf ("%p: state -> NORMAL.\n", GetCurrentThreadId ()););
1251         } else {
1252                 /*It can be NULL if it was asynchronously cleared*/
1253                 g_assert (prev_handle == INTERRUPTION_REQUESTED_HANDLE || prev_handle == NULL);
1254                 WAIT_DEBUG (printf ("%p: finished waiting.\n", GetCurrentThreadId ()););
1255         }
1256
1257         _wapi_handle_unref (thread_handle);
1258 }
1259
1260 void _wapi_thread_own_mutex (gpointer mutex)
1261 {
1262         struct _WapiHandle_thread *thread_handle;
1263         gboolean ok;
1264         gpointer thread;
1265         
1266         thread = _wapi_thread_handle_from_id (pthread_self ());
1267         if (thread == NULL) {
1268                 g_warning ("%s: error looking up thread by ID", __func__);
1269                 return;
1270         }
1271
1272         ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1273                                   (gpointer *)&thread_handle);
1274         if (ok == FALSE) {
1275                 g_warning ("%s: error looking up thread handle %p", __func__,
1276                            thread);
1277                 return;
1278         }
1279
1280         _wapi_handle_ref (mutex);
1281         
1282         g_ptr_array_add (thread_handle->owned_mutexes, mutex);
1283 }
1284
1285 void _wapi_thread_disown_mutex (gpointer mutex)
1286 {
1287         struct _WapiHandle_thread *thread_handle;
1288         gboolean ok;
1289         gpointer thread;
1290
1291         thread = _wapi_thread_handle_from_id (pthread_self ());
1292         if (thread == NULL) {
1293                 g_warning ("%s: error looking up thread by ID", __func__);
1294                 return;
1295         }
1296
1297         ok = _wapi_lookup_handle (thread, WAPI_HANDLE_THREAD,
1298                                   (gpointer *)&thread_handle);
1299         if (ok == FALSE) {
1300                 g_warning ("%s: error looking up thread handle %p", __func__,
1301                            thread);
1302                 return;
1303         }
1304
1305         _wapi_handle_unref (mutex);
1306         
1307         g_ptr_array_remove (thread_handle->owned_mutexes, mutex);
1308 }