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