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 self
->cancel_error
= error
;
162 self
->canceled
= true;
163 pthread_exit(PTHREAD_CANCELED
);
169 _pthread_is_canceled(pthread_t thread
)
171 const int flags
= (PTHREAD_CANCEL_ENABLE
|_PTHREAD_CANCEL_PENDING
);
172 int state
= os_atomic_load2o(thread
, cancel_state
, seq_cst
);
173 return (state
& flags
) == flags
;
176 PTHREAD_NOEXPORT_VARIANT
178 _pthread_testcancel(int isconforming
)
180 pthread_t self
= pthread_self();
181 if (_pthread_is_canceled(self
)) {
183 self
->canceled
= (isconforming
!= PTHREAD_CONFORM_DARWIN_LEGACY
);
185 pthread_exit(isconforming
? PTHREAD_CANCELED
: NULL
);
191 _pthread_markcancel_if_canceled(pthread_t thread
, mach_port_t kport
)
193 const int flags
= (PTHREAD_CANCEL_ENABLE
|_PTHREAD_CANCEL_PENDING
);
194 int state
= os_atomic_load2o(thread
, cancel_state
, relaxed
);
195 if ((state
& flags
) == flags
&& __unix_conforming
) {
196 __pthread_markcancel(kport
);
200 /* When a thread exits set the cancellation state to DISABLE and DEFERRED */
203 _pthread_setcancelstate_exit(pthread_t thread
, void *value_ptr
)
205 _pthread_update_cancel_state(thread
,
206 _PTHREAD_CANCEL_STATE_MASK
| _PTHREAD_CANCEL_TYPE_MASK
,
207 PTHREAD_CANCEL_DISABLE
| PTHREAD_CANCEL_DEFERRED
);
210 #endif /* !BUILDING_VARIANT ] */
213 * Query/update the cancelability 'state' of a thread
215 PTHREAD_ALWAYS_INLINE
217 _pthread_setcancelstate_internal(int state
, int *oldstateptr
, int conforming
)
219 pthread_t self
= pthread_self();
222 case PTHREAD_CANCEL_ENABLE
:
224 __pthread_canceled(1);
227 case PTHREAD_CANCEL_DISABLE
:
229 __pthread_canceled(2);
236 int oldstate
= _pthread_update_cancel_state(self
, _PTHREAD_CANCEL_STATE_MASK
, state
);
238 *oldstateptr
= oldstate
& _PTHREAD_CANCEL_STATE_MASK
;
241 /* See if we need to 'die' now... */
242 _pthread_testcancel(PTHREAD_CONFORM_DARWIN_LEGACY
);
247 PTHREAD_NOEXPORT_VARIANT
249 pthread_setcancelstate(int state
, int *oldstate
)
252 if (__unix_conforming
== 0) {
253 __unix_conforming
= 1;
255 return (_pthread_setcancelstate_internal(state
, oldstate
, 1));
256 #else /* __DARWIN_UNIX03 */
257 return (_pthread_setcancelstate_internal(state
, oldstate
, 0));
258 #endif /* __DARWIN_UNIX03 */
262 * Query/update the cancelability 'type' of a thread
264 PTHREAD_NOEXPORT_VARIANT
266 pthread_setcanceltype(int type
, int *oldtype
)
271 if (__unix_conforming
== 0)
272 __unix_conforming
= 1;
273 #endif /* __DARWIN_UNIX03 */
275 if ((type
!= PTHREAD_CANCEL_DEFERRED
) &&
276 (type
!= PTHREAD_CANCEL_ASYNCHRONOUS
))
278 self
= pthread_self();
279 int oldstate
= _pthread_update_cancel_state(self
, _PTHREAD_CANCEL_TYPE_MASK
, type
);
281 *oldtype
= oldstate
& _PTHREAD_CANCEL_TYPE_MASK
;
284 /* See if we need to 'die' now... */
285 _pthread_testcancel(PTHREAD_CONFORM_DARWIN_LEGACY
);
286 #endif /* __DARWIN_UNIX03 */
292 pthread_sigmask(int how
, const sigset_t
* set
, sigset_t
* oset
)
297 if (__pthread_sigmask(how
, set
, oset
) == -1) {
301 #else /* __DARWIN_UNIX03 */
302 return(__pthread_sigmask(how
, set
, oset
));
303 #endif /* __DARWIN_UNIX03 */
306 #ifndef BUILDING_VARIANT /* [ */
308 typedef struct pthread_join_context_s
{
312 semaphore_t custom_stack_sema
;
314 } pthread_join_context_s
, *pthread_join_context_t
;
317 _pthread_get_exit_value(pthread_t thread
)
319 if (__unix_conforming
&& _pthread_is_canceled(thread
)) {
320 return PTHREAD_CANCELED
;
322 return thread
->tl_exit_value
;
325 // called with _pthread_list_lock held
328 _pthread_joiner_prepost_wake(pthread_t thread
)
330 pthread_join_context_t ctx
= thread
->tl_join_ctx
;
331 semaphore_t sema
= MACH_PORT_NULL
;
333 if (thread
->tl_joinable
) {
334 sema
= ctx
->custom_stack_sema
;
335 thread
->tl_joinable
= false;
337 ctx
->detached
= true;
338 thread
->tl_join_ctx
= NULL
;
340 if (ctx
->value_ptr
) *ctx
->value_ptr
= _pthread_get_exit_value(thread
);
345 _pthread_joiner_abort_wait(pthread_t thread
, pthread_join_context_t ctx
)
347 bool aborted
= false;
349 _PTHREAD_LOCK(_pthread_list_lock
);
350 if (!ctx
->detached
&& thread
->tl_exit_gate
!= MACH_PORT_DEAD
) {
352 * _pthread_joiner_prepost_wake() didn't happen
353 * allow another thread to join
355 PTHREAD_DEBUG_ASSERT(thread
->tl_join_ctx
== ctx
);
356 thread
->tl_join_ctx
= NULL
;
357 thread
->tl_exit_gate
= MACH_PORT_NULL
;
360 _PTHREAD_UNLOCK(_pthread_list_lock
);
365 _pthread_joiner_wait(pthread_t thread
, pthread_join_context_t ctx
, int conforming
)
367 uint32_t *exit_gate
= &thread
->tl_exit_gate
;
368 int ulock_op
= UL_UNFAIR_LOCK
| ULF_NO_ERRNO
;
370 if (conforming
== PTHREAD_CONFORM_UNIX03_CANCELABLE
) {
371 ulock_op
|= ULF_WAIT_CANCEL_POINT
;
375 uint32_t cur
= os_atomic_load(exit_gate
, acquire
);
376 if (cur
== MACH_PORT_DEAD
) {
379 if (os_unlikely(cur
!= ctx
->kport
)) {
380 PTHREAD_CLIENT_CRASH(cur
, "pthread_join() state corruption");
382 int ret
= __ulock_wait(ulock_op
, exit_gate
, ctx
->kport
, 0);
391 * As specified, either the pthread_join() call is canceled, or it
392 * succeeds, but not both. The difference is obvious to the
393 * application, since either a cancellation handler is run or
394 * pthread_join() returns.
396 * When __ulock_wait() returns EINTR, we check if we have been
397 * canceled, and if we have, we try to abort the wait.
399 * If we can't, it means the other thread finished the join while we
400 * were being canceled and commited the waiter to return from
401 * pthread_join(). Returning from the join then takes precedence
402 * over the cancelation which will be acted upon at the next
405 if (conforming
== PTHREAD_CONFORM_UNIX03_CANCELABLE
&&
406 _pthread_is_canceled(ctx
->waiter
)) {
407 if (_pthread_joiner_abort_wait(thread
, ctx
)) {
408 ctx
->waiter
->canceled
= true;
409 pthread_exit(PTHREAD_CANCELED
);
416 bool cleanup
= false;
418 _PTHREAD_LOCK(_pthread_list_lock
);
419 // If pthread_detach() was called, we can't safely dereference the thread,
420 // else, decide who gets to deallocate the thread (see _pthread_terminate).
421 if (!ctx
->detached
) {
422 PTHREAD_DEBUG_ASSERT(thread
->tl_join_ctx
== ctx
);
423 thread
->tl_join_ctx
= NULL
;
424 cleanup
= thread
->tl_joiner_cleans_up
;
426 _PTHREAD_UNLOCK(_pthread_list_lock
);
429 _pthread_deallocate(thread
, false);
434 PTHREAD_NOEXPORT PTHREAD_NOINLINE
436 _pthread_join(pthread_t thread
, void **value_ptr
, int conforming
)
438 pthread_t self
= pthread_self();
439 pthread_join_context_s ctx
= {
441 .value_ptr
= value_ptr
,
442 .kport
= MACH_PORT_NULL
,
443 .custom_stack_sema
= MACH_PORT_NULL
,
448 if (!_pthread_validate_thread_and_list_lock(thread
)) {
452 if (!thread
->tl_joinable
|| (thread
->tl_join_ctx
!= NULL
)) {
454 } else if (thread
== self
||
455 (self
->tl_join_ctx
&& self
->tl_join_ctx
->waiter
== thread
)) {
457 } else if (thread
->tl_exit_gate
== MACH_PORT_DEAD
) {
458 TAILQ_REMOVE(&__pthread_head
, thread
, tl_plist
);
459 PTHREAD_DEBUG_ASSERT(thread
->tl_joiner_cleans_up
);
460 thread
->tl_joinable
= false;
461 if (value_ptr
) *value_ptr
= _pthread_get_exit_value(thread
);
463 ctx
.kport
= _pthread_kernel_thread(thread
);
464 thread
->tl_exit_gate
= ctx
.kport
;
465 thread
->tl_join_ctx
= &ctx
;
466 if (thread
->tl_has_custom_stack
) {
467 ctx
.custom_stack_sema
= (semaphore_t
)os_get_cached_semaphore();
470 _PTHREAD_UNLOCK(_pthread_list_lock
);
473 if (ctx
.kport
== MACH_PORT_NULL
) {
474 _pthread_deallocate(thread
, false);
476 res
= _pthread_joiner_wait(thread
, &ctx
, conforming
);
479 if (res
== 0 && ctx
.custom_stack_sema
&& !ctx
.detached
) {
480 // threads with a custom stack need to make sure _pthread_terminate
481 // returned before the joiner is unblocked, the joiner may quickly
482 // deallocate the stack with rather dire consequences.
484 // When we reach this point we know the pthread_join has to succeed
485 // so this can't be a cancelation point.
487 kr
= __semwait_signal_nocancel(ctx
.custom_stack_sema
, 0, 0, 0, 0, 0);
488 } while (kr
!= KERN_SUCCESS
);
490 if (ctx
.custom_stack_sema
) {
491 os_put_cached_semaphore(ctx
.custom_stack_sema
);
496 #endif /* !BUILDING_VARIANT ] */
497 #endif /* VARIANT_CANCELABLE */
500 * Wait for a thread to terminate and obtain its exit value.
503 pthread_join(pthread_t thread
, void **value_ptr
)
505 int conforming
= _pthread_conformance();
506 if (conforming
== PTHREAD_CONFORM_UNIX03_CANCELABLE
) {
507 _pthread_testcancel(conforming
);
509 return _pthread_join(thread
, value_ptr
, conforming
);
513 pthread_cond_wait(pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
515 return _pthread_cond_wait(cond
, mutex
, NULL
, 0, _pthread_conformance());
519 pthread_cond_timedwait(pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
520 const struct timespec
*abstime
)
522 return _pthread_cond_wait(cond
, mutex
, abstime
, 0, _pthread_conformance());
526 sigwait(const sigset_t
* set
, int * sig
)
529 int err
= 0, conformance
= _pthread_conformance();
531 if (__unix_conforming
== 0)
532 __unix_conforming
= 1;
534 if (conformance
== PTHREAD_CONFORM_UNIX03_CANCELABLE
) {
535 _pthread_testcancel(conformance
);
538 if (__sigwait(set
, sig
) == -1) {
541 if (conformance
== PTHREAD_CONFORM_UNIX03_CANCELABLE
) {
542 _pthread_testcancel(conformance
);
546 * EINTR that isn't a result of pthread_cancel()
547 * is translated to 0.
554 #else /* __DARWIN_UNIX03 */
555 if (__sigwait(set
, sig
) == -1) {
557 * EINTR that isn't a result of pthread_cancel()
558 * is translated to 0.
560 if (errno
!= EINTR
) {
566 #endif /* __DARWIN_UNIX03 */