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