2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
27 * Permission to use, copy, modify, and distribute this software and
28 * its documentation for any purpose and without fee is hereby granted,
29 * provided that the above copyright notice appears in all copies and
30 * that both the copyright notice and this permission notice appear in
31 * supporting documentation.
33 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
34 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
35 * FOR A PARTICULAR PURPOSE.
37 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
38 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
39 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
40 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
41 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
49 * POSIX Pthread Library
52 #include "pthread_internals.h"
55 #include <stdio.h> /* For printf(). */
57 #include <errno.h> /* For __mach_errno_addr() prototype. */
60 #include <sys/resource.h>
61 #include <sys/sysctl.h>
62 #include <sys/queue.h>
63 #include <machine/vmparam.h>
64 #include <mach/vm_statistics.h>
66 extern int __unix_conforming
;
67 extern void __posix_join_cleanup(void *arg
);
68 extern pthread_lock_t _pthread_list_lock
;
69 extern void _pthread_testcancel(pthread_t thread
, int isconforming
);
70 extern int _pthread_reap_thread(pthread_t th
, mach_port_t kernel_thread
, void **value_ptr
, int conforming
);
71 extern int _pthread_cond_wait(pthread_cond_t
*cond
,
72 pthread_mutex_t
*mutex
,
73 const struct timespec
*abstime
,
76 extern int __sigwait(const sigset_t
*set
, int *sig
);
79 * Wait for a thread to terminate and obtain its exit value.
82 pthread_join(pthread_t thread
,
85 kern_return_t kern_res
;
87 pthread_t self
= pthread_self();
91 task_t tself
= mach_task_self();
94 if (__unix_conforming
== 0)
95 __unix_conforming
= 1;
97 #ifdef VARIANT_CANCELABLE
98 _pthread_testcancel(self
, 1);
99 #endif /* VARIANT_CANCELABLE */
100 #endif /* __DARWIN_UNIX03 */
102 if ((res
= _pthread_lookup_thread(thread
, &kthport
, 1)) != 0)
105 if (thread
->sig
== _PTHREAD_SIG
)
107 if (thread
->newstyle
== 0) {
108 semaphore_t death
= new_sem_from_pool(); /* in case we need it */
111 if ((thread
->detached
& PTHREAD_CREATE_JOINABLE
) &&
112 thread
->death
== SEMAPHORE_NULL
)
115 assert(thread
->joiner
== NULL
);
116 if (thread
!= self
&& (self
== NULL
|| self
->joiner
!= thread
))
118 int already_exited
= (thread
->detached
& _PTHREAD_EXITED
);
120 thread
->death
= death
;
121 thread
->joiner
= self
;
122 UNLOCK(thread
->lock
);
127 /* Wait for it to signal... */
128 pthread_cleanup_push(__posix_join_cleanup
, (void *)thread
);
130 res
= __semwait_signal(death
, 0, 0, 0, 0, 0);
131 } while ((res
< 0) && (errno
== EINTR
));
132 pthread_cleanup_pop(0);
134 #else /* __DARWIN_UNIX03 */
135 /* Wait for it to signal... */
137 PTHREAD_MACH_CALL(semaphore_wait(death
), kern_res
);
138 } while (kern_res
!= KERN_SUCCESS
);
139 #endif /* __DARWIN_UNIX03 */
142 LOCK(_pthread_list_lock
);
143 TAILQ_REMOVE(&__pthread_head
, thread
, plist
);
145 __kdebug_trace(0x9000010, thread
, 0, 0, 16, 0);
147 UNLOCK(_pthread_list_lock
);
148 /* ... and wait for it to really be dead */
149 while ((res
= _pthread_reap_thread(thread
,
150 thread
->kernel_thread
,
151 value_ptr
, __unix_conforming
)) == EAGAIN
)
157 UNLOCK(thread
->lock
);
161 UNLOCK(thread
->lock
);
164 restore_sem_to_pool(death
);
169 semaphore_t death
= SEMAPHORE_NULL
; /* in case we need it */
170 semaphore_t joinsem
= SEMAPHORE_NULL
;
172 if (thread
->joiner_notify
== NULL
)
173 death
= new_sem_from_pool();
176 if ((thread
->detached
& PTHREAD_CREATE_JOINABLE
) &&
177 (thread
->joiner
== NULL
))
179 assert(thread
->kernel_thread
== kthport
);
180 if (thread
!= self
&& (self
== NULL
|| self
->joiner
!= thread
))
184 if (thread
->joiner_notify
== NULL
) {
185 if (death
== SEMAPHORE_NULL
)
187 thread
->joiner_notify
= death
;
188 death
= SEMAPHORE_NULL
;
190 joinsem
= thread
->joiner_notify
;
191 thread
->joiner
= self
;
192 UNLOCK(thread
->lock
);
194 if (death
!= SEMAPHORE_NULL
) {
195 restore_sem_to_pool(death
);
196 death
= SEMAPHORE_NULL
;
199 /* Wait for it to signal... */
200 pthread_cleanup_push(__posix_join_cleanup
, (void *)thread
);
202 res
= __semwait_signal(joinsem
, 0, 0, 0, 0, 0);
203 } while ((res
< 0) && (errno
== EINTR
));
204 pthread_cleanup_pop(0);
205 #else /* __DARWIN_UNIX03 */
206 /* Wait for it to signal... */
208 PTHREAD_MACH_CALL(semaphore_wait(joinsem
), kern_res
);
209 } while (kern_res
!= KERN_SUCCESS
);
210 #endif /* __DARWIN_UNIX03 */
212 restore_sem_to_pool(joinsem
);
213 res
= _pthread_join_cleanup(thread
, value_ptr
, conforming
);
215 UNLOCK(thread
->lock
);
219 UNLOCK(thread
->lock
);
222 if (death
!= SEMAPHORE_NULL
)
223 restore_sem_to_pool(death
);
225 }/* end of new style */
231 pthread_cond_wait(pthread_cond_t
*cond
,
232 pthread_mutex_t
*mutex
)
237 if (__unix_conforming
== 0)
238 __unix_conforming
= 1;
240 #ifdef VARIANT_CANCELABLE
242 #else /* !VARIANT_CANCELABLE */
244 #endif /* VARIANT_CANCELABLE */
245 #else /* __DARWIN_UNIX03 */
247 #endif /* __DARWIN_UNIX03 */
248 return (_pthread_cond_wait(cond
, mutex
, (struct timespec
*)NULL
, 0, conforming
));
252 pthread_cond_timedwait(pthread_cond_t
*cond
,
253 pthread_mutex_t
*mutex
,
254 const struct timespec
*abstime
)
258 if (__unix_conforming
== 0)
259 __unix_conforming
= 1;
261 #ifdef VARIANT_CANCELABLE
263 #else /* !VARIANT_CANCELABLE */
265 #endif /* VARIANT_CANCELABLE */
266 #else /* __DARWIN_UNIX03 */
268 #endif /* __DARWIN_UNIX03 */
270 return (_pthread_cond_wait(cond
, mutex
, abstime
, 0, conforming
));
274 sigwait(const sigset_t
* set
, int * sig
)
279 if (__unix_conforming
== 0)
280 __unix_conforming
= 1;
282 #ifdef VARIANT_CANCELABLE
283 _pthread_testcancel(pthread_self(), 1);
284 #endif /* VARIANT_CANCELABLE */
286 if (__sigwait(set
, sig
) == -1) {
290 #else /* __DARWIN_UNIX03 */
291 return(__sigwait(set
, sig
));
293 #endif /* __DARWIN_UNIX03 */