2 * Copyright (c) 2000-2013 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
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 <sys/ulock.h>
64 #include <machine/vmparam.h>
65 #include <mach/vm_statistics.h>
67 extern int _pthread_cond_wait(pthread_cond_t
*cond
,
68 pthread_mutex_t
*mutex
,
69 const struct timespec
*abstime
,
72 extern int __sigwait(const sigset_t
*set
, int *sig
);
73 extern int __pthread_sigmask(int, const sigset_t
*, sigset_t
*);
74 extern int __pthread_markcancel(mach_port_t
);
75 extern int __pthread_canceled(int);
76 extern int __semwait_signal_nocancel(int, int, int, int, __int64_t
, __int32_t
);
80 int _pthread_join(pthread_t thread
, void **value_ptr
, int conforming
);
83 _pthread_conformance(void)
86 if (__unix_conforming
== 0)
87 __unix_conforming
= 1;
88 #ifdef VARIANT_CANCELABLE
89 return PTHREAD_CONFORM_UNIX03_CANCELABLE
;
90 #else /* !VARIANT_CANCELABLE */
91 return PTHREAD_CONFORM_UNIX03_NOCANCEL
;
93 #else /* __DARWIN_UNIX03 */
94 return PTHREAD_CONFORM_DARWIN_LEGACY
;
95 #endif /* __DARWIN_UNIX03 */
98 #ifndef VARIANT_CANCELABLE
100 PTHREAD_ALWAYS_INLINE
102 _pthread_update_cancel_state(pthread_t thread
, int mask
, int state
)
104 int oldstate
, newstate
;
105 os_atomic_rmw_loop2o(thread
, cancel_state
, oldstate
, newstate
, seq_cst
, {
116 PTHREAD_NOEXPORT_VARIANT
118 pthread_cancel(pthread_t thread
)
121 if (__unix_conforming
== 0)
122 __unix_conforming
= 1;
123 #endif /* __DARWIN_UNIX03 */
125 if (!_pthread_is_valid(thread
, NULL
)) {
129 /* if the thread is a workqueue thread, then return error */
130 if (thread
->wqthread
!= 0) {
134 int state
= os_atomic_or2o(thread
, cancel_state
, _PTHREAD_CANCEL_PENDING
, relaxed
);
135 if (state
& PTHREAD_CANCEL_ENABLE
) {
136 mach_port_t kport
= _pthread_kernel_thread(thread
);
137 if (kport
) __pthread_markcancel(kport
);
139 #else /* __DARWIN_UNIX03 */
140 thread
->cancel_state
|= _PTHREAD_CANCEL_PENDING
;
141 #endif /* __DARWIN_UNIX03 */
147 pthread_testcancel(void)
149 _pthread_testcancel(_pthread_conformance());
152 #ifndef BUILDING_VARIANT /* [ */
154 PTHREAD_NOEXPORT_VARIANT
156 _pthread_exit_if_canceled(int error
)
158 if (((error
& 0xff) == EINTR
) && __unix_conforming
&& (__pthread_canceled(0) == 0)) {
159 pthread_t self
= pthread_self();
161 _pthread_validate_signature(self
);
162 self
->cancel_error
= error
;
163 self
->canceled
= true;
164 pthread_exit(PTHREAD_CANCELED
);
170 _pthread_is_canceled(pthread_t thread
)
172 const int flags
= (PTHREAD_CANCEL_ENABLE
|_PTHREAD_CANCEL_PENDING
);
173 int state
= os_atomic_load2o(thread
, cancel_state
, seq_cst
);
174 return (state
& flags
) == flags
;
177 PTHREAD_NOEXPORT_VARIANT
179 _pthread_testcancel(int isconforming
)
181 pthread_t self
= pthread_self();
182 if (_pthread_is_canceled(self
)) {
183 _pthread_validate_signature(self
);
185 self
->canceled
= (isconforming
!= PTHREAD_CONFORM_DARWIN_LEGACY
);
187 pthread_exit(isconforming
? PTHREAD_CANCELED
: NULL
);
193 _pthread_markcancel_if_canceled(pthread_t thread
, mach_port_t kport
)
195 const int flags
= (PTHREAD_CANCEL_ENABLE
|_PTHREAD_CANCEL_PENDING
);
196 int state
= os_atomic_load2o(thread
, cancel_state
, relaxed
);
197 if ((state
& flags
) == flags
&& __unix_conforming
) {
198 __pthread_markcancel(kport
);
202 /* When a thread exits set the cancellation state to DISABLE and DEFERRED */
205 _pthread_setcancelstate_exit(pthread_t thread
, void *value_ptr
)
207 _pthread_update_cancel_state(thread
,
208 _PTHREAD_CANCEL_STATE_MASK
| _PTHREAD_CANCEL_TYPE_MASK
,
209 PTHREAD_CANCEL_DISABLE
| PTHREAD_CANCEL_DEFERRED
);
212 #endif /* !BUILDING_VARIANT ] */
215 * Query/update the cancelability 'state' of a thread
217 PTHREAD_ALWAYS_INLINE
219 _pthread_setcancelstate_internal(int state
, int *oldstateptr
, int conforming
)
221 pthread_t self
= pthread_self();
223 _pthread_validate_signature(self
);
226 case PTHREAD_CANCEL_ENABLE
:
228 __pthread_canceled(1);
231 case PTHREAD_CANCEL_DISABLE
:
233 __pthread_canceled(2);
240 int oldstate
= _pthread_update_cancel_state(self
, _PTHREAD_CANCEL_STATE_MASK
, state
);
242 *oldstateptr
= oldstate
& _PTHREAD_CANCEL_STATE_MASK
;
245 /* See if we need to 'die' now... */
246 _pthread_testcancel(PTHREAD_CONFORM_DARWIN_LEGACY
);
251 PTHREAD_NOEXPORT_VARIANT
253 pthread_setcancelstate(int state
, int *oldstate
)
256 if (__unix_conforming
== 0) {
257 __unix_conforming
= 1;
259 return (_pthread_setcancelstate_internal(state
, oldstate
, 1));
260 #else /* __DARWIN_UNIX03 */
261 return (_pthread_setcancelstate_internal(state
, oldstate
, 0));
262 #endif /* __DARWIN_UNIX03 */
266 * Query/update the cancelability 'type' of a thread
268 PTHREAD_NOEXPORT_VARIANT
270 pthread_setcanceltype(int type
, int *oldtype
)
275 if (__unix_conforming
== 0)
276 __unix_conforming
= 1;
277 #endif /* __DARWIN_UNIX03 */
279 if ((type
!= PTHREAD_CANCEL_DEFERRED
) &&
280 (type
!= PTHREAD_CANCEL_ASYNCHRONOUS
))
282 self
= pthread_self();
283 _pthread_validate_signature(self
);
284 int oldstate
= _pthread_update_cancel_state(self
, _PTHREAD_CANCEL_TYPE_MASK
, type
);
286 *oldtype
= oldstate
& _PTHREAD_CANCEL_TYPE_MASK
;
289 /* See if we need to 'die' now... */
290 _pthread_testcancel(PTHREAD_CONFORM_DARWIN_LEGACY
);
291 #endif /* __DARWIN_UNIX03 */
297 pthread_sigmask(int how
, const sigset_t
* set
, sigset_t
* oset
)
302 if (__pthread_sigmask(how
, set
, oset
) == -1) {
306 #else /* __DARWIN_UNIX03 */
307 return(__pthread_sigmask(how
, set
, oset
));
308 #endif /* __DARWIN_UNIX03 */
311 #ifndef BUILDING_VARIANT /* [ */
313 typedef struct pthread_join_context_s
{
317 semaphore_t custom_stack_sema
;
319 } pthread_join_context_s
, *pthread_join_context_t
;
322 _pthread_get_exit_value(pthread_t thread
)
324 if (__unix_conforming
&& _pthread_is_canceled(thread
)) {
325 return PTHREAD_CANCELED
;
327 return thread
->tl_exit_value
;
330 // called with _pthread_list_lock held
333 _pthread_joiner_prepost_wake(pthread_t thread
)
335 pthread_join_context_t ctx
= thread
->tl_join_ctx
;
336 semaphore_t sema
= MACH_PORT_NULL
;
338 if (thread
->tl_joinable
) {
339 sema
= ctx
->custom_stack_sema
;
340 thread
->tl_joinable
= false;
342 ctx
->detached
= true;
343 thread
->tl_join_ctx
= NULL
;
345 if (ctx
->value_ptr
) *ctx
->value_ptr
= _pthread_get_exit_value(thread
);
350 _pthread_joiner_abort_wait(pthread_t thread
, pthread_join_context_t ctx
)
352 bool aborted
= false;
354 _PTHREAD_LOCK(_pthread_list_lock
);
355 if (!ctx
->detached
&& thread
->tl_exit_gate
!= MACH_PORT_DEAD
) {
357 * _pthread_joiner_prepost_wake() didn't happen
358 * allow another thread to join
360 PTHREAD_DEBUG_ASSERT(thread
->tl_join_ctx
== ctx
);
361 thread
->tl_join_ctx
= NULL
;
362 thread
->tl_exit_gate
= MACH_PORT_NULL
;
365 _PTHREAD_UNLOCK(_pthread_list_lock
);
370 _pthread_joiner_wait(pthread_t thread
, pthread_join_context_t ctx
, int conforming
)
372 uint32_t *exit_gate
= &thread
->tl_exit_gate
;
373 int ulock_op
= UL_UNFAIR_LOCK
| ULF_NO_ERRNO
;
375 if (conforming
== PTHREAD_CONFORM_UNIX03_CANCELABLE
) {
376 ulock_op
|= ULF_WAIT_CANCEL_POINT
;
380 uint32_t cur
= os_atomic_load(exit_gate
, acquire
);
381 if (cur
== MACH_PORT_DEAD
) {
384 if (os_unlikely(cur
!= ctx
->kport
)) {
385 PTHREAD_CLIENT_CRASH(cur
, "pthread_join() state corruption");
387 int ret
= __ulock_wait(ulock_op
, exit_gate
, ctx
->kport
, 0);
396 * As specified, either the pthread_join() call is canceled, or it
397 * succeeds, but not both. The difference is obvious to the
398 * application, since either a cancellation handler is run or
399 * pthread_join() returns.
401 * When __ulock_wait() returns EINTR, we check if we have been
402 * canceled, and if we have, we try to abort the wait.
404 * If we can't, it means the other thread finished the join while we
405 * were being canceled and commited the waiter to return from
406 * pthread_join(). Returning from the join then takes precedence
407 * over the cancelation which will be acted upon at the next
410 if (conforming
== PTHREAD_CONFORM_UNIX03_CANCELABLE
&&
411 _pthread_is_canceled(ctx
->waiter
)) {
412 if (_pthread_joiner_abort_wait(thread
, ctx
)) {
413 ctx
->waiter
->canceled
= true;
414 pthread_exit(PTHREAD_CANCELED
);
421 bool cleanup
= false;
423 _PTHREAD_LOCK(_pthread_list_lock
);
424 // If pthread_detach() was called, we can't safely dereference the thread,
425 // else, decide who gets to deallocate the thread (see _pthread_terminate).
426 if (!ctx
->detached
) {
427 PTHREAD_DEBUG_ASSERT(thread
->tl_join_ctx
== ctx
);
428 thread
->tl_join_ctx
= NULL
;
429 cleanup
= thread
->tl_joiner_cleans_up
;
431 _PTHREAD_UNLOCK(_pthread_list_lock
);
434 _pthread_deallocate(thread
, false);
439 PTHREAD_NOEXPORT PTHREAD_NOINLINE
441 _pthread_join(pthread_t thread
, void **value_ptr
, int conforming
)
443 pthread_t self
= pthread_self();
444 pthread_join_context_s ctx
= {
446 .value_ptr
= value_ptr
,
447 .kport
= MACH_PORT_NULL
,
448 .custom_stack_sema
= MACH_PORT_NULL
,
453 if (!_pthread_validate_thread_and_list_lock(thread
)) {
456 _pthread_validate_signature(self
);
458 if (!thread
->tl_joinable
|| (thread
->tl_join_ctx
!= NULL
)) {
460 } else if (thread
== self
||
461 (self
->tl_join_ctx
&& self
->tl_join_ctx
->waiter
== thread
)) {
463 } else if (thread
->tl_exit_gate
== MACH_PORT_DEAD
) {
464 TAILQ_REMOVE(&__pthread_head
, thread
, tl_plist
);
465 PTHREAD_DEBUG_ASSERT(thread
->tl_joiner_cleans_up
);
466 thread
->tl_joinable
= false;
467 if (value_ptr
) *value_ptr
= _pthread_get_exit_value(thread
);
469 ctx
.kport
= _pthread_kernel_thread(thread
);
470 thread
->tl_exit_gate
= ctx
.kport
;
471 thread
->tl_join_ctx
= &ctx
;
472 if (thread
->tl_has_custom_stack
) {
473 ctx
.custom_stack_sema
= (semaphore_t
)os_get_cached_semaphore();
476 _PTHREAD_UNLOCK(_pthread_list_lock
);
479 if (ctx
.kport
== MACH_PORT_NULL
) {
480 _pthread_deallocate(thread
, false);
482 res
= _pthread_joiner_wait(thread
, &ctx
, conforming
);
485 if (res
== 0 && ctx
.custom_stack_sema
&& !ctx
.detached
) {
486 // threads with a custom stack need to make sure _pthread_terminate
487 // returned before the joiner is unblocked, the joiner may quickly
488 // deallocate the stack with rather dire consequences.
490 // When we reach this point we know the pthread_join has to succeed
491 // so this can't be a cancelation point.
493 kr
= __semwait_signal_nocancel(ctx
.custom_stack_sema
, 0, 0, 0, 0, 0);
494 } while (kr
!= KERN_SUCCESS
);
496 if (ctx
.custom_stack_sema
) {
497 os_put_cached_semaphore(ctx
.custom_stack_sema
);
502 #endif /* !BUILDING_VARIANT ] */
503 #endif /* VARIANT_CANCELABLE */
506 * Wait for a thread to terminate and obtain its exit value.
509 pthread_join(pthread_t thread
, void **value_ptr
)
511 int conforming
= _pthread_conformance();
512 if (conforming
== PTHREAD_CONFORM_UNIX03_CANCELABLE
) {
513 _pthread_testcancel(conforming
);
515 return _pthread_join(thread
, value_ptr
, conforming
);
519 pthread_cond_wait(pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
521 return _pthread_cond_wait(cond
, mutex
, NULL
, 0, _pthread_conformance());
525 pthread_cond_timedwait(pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
526 const struct timespec
*abstime
)
528 return _pthread_cond_wait(cond
, mutex
, abstime
, 0, _pthread_conformance());
532 sigwait(const sigset_t
* set
, int * sig
)
535 int err
= 0, conformance
= _pthread_conformance();
537 if (__unix_conforming
== 0)
538 __unix_conforming
= 1;
540 if (conformance
== PTHREAD_CONFORM_UNIX03_CANCELABLE
) {
541 _pthread_testcancel(conformance
);
544 if (__sigwait(set
, sig
) == -1) {
547 if (conformance
== PTHREAD_CONFORM_UNIX03_CANCELABLE
) {
548 _pthread_testcancel(conformance
);
552 * EINTR that isn't a result of pthread_cancel()
553 * is translated to 0.
560 #else /* __DARWIN_UNIX03 */
561 if (__sigwait(set
, sig
) == -1) {
563 * EINTR that isn't a result of pthread_cancel()
564 * is translated to 0.
566 if (errno
!= EINTR
) {
572 #endif /* __DARWIN_UNIX03 */