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_or2o(thread
, cancel_state
,
195 _PTHREAD_CANCEL_INITIALIZED
, relaxed
);
196 if ((state
& flags
) == flags
&& __unix_conforming
) {
197 __pthread_markcancel(kport
);
201 /* When a thread exits set the cancellation state to DISABLE and DEFERRED */
204 _pthread_setcancelstate_exit(pthread_t thread
, void *value_ptr
)
206 _pthread_update_cancel_state(thread
,
207 _PTHREAD_CANCEL_STATE_MASK
| _PTHREAD_CANCEL_TYPE_MASK
,
208 PTHREAD_CANCEL_DISABLE
| PTHREAD_CANCEL_DEFERRED
);
211 #endif /* !BUILDING_VARIANT ] */
214 * Query/update the cancelability 'state' of a thread
216 PTHREAD_ALWAYS_INLINE
218 _pthread_setcancelstate_internal(int state
, int *oldstateptr
, int conforming
)
220 pthread_t self
= pthread_self();
223 case PTHREAD_CANCEL_ENABLE
:
225 __pthread_canceled(1);
228 case PTHREAD_CANCEL_DISABLE
:
230 __pthread_canceled(2);
237 int oldstate
= _pthread_update_cancel_state(self
, _PTHREAD_CANCEL_STATE_MASK
, state
);
239 *oldstateptr
= oldstate
& _PTHREAD_CANCEL_STATE_MASK
;
242 /* See if we need to 'die' now... */
243 _pthread_testcancel(PTHREAD_CONFORM_DARWIN_LEGACY
);
248 PTHREAD_NOEXPORT_VARIANT
250 pthread_setcancelstate(int state
, int *oldstate
)
253 if (__unix_conforming
== 0) {
254 __unix_conforming
= 1;
256 return (_pthread_setcancelstate_internal(state
, oldstate
, 1));
257 #else /* __DARWIN_UNIX03 */
258 return (_pthread_setcancelstate_internal(state
, oldstate
, 0));
259 #endif /* __DARWIN_UNIX03 */
263 * Query/update the cancelability 'type' of a thread
265 PTHREAD_NOEXPORT_VARIANT
267 pthread_setcanceltype(int type
, int *oldtype
)
272 if (__unix_conforming
== 0)
273 __unix_conforming
= 1;
274 #endif /* __DARWIN_UNIX03 */
276 if ((type
!= PTHREAD_CANCEL_DEFERRED
) &&
277 (type
!= PTHREAD_CANCEL_ASYNCHRONOUS
))
279 self
= pthread_self();
280 int oldstate
= _pthread_update_cancel_state(self
, _PTHREAD_CANCEL_TYPE_MASK
, type
);
282 *oldtype
= oldstate
& _PTHREAD_CANCEL_TYPE_MASK
;
285 /* See if we need to 'die' now... */
286 _pthread_testcancel(PTHREAD_CONFORM_DARWIN_LEGACY
);
287 #endif /* __DARWIN_UNIX03 */
293 pthread_sigmask(int how
, const sigset_t
* set
, sigset_t
* oset
)
298 if (__pthread_sigmask(how
, set
, oset
) == -1) {
302 #else /* __DARWIN_UNIX03 */
303 return(__pthread_sigmask(how
, set
, oset
));
304 #endif /* __DARWIN_UNIX03 */
307 #ifndef BUILDING_VARIANT /* [ */
309 typedef struct pthread_join_context_s
{
313 semaphore_t custom_stack_sema
;
315 } pthread_join_context_s
, *pthread_join_context_t
;
318 _pthread_get_exit_value(pthread_t thread
)
320 if (__unix_conforming
&& _pthread_is_canceled(thread
)) {
321 return PTHREAD_CANCELED
;
323 return thread
->tl_exit_value
;
326 // called with _pthread_list_lock held
329 _pthread_joiner_prepost_wake(pthread_t thread
)
331 pthread_join_context_t ctx
= thread
->tl_join_ctx
;
332 semaphore_t sema
= MACH_PORT_NULL
;
334 if (thread
->tl_joinable
) {
335 sema
= ctx
->custom_stack_sema
;
336 thread
->tl_joinable
= false;
338 ctx
->detached
= true;
339 thread
->tl_join_ctx
= NULL
;
341 if (ctx
->value_ptr
) *ctx
->value_ptr
= _pthread_get_exit_value(thread
);
346 _pthread_joiner_abort_wait(pthread_t thread
, pthread_join_context_t ctx
)
348 bool aborted
= false;
350 _PTHREAD_LOCK(_pthread_list_lock
);
351 if (!ctx
->detached
&& thread
->tl_exit_gate
!= MACH_PORT_DEAD
) {
353 * _pthread_joiner_prepost_wake() didn't happen
354 * allow another thread to join
357 PTHREAD_ASSERT(thread
->tl_join_ctx
== ctx
);
359 thread
->tl_join_ctx
= NULL
;
360 thread
->tl_exit_gate
= MACH_PORT_NULL
;
363 _PTHREAD_UNLOCK(_pthread_list_lock
);
368 _pthread_joiner_wait(pthread_t thread
, pthread_join_context_t ctx
, int conforming
)
370 uint32_t *exit_gate
= &thread
->tl_exit_gate
;
371 int ulock_op
= UL_UNFAIR_LOCK
| ULF_NO_ERRNO
;
373 if (conforming
== PTHREAD_CONFORM_UNIX03_CANCELABLE
) {
374 ulock_op
|= ULF_WAIT_CANCEL_POINT
;
378 uint32_t cur
= os_atomic_load(exit_gate
, acquire
);
379 if (cur
== MACH_PORT_DEAD
) {
382 if (os_unlikely(cur
!= ctx
->kport
)) {
383 PTHREAD_CLIENT_CRASH(cur
, "pthread_join() state corruption");
385 int ret
= __ulock_wait(ulock_op
, exit_gate
, ctx
->kport
, 0);
394 * As specified, either the pthread_join() call is canceled, or it
395 * succeeds, but not both. The difference is obvious to the
396 * application, since either a cancellation handler is run or
397 * pthread_join() returns.
399 * When __ulock_wait() returns EINTR, we check if we have been
400 * canceled, and if we have, we try to abort the wait.
402 * If we can't, it means the other thread finished the join while we
403 * were being canceled and commited the waiter to return from
404 * pthread_join(). Returning from the join then takes precedence
405 * over the cancelation which will be acted upon at the next
408 if (conforming
== PTHREAD_CONFORM_UNIX03_CANCELABLE
&&
409 _pthread_is_canceled(ctx
->waiter
)) {
410 if (_pthread_joiner_abort_wait(thread
, ctx
)) {
411 ctx
->waiter
->canceled
= true;
412 pthread_exit(PTHREAD_CANCELED
);
419 bool cleanup
= false;
421 _PTHREAD_LOCK(_pthread_list_lock
);
422 // If pthread_detach() was called, we can't safely dereference the thread,
423 // else, decide who gets to deallocate the thread (see _pthread_terminate).
424 if (!ctx
->detached
) {
426 PTHREAD_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
)) {
457 if (!thread
->tl_joinable
|| (thread
->tl_join_ctx
!= NULL
)) {
459 } else if (thread
== self
||
460 (self
->tl_join_ctx
&& self
->tl_join_ctx
->waiter
== thread
)) {
462 } else if (thread
->tl_exit_gate
== MACH_PORT_DEAD
) {
463 TAILQ_REMOVE(&__pthread_head
, thread
, tl_plist
);
465 PTHREAD_ASSERT(thread
->tl_joiner_cleans_up
);
467 thread
->tl_joinable
= false;
468 if (value_ptr
) *value_ptr
= _pthread_get_exit_value(thread
);
470 ctx
.kport
= _pthread_kernel_thread(thread
);
471 thread
->tl_exit_gate
= ctx
.kport
;
472 thread
->tl_join_ctx
= &ctx
;
473 if (thread
->tl_has_custom_stack
) {
474 ctx
.custom_stack_sema
= (semaphore_t
)os_get_cached_semaphore();
477 _PTHREAD_UNLOCK(_pthread_list_lock
);
480 if (ctx
.kport
== MACH_PORT_NULL
) {
481 _pthread_deallocate(thread
, false);
483 res
= _pthread_joiner_wait(thread
, &ctx
, conforming
);
486 if (res
== 0 && ctx
.custom_stack_sema
&& !ctx
.detached
) {
487 // threads with a custom stack need to make sure _pthread_terminate
488 // returned before the joiner is unblocked, the joiner may quickly
489 // deallocate the stack with rather dire consequences.
491 // When we reach this point we know the pthread_join has to succeed
492 // so this can't be a cancelation point.
494 kr
= __semwait_signal_nocancel(ctx
.custom_stack_sema
, 0, 0, 0, 0, 0);
495 } while (kr
!= KERN_SUCCESS
);
497 if (ctx
.custom_stack_sema
) {
498 os_put_cached_semaphore(ctx
.custom_stack_sema
);
503 #endif /* !BUILDING_VARIANT ] */
504 #endif /* VARIANT_CANCELABLE */
507 * Wait for a thread to terminate and obtain its exit value.
510 pthread_join(pthread_t thread
, void **value_ptr
)
512 int conforming
= _pthread_conformance();
513 if (conforming
== PTHREAD_CONFORM_UNIX03_CANCELABLE
) {
514 _pthread_testcancel(conforming
);
516 return _pthread_join(thread
, value_ptr
, conforming
);
520 pthread_cond_wait(pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
522 return _pthread_cond_wait(cond
, mutex
, NULL
, 0, _pthread_conformance());
526 pthread_cond_timedwait(pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
527 const struct timespec
*abstime
)
529 return _pthread_cond_wait(cond
, mutex
, abstime
, 0, _pthread_conformance());
533 sigwait(const sigset_t
* set
, int * sig
)
536 int err
= 0, conformance
= _pthread_conformance();
538 if (__unix_conforming
== 0)
539 __unix_conforming
= 1;
541 if (conformance
== PTHREAD_CONFORM_UNIX03_CANCELABLE
) {
542 _pthread_testcancel(conformance
);
545 if (__sigwait(set
, sig
) == -1) {
548 if (conformance
== PTHREAD_CONFORM_UNIX03_CANCELABLE
) {
549 _pthread_testcancel(conformance
);
553 * EINTR that isn't a result of pthread_cancel()
554 * is translated to 0.
561 #else /* __DARWIN_UNIX03 */
562 if (__sigwait(set
, sig
) == -1) {
564 * EINTR that isn't a result of pthread_cancel()
565 * is translated to 0.
567 if (errno
!= EINTR
) {
573 #endif /* __DARWIN_UNIX03 */