2 * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by John Birrell.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * $DragonFly: src/lib/libthread_xu/thread/thr_join.c,v 1.7 2006/04/06 13:03:09 davidxu Exp $
35 #include "namespace.h"
36 #include <machine/tls.h>
40 #include "un-namespace.h"
42 #include "thr_private.h"
44 static int join_common(pthread_t
, void **, const struct timespec
*);
46 static void backout_join(void *arg
)
48 struct pthread
*curthread
= tls_get_curthread();
49 struct pthread
*pthread
= (struct pthread
*)arg
;
51 THREAD_LIST_LOCK(curthread
);
52 pthread
->joiner
= NULL
;
53 THREAD_LIST_UNLOCK(curthread
);
57 _pthread_join(pthread_t pthread
, void **thread_return
)
59 return (join_common(pthread
, thread_return
, NULL
));
63 _pthread_timedjoin_np(pthread_t pthread
, void **thread_return
,
64 const struct timespec
*abstime
)
66 if (abstime
== NULL
|| abstime
->tv_sec
< 0 || abstime
->tv_nsec
< 0 ||
67 abstime
->tv_nsec
>= 1000000000)
70 return (join_common(pthread
, thread_return
, abstime
));
74 join_common(pthread_t pthread
, void **thread_return
,
75 const struct timespec
*abstime
)
77 struct pthread
*curthread
= tls_get_curthread();
78 struct timespec ts
, ts2
, *tsp
;
87 if (pthread
== curthread
)
90 THREAD_LIST_LOCK(curthread
);
91 if ((ret
= _thr_find_thread(curthread
, pthread
, 1)) != 0) {
93 } else if ((pthread
->tlflags
& TLFLAGS_DETACHED
) != 0) {
95 } else if (pthread
->joiner
!= NULL
) {
96 /* Multiple joiners are not supported. */
100 THREAD_LIST_UNLOCK(curthread
);
103 /* Set the running thread to be the joiner: */
104 pthread
->joiner
= curthread
;
106 THREAD_LIST_UNLOCK(curthread
);
108 THR_CLEANUP_PUSH(curthread
, backout_join
, pthread
);
109 oldcancel
= _thr_cancel_enter(curthread
);
111 while ((state
= pthread
->state
) != PS_DEAD
) {
112 if (abstime
!= NULL
) {
113 clock_gettime(CLOCK_REALTIME
, &ts
);
114 TIMESPEC_SUB(&ts2
, abstime
, &ts
);
115 if (ts2
.tv_sec
< 0) {
122 ret
= _thr_umtx_wait(&pthread
->state
, state
, tsp
,
124 if (ret
== ETIMEDOUT
)
128 _thr_cancel_leave(curthread
, oldcancel
);
129 THR_CLEANUP_POP(curthread
, 0);
131 if (ret
== ETIMEDOUT
) {
132 THREAD_LIST_LOCK(curthread
);
133 pthread
->joiner
= NULL
;
134 THREAD_LIST_UNLOCK(curthread
);
138 THREAD_LIST_LOCK(curthread
);
139 pthread
->tlflags
|= TLFLAGS_DETACHED
;
140 pthread
->joiner
= NULL
;
141 THR_GCLIST_ADD(pthread
);
142 THREAD_LIST_UNLOCK(curthread
);
144 if (thread_return
!= NULL
)
145 *thread_return
= tmp
;
150 __strong_reference(_pthread_join
, pthread_join
);
151 __strong_reference(_pthread_timedjoin_np
, pthread_timedjoin_np
);