5 #include "timed-thread.h"
7 #include "mono-mutex.h"
12 * Implementation of timed thread joining from the P1003.1d/D14 (July 1999)
13 * draft spec, figure B-6.
16 static pthread_key_t timed_thread_key;
17 static pthread_once_t timed_thread_once = PTHREAD_ONCE_INIT;
19 static void timed_thread_init(void)
21 pthread_key_create(&timed_thread_key, NULL);
24 void _wapi_timed_thread_exit(guint32 exitstatus)
29 if((specific = pthread_getspecific(timed_thread_key)) == NULL) {
30 /* Handle cases which won't happen with correct usage.
35 thread=(TimedThread *)specific;
37 mono_mutex_lock(&thread->join_mutex);
39 /* Tell a joiner that we're exiting.
42 g_message(G_GNUC_PRETTY_FUNCTION
43 ": Setting thread %p id %ld exit status to %d",
44 thread, thread->id, exitstatus);
47 thread->exitstatus=exitstatus;
50 if(thread->exit_routine!=NULL) {
51 thread->exit_routine(exitstatus, thread->exit_userdata);
54 pthread_cond_signal(&thread->exit_cond);
55 mono_mutex_unlock(&thread->join_mutex);
57 /* Call pthread_exit() to call destructors and really exit the
63 /* Routine to establish thread specific data value and run the actual
64 * thread start routine which was supplied to timed_thread_create()
66 static void *timed_thread_start_routine(gpointer args) G_GNUC_NORETURN;
67 static void *timed_thread_start_routine(gpointer args)
69 TimedThread *thread = (TimedThread *)args;
71 pthread_once(&timed_thread_once, timed_thread_init);
72 pthread_setspecific(timed_thread_key, (void *)thread);
73 _wapi_timed_thread_exit(thread->start_routine(thread->arg));
76 /* Allocate a thread which can be used with timed_thread_join().
78 int _wapi_timed_thread_create(TimedThread **threadp,
79 const pthread_attr_t *attr,
80 guint32 (*start_routine)(gpointer),
81 void (*exit_routine)(guint32, gpointer),
82 gpointer arg, gpointer exit_userdata)
87 thread=(TimedThread *)g_new0(TimedThread, 1);
89 mono_mutex_init(&thread->join_mutex, NULL);
90 pthread_cond_init(&thread->exit_cond, NULL);
91 thread->start_routine = start_routine;
92 thread->exit_routine = exit_routine;
94 thread->exit_userdata = exit_userdata;
95 thread->exitstatus = 0;
96 thread->exiting = FALSE;
100 if((result = pthread_create(&thread->id, attr,
101 timed_thread_start_routine,
102 (void *)thread)) != 0) {
107 pthread_detach(thread->id);
111 int _wapi_timed_thread_join(TimedThread *thread, struct timespec *timeout,
116 mono_mutex_lock(&thread->join_mutex);
119 /* Wait until the thread announces that it's exiting, or until
122 while(result == 0 && !thread->exiting) {
123 if(timeout == NULL) {
124 result = pthread_cond_wait(&thread->exit_cond,
125 &thread->join_mutex);
127 result = pthread_cond_timedwait(&thread->exit_cond,
133 mono_mutex_unlock(&thread->join_mutex);
134 if(result == 0 && thread->exiting) {
135 if(exitstatus!=NULL) {
136 *exitstatus = thread->exitstatus;