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