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 #ifndef BUILDING_VARIANT /* [ */
71 _pthread_update_cancel_state(pthread_t thread
, int mask
, int state
)
73 uint16_t oldstate
, newstate
;
74 os_atomic_rmw_loop(&thread
->cancel_state
, oldstate
, newstate
, relaxed
, {
82 /* When a thread exits set the cancellation state to DISABLE and DEFERRED */
84 _pthread_setcancelstate_exit(pthread_t thread
, void *value_ptr
)
86 _pthread_update_cancel_state(thread
,
87 _PTHREAD_CANCEL_STATE_MASK
| _PTHREAD_CANCEL_TYPE_MASK
,
88 PTHREAD_CANCEL_DISABLE
| PTHREAD_CANCEL_DEFERRED
|
89 _PTHREAD_CANCEL_EXITING
);
95 PTHREAD_NOEXPORT_VARIANT
97 pthread_cancel(pthread_t thread
)
99 if (!_pthread_is_valid(thread
, NULL
)) {
103 /* if the thread is a workqueue thread, then return error */
104 if (thread
->wqthread
!= 0) {
107 int state
= os_atomic_or(&thread
->cancel_state
, _PTHREAD_CANCEL_PENDING
, relaxed
);
108 if (state
& PTHREAD_CANCEL_ENABLE
) {
109 mach_port_t kport
= _pthread_tsd_slot(thread
, MACH_THREAD_SELF
);
110 if (kport
) __pthread_markcancel(kport
);
116 * Query/update the cancelability 'state' of a thread
118 PTHREAD_NOEXPORT_VARIANT
120 pthread_setcancelstate(int state
, int *oldstateptr
)
122 pthread_t self
= pthread_self();
124 _pthread_validate_signature(self
);
127 case PTHREAD_CANCEL_ENABLE
:
128 __pthread_canceled(1);
130 case PTHREAD_CANCEL_DISABLE
:
131 __pthread_canceled(2);
137 int oldstate
= _pthread_update_cancel_state(self
, _PTHREAD_CANCEL_STATE_MASK
, state
);
139 *oldstateptr
= oldstate
& _PTHREAD_CANCEL_STATE_MASK
;
145 * Query/update the cancelability 'type' of a thread
147 PTHREAD_NOEXPORT_VARIANT
149 pthread_setcanceltype(int type
, int *oldtype
)
151 pthread_t self
= pthread_self();
153 _pthread_validate_signature(self
);
155 if ((type
!= PTHREAD_CANCEL_DEFERRED
) &&
156 (type
!= PTHREAD_CANCEL_ASYNCHRONOUS
))
158 int oldstate
= _pthread_update_cancel_state(self
, _PTHREAD_CANCEL_TYPE_MASK
, type
);
160 *oldtype
= oldstate
& _PTHREAD_CANCEL_TYPE_MASK
;
168 _pthread_is_canceled(pthread_t thread
)
170 const int flags
= (PTHREAD_CANCEL_ENABLE
|_PTHREAD_CANCEL_PENDING
);
171 int state
= os_atomic_load(&thread
->cancel_state
, seq_cst
);
172 return (state
& flags
) == flags
;
177 _pthread_get_exit_value(pthread_t thread
)
179 if (os_unlikely(_pthread_is_canceled(thread
))) {
180 return PTHREAD_CANCELED
;
182 return thread
->tl_exit_value
;
186 pthread_testcancel(void)
188 pthread_t self
= pthread_self();
189 if (os_unlikely(_pthread_is_canceled(self
))) {
190 _pthread_validate_signature(self
);
192 self
->canceled
= true;
194 pthread_exit(PTHREAD_CANCELED
);
199 _pthread_markcancel_if_canceled(pthread_t thread
, mach_port_t kport
)
201 if (os_unlikely(_pthread_is_canceled(thread
))) {
202 __pthread_markcancel(kport
);
207 _pthread_exit_if_canceled(int error
)
209 if ((error
& 0xff) == EINTR
&& __pthread_canceled(0) == 0) {
210 pthread_t self
= pthread_self();
212 _pthread_validate_signature(self
);
213 self
->cancel_error
= error
;
214 self
->canceled
= true;
215 pthread_exit(PTHREAD_CANCELED
);
220 pthread_sigmask(int how
, const sigset_t
* set
, sigset_t
* oset
)
224 if (__pthread_sigmask(how
, set
, oset
) == -1) {
230 // called with _pthread_list_lock held
232 _pthread_joiner_prepost_wake(pthread_t thread
)
234 pthread_join_context_t ctx
= thread
->tl_join_ctx
;
235 semaphore_t sema
= MACH_PORT_NULL
;
237 if (thread
->tl_joinable
) {
238 sema
= ctx
->custom_stack_sema
;
239 thread
->tl_joinable
= false;
241 ctx
->detached
= true;
242 thread
->tl_join_ctx
= NULL
;
244 if (ctx
->value_ptr
) *ctx
->value_ptr
= _pthread_get_exit_value(thread
);
249 _pthread_joiner_abort_wait(pthread_t thread
, pthread_join_context_t ctx
)
251 bool aborted
= false;
253 _pthread_lock_lock(&_pthread_list_lock
);
254 if (!ctx
->detached
&& thread
->tl_exit_gate
!= MACH_PORT_DEAD
) {
256 * _pthread_joiner_prepost_wake() didn't happen
257 * allow another thread to join
259 PTHREAD_DEBUG_ASSERT(thread
->tl_join_ctx
== ctx
);
260 thread
->tl_join_ctx
= NULL
;
261 thread
->tl_exit_gate
= MACH_PORT_NULL
;
264 _pthread_lock_unlock(&_pthread_list_lock
);
269 _pthread_joiner_wait(pthread_t thread
, pthread_join_context_t ctx
,
270 pthread_conformance_t conforming
)
272 uint32_t *exit_gate
= &thread
->tl_exit_gate
;
273 int ulock_op
= UL_UNFAIR_LOCK
| ULF_NO_ERRNO
;
275 if (conforming
== PTHREAD_CONFORM_UNIX03_CANCELABLE
) {
276 ulock_op
|= ULF_WAIT_CANCEL_POINT
;
280 uint32_t cur
= os_atomic_load(exit_gate
, acquire
);
281 if (cur
== MACH_PORT_DEAD
) {
284 if (os_unlikely(cur
!= ctx
->kport
)) {
285 PTHREAD_CLIENT_CRASH(cur
, "pthread_join() state corruption");
287 int ret
= __ulock_wait(ulock_op
, exit_gate
, ctx
->kport
, 0);
296 * As specified, either the pthread_join() call is canceled, or it
297 * succeeds, but not both. The difference is obvious to the
298 * application, since either a cancellation handler is run or
299 * pthread_join() returns.
301 * When __ulock_wait() returns EINTR, we check if we have been
302 * canceled, and if we have, we try to abort the wait.
304 * If we can't, it means the other thread finished the join while we
305 * were being canceled and commited the waiter to return from
306 * pthread_join(). Returning from the join then takes precedence
307 * over the cancelation which will be acted upon at the next
310 if (os_unlikely(conforming
== PTHREAD_CONFORM_UNIX03_CANCELABLE
&&
311 _pthread_is_canceled(ctx
->waiter
))) {
312 if (_pthread_joiner_abort_wait(thread
, ctx
)) {
313 ctx
->waiter
->canceled
= true;
314 pthread_exit(PTHREAD_CANCELED
);
321 bool cleanup
= false;
323 _pthread_lock_lock(&_pthread_list_lock
);
324 // If pthread_detach() was called, we can't safely dereference the thread,
325 // else, decide who gets to deallocate the thread (see _pthread_terminate).
326 if (!ctx
->detached
) {
327 PTHREAD_DEBUG_ASSERT(thread
->tl_join_ctx
== ctx
);
328 thread
->tl_join_ctx
= NULL
;
329 cleanup
= thread
->tl_joiner_cleans_up
;
331 _pthread_lock_unlock(&_pthread_list_lock
);
334 _pthread_deallocate(thread
, false);
341 _pthread_join(pthread_t thread
, void **value_ptr
, pthread_conformance_t conforming
)
343 pthread_t self
= pthread_self();
344 pthread_join_context_s ctx
= {
346 .value_ptr
= value_ptr
,
347 .kport
= MACH_PORT_NULL
,
348 .custom_stack_sema
= MACH_PORT_NULL
,
353 if (!_pthread_validate_thread_and_list_lock(thread
)) {
357 _pthread_validate_signature(self
);
359 if (!thread
->tl_joinable
|| (thread
->tl_join_ctx
!= NULL
)) {
361 } else if (thread
== self
||
362 (self
->tl_join_ctx
&& self
->tl_join_ctx
->waiter
== thread
)) {
364 } else if (thread
->tl_exit_gate
== MACH_PORT_DEAD
) {
365 TAILQ_REMOVE(&__pthread_head
, thread
, tl_plist
);
366 PTHREAD_DEBUG_ASSERT(thread
->tl_joiner_cleans_up
);
367 thread
->tl_joinable
= false;
368 if (value_ptr
) *value_ptr
= _pthread_get_exit_value(thread
);
370 ctx
.kport
= _pthread_tsd_slot(thread
, MACH_THREAD_SELF
);
371 thread
->tl_exit_gate
= ctx
.kport
;
372 thread
->tl_join_ctx
= &ctx
;
373 if (thread
->tl_has_custom_stack
) {
374 ctx
.custom_stack_sema
= (semaphore_t
)os_get_cached_semaphore();
377 _pthread_lock_unlock(&_pthread_list_lock
);
380 if (ctx
.kport
== MACH_PORT_NULL
) {
381 _pthread_deallocate(thread
, false);
383 res
= _pthread_joiner_wait(thread
, &ctx
, conforming
);
386 if (res
== 0 && ctx
.custom_stack_sema
&& !ctx
.detached
) {
387 // threads with a custom stack need to make sure _pthread_terminate
388 // returned before the joiner is unblocked, the joiner may quickly
389 // deallocate the stack with rather dire consequences.
391 // When we reach this point we know the pthread_join has to succeed
392 // so this can't be a cancelation point.
394 kr
= __semwait_signal_nocancel(ctx
.custom_stack_sema
, 0, 0, 0, 0, 0);
395 } while (kr
!= KERN_SUCCESS
);
397 if (ctx
.custom_stack_sema
) {
398 os_put_cached_semaphore(ctx
.custom_stack_sema
);
403 #endif /* !BUILDING_VARIANT ] */
405 static inline pthread_conformance_t
406 _pthread_conformance(void)
408 #ifdef VARIANT_CANCELABLE
409 return PTHREAD_CONFORM_UNIX03_CANCELABLE
;
410 #else /* !VARIANT_CANCELABLE */
411 return PTHREAD_CONFORM_UNIX03_NOCANCEL
;
416 _pthread_testcancel_if_cancelable_variant(void)
418 #ifdef VARIANT_CANCELABLE
419 pthread_testcancel();
424 pthread_join(pthread_t thread
, void **value_ptr
)
426 _pthread_testcancel_if_cancelable_variant();
427 return _pthread_join(thread
, value_ptr
, _pthread_conformance());
431 pthread_cond_wait(pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
433 return _pthread_cond_wait(cond
, mutex
, NULL
, 0, _pthread_conformance());
437 pthread_cond_timedwait(pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
438 const struct timespec
*abstime
)
440 return _pthread_cond_wait(cond
, mutex
, abstime
, 0, _pthread_conformance());
444 sigwait(const sigset_t
* set
, int * sig
)
448 _pthread_testcancel_if_cancelable_variant();
450 if (__sigwait(set
, sig
) == -1) {
453 _pthread_testcancel_if_cancelable_variant();
456 * EINTR that isn't a result of pthread_cancel()
457 * is translated to 0.