8 #include "timed-thread.h"
10 #include "mono-mutex.h"
15 * Implementation of timed thread joining from the P1003.1d/D14 (July 1999)
16 * draft spec, figure B-6.
19 static pthread_key_t timed_thread_key;
20 static pthread_once_t timed_thread_once = PTHREAD_ONCE_INIT;
22 static void timed_thread_init(void)
24 pthread_key_create(&timed_thread_key, NULL);
27 void _wapi_timed_thread_exit(guint32 exitstatus)
32 if((specific = pthread_getspecific(timed_thread_key)) == NULL) {
33 /* Handle cases which won't happen with correct usage.
38 thread=(TimedThread *)specific;
40 mono_mutex_lock(&thread->join_mutex);
42 /* Tell a joiner that we're exiting.
45 g_message(G_GNUC_PRETTY_FUNCTION
46 ": Setting thread %p id %ld exit status to %d",
47 thread, thread->id, exitstatus);
50 thread->exitstatus=exitstatus;
53 if(thread->exit_routine!=NULL) {
54 thread->exit_routine(exitstatus, thread->exit_userdata);
57 pthread_cond_signal(&thread->exit_cond);
58 mono_mutex_unlock(&thread->join_mutex);
60 /* Call pthread_exit() to call destructors and really exit the
66 /* Routine to establish thread specific data value and run the actual
67 * thread start routine which was supplied to timed_thread_create()
69 static void *timed_thread_start_routine(gpointer args) G_GNUC_NORETURN;
70 static void *timed_thread_start_routine(gpointer args)
72 TimedThread *thread = (TimedThread *)args;
74 pthread_once(&timed_thread_once, timed_thread_init);
75 pthread_setspecific(timed_thread_key, (void *)thread);
76 pthread_detach(thread->id);
77 _wapi_timed_thread_exit(thread->start_routine(thread->arg));
80 /* Allocate a thread which can be used with timed_thread_join().
82 int _wapi_timed_thread_create(TimedThread **threadp,
83 const pthread_attr_t *attr,
84 guint32 (*start_routine)(gpointer),
85 void (*exit_routine)(guint32, gpointer),
86 gpointer arg, gpointer exit_userdata)
91 thread=(TimedThread *)g_new0(TimedThread, 1);
93 mono_mutex_init(&thread->join_mutex, NULL);
94 pthread_cond_init(&thread->exit_cond, NULL);
95 thread->start_routine = start_routine;
96 thread->exit_routine = exit_routine;
98 thread->exit_userdata = exit_userdata;
99 thread->exitstatus = 0;
100 thread->exiting = FALSE;
104 if((result = pthread_create(&thread->id, attr,
105 timed_thread_start_routine,
106 (void *)thread)) != 0) {
114 int _wapi_timed_thread_join(TimedThread *thread, struct timespec *timeout,
119 mono_mutex_lock(&thread->join_mutex);
122 /* Wait until the thread announces that it's exiting, or until
125 while(result == 0 && !thread->exiting) {
126 if(timeout == NULL) {
127 result = pthread_cond_wait(&thread->exit_cond,
128 &thread->join_mutex);
130 result = pthread_cond_timedwait(&thread->exit_cond,
136 mono_mutex_unlock(&thread->join_mutex);
137 if(result == 0 && thread->exiting) {
138 if(exitstatus!=NULL) {
139 *exitstatus = thread->exitstatus;
145 void _wapi_timed_thread_destroy (TimedThread *thread)
147 mono_mutex_destroy (&thread->join_mutex);
148 pthread_cond_destroy (&thread->exit_cond);