2 * timed-thread.c: Implementation of timed thread joining
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002 Ximian, Inc.
17 #include "timed-thread.h"
19 #include "mono-mutex.h"
24 * Implementation of timed thread joining from the P1003.1d/D14 (July 1999)
25 * draft spec, figure B-6.
28 static pthread_key_t timed_thread_key;
29 static pthread_once_t timed_thread_once = PTHREAD_ONCE_INIT;
31 static void timed_thread_init(void)
33 pthread_key_create(&timed_thread_key, NULL);
36 void _wapi_timed_thread_exit(guint32 exitstatus)
41 if((specific = pthread_getspecific(timed_thread_key)) == NULL) {
42 /* Handle cases which won't happen with correct usage.
47 thread=(TimedThread *)specific;
49 mono_mutex_lock(&thread->join_mutex);
51 /* Tell a joiner that we're exiting.
54 g_message(G_GNUC_PRETTY_FUNCTION
55 ": Setting thread %p id %ld exit status to %d",
56 thread, thread->id, exitstatus);
59 thread->exitstatus=exitstatus;
62 if(thread->exit_routine!=NULL) {
63 thread->exit_routine(exitstatus, thread->exit_userdata);
66 pthread_cond_signal(&thread->exit_cond);
67 mono_mutex_unlock(&thread->join_mutex);
69 /* Call pthread_exit() to call destructors and really exit the
75 /* Routine to establish thread specific data value and run the actual
76 * thread start routine which was supplied to timed_thread_create()
78 static void *timed_thread_start_routine(gpointer args) G_GNUC_NORETURN;
79 static void *timed_thread_start_routine(gpointer args)
81 TimedThread *thread = (TimedThread *)args;
83 pthread_once(&timed_thread_once, timed_thread_init);
84 pthread_setspecific(timed_thread_key, (void *)thread);
85 pthread_detach(thread->id);
86 _wapi_timed_thread_exit(thread->start_routine(thread->arg));
89 /* Allocate a thread which can be used with timed_thread_join().
91 int _wapi_timed_thread_create(TimedThread **threadp,
92 const pthread_attr_t *attr,
93 guint32 (*start_routine)(gpointer),
94 void (*exit_routine)(guint32, gpointer),
95 gpointer arg, gpointer exit_userdata)
100 thread=(TimedThread *)g_new0(TimedThread, 1);
102 mono_mutex_init(&thread->join_mutex, NULL);
103 pthread_cond_init(&thread->exit_cond, NULL);
104 thread->start_routine = start_routine;
105 thread->exit_routine = exit_routine;
107 thread->exit_userdata = exit_userdata;
108 thread->exitstatus = 0;
109 thread->exiting = FALSE;
113 if((result = pthread_create(&thread->id, attr,
114 timed_thread_start_routine,
115 (void *)thread)) != 0) {
123 int _wapi_timed_thread_join(TimedThread *thread, struct timespec *timeout,
128 mono_mutex_lock(&thread->join_mutex);
131 /* Wait until the thread announces that it's exiting, or until
134 while(result == 0 && !thread->exiting) {
135 if(timeout == NULL) {
136 result = pthread_cond_wait(&thread->exit_cond,
137 &thread->join_mutex);
139 result = pthread_cond_timedwait(&thread->exit_cond,
145 mono_mutex_unlock(&thread->join_mutex);
146 if(result == 0 && thread->exiting) {
147 if(exitstatus!=NULL) {
148 *exitstatus = thread->exitstatus;
154 void _wapi_timed_thread_destroy (TimedThread *thread)
156 mono_mutex_destroy (&thread->join_mutex);
157 pthread_cond_destroy (&thread->exit_cond);