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