--- /dev/null
+/*
+ * Copyright (c) 2013, 2016 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef __PTHREAD_INTROSPECTION__
+#define __PTHREAD_INTROSPECTION__
+
+#include <sys/cdefs.h>
+#include <pthread/pthread.h>
+#include <Availability.h>
+
+/*!
+ * @header
+ *
+ * @abstract
+ * Introspection API for libpthread.
+ *
+ * This should only be used for introspection and debugging tools. Do not rely
+ * on it in shipping code.
+ */
+
+__BEGIN_DECLS
+
+/*!
+ * @typedef pthread_introspection_hook_t
+ *
+ * @abstract
+ * A function pointer called at various points in a PThread's lifetime. The
+ * function must be able to be called in contexts with invalid thread state.
+ *
+ * @param event
+ * One of the events in pthread_introspection_event_t.
+ *
+ * @param thread
+ * pthread_t associated with the event.
+ *
+ * @param addr
+ * Address associated with the event, e.g. stack address.
+ *
+ * @param size
+ * Size associated with the event, e.g. stack size.
+ */
+typedef void (*pthread_introspection_hook_t)(unsigned int event,
+ pthread_t thread, void *addr, size_t size);
+
+/*!
+ * @enum pthread_introspection_event_t
+ * Events sent by libpthread about threads lifetimes.
+ *
+ * @const PTHREAD_INTROSPECTION_THREAD_CREATE
+ * The specified pthread_t was created, and there will be a paired
+ * PTHREAD_INTROSPECTION_THREAD_DESTROY event. However, there may not be
+ * a START/TERMINATE pair of events for this pthread_t.
+ *
+ * Starting with macOS 10.14, and iOS 12, this event is always sent before
+ * PTHREAD_INTROSPECTION_THREAD_START is sent. This event is however not sent
+ * for the main thread.
+ *
+ * This event may not be sent from the context of the passed in pthread_t.
+ *
+ * Note that all properties of this thread may not be functional yet, and it is
+ * not permitted to call functions on this thread past observing its address.
+ *
+ * @const PTHREAD_INTROSPECTION_THREAD_START
+ * Thread has started and its stack was allocated. There will be a matching
+ * PTHREAD_INTROSPECTION_THREAD_TERMINATE event.
+ *
+ * This event is always sent from the context of the passed in pthread_t.
+ *
+ * @const PTHREAD_INTROSPECTION_THREAD_TERMINATE
+ * Thread is about to be terminated and stack will be deallocated. This always
+ * matches a PTHREAD_INTROSPECTION_THREAD_START event.
+ *
+ * This event is always sent from the context of the passed in pthread_t.
+ *
+ * @const PTHREAD_INTROSPECTION_THREAD_DESTROY
+ * pthread_t is about to be destroyed. This always matches
+ * a PTHREAD_INTROSPECTION_THREAD_CREATE event, but there may not have been
+ * a START/TERMINATE pair of events for this pthread_t.
+ *
+ * This event may not be sent from the context of the passed in pthread_t.
+ */
+enum {
+ PTHREAD_INTROSPECTION_THREAD_CREATE = 1,
+ PTHREAD_INTROSPECTION_THREAD_START,
+ PTHREAD_INTROSPECTION_THREAD_TERMINATE,
+ PTHREAD_INTROSPECTION_THREAD_DESTROY,
+};
+
+/*!
+ * @function pthread_introspection_hook_install
+ *
+ * @abstract
+ * Install introspection hook function into libpthread.
+ *
+ * @discussion
+ * The caller is responsible for implementing chaining to the hook that was
+ * previously installed (if any).
+ *
+ * @param hook
+ * Pointer to hook function.
+ *
+ * @result
+ * Previously installed hook function or NULL.
+ */
+
+__API_AVAILABLE(macos(10.9), ios(7.0))
+__attribute__((__nonnull__, __warn_unused_result__))
+extern pthread_introspection_hook_t
+pthread_introspection_hook_install(pthread_introspection_hook_t hook);
+
+/*!
+ * @function pthread_introspection_setspecific_np
+ *
+ * @abstract
+ * Performs the moral equivalent of pthread_setspecific() on a target thread
+ * during the @c PTHREAD_INTROSPECTION_START callback.
+ *
+ * @description
+ * This function is only valid to call during the delivery
+ * of an @c PTHREAD_INTROSPECTION_THREAD_CREATE introspection hook.
+ *
+ * Using this function outside of this context is undefined.
+ *
+ * If the created thread is started, then the destructor for this key
+ * will be called when the thread is terminated. However if the thread
+ * is not started, it will not be called, and
+ * pthread_introspection_getspecific_np() must be called manually during
+ * the @c PTHREAD_INTROSPECTION_THREAD_DESTROY callback to perform manual
+ * cleanup.
+ */
+__API_AVAILABLE(macos(10.16), ios(14.0), tvos(14.0), watchos(7.0))
+int
+pthread_introspection_setspecific_np(pthread_t thread,
+ pthread_key_t key, const void * _Nullable value);
+
+/*!
+ * @function pthread_introspection_getspecific_np
+ *
+ * @abstract
+ * Performs the moral equivalent of pthread_getspecific() on a target thread
+ * during the @c PTHREAD_INTROSPECTION_THREAD_DESTROY callback.
+ *
+ * @description
+ * This function is only valid to call during the delivery
+ * of an @c PTHREAD_INTROSPECTION_THREAD_DESTROY introspection hook.
+ *
+ * If the thread was started then this will always return NULL even
+ * when pthread_introspection_setspecific_np() was used.
+ */
+__API_AVAILABLE(macos(10.16), ios(14.0), tvos(14.0), watchos(7.0))
+void * _Nullable
+pthread_introspection_getspecific_np(pthread_t _Nonnull thread,
+ pthread_key_t key);
+
+__END_DECLS
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+/*
+ * MkLinux
+ */
+
+/*
+ * POSIX Threads - IEEE 1003.1c
+ */
+
+#ifndef _PTHREAD_H
+#define _PTHREAD_H
+
+#include <_types.h>
+#include <pthread/sched.h>
+#include <time.h>
+#include <sys/_pthread/_pthread_types.h>
+#include <sys/_pthread/_pthread_attr_t.h>
+#include <sys/_pthread/_pthread_cond_t.h>
+#include <sys/_pthread/_pthread_condattr_t.h>
+#include <sys/_pthread/_pthread_key_t.h>
+#include <sys/_pthread/_pthread_mutex_t.h>
+#include <sys/_pthread/_pthread_mutexattr_t.h>
+#include <sys/_pthread/_pthread_once_t.h>
+#include <sys/_pthread/_pthread_rwlock_t.h>
+#include <sys/_pthread/_pthread_rwlockattr_t.h>
+#include <sys/_pthread/_pthread_t.h>
+
+#include <pthread/qos.h>
+
+#if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE) || defined(__cplusplus)
+
+#include <sys/_types/_mach_port_t.h>
+#include <sys/_types/_sigset_t.h>
+
+#endif /* (!_POSIX_C_SOURCE && !_XOPEN_SOURCE) || _DARWIN_C_SOURCE || __cplusplus */
+
+/*
+ * These symbols indicate which [optional] features are available
+ * They can be tested at compile time via '#ifdef XXX'
+ * The way to check for pthreads is like so:
+
+ * #include <unistd.h>
+ * #ifdef _POSIX_THREADS
+ * #include <pthread.h>
+ * #endif
+
+ */
+
+/* These will be moved to unistd.h */
+
+/*
+ * Note: These data structures are meant to be opaque. Only enough
+ * structure is exposed to support initializers.
+ * All of the typedefs will be moved to <sys/types.h>
+ */
+
+#include <sys/cdefs.h>
+#include <Availability.h>
+
+#if __has_feature(assume_nonnull)
+_Pragma("clang assume_nonnull begin")
+#endif
+__BEGIN_DECLS
+/*
+ * Threads
+ */
+
+
+/*
+ * Cancel cleanup handler management. Note, since these are implemented as macros,
+ * they *MUST* occur in matched pairs!
+ */
+
+#define pthread_cleanup_push(func, val) \
+ { \
+ struct __darwin_pthread_handler_rec __handler; \
+ pthread_t __self = pthread_self(); \
+ __handler.__routine = func; \
+ __handler.__arg = val; \
+ __handler.__next = __self->__cleanup_stack; \
+ __self->__cleanup_stack = &__handler;
+
+#define pthread_cleanup_pop(execute) \
+ /* Note: 'handler' must be in this same lexical context! */ \
+ __self->__cleanup_stack = __handler.__next; \
+ if (execute) (__handler.__routine)(__handler.__arg); \
+ }
+
+/*
+ * Thread attributes
+ */
+
+#define PTHREAD_CREATE_JOINABLE 1
+#define PTHREAD_CREATE_DETACHED 2
+
+#define PTHREAD_INHERIT_SCHED 1
+#define PTHREAD_EXPLICIT_SCHED 2
+
+#define PTHREAD_CANCEL_ENABLE 0x01 /* Cancel takes place at next cancellation point */
+#define PTHREAD_CANCEL_DISABLE 0x00 /* Cancel postponed */
+#define PTHREAD_CANCEL_DEFERRED 0x02 /* Cancel waits until cancellation point */
+#define PTHREAD_CANCEL_ASYNCHRONOUS 0x00 /* Cancel occurs immediately */
+
+/* Value returned from pthread_join() when a thread is canceled */
+#define PTHREAD_CANCELED ((void *) 1)
+
+/* We only support PTHREAD_SCOPE_SYSTEM */
+#define PTHREAD_SCOPE_SYSTEM 1
+#define PTHREAD_SCOPE_PROCESS 2
+
+#define PTHREAD_PROCESS_SHARED 1
+#define PTHREAD_PROCESS_PRIVATE 2
+
+/*
+ * Mutex protocol attributes
+ */
+#define PTHREAD_PRIO_NONE 0
+#define PTHREAD_PRIO_INHERIT 1
+#define PTHREAD_PRIO_PROTECT 2
+
+/*
+ * Mutex type attributes
+ */
+#define PTHREAD_MUTEX_NORMAL 0
+#define PTHREAD_MUTEX_ERRORCHECK 1
+#define PTHREAD_MUTEX_RECURSIVE 2
+#define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL
+
+/*
+ * Mutex policy attributes
+ */
+#define PTHREAD_MUTEX_POLICY_FAIRSHARE_NP 1
+#define PTHREAD_MUTEX_POLICY_FIRSTFIT_NP 3
+
+/*
+ * RWLock variables
+ */
+#define PTHREAD_RWLOCK_INITIALIZER {_PTHREAD_RWLOCK_SIG_init, {0}}
+
+/*
+ * Mutex variables
+ */
+#define PTHREAD_MUTEX_INITIALIZER {_PTHREAD_MUTEX_SIG_init, {0}}
+
+/* <rdar://problem/10854763> */
+#if ((__MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000)) || defined(__DRIVERKIT_VERSION_MIN_REQUIRED)
+# if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE)
+# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER {_PTHREAD_ERRORCHECK_MUTEX_SIG_init, {0}}
+# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER {_PTHREAD_RECURSIVE_MUTEX_SIG_init, {0}}
+# endif /* (!_POSIX_C_SOURCE && !_XOPEN_SOURCE) || _DARWIN_C_SOURCE */
+#endif
+
+/* <rdar://problem/25944576> */
+#define _PTHREAD_SWIFT_IMPORTER_NULLABILITY_COMPAT \
+ defined(SWIFT_CLASS_EXTRA) && (!defined(SWIFT_SDK_OVERLAY_PTHREAD_EPOCH) || (SWIFT_SDK_OVERLAY_PTHREAD_EPOCH < 1))
+
+/*
+ * Condition variable attributes
+ */
+
+/*
+ * Condition variables
+ */
+
+#define PTHREAD_COND_INITIALIZER {_PTHREAD_COND_SIG_init, {0}}
+
+/*
+ * Initialization control (once) variables
+ */
+
+#define PTHREAD_ONCE_INIT {_PTHREAD_ONCE_SIG_init, {0}}
+
+/*
+ * Prototypes for all PTHREAD interfaces
+ */
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_atfork(void (* _Nullable)(void), void (* _Nullable)(void),
+ void (* _Nullable)(void));
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_destroy(pthread_attr_t *);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_getdetachstate(const pthread_attr_t *, int *);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_getguardsize(const pthread_attr_t * __restrict, size_t * __restrict);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_getinheritsched(const pthread_attr_t * __restrict, int * __restrict);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_getschedparam(const pthread_attr_t * __restrict,
+ struct sched_param * __restrict);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_getschedpolicy(const pthread_attr_t * __restrict, int * __restrict);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_getscope(const pthread_attr_t * __restrict, int * __restrict);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_getstack(const pthread_attr_t * __restrict,
+ void * _Nullable * _Nonnull __restrict, size_t * __restrict);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_getstackaddr(const pthread_attr_t * __restrict,
+ void * _Nullable * _Nonnull __restrict);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_getstacksize(const pthread_attr_t * __restrict, size_t * __restrict);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_init(pthread_attr_t *);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_setdetachstate(pthread_attr_t *, int);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_setguardsize(pthread_attr_t *, size_t);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_setinheritsched(pthread_attr_t *, int);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_setschedparam(pthread_attr_t * __restrict,
+ const struct sched_param * __restrict);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_setschedpolicy(pthread_attr_t *, int);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_setscope(pthread_attr_t *, int);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_setstack(pthread_attr_t *, void *, size_t);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_setstackaddr(pthread_attr_t *, void *);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_attr_setstacksize(pthread_attr_t *, size_t);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_cancel(pthread_t) __DARWIN_ALIAS(pthread_cancel);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_cond_broadcast(pthread_cond_t *);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_cond_destroy(pthread_cond_t *);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_cond_init(
+ pthread_cond_t * __restrict,
+ const pthread_condattr_t * _Nullable __restrict)
+ __DARWIN_ALIAS(pthread_cond_init);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_cond_signal(pthread_cond_t *);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_cond_timedwait(
+ pthread_cond_t * __restrict, pthread_mutex_t * __restrict,
+ const struct timespec * _Nullable __restrict)
+ __DARWIN_ALIAS_C(pthread_cond_timedwait);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_cond_wait(pthread_cond_t * __restrict,
+ pthread_mutex_t * __restrict) __DARWIN_ALIAS_C(pthread_cond_wait);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_condattr_destroy(pthread_condattr_t *);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_condattr_init(pthread_condattr_t *);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_condattr_getpshared(const pthread_condattr_t * __restrict,
+ int * __restrict);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_condattr_setpshared(pthread_condattr_t *, int);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+#if !_PTHREAD_SWIFT_IMPORTER_NULLABILITY_COMPAT
+int pthread_create(pthread_t _Nullable * _Nonnull __restrict,
+ const pthread_attr_t * _Nullable __restrict,
+ void * _Nullable (* _Nonnull)(void * _Nullable),
+ void * _Nullable __restrict);
+#else
+int pthread_create(pthread_t * __restrict,
+ const pthread_attr_t * _Nullable __restrict,
+ void *(* _Nonnull)(void *), void * _Nullable __restrict);
+#endif // _PTHREAD_SWIFT_IMPORTER_NULLABILITY_COMPAT
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_detach(pthread_t);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_equal(pthread_t _Nullable, pthread_t _Nullable);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+void pthread_exit(void * _Nullable) __dead2;
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_getconcurrency(void);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_getschedparam(pthread_t , int * _Nullable __restrict,
+ struct sched_param * _Nullable __restrict);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+void* _Nullable pthread_getspecific(pthread_key_t);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_join(pthread_t , void * _Nullable * _Nullable)
+ __DARWIN_ALIAS_C(pthread_join);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_key_create(pthread_key_t *, void (* _Nullable)(void *));
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_key_delete(pthread_key_t);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_mutex_destroy(pthread_mutex_t *);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_mutex_getprioceiling(const pthread_mutex_t * __restrict,
+ int * __restrict);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_mutex_init(pthread_mutex_t * __restrict,
+ const pthread_mutexattr_t * _Nullable __restrict);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_mutex_lock(pthread_mutex_t *);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_mutex_setprioceiling(pthread_mutex_t * __restrict, int,
+ int * __restrict);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_mutex_trylock(pthread_mutex_t *);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_mutex_unlock(pthread_mutex_t *);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_mutexattr_destroy(pthread_mutexattr_t *) __DARWIN_ALIAS(pthread_mutexattr_destroy);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t * __restrict,
+ int * __restrict);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_mutexattr_getprotocol(const pthread_mutexattr_t * __restrict,
+ int * __restrict);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_mutexattr_getpshared(const pthread_mutexattr_t * __restrict,
+ int * __restrict);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_mutexattr_gettype(const pthread_mutexattr_t * __restrict,
+ int * __restrict);
+
+__API_AVAILABLE(macos(10.13.4), ios(11.3), watchos(4.3), tvos(11.3))
+int pthread_mutexattr_getpolicy_np(const pthread_mutexattr_t * __restrict,
+ int * __restrict);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_mutexattr_init(pthread_mutexattr_t *);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *, int);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_mutexattr_setprotocol(pthread_mutexattr_t *, int);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
+
+__API_AVAILABLE(macos(10.7), ios(5.0))
+int pthread_mutexattr_setpolicy_np(pthread_mutexattr_t *, int);
+
+__SWIFT_UNAVAILABLE_MSG("Use lazily initialized globals instead")
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_once(pthread_once_t *, void (* _Nonnull)(void));
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_rwlock_destroy(pthread_rwlock_t * ) __DARWIN_ALIAS(pthread_rwlock_destroy);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_rwlock_init(pthread_rwlock_t * __restrict,
+ const pthread_rwlockattr_t * _Nullable __restrict)
+ __DARWIN_ALIAS(pthread_rwlock_init);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_rwlock_rdlock(pthread_rwlock_t *) __DARWIN_ALIAS(pthread_rwlock_rdlock);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_rwlock_tryrdlock(pthread_rwlock_t *) __DARWIN_ALIAS(pthread_rwlock_tryrdlock);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_rwlock_trywrlock(pthread_rwlock_t *) __DARWIN_ALIAS(pthread_rwlock_trywrlock);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_rwlock_wrlock(pthread_rwlock_t *) __DARWIN_ALIAS(pthread_rwlock_wrlock);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_rwlock_unlock(pthread_rwlock_t *) __DARWIN_ALIAS(pthread_rwlock_unlock);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_rwlockattr_destroy(pthread_rwlockattr_t *);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t * __restrict,
+ int * __restrict);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_rwlockattr_init(pthread_rwlockattr_t *);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+pthread_t pthread_self(void);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_setcancelstate(int , int * _Nullable)
+ __DARWIN_ALIAS(pthread_setcancelstate);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_setcanceltype(int , int * _Nullable)
+ __DARWIN_ALIAS(pthread_setcanceltype);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_setconcurrency(int);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_setschedparam(pthread_t, int, const struct sched_param *);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_setspecific(pthread_key_t , const void * _Nullable);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+void pthread_testcancel(void) __DARWIN_ALIAS(pthread_testcancel);
+
+#if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE) || defined(__cplusplus)
+
+/* returns non-zero if pthread_create or cthread_fork have been called */
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_is_threaded_np(void);
+
+__API_AVAILABLE(macos(10.6), ios(3.2))
+int pthread_threadid_np(pthread_t _Nullable,__uint64_t* _Nullable);
+
+/*SPI to set and get pthread name*/
+__API_AVAILABLE(macos(10.6), ios(3.2))
+int pthread_getname_np(pthread_t,char*,size_t);
+
+__API_AVAILABLE(macos(10.6), ios(3.2))
+int pthread_setname_np(const char*);
+
+/* returns non-zero if the current thread is the main thread */
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_main_np(void);
+
+/* return the mach thread bound to the pthread */
+__API_AVAILABLE(macos(10.4), ios(2.0))
+mach_port_t pthread_mach_thread_np(pthread_t);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+size_t pthread_get_stacksize_np(pthread_t);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+void* pthread_get_stackaddr_np(pthread_t);
+
+/* Like pthread_cond_signal(), but only wake up the specified pthread */
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_cond_signal_thread_np(pthread_cond_t *, pthread_t _Nullable);
+
+/* Like pthread_cond_timedwait, but use a relative timeout */
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_cond_timedwait_relative_np(pthread_cond_t *, pthread_mutex_t *,
+ const struct timespec * _Nullable);
+
+/* Like pthread_create(), but leaves the thread suspended */
+__API_AVAILABLE(macos(10.4), ios(2.0))
+#if !_PTHREAD_SWIFT_IMPORTER_NULLABILITY_COMPAT
+int pthread_create_suspended_np(
+ pthread_t _Nullable * _Nonnull, const pthread_attr_t * _Nullable,
+ void * _Nullable (* _Nonnull)(void * _Nullable), void * _Nullable);
+#else
+int pthread_create_suspended_np(pthread_t *, const pthread_attr_t * _Nullable,
+ void *(* _Nonnull)(void *), void * _Nullable);
+#endif
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_kill(pthread_t, int);
+
+__API_AVAILABLE(macos(10.5), ios(2.0))
+_Nullable pthread_t pthread_from_mach_thread_np(mach_port_t);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+int pthread_sigmask(int, const sigset_t * _Nullable, sigset_t * _Nullable)
+ __DARWIN_ALIAS(pthread_sigmask);
+
+__API_AVAILABLE(macos(10.4), ios(2.0))
+void pthread_yield_np(void);
+
+__API_AVAILABLE(macos(10.16))
+__SPI_AVAILABLE(ios(14.0), tvos(14.0), watchos(7.0), bridgeos(5.0), driverkit(20.0))
+void pthread_jit_write_protect_np(int enabled);
+
+__API_AVAILABLE(macos(10.16))
+__SPI_AVAILABLE(ios(14.0), tvos(14.0), watchos(7.0), bridgeos(5.0), driverkit(20.0))
+int pthread_jit_write_protect_supported_np(void);
+
+/*!
+ * @function pthread_cpu_number_np
+ *
+ * @param cpu_number_out
+ * The CPU number that the thread was running on at the time of query.
+ * This cpu number is in the interval [0, ncpus) (from sysctlbyname("hw.ncpu"))
+ *
+ * @result
+ * This function returns 0 or the value of errno if an error occurred.
+ *
+ * @note
+ * Optimizations of per-CPU datastructures based on the result of this function
+ * still require synchronization since it is not guaranteed that the thread will
+ * still be on the same CPU by the time the function returns.
+ */
+__API_AVAILABLE(macos(11.0), ios(14.2), tvos(14.2), watchos(7.1))
+int
+pthread_cpu_number_np(size_t *cpu_number_out);
+
+#endif /* (!_POSIX_C_SOURCE && !_XOPEN_SOURCE) || _DARWIN_C_SOURCE || __cplusplus */
+__END_DECLS
+#if __has_feature(assume_nonnull)
+_Pragma("clang assume_nonnull end")
+#endif
+
+#endif /* _PTHREAD_H */
--- /dev/null
+/*
+ * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef _PTHREAD_IMPL_H_
+#define _PTHREAD_IMPL_H_
+/*
+ * Internal implementation details
+ */
+
+/* This whole header file will disappear, so don't depend on it... */
+
+#if __has_feature(assume_nonnull)
+_Pragma("clang assume_nonnull begin")
+#endif
+
+#ifndef __POSIX_LIB__
+
+/*
+ * [Internal] data structure signatures
+ */
+#define _PTHREAD_MUTEX_SIG_init 0x32AAABA7
+
+#define _PTHREAD_ERRORCHECK_MUTEX_SIG_init 0x32AAABA1
+#define _PTHREAD_RECURSIVE_MUTEX_SIG_init 0x32AAABA2
+#define _PTHREAD_FIRSTFIT_MUTEX_SIG_init 0x32AAABA3
+
+#define _PTHREAD_COND_SIG_init 0x3CB0B1BB
+#define _PTHREAD_ONCE_SIG_init 0x30B1BCBA
+#define _PTHREAD_RWLOCK_SIG_init 0x2DA8B3B4
+
+/*
+ * POSIX scheduling policies
+ */
+#define SCHED_OTHER 1
+#define SCHED_FIFO 4
+#define SCHED_RR 2
+
+#define __SCHED_PARAM_SIZE__ 4
+
+#endif /* __POSIX_LIB__ */
+
+#if __has_feature(assume_nonnull)
+_Pragma("clang assume_nonnull end")
+#endif
+
+#endif /* _PTHREAD_IMPL_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+/*
+ * MkLinux
+ */
+
+/*
+ * Extension SPIs; installed to /usr/include.
+ */
+
+#ifndef _PTHREAD_SPIS_H
+#define _PTHREAD_SPIS_H
+
+
+#include <pthread/pthread.h>
+
+#if __has_feature(assume_nonnull)
+_Pragma("clang assume_nonnull begin")
+#endif
+__BEGIN_DECLS
+
+#if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE)
+/* firstfit */
+#define PTHREAD_FIRSTFIT_MUTEX_INITIALIZER {_PTHREAD_FIRSTFIT_MUTEX_SIG_init, {0}}
+
+/*
+ * Mutex attributes
+ */
+#define _PTHREAD_MUTEX_POLICY_NONE PTHREAD_MUTEX_POLICY_NONE
+#define _PTHREAD_MUTEX_POLICY_FAIRSHARE PTHREAD_MUTEX_POLICY_FAIRSHARE_NP
+#define _PTHREAD_MUTEX_POLICY_FIRSTFIT PTHREAD_MUTEX_POLICY_FIRSTFIT_NP
+
+#endif /* (!_POSIX_C_SOURCE && !_XOPEN_SOURCE) || _DARWIN_C_SOURCE */
+
+__API_AVAILABLE(macos(10.11)) __API_UNAVAILABLE(ios, tvos, watchos, bridgeos)
+void _pthread_mutex_enable_legacy_mode(void);
+
+/*
+ * A version of pthread_create that is safely callable from an injected mach thread.
+ *
+ * The _create introspection hook will not fire for threads created from this function.
+ *
+ * It is not safe to call this function concurrently.
+ */
+__API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
+#if !_PTHREAD_SWIFT_IMPORTER_NULLABILITY_COMPAT
+int pthread_create_from_mach_thread(
+ pthread_t _Nullable * _Nonnull __restrict,
+ const pthread_attr_t * _Nullable __restrict,
+ void * _Nullable (* _Nonnull)(void * _Nullable),
+ void * _Nullable __restrict);
+#else
+int pthread_create_from_mach_thread(pthread_t * __restrict,
+ const pthread_attr_t * _Nullable __restrict,
+ void *(* _Nonnull)(void *), void * _Nullable __restrict);
+#endif
+
+
+__END_DECLS
+#if __has_feature(assume_nonnull)
+_Pragma("clang assume_nonnull end")
+#endif
+
+#endif /* _PTHREAD_SPIS_H */
--- /dev/null
+/*
+ * Copyright (c) 2013-2014 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef _PTHREAD_QOS_H
+#define _PTHREAD_QOS_H
+
+#include <sys/cdefs.h>
+#include <sys/_pthread/_pthread_attr_t.h> /* pthread_attr_t */
+#include <sys/_pthread/_pthread_t.h> /* pthread_t */
+#include <Availability.h>
+
+#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
+
+#include <sys/qos.h>
+
+#ifndef KERNEL
+
+#if __has_feature(assume_nonnull)
+_Pragma("clang assume_nonnull begin")
+#endif
+__BEGIN_DECLS
+
+/*!
+ * @function pthread_attr_set_qos_class_np
+ *
+ * @abstract
+ * Sets the QOS class and relative priority of a pthread attribute structure
+ * which may be used to specify the requested QOS class of newly created
+ * threads.
+ *
+ * @discussion
+ * The QOS class and relative priority represent an overall combination of
+ * system quality of service attributes on a thread.
+ *
+ * Subsequent calls to interfaces such as pthread_attr_setschedparam() that are
+ * incompatible or in conflict with the QOS class system will unset the QOS
+ * class requested with this interface and pthread_attr_get_qos_class_np() will
+ * return QOS_CLASS_UNSPECIFIED.
+ *
+ * @param __attr
+ * The pthread attribute structure to modify.
+ *
+ * @param __qos_class
+ * A QOS class value:
+ * - QOS_CLASS_USER_INTERACTIVE
+ * - QOS_CLASS_USER_INITIATED
+ * - QOS_CLASS_DEFAULT
+ * - QOS_CLASS_UTILITY
+ * - QOS_CLASS_BACKGROUND
+ * EINVAL will be returned if any other value is provided.
+ *
+ * @param __relative_priority
+ * A relative priority within the QOS class. This value is a negative offset
+ * from the maximum supported scheduler priority for the given class.
+ * EINVAL will be returned if the value is greater than zero or less than
+ * QOS_MIN_RELATIVE_PRIORITY.
+ *
+ * @return
+ * Zero if successful, otherwise an errno value.
+ */
+__API_AVAILABLE(macos(10.10), ios(8.0))
+int
+pthread_attr_set_qos_class_np(pthread_attr_t *__attr,
+ qos_class_t __qos_class, int __relative_priority);
+
+/*!
+ * @function pthread_attr_get_qos_class_np
+ *
+ * @abstract
+ * Gets the QOS class and relative priority of a pthread attribute structure.
+ *
+ * @param __attr
+ * The pthread attribute structure to inspect.
+ *
+ * @param __qos_class
+ * On output, a QOS class value:
+ * - QOS_CLASS_USER_INTERACTIVE
+ * - QOS_CLASS_USER_INITIATED
+ * - QOS_CLASS_DEFAULT
+ * - QOS_CLASS_UTILITY
+ * - QOS_CLASS_BACKGROUND
+ * - QOS_CLASS_UNSPECIFIED
+ * This value may be NULL in which case no value is returned.
+ *
+ * @param __relative_priority
+ * On output, a relative priority offset within the QOS class.
+ * This value may be NULL in which case no value is returned.
+ *
+ * @return
+ * Zero if successful, otherwise an errno value.
+ */
+__API_AVAILABLE(macos(10.10), ios(8.0))
+int
+pthread_attr_get_qos_class_np(pthread_attr_t * __restrict __attr,
+ qos_class_t * _Nullable __restrict __qos_class,
+ int * _Nullable __restrict __relative_priority);
+
+/*!
+ * @function pthread_set_qos_class_self_np
+ *
+ * @abstract
+ * Sets the requested QOS class and relative priority of the current thread.
+ *
+ * @discussion
+ * The QOS class and relative priority represent an overall combination of
+ * system quality of service attributes on a thread.
+ *
+ * Subsequent calls to interfaces such as pthread_setschedparam() that are
+ * incompatible or in conflict with the QOS class system will unset the QOS
+ * class requested with this interface and pthread_get_qos_class_np() will
+ * return QOS_CLASS_UNSPECIFIED thereafter. A thread so modified is permanently
+ * opted-out of the QOS class system and calls to this function to request a QOS
+ * class for such a thread will fail and return EPERM.
+ *
+ * @param __qos_class
+ * A QOS class value:
+ * - QOS_CLASS_USER_INTERACTIVE
+ * - QOS_CLASS_USER_INITIATED
+ * - QOS_CLASS_DEFAULT
+ * - QOS_CLASS_UTILITY
+ * - QOS_CLASS_BACKGROUND
+ * EINVAL will be returned if any other value is provided.
+ *
+ * @param __relative_priority
+ * A relative priority within the QOS class. This value is a negative offset
+ * from the maximum supported scheduler priority for the given class.
+ * EINVAL will be returned if the value is greater than zero or less than
+ * QOS_MIN_RELATIVE_PRIORITY.
+ *
+ * @return
+ * Zero if successful, otherwise an errno value.
+ */
+__API_AVAILABLE(macos(10.10), ios(8.0))
+int
+pthread_set_qos_class_self_np(qos_class_t __qos_class,
+ int __relative_priority);
+
+/*!
+ * @function pthread_get_qos_class_np
+ *
+ * @abstract
+ * Gets the requested QOS class and relative priority of a thread.
+ *
+ * @param __pthread
+ * The target thread to inspect.
+ *
+ * @param __qos_class
+ * On output, a QOS class value:
+ * - QOS_CLASS_USER_INTERACTIVE
+ * - QOS_CLASS_USER_INITIATED
+ * - QOS_CLASS_DEFAULT
+ * - QOS_CLASS_UTILITY
+ * - QOS_CLASS_BACKGROUND
+ * - QOS_CLASS_UNSPECIFIED
+ * This value may be NULL in which case no value is returned.
+ *
+ * @param __relative_priority
+ * On output, a relative priority offset within the QOS class.
+ * This value may be NULL in which case no value is returned.
+ *
+ * @return
+ * Zero if successful, otherwise an errno value.
+ */
+__API_AVAILABLE(macos(10.10), ios(8.0))
+int
+pthread_get_qos_class_np(pthread_t __pthread,
+ qos_class_t * _Nullable __restrict __qos_class,
+ int * _Nullable __restrict __relative_priority);
+
+/*!
+ * @typedef pthread_override_t
+ *
+ * @abstract
+ * An opaque object representing a QOS class override of a thread.
+ *
+ * @discussion
+ * A QOS class override of a target thread expresses that an item of pending
+ * work classified with a specific QOS class and relative priority depends on
+ * the completion of the work currently being executed by the thread (e.g. due
+ * to ordering requirements).
+ *
+ * While overrides are in effect, the target thread will execute at the maximum
+ * QOS class and relative priority of all overrides and of the QOS class
+ * requested by the thread itself.
+ *
+ * A QOS class override does not modify the target thread's requested QOS class
+ * value and the effect of an override is not visible to the qos_class_self()
+ * and pthread_get_qos_class_np() interfaces.
+ */
+
+typedef struct pthread_override_s* pthread_override_t;
+
+/*!
+ * @function pthread_override_qos_class_start_np
+ *
+ * @abstract
+ * Starts a QOS class override of the specified target thread.
+ *
+ * @discussion
+ * Starting a QOS class override of the specified target thread expresses that
+ * an item of pending work classified with the specified QOS class and relative
+ * priority depends on the completion of the work currently being executed by
+ * the thread (e.g. due to ordering requirements).
+ *
+ * While overrides are in effect, the specified target thread will execute at
+ * the maximum QOS class and relative priority of all overrides and of the QOS
+ * class requested by the thread itself.
+ *
+ * Starting a QOS class override does not modify the target thread's requested
+ * QOS class value and the effect of an override is not visible to the
+ * qos_class_self() and pthread_get_qos_class_np() interfaces.
+ *
+ * The returned newly allocated override object is intended to be associated
+ * with the item of pending work in question. Once the dependency has been
+ * satisfied and enabled that work to begin executing, the QOS class override
+ * must be ended by passing the associated override object to
+ * pthread_override_qos_class_end_np(). Failure to do so will result in the
+ * associated resources to be leaked and the target thread to be permanently
+ * executed at an inappropriately elevated QOS class.
+ *
+ * @param __pthread
+ * The target thread to modify.
+ *
+ * @param __qos_class
+ * A QOS class value:
+ * - QOS_CLASS_USER_INTERACTIVE
+ * - QOS_CLASS_USER_INITIATED
+ * - QOS_CLASS_DEFAULT
+ * - QOS_CLASS_UTILITY
+ * - QOS_CLASS_BACKGROUND
+ * NULL will be returned if any other value is provided.
+ *
+ * @param __relative_priority
+ * A relative priority within the QOS class. This value is a negative offset
+ * from the maximum supported scheduler priority for the given class.
+ * NULL will be returned if the value is greater than zero or less than
+ * QOS_MIN_RELATIVE_PRIORITY.
+ *
+ * @return
+ * A newly allocated override object if successful, or NULL if the override
+ * could not be started.
+ */
+__API_AVAILABLE(macos(10.10), ios(8.0))
+pthread_override_t
+pthread_override_qos_class_start_np(pthread_t __pthread,
+ qos_class_t __qos_class, int __relative_priority);
+
+/*!
+ * @function pthread_override_qos_class_end_np
+ *
+ * @abstract
+ * Ends a QOS class override.
+ *
+ * @discussion
+ * Passing an override object returned by pthread_override_qos_class_start_np()
+ * ends the QOS class override started by that call and deallocates all
+ * associated resources as well as the override object itself.
+ *
+ * The thread starting and the thread ending a QOS class override need not be
+ * identical. If the thread ending the override is the the target thread of the
+ * override itself, it should take care to elevate its requested QOS class
+ * appropriately with pthread_set_qos_class_self_np() before ending the
+ * override.
+ *
+ * @param __override
+ * An override object returned by pthread_override_qos_class_start_np().
+ *
+ * @return
+ * Zero if successful, otherwise an errno value.
+ */
+__API_AVAILABLE(macos(10.10), ios(8.0))
+int
+pthread_override_qos_class_end_np(pthread_override_t __override);
+
+__END_DECLS
+#if __has_feature(assume_nonnull)
+_Pragma("clang assume_nonnull end")
+#endif
+
+#endif // KERNEL
+
+#endif // __DARWIN_C_LEVEL >= __DARWIN_C_FULL
+
+#endif // _PTHREAD_QOS_H
--- /dev/null
+/*
+ * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef _SCHED_H_
+#define _SCHED_H_
+
+#include <sys/cdefs.h>
+#include <pthread/pthread_impl.h>
+
+__BEGIN_DECLS
+/*
+ * Scheduling paramters
+ */
+#ifndef __POSIX_LIB__
+struct sched_param { int sched_priority; char __opaque[__SCHED_PARAM_SIZE__]; };
+#else
+struct sched_param;
+#endif
+
+extern int sched_yield(void);
+extern int sched_get_priority_min(int);
+extern int sched_get_priority_max(int);
+__END_DECLS
+
+#endif /* _SCHED_H_ */
+
--- /dev/null
+/*
+ * Copyright (c) 2014 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef _PTHREAD_SPAWN_H
+#define _PTHREAD_SPAWN_H
+
+/*!
+ * @group posix_spawn QOS class support
+ * Apple extensions to posix_spawn(2) and posix_spawnp(2)
+ */
+
+#include <pthread/pthread.h>
+#include <spawn.h>
+
+__BEGIN_DECLS
+
+/*!
+ * @function posix_spawnattr_set_qos_class_np
+ *
+ * @abstract
+ * Sets the QOS class property of a posix_spawn attributes object, which may be
+ * used to specify the QOS class a process should be spawned with.
+ *
+ * @discussion
+ * The QOS class specified at the time of process spawn determines both the
+ * initial requested QOS class of the main thread in the new process, and the
+ * interpretation by the system of all QOS class values requested by threads in
+ * the process.
+ *
+ * @param __attr
+ * The spawn attributes object to modify.
+ *
+ * @param __qos_class
+ * A QOS class value:
+ * - QOS_CLASS_UTILITY
+ * - QOS_CLASS_BACKGROUND
+ * EINVAL will be returned if any other value is provided.
+ *
+ * @return
+ * Zero if successful, otherwise an errno value.
+ */
+__API_AVAILABLE(macos(10.10), ios(8.0))
+int
+posix_spawnattr_set_qos_class_np(posix_spawnattr_t * __restrict __attr,
+ qos_class_t __qos_class);
+
+/*!
+ * @function posix_spawnattr_get_qos_class_np
+ *
+ * @abstract
+ * Gets the QOS class property of a posix_spawn attributes object.
+ *
+ * @param __attr
+ * The spawn attributes object to inspect.
+ *
+ * @param __qos_class
+ * On output, a QOS class value:
+ * - QOS_CLASS_UTILITY
+ * - QOS_CLASS_BACKGROUND
+ * - QOS_CLASS_UNSPECIFIED
+ *
+ * @return
+ * Zero if successful, otherwise an errno value.
+ */
+__API_AVAILABLE(macos(10.10), ios(8.0))
+int
+posix_spawnattr_get_qos_class_np(const posix_spawnattr_t *__restrict __attr,
+ qos_class_t * __restrict __qos_class);
+
+__END_DECLS
+
+#endif // _PTHREAD_SPAWN_H
--- /dev/null
+/*
+ * Copyright (c) 2018 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#ifndef __PTHREAD_STACK_NP__
+#define __PTHREAD_STACK_NP__
+
+#include <Availability.h>
+#include <sys/cdefs.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <os/base.h>
+
+OS_ASSUME_NONNULL_BEGIN
+
+/*! @header
+ * Low-level API to introspect thread stacks.
+ */
+
+__BEGIN_DECLS
+
+/*!
+ * @function pthread_stack_frame_decode_np
+ *
+ * @abstract
+ * Decodes the return address and the next stack frame address
+ * from the given stack frame address.
+ *
+ * @discussion
+ * Validation of the frame address is not performed by this function.
+ * The caller is responsible for making sure the frame address is valid,
+ * for example using pthread_get_stackaddr_np() and pthread_get_stacksize_np().
+ *
+ * @param frame_addr
+ * A valid stack frame address such as __builtin_frame_address(0) or the return
+ * value of a previous call to pthread_stack_frame_decode_np().
+ *
+ * @param return_addr
+ * An optional out paramter that will be filled with the return address stored
+ * at the specified stack frame.
+ *
+ * @returns
+ * This returns the next frame address stored at the specified stack frame.
+ */
+__OSX_AVAILABLE(10.14) __IOS_AVAILABLE(12.0)
+__TVOS_AVAILABLE(12.0) __WATCHOS_AVAILABLE(5.0)
+uintptr_t
+pthread_stack_frame_decode_np(uintptr_t frame_addr,
+ uintptr_t *_Nullable return_addr);
+
+__END_DECLS
+
+OS_ASSUME_NONNULL_END
+
+#endif // __PTHREAD_STACK_NP__
--- /dev/null
+/*
+ * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+#ifndef _PTHREAD_ATTR_T
+#define _PTHREAD_ATTR_T
+#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_attr_t */
+typedef __darwin_pthread_attr_t pthread_attr_t;
+#endif /* _PTHREAD_ATTR_T */
--- /dev/null
+/*
+ * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+#ifndef _PTHREAD_COND_T
+#define _PTHREAD_COND_T
+#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_cond_t */
+typedef __darwin_pthread_cond_t pthread_cond_t;
+#endif /* _PTHREAD_COND_T */
--- /dev/null
+/*
+ * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+#ifndef _PTHREAD_CONDATTR_T
+#define _PTHREAD_CONDATTR_T
+#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_condattr_t */
+typedef __darwin_pthread_condattr_t pthread_condattr_t;
+#endif /* _PTHREAD_CONDATTR_T */
--- /dev/null
+/*
+ * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+#ifndef _PTHREAD_KEY_T
+#define _PTHREAD_KEY_T
+#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_key_t */
+typedef __darwin_pthread_key_t pthread_key_t;
+#endif /* _PTHREAD_KEY_T */
--- /dev/null
+/*
+ * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+#ifndef _PTHREAD_MUTEX_T
+#define _PTHREAD_MUTEX_T
+#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_mutex_t */
+typedef __darwin_pthread_mutex_t pthread_mutex_t;
+#endif /*_PTHREAD_MUTEX_T */
--- /dev/null
+/*
+ * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+#ifndef _PTHREAD_MUTEXATTR_T
+#define _PTHREAD_MUTEXATTR_T
+#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_mutexattr_t */
+typedef __darwin_pthread_mutexattr_t pthread_mutexattr_t;
+#endif /* _PTHREAD_MUTEXATTR_T */
--- /dev/null
+/*
+ * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+#ifndef _PTHREAD_ONCE_T
+#define _PTHREAD_ONCE_T
+#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_once_t */
+typedef __darwin_pthread_once_t pthread_once_t;
+#endif /* _PTHREAD_ONCE_T */
--- /dev/null
+/*
+ * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+#ifndef _PTHREAD_RWLOCK_T
+#define _PTHREAD_RWLOCK_T
+#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_rwlock_t */
+typedef __darwin_pthread_rwlock_t pthread_rwlock_t;
+#endif /* _PTHREAD_RWLOCK_T */
--- /dev/null
+/*
+ * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+#ifndef _PTHREAD_RWLOCKATTR_T
+#define _PTHREAD_RWLOCKATTR_T
+#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_rwlockattr_t */
+typedef __darwin_pthread_rwlockattr_t pthread_rwlockattr_t;
+#endif /* _PTHREAD_RWLOCKATTR_T */
--- /dev/null
+/*
+ * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+#ifndef _PTHREAD_T
+#define _PTHREAD_T
+#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_t */
+typedef __darwin_pthread_t pthread_t;
+#endif /* _PTHREAD_T */
--- /dev/null
+/*
+ * Copyright (c) 2003-2013 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#ifndef _SYS__PTHREAD_TYPES_H_
+#define _SYS__PTHREAD_TYPES_H_
+
+#include <sys/cdefs.h>
+
+// pthread opaque structures
+#if defined(__LP64__)
+#define __PTHREAD_SIZE__ 8176
+#define __PTHREAD_ATTR_SIZE__ 56
+#define __PTHREAD_MUTEXATTR_SIZE__ 8
+#define __PTHREAD_MUTEX_SIZE__ 56
+#define __PTHREAD_CONDATTR_SIZE__ 8
+#define __PTHREAD_COND_SIZE__ 40
+#define __PTHREAD_ONCE_SIZE__ 8
+#define __PTHREAD_RWLOCK_SIZE__ 192
+#define __PTHREAD_RWLOCKATTR_SIZE__ 16
+#else // !__LP64__
+#define __PTHREAD_SIZE__ 4088
+#define __PTHREAD_ATTR_SIZE__ 36
+#define __PTHREAD_MUTEXATTR_SIZE__ 8
+#define __PTHREAD_MUTEX_SIZE__ 40
+#define __PTHREAD_CONDATTR_SIZE__ 4
+#define __PTHREAD_COND_SIZE__ 24
+#define __PTHREAD_ONCE_SIZE__ 4
+#define __PTHREAD_RWLOCK_SIZE__ 124
+#define __PTHREAD_RWLOCKATTR_SIZE__ 12
+#endif // !__LP64__
+
+struct __darwin_pthread_handler_rec {
+ void (*__routine)(void *); // Routine to call
+ void *__arg; // Argument to pass
+ struct __darwin_pthread_handler_rec *__next;
+};
+
+struct _opaque_pthread_attr_t {
+ long __sig;
+ char __opaque[__PTHREAD_ATTR_SIZE__];
+};
+
+struct _opaque_pthread_cond_t {
+ long __sig;
+ char __opaque[__PTHREAD_COND_SIZE__];
+};
+
+struct _opaque_pthread_condattr_t {
+ long __sig;
+ char __opaque[__PTHREAD_CONDATTR_SIZE__];
+};
+
+struct _opaque_pthread_mutex_t {
+ long __sig;
+ char __opaque[__PTHREAD_MUTEX_SIZE__];
+};
+
+struct _opaque_pthread_mutexattr_t {
+ long __sig;
+ char __opaque[__PTHREAD_MUTEXATTR_SIZE__];
+};
+
+struct _opaque_pthread_once_t {
+ long __sig;
+ char __opaque[__PTHREAD_ONCE_SIZE__];
+};
+
+struct _opaque_pthread_rwlock_t {
+ long __sig;
+ char __opaque[__PTHREAD_RWLOCK_SIZE__];
+};
+
+struct _opaque_pthread_rwlockattr_t {
+ long __sig;
+ char __opaque[__PTHREAD_RWLOCKATTR_SIZE__];
+};
+
+struct _opaque_pthread_t {
+ long __sig;
+ struct __darwin_pthread_handler_rec *__cleanup_stack;
+ char __opaque[__PTHREAD_SIZE__];
+};
+
+typedef struct _opaque_pthread_attr_t __darwin_pthread_attr_t;
+typedef struct _opaque_pthread_cond_t __darwin_pthread_cond_t;
+typedef struct _opaque_pthread_condattr_t __darwin_pthread_condattr_t;
+typedef unsigned long __darwin_pthread_key_t;
+typedef struct _opaque_pthread_mutex_t __darwin_pthread_mutex_t;
+typedef struct _opaque_pthread_mutexattr_t __darwin_pthread_mutexattr_t;
+typedef struct _opaque_pthread_once_t __darwin_pthread_once_t;
+typedef struct _opaque_pthread_rwlock_t __darwin_pthread_rwlock_t;
+typedef struct _opaque_pthread_rwlockattr_t __darwin_pthread_rwlockattr_t;
+typedef struct _opaque_pthread_t *__darwin_pthread_t;
+
+#endif // _SYS__PTHREAD_TYPES_H_
--- /dev/null
+/*
+ * Copyright (c) 2013-2014 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef _SYS_QOS_H
+#define _SYS_QOS_H
+
+#include <sys/cdefs.h>
+#include <Availability.h>
+
+/*!
+ * @typedef qos_class_t
+ *
+ * @abstract
+ * An abstract thread quality of service (QOS) classification.
+ *
+ * @discussion
+ * Thread quality of service (QOS) classes are ordered abstract representations
+ * of the nature of work that is expected to be performed by a pthread, dispatch
+ * queue, or NSOperation. Each class specifies a maximum thread scheduling
+ * priority for that band (which may be used in combination with a relative
+ * priority offset within the band), as well as quality of service
+ * characteristics for timer latency, CPU throughput, I/O throughput, network
+ * socket traffic management behavior and more.
+ *
+ * A best effort is made to allocate available system resources to every QOS
+ * class. Quality of service degredation only occurs during system resource
+ * contention, proportionally to the QOS class. That said, QOS classes
+ * representing user-initiated work attempt to achieve peak throughput while
+ * QOS classes for other work attempt to achieve peak energy and thermal
+ * efficiency, even in the absence of contention. Finally, the use of QOS
+ * classes does not allow threads to supersede any limits that may be applied
+ * to the overall process.
+ */
+
+/*!
+ * @constant QOS_CLASS_USER_INTERACTIVE
+ * @abstract A QOS class which indicates work performed by this thread
+ * is interactive with the user.
+ * @discussion Such work is requested to run at high priority relative to other
+ * work on the system. Specifying this QOS class is a request to run with
+ * nearly all available system CPU and I/O bandwidth even under contention.
+ * This is not an energy-efficient QOS class to use for large tasks. The use of
+ * this QOS class should be limited to critical interaction with the user such
+ * as handling events on the main event loop, view drawing, animation, etc.
+ *
+ * @constant QOS_CLASS_USER_INITIATED
+ * @abstract A QOS class which indicates work performed by this thread
+ * was initiated by the user and that the user is likely waiting for the
+ * results.
+ * @discussion Such work is requested to run at a priority below critical user-
+ * interactive work, but relatively higher than other work on the system. This
+ * is not an energy-efficient QOS class to use for large tasks. Its use
+ * should be limited to operations of short enough duration that the user is
+ * unlikely to switch tasks while waiting for the results. Typical
+ * user-initiated work will have progress indicated by the display of
+ * placeholder content or modal user interface.
+ *
+ * @constant QOS_CLASS_DEFAULT
+ * @abstract A default QOS class used by the system in cases where more specific
+ * QOS class information is not available.
+ * @discussion Such work is requested to run at a priority below critical user-
+ * interactive and user-initiated work, but relatively higher than utility and
+ * background tasks. Threads created by pthread_create() without an attribute
+ * specifying a QOS class will default to QOS_CLASS_DEFAULT. This QOS class
+ * value is not intended to be used as a work classification, it should only be
+ * set when propagating or restoring QOS class values provided by the system.
+ *
+ * @constant QOS_CLASS_UTILITY
+ * @abstract A QOS class which indicates work performed by this thread
+ * may or may not be initiated by the user and that the user is unlikely to be
+ * immediately waiting for the results.
+ * @discussion Such work is requested to run at a priority below critical user-
+ * interactive and user-initiated work, but relatively higher than low-level
+ * system maintenance tasks. The use of this QOS class indicates the work
+ * should be run in an energy and thermally-efficient manner. The progress of
+ * utility work may or may not be indicated to the user, but the effect of such
+ * work is user-visible.
+ *
+ * @constant QOS_CLASS_BACKGROUND
+ * @abstract A QOS class which indicates work performed by this thread was not
+ * initiated by the user and that the user may be unaware of the results.
+ * @discussion Such work is requested to run at a priority below other work.
+ * The use of this QOS class indicates the work should be run in the most energy
+ * and thermally-efficient manner.
+ *
+ * @constant QOS_CLASS_UNSPECIFIED
+ * @abstract A QOS class value which indicates the absence or removal of QOS
+ * class information.
+ * @discussion As an API return value, may indicate that threads or pthread
+ * attributes were configured with legacy API incompatible or in conflict with
+ * the QOS class system.
+ */
+
+#define __QOS_ENUM(name, type, ...) enum { __VA_ARGS__ }; typedef type name##_t
+#define __QOS_CLASS_AVAILABLE(...)
+
+#if defined(__cplusplus) || defined(__OBJC__) || __LP64__
+#if defined(__has_feature) && defined(__has_extension)
+#if __has_feature(objc_fixed_enum) || __has_extension(cxx_strong_enums)
+#undef __QOS_ENUM
+#define __QOS_ENUM(name, type, ...) typedef enum : type { __VA_ARGS__ } name##_t
+#endif
+#endif
+#if __has_feature(enumerator_attributes)
+#undef __QOS_CLASS_AVAILABLE
+#define __QOS_CLASS_AVAILABLE __API_AVAILABLE
+#endif
+#endif
+
+__QOS_ENUM(qos_class, unsigned int,
+ QOS_CLASS_USER_INTERACTIVE
+ __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x21,
+ QOS_CLASS_USER_INITIATED
+ __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x19,
+ QOS_CLASS_DEFAULT
+ __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x15,
+ QOS_CLASS_UTILITY
+ __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x11,
+ QOS_CLASS_BACKGROUND
+ __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x09,
+ QOS_CLASS_UNSPECIFIED
+ __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x00,
+);
+
+#undef __QOS_ENUM
+
+/*!
+ * @constant QOS_MIN_RELATIVE_PRIORITY
+ * @abstract The minimum relative priority that may be specified within a
+ * QOS class. These priorities are relative only within a given QOS class
+ * and meaningful only for the current process.
+ */
+#define QOS_MIN_RELATIVE_PRIORITY (-15)
+
+/* Userspace (only) definitions */
+
+#ifndef KERNEL
+
+__BEGIN_DECLS
+
+/*!
+ * @function qos_class_self
+ *
+ * @abstract
+ * Returns the requested QOS class of the current thread.
+ *
+ * @return
+ * One of the QOS class values in qos_class_t.
+ */
+__API_AVAILABLE(macos(10.10), ios(8.0))
+qos_class_t
+qos_class_self(void);
+
+/*!
+ * @function qos_class_main
+ *
+ * @abstract
+ * Returns the initial requested QOS class of the main thread.
+ *
+ * @discussion
+ * The QOS class that the main thread of a process is created with depends on
+ * the type of process (e.g. application or daemon) and on how it has been
+ * launched.
+ *
+ * This function returns that initial requested QOS class value chosen by the
+ * system to enable propagation of that classification to matching work not
+ * executing on the main thread.
+ *
+ * @return
+ * One of the QOS class values in qos_class_t.
+ */
+__API_AVAILABLE(macos(10.10), ios(8.0))
+qos_class_t
+qos_class_main(void);
+
+__END_DECLS
+
+#endif // KERNEL
+
+#endif // _SYS_QOS_H
--- /dev/null
+// Module map for sys/_pthread/_pthread_types.h.
+//
+// Expected to be included as a submodule of the top-level module for stdint.h.
+
+module Darwin_C_stdint._pthread_types {
+ export *
+ header "sys/_pthread/_pthread_types.h"
+}
#include <kern/thread.h>
#include <kern/debug.h>
-#include "kern_internal.h"
+#include "kern/kern_internal.h"
kern_return_t pthread_start(kmod_info_t * ki, void *d);
kern_return_t pthread_stop(kmod_info_t *ki, void *d);
#include <sys/pthread_shims.h>
#include <sys/queue.h>
#include <sys/proc_info.h>
-
-#ifdef __arm64__
-#define PTHREAD_INLINE_RMW_ATOMICS 0
-#else
-#define PTHREAD_INLINE_RMW_ATOMICS 1
-#endif
#endif // KERNEL
#include "kern/synch_internal.h"
-#include "kern/workqueue_internal.h"
#include "kern/kern_trace.h"
#include "pthread/qos.h"
-#include "private/qos_private.h"
+#include "pthread/qos_private.h"
/* pthread userspace SPI feature checking, these constants are returned from bsdthread_register,
* as a bitmask, to inform userspace of the supported feature set. Old releases of OS X return
uint32_t return_to_kernel_offset; /* copy-in */
uint32_t mach_thread_self_offset; /* copy-in */
mach_vm_address_t stack_addr_hint; /* copy-out */
+#define _PTHREAD_REG_DEFAULT_POLICY_MASK 0xff
+#define _PTHREAD_REG_DEFAULT_USE_ULOCK 0x100
+#define _PTHREAD_REG_DEFAULT_USE_ADAPTIVE_SPIN 0x200
uint32_t mutex_default_policy; /* copy-out */
+ uint32_t joinable_offset_bits; /* copy-in */
} __attribute__ ((packed));
/*
#endif // KERNEL
+// magical `nkevents` values for _pthread_wqthread
+#define WORKQ_EXIT_THREAD_NKEVENT (-1)
+
#endif /* _SYS_PTHREAD_INTERNAL_H_ */
#include <machine/machine_routines.h>
#include <mach/shared_region.h>
-#include <libkern/OSAtomic.h>
-#include <libkern/libkern.h>
-
-#include "kern_internal.h"
+#include "kern/kern_internal.h"
#ifndef WQ_SETUP_EXIT_THREAD
#define WQ_SETUP_EXIT_THREAD 8
#include <vm/vm_map.h>
#include <mach/vm_region.h>
-#include <libkern/OSAtomic.h>
-
-#include <pexpert/pexpert.h>
-
-#include "kern_internal.h"
-#include "synch_internal.h"
-#include "kern_trace.h"
+#include "kern/kern_internal.h"
+#include "kern/synch_internal.h"
+#include "kern/kern_trace.h"
typedef struct uthread *uthread_t;
// WQ_TRACE_REQUESTS_SUBCLASS is 2, in xnu
# define _TRACE_SUB_MUTEX 3
# define _TRACE_SUB_CONDVAR 4
+# define _TRACE_SUB_ULMUTEX 5
+# define _TRACE_SUB_ULCOND 6
#ifndef _PTHREAD_BUILDING_CODES_
# define PTHREAD_TRACE(x,a,b,c,d) \
{ if (pthread_debug_tracing) { KERNEL_DEBUG_CONSTANT(TRACE_##x, a, b, c, d, 0); } }
-# define PTHREAD_TRACE_WQ(x,a,b,c,d) \
- { if (pthread_debug_tracing) { KERNEL_DEBUG_CONSTANT(TRACE_##x, VM_UNSLIDE(a), b, c, d, 0); } }
-
-# define PTHREAD_TRACE_WQ_REQ(x,a,b,c,d,e) \
- { if (pthread_debug_tracing) { KERNEL_DEBUG_CONSTANT(TRACE_##x, VM_UNSLIDE(a), VM_UNSLIDE(b), c, d, e); } }
-
#else // KERNEL
#if ENABLE_USERSPACE_TRACE
TRACE_CODE(pthread_thread_terminate, _TRACE_SUB_DEFAULT, 0x20);
TRACE_CODE(pthread_set_qos_self, _TRACE_SUB_DEFAULT, 0x30);
-// workqueue trace points
-TRACE_CODE(wq_pthread_exit, _TRACE_SUB_WORKQUEUE, 0x01);
-TRACE_CODE(wq_workqueue_exit, _TRACE_SUB_WORKQUEUE, 0x02);
-TRACE_CODE(wq_runthread, _TRACE_SUB_WORKQUEUE, 0x03);
-TRACE_CODE(wq_runitem, _TRACE_SUB_WORKQUEUE, 0x04);
-TRACE_CODE(wq_thread_block, _TRACE_SUB_WORKQUEUE, 0x9);
-TRACE_CODE(wq_thactive_update, _TRACE_SUB_WORKQUEUE, 0xa);
-TRACE_CODE(wq_add_timer, _TRACE_SUB_WORKQUEUE, 0xb);
-TRACE_CODE(wq_start_add_timer, _TRACE_SUB_WORKQUEUE, 0x0c);
-TRACE_CODE(wq_override_start, _TRACE_SUB_WORKQUEUE, 0x12);
-TRACE_CODE(wq_override_end, _TRACE_SUB_WORKQUEUE, 0x13);
-TRACE_CODE(wq_override_dispatch, _TRACE_SUB_WORKQUEUE, 0x14);
-TRACE_CODE(wq_override_reset, _TRACE_SUB_WORKQUEUE, 0x15);
-TRACE_CODE(wq_thread_create_failed, _TRACE_SUB_WORKQUEUE, 0x1d);
-TRACE_CODE(wq_thread_create, _TRACE_SUB_WORKQUEUE, 0x1f);
-TRACE_CODE(wq_run_threadreq, _TRACE_SUB_WORKQUEUE, 0x20);
-TRACE_CODE(wq_run_threadreq_mgr_merge, _TRACE_SUB_WORKQUEUE, 0x21);
-TRACE_CODE(wq_run_threadreq_req_select, _TRACE_SUB_WORKQUEUE, 0x22);
-TRACE_CODE(wq_run_threadreq_thread_select, _TRACE_SUB_WORKQUEUE, 0x23);
-TRACE_CODE(wq_thread_reset_priority, _TRACE_SUB_WORKQUEUE, 0x24);
-TRACE_CODE(wq_constrained_admission, _TRACE_SUB_WORKQUEUE, 0x25);
-TRACE_CODE(wq_wqops_reqthreads, _TRACE_SUB_WORKQUEUE, 0x26);
-TRACE_CODE(wq_kevent_reqthreads, _TRACE_SUB_WORKQUEUE, 0x27);
-TRACE_CODE(wq_thread_park, _TRACE_SUB_WORKQUEUE, 0x28);
-TRACE_CODE(wq_thread_squash, _TRACE_SUB_WORKQUEUE, 0x29);
-
// synch trace points
TRACE_CODE(psynch_mutex_ulock, _TRACE_SUB_MUTEX, 0x0);
TRACE_CODE(psynch_mutex_utrylock_failed, _TRACE_SUB_MUTEX, 0x1);
TRACE_CODE(psynch_cvar_zeroed, _TRACE_SUB_CONDVAR, 0x6);
TRACE_CODE(psynch_cvar_updateval, _TRACE_SUB_CONDVAR, 0x7);
+TRACE_CODE(ulmutex_lock, _TRACE_SUB_ULMUTEX, 0x0);
+TRACE_CODE(ulmutex_trylock, _TRACE_SUB_ULMUTEX, 0x1);
+TRACE_CODE(ulmutex_lock_wait, _TRACE_SUB_ULMUTEX, 0x2);
+TRACE_CODE(ulmutex_unlock, _TRACE_SUB_ULMUTEX, 0x3);
+TRACE_CODE(ulmutex_unlock_wake, _TRACE_SUB_ULMUTEX, 0x4);
+TRACE_CODE(ulmutex_unlock_steal, _TRACE_SUB_ULMUTEX, 0x5);
+
+TRACE_CODE(ulcond_wait, _TRACE_SUB_ULCOND, 0x0);
+TRACE_CODE(ulcond_signal, _TRACE_SUB_ULCOND, 0x1);
+
#endif // _KERN_TRACE_H_
+++ /dev/null
-/*
- * Copyright (c) 2014 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-
-#ifndef _WORKQUEUE_INTERNAL_H_
-#define _WORKQUEUE_INTERNAL_H_
-
-/* These definitions are shared between the kext and userspace inside the pthread project. Consolidating
- * duplicate definitions that used to exist in both projects, when separate.
- */
-
-// Sometimes something gets passed a bucket number and we need a way to express
-// that it's actually the event manager. Use the (0)th bucket for that.
-#define WORKQ_THREAD_QOS_MIN (THREAD_QOS_MAINTENANCE)
-#define WORKQ_THREAD_QOS_MAX (THREAD_QOS_LAST - 1)
-#define WORKQ_THREAD_QOS_CLEANUP (THREAD_QOS_LEGACY)
-#define WORKQ_THREAD_QOS_MANAGER (THREAD_QOS_LAST) // outside of MIN/MAX
-
-#define WORKQ_NUM_QOS_BUCKETS (WORKQ_THREAD_QOS_MAX)
-#define WORKQ_NUM_BUCKETS (WORKQ_THREAD_QOS_MAX + 1)
-#define WORKQ_IDX(qos) ((qos) - 1) // 0 based index
-
-// magical `nkevents` values for _pthread_wqthread
-#define WORKQ_EXIT_THREAD_NKEVENT (-1)
-
-#endif // _WORKQUEUE_INTERNAL_H_
/* Begin PBXBuildFile section */
6E2A3BBE2101222F0003B53B /* stack_np.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E2A3BBD210122230003B53B /* stack_np.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 6E2A3BBF210122300003B53B /* stack_np.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E2A3BBD210122230003B53B /* stack_np.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 6E2A3BBF210122300003B53B /* stack_np.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E2A3BBD210122230003B53B /* stack_np.h */; };
6E2A3BC0210122340003B53B /* stack_np.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E2A3BBD210122230003B53B /* stack_np.h */; };
6E5869C720C9040A00F1CB75 /* dependency_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E5869C620C8FE8300F1CB75 /* dependency_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 6E5869C820C9040B00F1CB75 /* dependency_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E5869C620C8FE8300F1CB75 /* dependency_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 6E5869C820C9040B00F1CB75 /* dependency_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E5869C620C8FE8300F1CB75 /* dependency_private.h */; };
6E5869C920C9040C00F1CB75 /* dependency_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E5869C620C8FE8300F1CB75 /* dependency_private.h */; };
6E5869CB20C9043200F1CB75 /* pthread_dependency.c in Sources */ = {isa = PBXBuildFile; fileRef = 6E5869CA20C9043200F1CB75 /* pthread_dependency.c */; };
6E5869CC20C9043B00F1CB75 /* pthread_dependency.c in Sources */ = {isa = PBXBuildFile; fileRef = 6E5869CA20C9043200F1CB75 /* pthread_dependency.c */; };
6E8C165C1B14F08A00C8987C /* pthread_rwlock.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F615B7513200270056 /* pthread_rwlock.c */; };
6E8C165D1B14F08A00C8987C /* pthread_tsd.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F815B7513200270056 /* pthread_tsd.c */; };
6E8C165E1B14F08A00C8987C /* pthread_cancelable_cancel.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A1BF5215C9A9F5006BB313 /* pthread_cancelable_cancel.c */; };
- 6E8C165F1B14F08A00C8987C /* pthread_cancelable_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A1BF5415C9CB9D006BB313 /* pthread_cancelable_legacy.c */; };
- 6E8C16601B14F08A00C8987C /* pthread_cond_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5D615C9CECA0098ECD8 /* pthread_cond_legacy.c */; };
- 6E8C16611B14F08A00C8987C /* pthread_mutex_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5D815C9CEEA0098ECD8 /* pthread_mutex_legacy.c */; };
- 6E8C16621B14F08A00C8987C /* pthread_rwlock_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5DA15C9CEFA0098ECD8 /* pthread_rwlock_legacy.c */; };
6E8C16651B14F08A00C8987C /* pthread_atfork.c in Sources */ = {isa = PBXBuildFile; fileRef = C90E7AB415DC40D900A06D48 /* pthread_atfork.c */; };
6E8C16661B14F08A00C8987C /* pthread_asm.s in Sources */ = {isa = PBXBuildFile; fileRef = C99AD87D15DF04D10009A6F8 /* pthread_asm.s */; };
6E8C16691B14F08A00C8987C /* qos.h in Headers */ = {isa = PBXBuildFile; fileRef = C9244C1A185FCFED00075748 /* qos.h */; };
6EB232CC1B0EB2F0005915CE /* resolver.c in Sources */ = {isa = PBXBuildFile; fileRef = 6EB232C91B0EB29D005915CE /* resolver.c */; };
6EB232CE1B0EB31B005915CE /* resolver.c in Sources */ = {isa = PBXBuildFile; fileRef = 6EB232C91B0EB29D005915CE /* resolver.c */; };
6EB232D01B0EB325005915CE /* resolver.c in Sources */ = {isa = PBXBuildFile; fileRef = 6EB232C91B0EB29D005915CE /* resolver.c */; };
+ 6ED6E65522BFCD1200CE82C2 /* internal.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325F315B7513200270056 /* internal.h */; };
+ 6ED6E65622BFCD1200CE82C2 /* types_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED6E63F22BFC64700CE82C2 /* types_internal.h */; };
+ 6ED6E65722BFCD1200CE82C2 /* offsets_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E514A0220B67C0900844EE1 /* offsets_internal.h */; };
+ 6ED6E65822BFCD1300CE82C2 /* internal.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325F315B7513200270056 /* internal.h */; };
+ 6ED6E65922BFCD1300CE82C2 /* types_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED6E63F22BFC64700CE82C2 /* types_internal.h */; };
+ 6ED6E65A22BFCD1300CE82C2 /* offsets_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E514A0220B67C0900844EE1 /* offsets_internal.h */; };
+ 6ED6E65B22BFCD1400CE82C2 /* internal.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325F315B7513200270056 /* internal.h */; };
+ 6ED6E65C22BFCD1400CE82C2 /* types_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED6E63F22BFC64700CE82C2 /* types_internal.h */; };
+ 6ED6E65D22BFCD1400CE82C2 /* offsets_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E514A0220B67C0900844EE1 /* offsets_internal.h */; };
+ 6ED6E66022BFF81D00CE82C2 /* exports_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED6E65F22BFF5A500CE82C2 /* exports_internal.h */; };
+ 6ED6E66122BFF81D00CE82C2 /* inline_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED6E65E22BFF03C00CE82C2 /* inline_internal.h */; };
+ 6ED6E66222BFF81E00CE82C2 /* exports_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED6E65F22BFF5A500CE82C2 /* exports_internal.h */; };
+ 6ED6E66322BFF81E00CE82C2 /* inline_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED6E65E22BFF03C00CE82C2 /* inline_internal.h */; };
+ 6ED6E66422BFF81F00CE82C2 /* exports_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED6E65F22BFF5A500CE82C2 /* exports_internal.h */; };
+ 6ED6E66522BFF81F00CE82C2 /* inline_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED6E65E22BFF03C00CE82C2 /* inline_internal.h */; };
+ 6ED6E66D22BFFC3700CE82C2 /* imports_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED6E66C22BFFC3200CE82C2 /* imports_internal.h */; };
+ 6ED6E66E22BFFC3700CE82C2 /* imports_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED6E66C22BFFC3200CE82C2 /* imports_internal.h */; };
+ 6ED6E66F22BFFC3800CE82C2 /* imports_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED6E66C22BFFC3200CE82C2 /* imports_internal.h */; };
+ 6ED6E67422C0034300CE82C2 /* prototypes_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED6E67322C0033B00CE82C2 /* prototypes_internal.h */; };
+ 6ED6E67522C0034300CE82C2 /* prototypes_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED6E67322C0033B00CE82C2 /* prototypes_internal.h */; };
+ 6ED6E67622C0034400CE82C2 /* prototypes_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED6E67322C0033B00CE82C2 /* prototypes_internal.h */; };
74E594931613AAF4006C417B /* pthread.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325FA15B7513200270056 /* pthread.c */; };
74E594941613AAF4006C417B /* pthread_cancelable.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F115B7513200270056 /* pthread_cancelable.c */; };
74E594951613AAF4006C417B /* pthread_cond.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F215B7513200270056 /* pthread_cond.c */; };
C9244C1D1860D8EF00075748 /* qos.c in Sources */ = {isa = PBXBuildFile; fileRef = C9244C1C1860D8EF00075748 /* qos.c */; };
C9244C1E1860D96D00075748 /* qos.c in Sources */ = {isa = PBXBuildFile; fileRef = C9244C1C1860D8EF00075748 /* qos.c */; };
C9244C1F1860D96E00075748 /* qos.c in Sources */ = {isa = PBXBuildFile; fileRef = C9244C1C1860D8EF00075748 /* qos.c */; };
- C975D5D715C9CECA0098ECD8 /* pthread_cond_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5D615C9CECA0098ECD8 /* pthread_cond_legacy.c */; };
- C975D5D915C9CEEA0098ECD8 /* pthread_mutex_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5D815C9CEEA0098ECD8 /* pthread_mutex_legacy.c */; };
- C975D5DB15C9CEFA0098ECD8 /* pthread_rwlock_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5DA15C9CEFA0098ECD8 /* pthread_rwlock_legacy.c */; };
C98C95D918FF1F4E005654FB /* spawn.h in Headers */ = {isa = PBXBuildFile; fileRef = C98C95D818FF1F4E005654FB /* spawn.h */; settings = {ATTRIBUTES = (Public, ); }; };
C99AD87B15DEC4BC0009A6F8 /* posix_sched.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325F015B7513200270056 /* posix_sched.h */; settings = {ATTRIBUTES = (Private, ); }; };
C99AD87C15DEC5290009A6F8 /* spinlock_private.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325F715B7513200270056 /* spinlock_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
C9A1BF4F15C9A598006BB313 /* pthread_spis.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A3260015B7513700270056 /* pthread_spis.h */; settings = {ATTRIBUTES = (Public, ); }; };
C9A1BF5015C9A59B006BB313 /* sched.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A3260115B7513700270056 /* sched.h */; settings = {ATTRIBUTES = (Public, ); }; };
C9A1BF5315C9A9F5006BB313 /* pthread_cancelable_cancel.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A1BF5215C9A9F5006BB313 /* pthread_cancelable_cancel.c */; };
- C9A1BF5515C9CB9D006BB313 /* pthread_cancelable_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A1BF5415C9CB9D006BB313 /* pthread_cancelable_legacy.c */; };
C9BB478B15E6ABD900F135B7 /* workqueue_private.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325F915B7513200270056 /* workqueue_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
C9BB478D15E6ADF700F135B7 /* tsd_private.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325F415B7513200270056 /* tsd_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
C9CCFB9D18B6D0910060CAAE /* qos_private.h in Headers */ = {isa = PBXBuildFile; fileRef = C99B17DA189C2E1B00991D38 /* qos_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
E4F449B11E82D03500A7FB9A /* pthread_cwd.c in Sources */ = {isa = PBXBuildFile; fileRef = 924D8EDE1C11832A002AC2BC /* pthread_cwd.c */; };
E4F449B21E82D03500A7FB9A /* pthread_tsd.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F815B7513200270056 /* pthread_tsd.c */; };
E4F449B31E82D03500A7FB9A /* pthread_cancelable_cancel.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A1BF5215C9A9F5006BB313 /* pthread_cancelable_cancel.c */; };
- E4F449B41E82D03500A7FB9A /* pthread_cancelable_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A1BF5415C9CB9D006BB313 /* pthread_cancelable_legacy.c */; };
- E4F449B51E82D03500A7FB9A /* pthread_cond_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5D615C9CECA0098ECD8 /* pthread_cond_legacy.c */; };
- E4F449B61E82D03500A7FB9A /* pthread_mutex_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5D815C9CEEA0098ECD8 /* pthread_mutex_legacy.c */; };
- E4F449B71E82D03500A7FB9A /* pthread_rwlock_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5DA15C9CEFA0098ECD8 /* pthread_rwlock_legacy.c */; };
E4F449BA1E82D03500A7FB9A /* pthread_atfork.c in Sources */ = {isa = PBXBuildFile; fileRef = C90E7AB415DC40D900A06D48 /* pthread_atfork.c */; };
E4F449BB1E82D03500A7FB9A /* pthread_asm.s in Sources */ = {isa = PBXBuildFile; fileRef = C99AD87D15DF04D10009A6F8 /* pthread_asm.s */; };
- E4F449BE1E82D03500A7FB9A /* qos.h in Headers */ = {isa = PBXBuildFile; fileRef = C9244C1A185FCFED00075748 /* qos.h */; settings = {ATTRIBUTES = (Public, ); }; };
- E4F449BF1E82D03500A7FB9A /* pthread.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325FE15B7513700270056 /* pthread.h */; settings = {ATTRIBUTES = (Public, ); }; };
- E4F449C01E82D03500A7FB9A /* pthread_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325FF15B7513700270056 /* pthread_impl.h */; settings = {ATTRIBUTES = (Public, ); }; };
- E4F449C11E82D03500A7FB9A /* qos.h in Headers */ = {isa = PBXBuildFile; fileRef = E4063CF21906B4FB000202F9 /* qos.h */; settings = {ATTRIBUTES = (Private, ); }; };
- E4F449C21E82D03500A7FB9A /* pthread_spis.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A3260015B7513700270056 /* pthread_spis.h */; settings = {ATTRIBUTES = (Public, ); }; };
- E4F449C31E82D03500A7FB9A /* introspection.h in Headers */ = {isa = PBXBuildFile; fileRef = 9202B2301D1A5B3F00945880 /* introspection.h */; settings = {ATTRIBUTES = (Public, ); }; };
- E4F449C41E82D03500A7FB9A /* sched.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A3260115B7513700270056 /* sched.h */; settings = {ATTRIBUTES = (Public, ); }; };
- E4F449C51E82D03500A7FB9A /* introspection_private.h in Headers */ = {isa = PBXBuildFile; fileRef = E4657D4017284F7B007D1847 /* introspection_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
- E4F449C61E82D03500A7FB9A /* tsd_private.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325F415B7513200270056 /* tsd_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
- E4F449C71E82D03500A7FB9A /* posix_sched.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325F015B7513200270056 /* posix_sched.h */; settings = {ATTRIBUTES = (Private, ); }; };
- E4F449C81E82D03500A7FB9A /* qos_private.h in Headers */ = {isa = PBXBuildFile; fileRef = C99B17DA189C2E1B00991D38 /* qos_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
- E4F449C91E82D03500A7FB9A /* spawn.h in Headers */ = {isa = PBXBuildFile; fileRef = C98C95D818FF1F4E005654FB /* spawn.h */; settings = {ATTRIBUTES = (Public, ); }; };
- E4F449CA1E82D03500A7FB9A /* spinlock_private.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325F715B7513200270056 /* spinlock_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
- E4F449CB1E82D03500A7FB9A /* workqueue_private.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325F915B7513200270056 /* workqueue_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
- E4F449CC1E82D03500A7FB9A /* private.h in Headers */ = {isa = PBXBuildFile; fileRef = C9153095167ACC22006BB094 /* private.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ E4F449BE1E82D03500A7FB9A /* qos.h in Headers */ = {isa = PBXBuildFile; fileRef = C9244C1A185FCFED00075748 /* qos.h */; };
+ E4F449BF1E82D03500A7FB9A /* pthread.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325FE15B7513700270056 /* pthread.h */; };
+ E4F449C01E82D03500A7FB9A /* pthread_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325FF15B7513700270056 /* pthread_impl.h */; };
+ E4F449C11E82D03500A7FB9A /* qos.h in Headers */ = {isa = PBXBuildFile; fileRef = E4063CF21906B4FB000202F9 /* qos.h */; };
+ E4F449C21E82D03500A7FB9A /* pthread_spis.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A3260015B7513700270056 /* pthread_spis.h */; };
+ E4F449C31E82D03500A7FB9A /* introspection.h in Headers */ = {isa = PBXBuildFile; fileRef = 9202B2301D1A5B3F00945880 /* introspection.h */; };
+ E4F449C41E82D03500A7FB9A /* sched.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A3260115B7513700270056 /* sched.h */; };
+ E4F449C51E82D03500A7FB9A /* introspection_private.h in Headers */ = {isa = PBXBuildFile; fileRef = E4657D4017284F7B007D1847 /* introspection_private.h */; };
+ E4F449C61E82D03500A7FB9A /* tsd_private.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325F415B7513200270056 /* tsd_private.h */; };
+ E4F449C71E82D03500A7FB9A /* posix_sched.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325F015B7513200270056 /* posix_sched.h */; };
+ E4F449C81E82D03500A7FB9A /* qos_private.h in Headers */ = {isa = PBXBuildFile; fileRef = C99B17DA189C2E1B00991D38 /* qos_private.h */; };
+ E4F449C91E82D03500A7FB9A /* spawn.h in Headers */ = {isa = PBXBuildFile; fileRef = C98C95D818FF1F4E005654FB /* spawn.h */; };
+ E4F449CA1E82D03500A7FB9A /* spinlock_private.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325F715B7513200270056 /* spinlock_private.h */; };
+ E4F449CB1E82D03500A7FB9A /* workqueue_private.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325F915B7513200270056 /* workqueue_private.h */; };
+ E4F449CC1E82D03500A7FB9A /* private.h in Headers */ = {isa = PBXBuildFile; fileRef = C9153095167ACC22006BB094 /* private.h */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
/* Begin PBXFileReference section */
6E2A3BBD210122230003B53B /* stack_np.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stack_np.h; sourceTree = "<group>"; };
- 6E514A0220B67C0900844EE1 /* offsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = offsets.h; sourceTree = "<group>"; };
+ 6E39974822D3C82C0057625B /* pthread_driverkit.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = pthread_driverkit.xcconfig; sourceTree = "<group>"; };
+ 6E514A0220B67C0900844EE1 /* offsets_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = offsets_internal.h; sourceTree = "<group>"; };
6E5869C620C8FE8300F1CB75 /* dependency_private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dependency_private.h; sourceTree = "<group>"; };
6E5869CA20C9043200F1CB75 /* pthread_dependency.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = pthread_dependency.c; sourceTree = "<group>"; };
6E8C16801B14F08A00C8987C /* libsystem_pthread.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libsystem_pthread.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
6E8C16851B14F14000C8987C /* pthread_introspection.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = pthread_introspection.xcconfig; sourceTree = "<group>"; };
6EB232C91B0EB29D005915CE /* resolver.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = resolver.c; sourceTree = "<group>"; };
6EB232CA1B0EB29D005915CE /* resolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resolver.h; sourceTree = "<group>"; };
+ 6ED6E63F22BFC64700CE82C2 /* types_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types_internal.h; sourceTree = "<group>"; };
+ 6ED6E65E22BFF03C00CE82C2 /* inline_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = inline_internal.h; sourceTree = "<group>"; };
+ 6ED6E65F22BFF5A500CE82C2 /* exports_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = exports_internal.h; sourceTree = "<group>"; };
+ 6ED6E66C22BFFC3200CE82C2 /* imports_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imports_internal.h; sourceTree = "<group>"; };
+ 6ED6E67322C0033B00CE82C2 /* prototypes_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = prototypes_internal.h; sourceTree = "<group>"; };
74E594A41613AAF4006C417B /* libpthread_eOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpthread_eOS.a; sourceTree = BUILT_PRODUCTS_DIR; };
9202B2301D1A5B3F00945880 /* introspection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = introspection.h; sourceTree = "<group>"; };
9235CA551CA48D010015C92B /* kext_development.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = kext_development.xcconfig; sourceTree = "<group>"; };
C948FCEF15D187FA00180BF5 /* pthread_setcancelstate.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = pthread_setcancelstate.3; sourceTree = "<group>"; };
C948FCF015D187FA00180BF5 /* pthread_setspecific.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = pthread_setspecific.3; sourceTree = "<group>"; };
C948FCF115D187FA00180BF5 /* pthread.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = pthread.3; sourceTree = "<group>"; };
- C975D5D615C9CECA0098ECD8 /* pthread_cond_legacy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pthread_cond_legacy.c; sourceTree = "<group>"; };
- C975D5D815C9CEEA0098ECD8 /* pthread_mutex_legacy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pthread_mutex_legacy.c; sourceTree = "<group>"; };
- C975D5DA15C9CEFA0098ECD8 /* pthread_rwlock_legacy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pthread_rwlock_legacy.c; sourceTree = "<group>"; };
C979E9FB18A1BC2A000951E5 /* kern_trace.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = kern_trace.h; sourceTree = "<group>"; };
C979E9FC18A2BF2C000951E5 /* install-codes.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "install-codes.sh"; sourceTree = "<group>"; };
- C98005141899BD2000368E4D /* workqueue_internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = workqueue_internal.h; sourceTree = "<group>"; };
C98C95D818FF1F4E005654FB /* spawn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = spawn.h; sourceTree = "<group>"; };
C99AD87D15DF04D10009A6F8 /* pthread_asm.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = pthread_asm.s; sourceTree = "<group>"; };
C99B17DA189C2E1B00991D38 /* qos_private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = qos_private.h; sourceTree = "<group>"; };
C99EA612161F8288003EBC56 /* eos.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = eos.xcconfig; sourceTree = "<group>"; };
C9A1998A1C8E271F00CE102A /* tests */ = {isa = PBXFileReference; lastKnownFileType = folder; path = tests; sourceTree = "<group>"; };
C9A1BF5215C9A9F5006BB313 /* pthread_cancelable_cancel.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pthread_cancelable_cancel.c; sourceTree = "<group>"; };
- C9A1BF5415C9CB9D006BB313 /* pthread_cancelable_legacy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pthread_cancelable_legacy.c; sourceTree = "<group>"; };
C9A325E215B7347000270056 /* libsystem_pthread.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libsystem_pthread.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
C9A325EF15B7513200270056 /* plockstat.d */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.dtrace; path = plockstat.d; sourceTree = "<group>"; };
C9A325F015B7513200270056 /* posix_sched.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = posix_sched.h; sourceTree = "<group>"; };
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ 6E8C8C2E22BDC9DE00136359 /* pthread */ = {
+ isa = PBXGroup;
+ children = (
+ 6E5869C620C8FE8300F1CB75 /* dependency_private.h */,
+ E4657D4017284F7B007D1847 /* introspection_private.h */,
+ C9A325F015B7513200270056 /* posix_sched.h */,
+ C9153095167ACC22006BB094 /* private.h */,
+ C99B17DA189C2E1B00991D38 /* qos_private.h */,
+ E4063CF21906B4FB000202F9 /* qos.h */,
+ C9A325F715B7513200270056 /* spinlock_private.h */,
+ C9A325F415B7513200270056 /* tsd_private.h */,
+ C9A325F915B7513200270056 /* workqueue_private.h */,
+ );
+ path = pthread;
+ sourceTree = "<group>";
+ };
+ 6E8C8C2F22BDCD4600136359 /* include */ = {
+ isa = PBXGroup;
+ children = (
+ C9A325FD15B7513700270056 /* pthread */,
+ FC5A372217CEB3D6008C323E /* sys */,
+ );
+ path = include;
+ sourceTree = "<group>";
+ };
+ 6E8C8C3022BDD05700136359 /* sys */ = {
+ isa = PBXGroup;
+ children = (
+ A98FE72D19479F7C007718DA /* qos_private.h */,
+ );
+ path = sys;
+ sourceTree = "<group>";
+ };
9240BF331AA669EB003C99B4 /* tools */ = {
isa = PBXGroup;
children = (
C9169DDC1603DE84005A2F8C /* kern_support.c */,
C979E9FB18A1BC2A000951E5 /* kern_trace.h */,
FC30E28D16A747AD00A25B5F /* synch_internal.h */,
- C98005141899BD2000368E4D /* workqueue_internal.h */,
);
path = kern;
sourceTree = "<group>";
isa = PBXGroup;
children = (
C9A1BF5215C9A9F5006BB313 /* pthread_cancelable_cancel.c */,
- C9A1BF5415C9CB9D006BB313 /* pthread_cancelable_legacy.c */,
- C975D5D615C9CECA0098ECD8 /* pthread_cond_legacy.c */,
- C975D5D815C9CEEA0098ECD8 /* pthread_mutex_legacy.c */,
- C975D5DA15C9CEFA0098ECD8 /* pthread_rwlock_legacy.c */,
);
path = variants;
sourceTree = "<group>";
C9A325D715B7347000270056 = {
isa = PBXGroup;
children = (
- C9169DD91603DE68005A2F8C /* kern */,
- C9A960B218452B0700AE10C8 /* lldbmacros */,
- C9A325FD15B7513700270056 /* pthread */,
- FC5A372217CEB3D6008C323E /* sys */,
+ 6E8C8C2F22BDCD4600136359 /* include */,
C9D70EBE167AC7D100D52713 /* private */,
- C948FCC015D187AD00180BF5 /* man */,
+ C9169DD91603DE68005A2F8C /* kern */,
C9A325ED15B74FB600270056 /* src */,
C9A1998A1C8E271F00CE102A /* tests */,
+ C9A960B218452B0700AE10C8 /* lldbmacros */,
+ C948FCC015D187AD00180BF5 /* man */,
9240BF331AA669EB003C99B4 /* tools */,
C9A3260B15B759A100270056 /* xcodescripts */,
C9CA27DA1602813000259F78 /* Frameworks */,
C9A325ED15B74FB600270056 /* src */ = {
isa = PBXGroup;
children = (
- 6E514A0220B67C0900844EE1 /* offsets.h */,
C9A325F315B7513200270056 /* internal.h */,
+ 6ED6E63F22BFC64700CE82C2 /* types_internal.h */,
+ 6E514A0220B67C0900844EE1 /* offsets_internal.h */,
+ 6ED6E66C22BFFC3200CE82C2 /* imports_internal.h */,
+ 6ED6E67322C0033B00CE82C2 /* prototypes_internal.h */,
+ 6ED6E65F22BFF5A500CE82C2 /* exports_internal.h */,
+ 6ED6E65E22BFF03C00CE82C2 /* inline_internal.h */,
C9A325EF15B7513200270056 /* plockstat.d */,
C9A325FA15B7513200270056 /* pthread.c */,
C99AD87D15DF04D10009A6F8 /* pthread_asm.s */,
isa = PBXGroup;
children = (
9202B2301D1A5B3F00945880 /* introspection.h */,
- C9A325FE15B7513700270056 /* pthread.h */,
C9A325FF15B7513700270056 /* pthread_impl.h */,
C9A3260015B7513700270056 /* pthread_spis.h */,
+ C9A325FE15B7513700270056 /* pthread.h */,
+ C9244C1A185FCFED00075748 /* qos.h */,
C9A3260115B7513700270056 /* sched.h */,
C98C95D818FF1F4E005654FB /* spawn.h */,
6E2A3BBD210122230003B53B /* stack_np.h */,
- C9244C1A185FCFED00075748 /* qos.h */,
);
path = pthread;
sourceTree = "<group>";
C9A3260C15B759B600270056 /* pthread.xcconfig */,
E4F449A31E82CF0100A7FB9A /* resolver.xcconfig */,
E41505E81E818D4D00F243FB /* resolved.xcconfig */,
+ 6E39974822D3C82C0057625B /* pthread_driverkit.xcconfig */,
6E8C16851B14F14000C8987C /* pthread_introspection.xcconfig */,
C99EA612161F8288003EBC56 /* eos.xcconfig */,
C04545B91C584F8B006A53B3 /* static.xcconfig */,
C9D70EBE167AC7D100D52713 /* private */ = {
isa = PBXGroup;
children = (
- C9153095167ACC22006BB094 /* private.h */,
- C9A325F015B7513200270056 /* posix_sched.h */,
- C9A325F715B7513200270056 /* spinlock_private.h */,
- C9A325F415B7513200270056 /* tsd_private.h */,
- C9A325F915B7513200270056 /* workqueue_private.h */,
- E4657D4017284F7B007D1847 /* introspection_private.h */,
- C99B17DA189C2E1B00991D38 /* qos_private.h */,
- E4063CF21906B4FB000202F9 /* qos.h */,
- 6E5869C620C8FE8300F1CB75 /* dependency_private.h */,
+ 6E8C8C2E22BDC9DE00136359 /* pthread */,
+ 6E8C8C3022BDD05700136359 /* sys */,
);
path = private;
sourceTree = "<group>";
FC5A372217CEB3D6008C323E /* sys */ = {
isa = PBXGroup;
children = (
- E4D962F919086AD600E8A9F2 /* qos.h */,
FC5A372317CEB3D6008C323E /* _pthread */,
- A98FE72D19479F7C007718DA /* qos_private.h */,
+ E4D962F919086AD600E8A9F2 /* qos.h */,
);
path = sys;
sourceTree = "<group>";
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
+ 6ED6E67622C0034400CE82C2 /* prototypes_internal.h in Headers */,
+ 6ED6E66422BFF81F00CE82C2 /* exports_internal.h in Headers */,
6E2A3BC0210122340003B53B /* stack_np.h in Headers */,
6E8C16711B14F08A00C8987C /* posix_sched.h in Headers */,
6E8C166F1B14F08A00C8987C /* introspection_private.h in Headers */,
+ 6ED6E65522BFCD1200CE82C2 /* internal.h in Headers */,
E41A64AE1E83C470009479A9 /* introspection.h in Headers */,
6E8C166C1B14F08A00C8987C /* qos.h in Headers */,
+ 6ED6E65722BFCD1200CE82C2 /* offsets_internal.h in Headers */,
+ 6ED6E65622BFCD1200CE82C2 /* types_internal.h in Headers */,
6E8C16701B14F08A00C8987C /* tsd_private.h in Headers */,
6E8C16731B14F08A00C8987C /* qos_private.h in Headers */,
6E8C16761B14F08A00C8987C /* spinlock_private.h in Headers */,
6E8C16771B14F08A00C8987C /* workqueue_private.h in Headers */,
6E8C16781B14F08A00C8987C /* private.h in Headers */,
+ 6ED6E66522BFF81F00CE82C2 /* inline_internal.h in Headers */,
6E8C16691B14F08A00C8987C /* qos.h in Headers */,
6E8C166A1B14F08A00C8987C /* pthread.h in Headers */,
6E8C166B1B14F08A00C8987C /* pthread_impl.h in Headers */,
6E8C166D1B14F08A00C8987C /* pthread_spis.h in Headers */,
+ 6ED6E66F22BFFC3800CE82C2 /* imports_internal.h in Headers */,
6E8C166E1B14F08A00C8987C /* sched.h in Headers */,
6E5869C920C9040C00F1CB75 /* dependency_private.h in Headers */,
6E8C16751B14F08A00C8987C /* spawn.h in Headers */,
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
+ 6ED6E67422C0034300CE82C2 /* prototypes_internal.h in Headers */,
+ 6ED6E66022BFF81D00CE82C2 /* exports_internal.h in Headers */,
6E2A3BBE2101222F0003B53B /* stack_np.h in Headers */,
C9244C1B185FD33000075748 /* qos.h in Headers */,
C9A1BF4D15C9A58E006BB313 /* pthread.h in Headers */,
+ 6ED6E65B22BFCD1400CE82C2 /* internal.h in Headers */,
C9A1BF4E15C9A594006BB313 /* pthread_impl.h in Headers */,
E4063CF31906B75A000202F9 /* qos.h in Headers */,
+ 6ED6E65D22BFCD1400CE82C2 /* offsets_internal.h in Headers */,
+ 6ED6E65C22BFCD1400CE82C2 /* types_internal.h in Headers */,
C9A1BF4F15C9A598006BB313 /* pthread_spis.h in Headers */,
9202B2321D1A5B6200945880 /* introspection.h in Headers */,
C9A1BF5015C9A59B006BB313 /* sched.h in Headers */,
E4657D4117284F7B007D1847 /* introspection_private.h in Headers */,
C9BB478D15E6ADF700F135B7 /* tsd_private.h in Headers */,
+ 6ED6E66122BFF81D00CE82C2 /* inline_internal.h in Headers */,
C99AD87B15DEC4BC0009A6F8 /* posix_sched.h in Headers */,
C9CCFB9D18B6D0910060CAAE /* qos_private.h in Headers */,
C98C95D918FF1F4E005654FB /* spawn.h in Headers */,
C99AD87C15DEC5290009A6F8 /* spinlock_private.h in Headers */,
+ 6ED6E66D22BFFC3700CE82C2 /* imports_internal.h in Headers */,
C9BB478B15E6ABD900F135B7 /* workqueue_private.h in Headers */,
6E5869C720C9040A00F1CB75 /* dependency_private.h in Headers */,
C9153096167ACC2B006BB094 /* private.h in Headers */,
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
+ 6ED6E67522C0034300CE82C2 /* prototypes_internal.h in Headers */,
+ 6ED6E66222BFF81E00CE82C2 /* exports_internal.h in Headers */,
6E2A3BBF210122300003B53B /* stack_np.h in Headers */,
E4F449BE1E82D03500A7FB9A /* qos.h in Headers */,
E4F449BF1E82D03500A7FB9A /* pthread.h in Headers */,
+ 6ED6E65822BFCD1300CE82C2 /* internal.h in Headers */,
E4F449C01E82D03500A7FB9A /* pthread_impl.h in Headers */,
E4F449C11E82D03500A7FB9A /* qos.h in Headers */,
+ 6ED6E65A22BFCD1300CE82C2 /* offsets_internal.h in Headers */,
+ 6ED6E65922BFCD1300CE82C2 /* types_internal.h in Headers */,
E4F449C21E82D03500A7FB9A /* pthread_spis.h in Headers */,
E4F449C31E82D03500A7FB9A /* introspection.h in Headers */,
E4F449C41E82D03500A7FB9A /* sched.h in Headers */,
E4F449C51E82D03500A7FB9A /* introspection_private.h in Headers */,
E4F449C61E82D03500A7FB9A /* tsd_private.h in Headers */,
+ 6ED6E66322BFF81E00CE82C2 /* inline_internal.h in Headers */,
E4F449C71E82D03500A7FB9A /* posix_sched.h in Headers */,
E4F449C81E82D03500A7FB9A /* qos_private.h in Headers */,
E4F449C91E82D03500A7FB9A /* spawn.h in Headers */,
E4F449CA1E82D03500A7FB9A /* spinlock_private.h in Headers */,
+ 6ED6E66E22BFFC3700CE82C2 /* imports_internal.h in Headers */,
E4F449CB1E82D03500A7FB9A /* workqueue_private.h in Headers */,
6E5869C820C9040B00F1CB75 /* dependency_private.h in Headers */,
E4F449CC1E82D03500A7FB9A /* private.h in Headers */,
C9A325D915B7347000270056 /* Project object */ = {
isa = PBXProject;
attributes = {
+ DefaultBuildSystemTypeForWorkspace = Latest;
LastUpgradeCheck = 1100;
ORGANIZATIONNAME = "";
TargetAttributes = {
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
+ English,
en,
);
mainGroup = C9A325D715B7347000270056;
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = "/bin/bash -e -x";
- shellScript = ". \"${SCRIPT_INPUT_FILE_0}\" /bin/ln -sf \"../../../..${INSTALL_PATH}/libpthread.a\" \"${DSTROOT}/usr/local/lib/loaderd/libpthread.a\"";
+ shellScript = ". \"${SCRIPT_INPUT_FILE_0}\" /bin/ln -sf \"../../../..${INSTALL_PATH}/libpthread.a\" \"${DSTROOT}/usr/local/lib/loaderd/libpthread.a\"\n";
showEnvVarsInLog = 0;
};
C979E9FD18A2BF3D000951E5 /* Install Codes file */ = {
6E8C165C1B14F08A00C8987C /* pthread_rwlock.c in Sources */,
6E8C165D1B14F08A00C8987C /* pthread_tsd.c in Sources */,
6E8C165E1B14F08A00C8987C /* pthread_cancelable_cancel.c in Sources */,
- 6E8C165F1B14F08A00C8987C /* pthread_cancelable_legacy.c in Sources */,
- 6E8C16601B14F08A00C8987C /* pthread_cond_legacy.c in Sources */,
- 6E8C16611B14F08A00C8987C /* pthread_mutex_legacy.c in Sources */,
- 6E8C16621B14F08A00C8987C /* pthread_rwlock_legacy.c in Sources */,
6E8C16651B14F08A00C8987C /* pthread_atfork.c in Sources */,
6E5869CD20C9043B00F1CB75 /* pthread_dependency.c in Sources */,
6E8C16661B14F08A00C8987C /* pthread_asm.s in Sources */,
924D8EE11C11833E002AC2BC /* pthread_cwd.c in Sources */,
C9A1BF4C15C9A578006BB313 /* pthread_tsd.c in Sources */,
C9A1BF5315C9A9F5006BB313 /* pthread_cancelable_cancel.c in Sources */,
- C9A1BF5515C9CB9D006BB313 /* pthread_cancelable_legacy.c in Sources */,
- C975D5D715C9CECA0098ECD8 /* pthread_cond_legacy.c in Sources */,
- C975D5D915C9CEEA0098ECD8 /* pthread_mutex_legacy.c in Sources */,
- C975D5DB15C9CEFA0098ECD8 /* pthread_rwlock_legacy.c in Sources */,
C90E7AB815DC40D900A06D48 /* pthread_atfork.c in Sources */,
6E5869CB20C9043200F1CB75 /* pthread_dependency.c in Sources */,
C99AD88015E2D8B50009A6F8 /* pthread_asm.s in Sources */,
E4F449B11E82D03500A7FB9A /* pthread_cwd.c in Sources */,
E4F449B21E82D03500A7FB9A /* pthread_tsd.c in Sources */,
E4F449B31E82D03500A7FB9A /* pthread_cancelable_cancel.c in Sources */,
- E4F449B41E82D03500A7FB9A /* pthread_cancelable_legacy.c in Sources */,
- E4F449B51E82D03500A7FB9A /* pthread_cond_legacy.c in Sources */,
- E4F449B61E82D03500A7FB9A /* pthread_mutex_legacy.c in Sources */,
- E4F449B71E82D03500A7FB9A /* pthread_rwlock_legacy.c in Sources */,
E4F449BA1E82D03500A7FB9A /* pthread_atfork.c in Sources */,
6E5869CC20C9043B00F1CB75 /* pthread_dependency.c in Sources */,
E4F449BB1E82D03500A7FB9A /* pthread_asm.s in Sources */,
9235CA4D1CA48CEA0015C92B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- SUPPORTED_PLATFORMS = "macosx iphoneos appletvos watchos";
};
name = Debug;
};
9235CA541CA48CEA0015C92B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- SDKROOT = macosx.internal;
- SUPPORTED_PLATFORMS = "iphoneos macosx watchos appletvos";
};
name = Debug;
};
92799B461B96A5FE00861404 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- SUPPORTED_PLATFORMS = "macosx iphoneos appletvos watchos";
};
name = Release;
};
92B275F21BCE4C5E007D06D7 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- SDKROOT = macosx.internal;
- SUPPORTED_PLATFORMS = "iphoneos macosx watchos appletvos";
};
name = Release;
};
};
E4B7FCB022000AF50010A840 /* Release */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 6E39974822D3C82C0057625B /* pthread_driverkit.xcconfig */;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
};
E4B7FCB122000AF50010A840 /* Debug */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 6E39974822D3C82C0057625B /* pthread_driverkit.xcconfig */;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
--- /dev/null
+.\" Copyright (c) 2020 Apple Inc. All rights reserved.
+.\"
+.\" @APPLE_LICENSE_HEADER_START@
+.\"
+.\" This file contains Original Code and/or Modifications of Original Code
+.\" as defined in and that are subject to the Apple Public Source License
+.\" Version 2.0 (the 'License'). You may not use this file except in
+.\" compliance with the License. Please obtain a copy of the License at
+.\" http://www.opensource.apple.com/apsl/ and read it before using this
+.\" file.
+.\"
+.\" The Original Code and all software distributed under the License are
+.\" distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+.\" FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+.\" Please see the License for the specific language governing rights and
+.\" limitations under the License.
+.\"
+.\" @APPLE_LICENSE_HEADER_END@
+.\"
+.Dd May 1, 2020
+.Dt PTHREAD_JIT_WRITE_PROTECT_NP 3
+.Os
+.Sh NAME
+.Nm pthread_jit_write_protect_supported_np ,
+.Nm pthread_jit_write_protect_np
+.Nd thread JIT region write protection settings
+.Sh SYNOPSIS
+.In pthread.h
+.Ft int
+.Fn pthread_jit_write_protect_supported_np "void"
+.Ft void
+.Fn pthread_jit_write_protect_np "int enabled"
+.Sh DESCRIPTION
+The
+.Fn pthread_jit_write_protect_supported_np
+function returns whether the
+.Fn pthread_jit_write_protect_np
+API is supported on this platform. If
+.Fn pthread_jit_write_protect_np
+API is supported on this platform,
+.Fn pthread_jit_write_protect_np
+must be called to toggle per-thread write protection on the MAP_JIT region before the thread writes to or executes from the MAP_JIT region.
+.Pp
+The
+.Fn pthread_jit_write_protect_np
+function sets whether MAP_JIT region write protection is enabled for this thread.
+.Pp
+On platforms where
+.Fn pthread_jit_write_protect_supported_np
+is true, MAP_JIT regions are never writeable and executable simultaneously.
+When write protection is enabled for the thread, writes by the thread to the MAP_JIT region are denied and the MAP_JIT region is executable.
+When write protection is disabled for the thread, writes by the thread to the MAP_JIT region are allowed and the MAP_JIT region is not executable.
+Pass a non-zero value for the
+.Fa enabled
+parameter to enable thread JIT region write protection and allow execution. Pass a zero value for the
+.Fa enabled
+parameter to disable thread JIT write protection and deny execution.
+.Pp
+On platforms where
+.Fn pthread_jit_write_protect_supported_np
+is not supported, MAP_JIT regions are both simultaenously writeable and executable. Calls to
+.Fn pthread_jit_write_protect_np
+are no-ops on unsupported platforms.
+.Sh RETURN VALUES
+If supported, the
+.Fn pthread_jit_write_protect_supported_np
+function will return one. Otherwise the function will return zero.
+.Sh SEE ALSO
+.Xr mmap 2
+++ /dev/null
-/*
- * Copyright (c) 2018 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef __PTHREAD_DEPENDENCY_PRIVATE__
-#define __PTHREAD_DEPENDENCY_PRIVATE__
-
-#include <os/base.h>
-#include <sys/cdefs.h>
-#include <pthread/pthread.h>
-#include <Availability.h>
-
-__BEGIN_DECLS
-
-OS_ASSUME_NONNULL_BEGIN
-
-/*!
- * @typedef pthread_dependency_t
- *
- * @abstract
- * A pthread dependency is a one-time dependency between a thread producing
- * a value and a waiter thread, expressed to the system in a way
- * that priority inversion avoidance can be applied if necessary.
- *
- * @discussion
- * These tokens are one-time use, and meant to be on the stack of the waiter
- * thread.
- *
- * These tokens must be both fulfilled and waited on, exactly one of each.
- */
-typedef struct pthread_dependency_s {
- uint32_t __pdep_owner;
- uint32_t __pdep_opaque1;
- uint64_t __pdep_opaque2;
-} pthread_dependency_t;
-
-/*!
- * @typedef pthread_dependency_attr_t
- *
- * @abstract
- * An opaque type to allow for future expansion of the pthread_dependency
- * interface.
- */
-typedef struct pthread_dependency_attr_s pthread_dependency_attr_t;
-
-#if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE) || defined(__cplusplus)
-/*!
- * @macro PTHREAD_DEPENDENCY_INITIALIZER_NP
- *
- * @abstract
- * Initialize a one-time dependency token.
- *
- * @param __pthread
- * The thread that will be waited on for this dependency to be fulfilled.
- * It is expected that this thread will call pthread_dependency_fulfill_np().
- */
-#define PTHREAD_DEPENDENCY_INITIALIZER_NP(__pthread) \
- { pthread_mach_thread_np(__pthread), 0, 0 }
-#endif
-
-/*!
- * @function pthread_dependency_init_np
- *
- * @abstract
- * Initialize a dependency token.
- *
- * @param __dependency
- * A pointer to a dependency token to initialize.
- *
- * @param __pthread
- * The thread that will be waited on for this dependency to be fulfilled.
- * It is expected that this thread will call pthread_dependency_fulfill_np().
- *
- * @param __attrs
- * This argument is reserved for future expansion purposes, and NULL should be
- * passed.
- */
-__API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
-OS_NONNULL1 OS_NONNULL2 OS_NOTHROW
-void pthread_dependency_init_np(pthread_dependency_t *__dependency,
- pthread_t __pthread, pthread_dependency_attr_t *_Nullable __attrs);
-
-/*!
- * @function pthread_dependency_fulfill_np
- *
- * @abstract
- * Fulfill a dependency.
- *
- * @discussion
- * Calling pthread_dependency_fulfill_np() with a token that hasn't been
- * initialized yet, or calling pthread_dependency_fulfill_np() on the same
- * dependency token more than once is undefined and will cause the process
- * to be terminated.
- *
- * The thread that calls pthread_dependency_fulfill_np() must be the same
- * as the pthread_t that was specified when initializing the token. Not doing so
- * is undefined and will cause the process to be terminated.
- *
- * @param __dependency
- * A pointer to a dependency token that was previously initialized.
- *
- * @param __value
- * An optional value that can be returned through the dependency token
- * to the waiter.
- */
-__API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
-OS_NONNULL1 OS_NOTHROW
-void pthread_dependency_fulfill_np(pthread_dependency_t *__dependency,
- void * _Nullable __value);
-
-/*!
- * @function pthread_dependency_wait_np
- *
- * @abstract
- * Wait on a dependency.
- *
- * @discussion
- * Calling pthread_dependency_wait_np() with a token that hasn't been
- * initialized yet, or calling pthread_dependency_wait_np() on the same
- * dependency token more than once is undefined and will cause the process
- * to be terminated.
- *
- * If the dependency is not fulfilled yet when this function is called, priority
- * inversion avoidance will be applied to the thread that was specified when
- * initializing the token, to ensure that it can call
- * pthread_dependency_fulfill_np() without causing a priority inversion for the
- * thread calling pthread_dependency_wait_np().
- *
- * @param __dependency
- * A pointer to a dependency token that was previously initialized with
- * PTHREAD_DEPENDENCY_INITIALIZER_NP() or pthread_dependency_init_np().
- *
- * @returns
- * The value that was passed to pthread_dependency_fulfill_np() as the `__value`
- * argument.
- */
-__API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
-OS_NONNULL1 OS_NOTHROW
-void *_Nullable pthread_dependency_wait_np(pthread_dependency_t *__dependency);
-
-OS_ASSUME_NONNULL_END
-
-__END_DECLS
-
-#endif //__PTHREAD_DEPENDENCY_PRIVATE__
+++ /dev/null
-/*
- * Copyright (c) 2013, 2016 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef __PTHREAD_INTROSPECTION_PRIVATE__
-#define __PTHREAD_INTROSPECTION_PRIVATE__
-
-#include <pthread/introspection.h>
-
-#endif
+++ /dev/null
-/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
- * All Rights Reserved
- *
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appears in all copies and
- * that both the copyright notice and this permission notice appear in
- * supporting documentation.
- *
- * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
- * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-/*
- * MkLinux
- */
-
-/*
- * POSIX Realtime Scheduling Framework - IEEE 1003.1b
- */
-
-#ifndef _POSIX_SCHED_H
-#define _POSIX_SCHED_H
-
-struct sched_param
-{
- int sched_priority;
- int quantum;
-};
-
-/*
- * POSIX scheduling policies
- */
-
-#define SCHED_OTHER POLICY_TIMESHARE
-#define SCHED_FIFO POLICY_FIFO
-#define SCHED_RR POLICY_RR
-
-#endif /* _POSIX_SCHED_H */
+++ /dev/null
-/*
- * Copyright (c) 2012 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef __PTHREAD_PRIVATE_H__
-#define __PTHREAD_PRIVATE_H__
-
-#include <sys/cdefs.h>
-#include <Availability.h>
-#include <pthread/tsd_private.h>
-
-/* get the thread specific errno value */
-__header_always_inline int
-_pthread_get_errno_direct(void)
-{
- return *(int*)_pthread_getspecific_direct(_PTHREAD_TSD_SLOT_ERRNO);
-}
-
-/* set the thread specific errno value */
-__header_always_inline void
-_pthread_set_errno_direct(int value)
-{
- *((int*)_pthread_getspecific_direct(_PTHREAD_TSD_SLOT_ERRNO)) = value;
-}
-
-__API_AVAILABLE(macos(10.9), ios(7.0))
-pthread_t pthread_main_thread_np(void);
-
-struct _libpthread_functions {
- unsigned long version;
- void (*exit)(int); // added with version=1
- void *(*malloc)(size_t); // added with version=2
- void (*free)(void *); // added with version=2
-};
-
-/*!
- * @function pthread_chdir_np
- *
- * @abstract
- * Sets the per-thread current working directory.
- *
- * @discussion
- * This will set the per-thread current working directory to the provided path.
- * If this is used on a workqueue (dispatch) thread, it MUST be unset with
- * pthread_fchdir_np(-1) before returning.
- *
- * posix_spawn_file_actions_addchdir_np is a better approach if this call would
- * only be used to spawn a new process with a given working directory.
- *
- * @param path
- * The path of the new working directory.
- *
- * @result
- * 0 upon success, -1 upon error and errno is set.
- */
-__API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
-int pthread_chdir_np(const char *path);
-
-/*!
- * @function pthread_fchdir_np
- *
- * @abstract
- * Sets the per-thread current working directory.
- *
- * @discussion
- * This will set the per-thread current working directory to the provided
- * directory fd. If this is used on a workqueue (dispatch) thread, it MUST be
- * unset with pthread_fchdir_np(-1) before returning.
- *
- * posix_spawn_file_actions_addfchdir_np is a better approach if this call would
- * only be used to spawn a new process with a given working directory.
- *
- * @param fd
- * A file descriptor to the new working directory. Pass -1 to unset the
- * per-thread working directory.
- *
- * @result
- * 0 upon success, -1 upon error and errno is set.
- */
-__API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
-int pthread_fchdir_np(int fd);
-
-__API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
-int pthread_attr_setcpupercent_np(pthread_attr_t * __restrict, int, unsigned long);
-
-__API_AVAILABLE(macos(10.15), ios(13.0), tvos(13.0), watchos(6.0))
-int pthread_current_stack_contains_np(const void *, size_t);
-
-#ifdef _os_tsd_get_base
-
-#ifdef __LP64__
-#define _PTHREAD_STRUCT_DIRECT_THREADID_OFFSET -8
-#else
-#define _PTHREAD_STRUCT_DIRECT_THREADID_OFFSET -16
-#endif
-
-/* N.B. DO NOT USE UNLESS YOU ARE REBUILT AS PART OF AN OS TRAIN WORLDBUILD */
-__header_always_inline uint64_t
-_pthread_threadid_self_np_direct(void)
-{
-#ifndef __i386__
- if (_pthread_has_direct_tsd()) {
-#ifdef OS_GS_RELATIVE
- return *(uint64_t OS_GS_RELATIVE *)(_PTHREAD_STRUCT_DIRECT_THREADID_OFFSET);
-#else
- return *(uint64_t*)((char *)_os_tsd_get_base() + _PTHREAD_STRUCT_DIRECT_THREADID_OFFSET);
-#endif
- }
-#endif
- uint64_t threadid = 0;
- pthread_threadid_np(NULL, &threadid);
- return threadid;
-}
-
-#endif // _os_tsd_get_base
-
-#endif // __PTHREAD_PRIVATE_H__
--- /dev/null
+/*
+ * Copyright (c) 2018 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef __PTHREAD_DEPENDENCY_PRIVATE__
+#define __PTHREAD_DEPENDENCY_PRIVATE__
+
+#include <os/base.h>
+#include <sys/cdefs.h>
+#include <pthread/pthread.h>
+#include <Availability.h>
+
+__BEGIN_DECLS
+
+OS_ASSUME_NONNULL_BEGIN
+
+/*!
+ * @typedef pthread_dependency_t
+ *
+ * @abstract
+ * A pthread dependency is a one-time dependency between a thread producing
+ * a value and a waiter thread, expressed to the system in a way
+ * that priority inversion avoidance can be applied if necessary.
+ *
+ * @discussion
+ * These tokens are one-time use, and meant to be on the stack of the waiter
+ * thread.
+ *
+ * These tokens must be both fulfilled and waited on, exactly one of each.
+ */
+typedef struct pthread_dependency_s {
+ uint32_t __pdep_owner;
+ uint32_t __pdep_opaque1;
+ uint64_t __pdep_opaque2;
+} pthread_dependency_t;
+
+/*!
+ * @typedef pthread_dependency_attr_t
+ *
+ * @abstract
+ * An opaque type to allow for future expansion of the pthread_dependency
+ * interface.
+ */
+typedef struct pthread_dependency_attr_s pthread_dependency_attr_t;
+
+#if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE) || defined(__cplusplus)
+/*!
+ * @macro PTHREAD_DEPENDENCY_INITIALIZER_NP
+ *
+ * @abstract
+ * Initialize a one-time dependency token.
+ *
+ * @param __pthread
+ * The thread that will be waited on for this dependency to be fulfilled.
+ * It is expected that this thread will call pthread_dependency_fulfill_np().
+ */
+#define PTHREAD_DEPENDENCY_INITIALIZER_NP(__pthread) \
+ { pthread_mach_thread_np(__pthread), 0, 0 }
+#endif
+
+/*!
+ * @function pthread_dependency_init_np
+ *
+ * @abstract
+ * Initialize a dependency token.
+ *
+ * @param __dependency
+ * A pointer to a dependency token to initialize.
+ *
+ * @param __pthread
+ * The thread that will be waited on for this dependency to be fulfilled.
+ * It is expected that this thread will call pthread_dependency_fulfill_np().
+ *
+ * @param __attrs
+ * This argument is reserved for future expansion purposes, and NULL should be
+ * passed.
+ */
+__API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
+OS_NONNULL1 OS_NONNULL2 OS_NOTHROW
+void pthread_dependency_init_np(pthread_dependency_t *__dependency,
+ pthread_t __pthread, pthread_dependency_attr_t *_Nullable __attrs);
+
+/*!
+ * @function pthread_dependency_fulfill_np
+ *
+ * @abstract
+ * Fulfill a dependency.
+ *
+ * @discussion
+ * Calling pthread_dependency_fulfill_np() with a token that hasn't been
+ * initialized yet, or calling pthread_dependency_fulfill_np() on the same
+ * dependency token more than once is undefined and will cause the process
+ * to be terminated.
+ *
+ * The thread that calls pthread_dependency_fulfill_np() must be the same
+ * as the pthread_t that was specified when initializing the token. Not doing so
+ * is undefined and will cause the process to be terminated.
+ *
+ * @param __dependency
+ * A pointer to a dependency token that was previously initialized.
+ *
+ * @param __value
+ * An optional value that can be returned through the dependency token
+ * to the waiter.
+ */
+__API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
+OS_NONNULL1 OS_NOTHROW
+void pthread_dependency_fulfill_np(pthread_dependency_t *__dependency,
+ void * _Nullable __value);
+
+/*!
+ * @function pthread_dependency_wait_np
+ *
+ * @abstract
+ * Wait on a dependency.
+ *
+ * @discussion
+ * Calling pthread_dependency_wait_np() with a token that hasn't been
+ * initialized yet, or calling pthread_dependency_wait_np() on the same
+ * dependency token more than once is undefined and will cause the process
+ * to be terminated.
+ *
+ * If the dependency is not fulfilled yet when this function is called, priority
+ * inversion avoidance will be applied to the thread that was specified when
+ * initializing the token, to ensure that it can call
+ * pthread_dependency_fulfill_np() without causing a priority inversion for the
+ * thread calling pthread_dependency_wait_np().
+ *
+ * @param __dependency
+ * A pointer to a dependency token that was previously initialized with
+ * PTHREAD_DEPENDENCY_INITIALIZER_NP() or pthread_dependency_init_np().
+ *
+ * @returns
+ * The value that was passed to pthread_dependency_fulfill_np() as the `__value`
+ * argument.
+ */
+__API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
+OS_NONNULL1 OS_NOTHROW
+void *_Nullable pthread_dependency_wait_np(pthread_dependency_t *__dependency);
+
+OS_ASSUME_NONNULL_END
+
+__END_DECLS
+
+#endif //__PTHREAD_DEPENDENCY_PRIVATE__
--- /dev/null
+/*
+ * Copyright (c) 2013, 2016 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef __PTHREAD_INTROSPECTION_PRIVATE__
+#define __PTHREAD_INTROSPECTION_PRIVATE__
+
+#include <pthread/introspection.h>
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+/*
+ * MkLinux
+ */
+
+/*
+ * POSIX Realtime Scheduling Framework - IEEE 1003.1b
+ */
+
+#ifndef _POSIX_SCHED_H
+#define _POSIX_SCHED_H
+
+struct sched_param
+{
+ int sched_priority;
+ int quantum;
+};
+
+/*
+ * POSIX scheduling policies
+ */
+
+#define SCHED_OTHER POLICY_TIMESHARE
+#define SCHED_FIFO POLICY_FIFO
+#define SCHED_RR POLICY_RR
+
+#endif /* _POSIX_SCHED_H */
--- /dev/null
+/*
+ * Copyright (c) 2012 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef __PTHREAD_PRIVATE_H__
+#define __PTHREAD_PRIVATE_H__
+
+#include <sys/cdefs.h>
+#include <Availability.h>
+#include <pthread/tsd_private.h>
+
+__API_AVAILABLE(macos(10.9), ios(7.0))
+pthread_t pthread_main_thread_np(void);
+
+struct _libpthread_functions {
+ unsigned long version;
+ void (*exit)(int); // added with version=1
+ void *(*malloc)(size_t); // added with version=2
+ void (*free)(void *); // added with version=2
+};
+
+/*!
+ * @function pthread_chdir_np
+ *
+ * @abstract
+ * Sets the per-thread current working directory.
+ *
+ * @discussion
+ * This will set the per-thread current working directory to the provided path.
+ * If this is used on a workqueue (dispatch) thread, it MUST be unset with
+ * pthread_fchdir_np(-1) before returning.
+ *
+ * posix_spawn_file_actions_addchdir_np is a better approach if this call would
+ * only be used to spawn a new process with a given working directory.
+ *
+ * @param path
+ * The path of the new working directory.
+ *
+ * @result
+ * 0 upon success, -1 upon error and errno is set.
+ */
+__API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
+int pthread_chdir_np(const char *path);
+
+/*!
+ * @function pthread_fchdir_np
+ *
+ * @abstract
+ * Sets the per-thread current working directory.
+ *
+ * @discussion
+ * This will set the per-thread current working directory to the provided
+ * directory fd. If this is used on a workqueue (dispatch) thread, it MUST be
+ * unset with pthread_fchdir_np(-1) before returning.
+ *
+ * posix_spawn_file_actions_addfchdir_np is a better approach if this call would
+ * only be used to spawn a new process with a given working directory.
+ *
+ * @param fd
+ * A file descriptor to the new working directory. Pass -1 to unset the
+ * per-thread working directory.
+ *
+ * @result
+ * 0 upon success, -1 upon error and errno is set.
+ */
+__API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
+int pthread_fchdir_np(int fd);
+
+__API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
+int pthread_attr_setcpupercent_np(pthread_attr_t * __restrict, int, unsigned long);
+
+__API_AVAILABLE(macos(10.15), ios(13.0), tvos(13.0), watchos(6.0))
+int pthread_current_stack_contains_np(const void *, size_t);
+
+/*!
+ * @function pthread_self_is_exiting_np
+ *
+ * @abstract
+ * Returns whether the current thread is exiting.
+ *
+ * @discussion
+ * This can be useful for certain introspection tools to know that malloc/free
+ * is called from the TSD destruction codepath.
+ *
+ * @result
+ * 0 if the thread is not exiting
+ * 1 if the thread is exiting
+ */
+__API_AVAILABLE(macos(10.16), ios(14.0), tvos(14.0), watchos(7.0))
+int pthread_self_is_exiting_np(void);
+
+#ifdef __LP64__
+#define _PTHREAD_STRUCT_DIRECT_THREADID_OFFSET -8
+#define _PTHREAD_STRUCT_DIRECT_TSD_OFFSET 224
+#else
+#define _PTHREAD_STRUCT_DIRECT_THREADID_OFFSET -16
+#define _PTHREAD_STRUCT_DIRECT_TSD_OFFSET 176
+#endif
+
+#if !TARGET_OS_SIMULATOR
+#if defined(__i386__)
+#define _pthread_direct_tsd_relative_access(type, offset) \
+ (type *)((char *)_pthread_getspecific_direct(_PTHREAD_TSD_SLOT_PTHREAD_SELF) + \
+ _PTHREAD_STRUCT_DIRECT_TSD_OFFSET + _PTHREAD_STRUCT_DIRECT_##offset##_OFFSET)
+#elif defined(OS_GS_RELATIVE)
+#define _pthread_direct_tsd_relative_access(type, offset) \
+ (type OS_GS_RELATIVE *)(_PTHREAD_STRUCT_DIRECT_##offset##_OFFSET)
+#elif defined(_os_tsd_get_base)
+#define _pthread_direct_tsd_relative_access(type, offset) \
+ (type *)((char *)_os_tsd_get_base() + _PTHREAD_STRUCT_DIRECT_##offset##_OFFSET)
+#else
+#error "unknown configuration"
+#endif
+#endif // !TARGET_OS_SIMULATOR
+
+/* N.B. DO NOT USE UNLESS YOU ARE REBUILT AS PART OF AN OS TRAIN WORLDBUILD */
+__header_always_inline __pure2 uint64_t
+_pthread_threadid_self_np_direct(void)
+{
+#ifdef _pthread_direct_tsd_relative_access
+ return *_pthread_direct_tsd_relative_access(uint64_t, THREADID);
+#else
+ uint64_t threadid = 0;
+ pthread_threadid_np(NULL, &threadid);
+ return threadid;
+#endif
+}
+
+__header_always_inline __pure2 pthread_t
+_pthread_self_direct(void)
+{
+#if TARGET_OS_SIMULATOR || defined(__i386__) || defined(__x86_64__)
+ return (pthread_t)_pthread_getspecific_direct(_PTHREAD_TSD_SLOT_PTHREAD_SELF);
+#elif defined(__arm__) || defined(__arm64__)
+ uintptr_t tsd_base = (uintptr_t)_os_tsd_get_base();
+ return (pthread_t)(tsd_base - _PTHREAD_STRUCT_DIRECT_TSD_OFFSET);
+#else
+#error unsupported architecture
+#endif
+}
+
+__header_always_inline __pure2 mach_port_t
+_pthread_mach_thread_self_direct(void)
+{
+ return (mach_port_t)(uintptr_t)
+ _pthread_getspecific_direct(_PTHREAD_TSD_SLOT_MACH_THREAD_SELF);
+}
+
+__header_always_inline int *
+_pthread_errno_address_direct(void)
+{
+ return (int *)_pthread_getspecific_direct(_PTHREAD_TSD_SLOT_ERRNO);
+}
+
+/* get the thread specific errno value */
+__header_always_inline int
+_pthread_get_errno_direct(void)
+{
+ return *_pthread_errno_address_direct();
+}
+
+/* set the thread specific errno value */
+__header_always_inline void
+_pthread_set_errno_direct(int value)
+{
+ *_pthread_errno_address_direct() = value;
+}
+
+#endif // __PTHREAD_PRIVATE_H__
--- /dev/null
+/*
+ * Copyright (c) 2014 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef _QOS_LEGACY_H
+#define _QOS_LEGACY_H
+
+#include_next <pthread/qos.h>
+
+#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
+
+#ifdef __has_include
+#if __has_include(<pthread/qos_private.h>)
+#include <pthread/qos_private.h>
+#endif
+#endif
+
+#endif // __DARWIN_C_LEVEL >= __DARWIN_C_FULL
+
+#endif //_QOS_LEGACY_H
--- /dev/null
+/*
+ * Copyright (c) 2013-2014 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef _QOS_PRIVATE_H
+#define _QOS_PRIVATE_H
+
+#include <pthread/qos.h>
+#include <pthread/priority_private.h>
+#include <sys/qos.h> /* qos_class_t */
+#include <sys/qos_private.h>
+
+#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
+// allow __DARWIN_C_LEVEL to turn off the use of mach_port_t
+#include <mach/port.h>
+#endif
+
+// redeffed here to avoid leaving __QOS_ENUM defined in the public header
+#define __QOS_ENUM(name, type, ...) enum { __VA_ARGS__ }; typedef type name##_t
+#define __QOS_AVAILABLE_10_10
+#define __QOS_AVAILABLE_10_11
+#define __QOS_AVAILABLE_10_12
+
+#if defined(__has_feature) && defined(__has_extension)
+#if __has_feature(objc_fixed_enum) || __has_extension(cxx_strong_enums)
+#undef __QOS_ENUM
+#define __QOS_ENUM(name, type, ...) typedef enum : type { __VA_ARGS__ } name##_t
+#endif
+#if __has_feature(enumerator_attributes)
+#undef __QOS_AVAILABLE_10_10
+#define __QOS_AVAILABLE_10_10 __API_AVAILABLE(macos(10.10), ios(8.0))
+#undef __QOS_AVAILABLE_10_11
+#define __QOS_AVAILABLE_10_11 __API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0), watchos(2.0))
+#undef __QOS_AVAILABLE_10_12
+#define __QOS_AVAILABLE_10_12 __API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
+#undef __QOS_AVAILABLE_10_15_1
+#define __QOS_AVAILABLE_10_15_1 __API_AVAILABLE(macos(10.15.1), ios(13.2), tvos(13.2), watchos(6.2))
+#endif
+#endif
+
+// This enum matches workq_set_self_flags in
+// xnu's workqueue_internal.h.
+__QOS_ENUM(_pthread_set_flags, unsigned int,
+ _PTHREAD_SET_SELF_QOS_FLAG __QOS_AVAILABLE_10_10 = 0x1,
+ _PTHREAD_SET_SELF_VOUCHER_FLAG __QOS_AVAILABLE_10_10 = 0x2,
+ _PTHREAD_SET_SELF_FIXEDPRIORITY_FLAG __QOS_AVAILABLE_10_11 = 0x4,
+ _PTHREAD_SET_SELF_TIMESHARE_FLAG __QOS_AVAILABLE_10_11 = 0x8,
+ _PTHREAD_SET_SELF_WQ_KEVENT_UNBIND __QOS_AVAILABLE_10_12 = 0x10,
+ _PTHREAD_SET_SELF_ALTERNATE_AMX __QOS_AVAILABLE_10_15_1 = 0x20,
+);
+
+#undef __QOS_ENUM
+#undef __QOS_AVAILABLE_10_10
+#undef __QOS_AVAILABLE_10_11
+#undef __QOS_AVAILABLE_10_12
+
+#ifndef KERNEL
+
+__BEGIN_DECLS
+
+/*!
+ * @function pthread_set_qos_class_np
+ *
+ * @abstract
+ * Sets the requested QOS class and relative priority of the current thread.
+ *
+ * @discussion
+ * The QOS class and relative priority represent an overall combination of
+ * system quality of service attributes on a thread.
+ *
+ * Subsequent calls to interfaces such as pthread_setschedparam() that are
+ * incompatible or in conflict with the QOS class system will unset the QOS
+ * class requested with this interface and pthread_get_qos_class_np() will
+ * return QOS_CLASS_UNSPECIFIED thereafter. A thread so modified is permanently
+ * opted-out of the QOS class system and calls to this function to request a QOS
+ * class for such a thread will fail and return EPERM.
+ *
+ * @param __pthread
+ * The current thread as returned by pthread_self().
+ * EINVAL will be returned if any other thread is provided.
+ *
+ * @param __qos_class
+ * A QOS class value:
+ * - QOS_CLASS_USER_INTERACTIVE
+ * - QOS_CLASS_USER_INITIATED
+ * - QOS_CLASS_DEFAULT
+ * - QOS_CLASS_UTILITY
+ * - QOS_CLASS_BACKGROUND
+ * - QOS_CLASS_MAINTENANCE
+ * EINVAL will be returned if any other value is provided.
+ *
+ * @param __relative_priority
+ * A relative priority within the QOS class. This value is a negative offset
+ * from the maximum supported scheduler priority for the given class.
+ * EINVAL will be returned if the value is greater than zero or less than
+ * QOS_MIN_RELATIVE_PRIORITY.
+ *
+ * @return
+ * Zero if successful, othwerise an errno value.
+ */
+__API_DEPRECATED_WITH_REPLACEMENT("pthread_set_qos_class_self_np", macos(10.10, 10.10), ios(8.0, 8.0))
+int
+pthread_set_qos_class_np(pthread_t __pthread,
+ qos_class_t __qos_class,
+ int __relative_priority);
+
+/* Private interfaces for libdispatch to encode/decode specific values of pthread_priority_t. */
+
+// Encode a class+priority pair into a pthread_priority_t,
+__API_AVAILABLE(macos(10.10), ios(8.0))
+pthread_priority_t
+_pthread_qos_class_encode(qos_class_t qos_class, int relative_priority, unsigned long flags);
+
+// Decode a pthread_priority_t into a class+priority pair.
+__API_AVAILABLE(macos(10.10), ios(8.0))
+qos_class_t
+_pthread_qos_class_decode(pthread_priority_t priority, int *relative_priority, unsigned long *flags);
+
+// Encode a legacy workqueue API priority into a pthread_priority_t. This API
+// is deprecated and can be removed when the simulator no longer uses it.
+__API_DEPRECATED("no longer used", macos(10.10, 10.13), ios(8.0, 11.0))
+pthread_priority_t
+_pthread_qos_class_encode_workqueue(int queue_priority, unsigned long flags);
+
+#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
+
+// Set QoS or voucher, or both, on pthread_self()
+__API_AVAILABLE(macos(10.10), ios(8.0))
+int
+_pthread_set_properties_self(_pthread_set_flags_t flags, pthread_priority_t priority, mach_port_t voucher);
+
+// Set self to fixed priority without disturbing QoS or priority
+__API_AVAILABLE(macos(10.10), ios(8.0))
+int
+pthread_set_fixedpriority_self(void);
+
+// Inverse of pthread_set_fixedpriority_self()
+__API_AVAILABLE(macos(10.10), ios(8.0))
+int
+pthread_set_timeshare_self(void);
+
+// Set self to avoid running on the same AMX as
+// other work in this group.
+// Only allowed on non-workqueue pthreads
+__API_AVAILABLE(macos(10.15.1), ios(13.2), tvos(13.2), watchos(6.2))
+int
+pthread_prefer_alternate_amx_self(void);
+
+/*!
+ * @const PTHREAD_MAX_PARALLELISM_PHYSICAL
+ * Flag that can be used with pthread_qos_max_parallelism() and
+ * pthread_time_constraint_max_parallelism() to ask for a count of physical
+ * compute units available for parallelism (default is logical).
+ */
+#define PTHREAD_MAX_PARALLELISM_PHYSICAL 0x1
+
+/*!
+ * @function pthread_qos_max_parallelism
+ *
+ * @abstract
+ * Returns the number of compute units available for parallel computation at
+ * a specified QoS class.
+ *
+ * @param qos
+ * The specified QoS class.
+ *
+ * @param flags
+ * 0 or PTHREAD_MAX_PARALLELISM_PHYSICAL.
+ *
+ * @return
+ * The number of compute units available for parallel computation for the
+ * specified QoS, or -1 on failure (with errno set accordingly).
+ */
+__API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
+int
+pthread_qos_max_parallelism(qos_class_t qos, unsigned long flags);
+
+/*!
+ * @function pthread_time_constraint_max_parallelism()
+ *
+ * @abstract
+ * Returns the number of compute units available for parallel computation on
+ * realtime threads.
+ *
+ * @param flags
+ * 0 or PTHREAD_MAX_PARALLELISM_PHYSICAL.
+ *
+ * @return
+ * The number of compute units available for parallel computation on realtime
+ * threads, or -1 on failure (with errno set accordingly).
+ */
+__API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
+int
+pthread_time_constraint_max_parallelism(unsigned long flags);
+
+#endif // __DARWIN_C_LEVEL >= __DARWIN_C_FULL
+
+__END_DECLS
+
+#endif // KERNEL
+
+#endif //_QOS_PRIVATE_H
--- /dev/null
+/*
+ * Copyright (c) 2003, 2013 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+/*
+ * MkLinux
+ */
+
+/*
+ * POSIX Threads - IEEE 1003.1c
+ */
+
+#ifndef _POSIX_PTHREAD_SPINLOCK_H
+#define _POSIX_PTHREAD_SPINLOCK_H
+
+#include <sys/cdefs.h>
+#include <mach/mach.h>
+#include <libkern/OSAtomic.h>
+
+typedef volatile OSSpinLock pthread_lock_t __deprecated_msg("Use <os/lock.h> instead");
+
+#define LOCK_INIT(l) ((l) = OS_SPINLOCK_INIT)
+#define LOCK_INITIALIZER OS_SPINLOCK_INIT
+
+#define _DO_SPINLOCK_LOCK(v) OSSpinLockLock(v)
+#define _DO_SPINLOCK_UNLOCK(v) OSSpinLockUnlock(v)
+
+#define TRY_LOCK(v) OSSpinLockTry((volatile OSSpinLock *)&(v))
+#define LOCK(v) OSSpinLockLock((volatile OSSpinLock *)&(v))
+#define UNLOCK(v) OSSpinLockUnlock((volatile OSSpinLock *)&(v))
+
+extern void _spin_lock(pthread_lock_t *lockp) __deprecated_msg("Use <os/lock.h> instead");
+extern int _spin_lock_try(pthread_lock_t *lockp) __deprecated_msg("Use <os/lock.h> instead");
+extern void _spin_unlock(pthread_lock_t *lockp) __deprecated_msg("Use <os/lock.h> instead");
+
+extern void spin_lock(pthread_lock_t *lockp) __deprecated_msg("Use <os/lock.h> instead");
+extern int spin_lock_try(pthread_lock_t *lockp) __deprecated_msg("Use <os/lock.h> instead");
+extern void spin_unlock(pthread_lock_t *lockp) __deprecated_msg("Use <os/lock.h> instead");
+
+#endif /* _POSIX_PTHREAD_SPINLOCK_H */
--- /dev/null
+/*
+ * Copyright (c) 2003-2013 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * MkLinux
+ */
+
+#ifndef __PTHREAD_TSD_H__
+#define __PTHREAD_TSD_H__
+
+#ifndef __ASSEMBLER__
+
+#include <System/machine/cpu_capabilities.h>
+#include <sys/cdefs.h>
+#include <TargetConditionals.h>
+#include <Availability.h>
+#include <os/tsd.h>
+#include <pthread/spinlock_private.h>
+
+/* Constant TSD slots for inline pthread_getspecific() usage. */
+
+/* Keys 0 - 9 are for Libsyscall/libplatform usage */
+#define _PTHREAD_TSD_SLOT_PTHREAD_SELF __TSD_THREAD_SELF
+#define _PTHREAD_TSD_SLOT_ERRNO __TSD_ERRNO
+#define _PTHREAD_TSD_SLOT_MIG_REPLY __TSD_MIG_REPLY
+#define _PTHREAD_TSD_SLOT_MACH_THREAD_SELF __TSD_MACH_THREAD_SELF
+#define _PTHREAD_TSD_SLOT_PTHREAD_QOS_CLASS __TSD_THREAD_QOS_CLASS
+#define _PTHREAD_TSD_SLOT_RETURN_TO_KERNEL __TSD_RETURN_TO_KERNEL
+#define _PTHREAD_TSD_SLOT_PTR_MUNGE __TSD_PTR_MUNGE
+#define _PTHREAD_TSD_SLOT_MACH_SPECIAL_REPLY __TSD_MACH_SPECIAL_REPLY
+#define _PTHREAD_TSD_SLOT_SEMAPHORE_CACHE __TSD_SEMAPHORE_CACHE
+
+#define _PTHREAD_TSD_SLOT_PTHREAD_SELF_TYPE pthread_t
+#define _PTHREAD_TSD_SLOT_ERRNO_TYPE int *
+#define _PTHREAD_TSD_SLOT_MIG_REPLY_TYPE mach_port_t
+#define _PTHREAD_TSD_SLOT_MACH_THREAD_SELF_TYPE mach_port_t
+#define _PTHREAD_TSD_SLOT_PTHREAD_QOS_CLASS_TYPE pthread_priority_t
+#define _PTHREAD_TSD_SLOT_RETURN_TO_KERNEL_TYPE uintptr_t
+#define _PTHREAD_TSD_SLOT_PTR_MUNGE_TYPE uintptr_t
+#define _PTHREAD_TSD_SLOT_MACH_SPECIAL_REPLY_TYPE mach_port_t
+#define _PTHREAD_TSD_SLOT_SEMAPHORE_CACHE_TYPE semaphore_t
+
+/*
+ * Windows 64-bit ABI bakes %gs relative accesses into its code in the same
+ * range as our TSD keys. To allow some limited interoperability for code
+ * targeting that ABI, we leave slots 6 and 11 unused.
+ *
+ * The Go runtime on x86_64 also uses this because their ABI doesn't reserve a
+ * register for the TSD base. They were previously using an arbitrarily chosen
+ * dynamic key and relying on being able to get it at runtime, but switched to
+ * this slot to avoid issues with that approach. It's assumed that Go and
+ * Windows code won't run in the same address space.
+ */
+//#define _PTHREAD_TSD_SLOT_RESERVED_WIN64 6
+
+#define _PTHREAD_TSD_RESERVED_SLOT_COUNT _PTHREAD_TSD_RESERVED_SLOT_COUNT
+
+/* Keys 10 - 29 are for Libc/Libsystem internal usage */
+/* used as __pthread_tsd_first + Num */
+#define __PTK_LIBC_LOCALE_KEY 10
+//#define __PTK_LIBC_RESERVED_WIN64 11
+#define __PTK_LIBC_LOCALTIME_KEY 12
+#define __PTK_LIBC_GMTIME_KEY 13
+#define __PTK_LIBC_GDTOA_BIGINT_KEY 14
+#define __PTK_LIBC_PARSEFLOAT_KEY 15
+#define __PTK_LIBC_TTYNAME_KEY 16
+/* for usage by dyld */
+#define __PTK_LIBC_DYLD_Unwind_SjLj_Key 18
+
+/* Keys 20-29 for libdispatch usage */
+#define __PTK_LIBDISPATCH_KEY0 20
+#define __PTK_LIBDISPATCH_KEY1 21
+#define __PTK_LIBDISPATCH_KEY2 22
+#define __PTK_LIBDISPATCH_KEY3 23
+#define __PTK_LIBDISPATCH_KEY4 24
+#define __PTK_LIBDISPATCH_KEY5 25
+#define __PTK_LIBDISPATCH_KEY6 26
+#define __PTK_LIBDISPATCH_KEY7 27
+#define __PTK_LIBDISPATCH_KEY8 28
+#define __PTK_LIBDISPATCH_KEY9 29
+
+/* Keys 30-255 for Non Libsystem usage */
+
+/* Keys 30-39 for Graphic frameworks usage */
+#define _PTHREAD_TSD_SLOT_OPENGL 30 /* backwards compat sake */
+#define __PTK_FRAMEWORK_OPENGL_KEY 30
+#define __PTK_FRAMEWORK_GRAPHICS_KEY1 31
+#define __PTK_FRAMEWORK_GRAPHICS_KEY2 32
+#define __PTK_FRAMEWORK_GRAPHICS_KEY3 33
+#define __PTK_FRAMEWORK_GRAPHICS_KEY4 34
+#define __PTK_FRAMEWORK_GRAPHICS_KEY5 35
+#define __PTK_FRAMEWORK_GRAPHICS_KEY6 36
+#define __PTK_FRAMEWORK_GRAPHICS_KEY7 37
+#define __PTK_FRAMEWORK_GRAPHICS_KEY8 38
+#define __PTK_FRAMEWORK_GRAPHICS_KEY9 39
+
+/* Keys 40-49 for Objective-C runtime usage */
+#define __PTK_FRAMEWORK_OBJC_KEY0 40
+#define __PTK_FRAMEWORK_OBJC_KEY1 41
+#define __PTK_FRAMEWORK_OBJC_KEY2 42
+#define __PTK_FRAMEWORK_OBJC_KEY3 43
+#define __PTK_FRAMEWORK_OBJC_KEY4 44
+#define __PTK_FRAMEWORK_OBJC_KEY5 45
+#define __PTK_FRAMEWORK_OBJC_KEY6 46
+#define __PTK_FRAMEWORK_OBJC_KEY7 47
+#define __PTK_FRAMEWORK_OBJC_KEY8 48
+#define __PTK_FRAMEWORK_OBJC_KEY9 49
+
+/* Keys 50-59 for Core Foundation usage */
+#define __PTK_FRAMEWORK_COREFOUNDATION_KEY0 50
+#define __PTK_FRAMEWORK_COREFOUNDATION_KEY1 51
+#define __PTK_FRAMEWORK_COREFOUNDATION_KEY2 52
+#define __PTK_FRAMEWORK_COREFOUNDATION_KEY3 53
+#define __PTK_FRAMEWORK_COREFOUNDATION_KEY4 54
+#define __PTK_FRAMEWORK_COREFOUNDATION_KEY5 55
+#define __PTK_FRAMEWORK_COREFOUNDATION_KEY6 56
+#define __PTK_FRAMEWORK_COREFOUNDATION_KEY7 57
+#define __PTK_FRAMEWORK_COREFOUNDATION_KEY8 58
+#define __PTK_FRAMEWORK_COREFOUNDATION_KEY9 59
+
+/* Keys 60-69 for Foundation usage */
+#define __PTK_FRAMEWORK_FOUNDATION_KEY0 60
+#define __PTK_FRAMEWORK_FOUNDATION_KEY1 61
+#define __PTK_FRAMEWORK_FOUNDATION_KEY2 62
+#define __PTK_FRAMEWORK_FOUNDATION_KEY3 63
+#define __PTK_FRAMEWORK_FOUNDATION_KEY4 64
+#define __PTK_FRAMEWORK_FOUNDATION_KEY5 65
+#define __PTK_FRAMEWORK_FOUNDATION_KEY6 66
+#define __PTK_FRAMEWORK_FOUNDATION_KEY7 67
+#define __PTK_FRAMEWORK_FOUNDATION_KEY8 68
+#define __PTK_FRAMEWORK_FOUNDATION_KEY9 69
+
+/* Keys 70-79 for Core Animation/QuartzCore usage */
+#define __PTK_FRAMEWORK_QUARTZCORE_KEY0 70
+#define __PTK_FRAMEWORK_QUARTZCORE_KEY1 71
+#define __PTK_FRAMEWORK_QUARTZCORE_KEY2 72
+#define __PTK_FRAMEWORK_QUARTZCORE_KEY3 73
+#define __PTK_FRAMEWORK_QUARTZCORE_KEY4 74
+#define __PTK_FRAMEWORK_QUARTZCORE_KEY5 75
+#define __PTK_FRAMEWORK_QUARTZCORE_KEY6 76
+#define __PTK_FRAMEWORK_QUARTZCORE_KEY7 77
+#define __PTK_FRAMEWORK_QUARTZCORE_KEY8 78
+#define __PTK_FRAMEWORK_QUARTZCORE_KEY9 79
+
+
+/* Keys 80-89 for CoreData */
+#define __PTK_FRAMEWORK_COREDATA_KEY0 80
+#define __PTK_FRAMEWORK_COREDATA_KEY1 81
+#define __PTK_FRAMEWORK_COREDATA_KEY2 82
+#define __PTK_FRAMEWORK_COREDATA_KEY3 83
+#define __PTK_FRAMEWORK_COREDATA_KEY4 84
+#define __PTK_FRAMEWORK_COREDATA_KEY5 85
+#define __PTK_FRAMEWORK_COREDATA_KEY6 86
+#define __PTK_FRAMEWORK_COREDATA_KEY7 87
+#define __PTK_FRAMEWORK_COREDATA_KEY8 88
+#define __PTK_FRAMEWORK_COREDATA_KEY9 89
+
+/* Keys 90-94 for JavaScriptCore Collection */
+#define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0 90
+#define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY1 91
+#define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY2 92
+#define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY3 93
+#define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY4 94
+/* Keys 95 for CoreText */
+#define __PTK_FRAMEWORK_CORETEXT_KEY0 95
+
+/* Keys 100-109 are for the Swift runtime */
+#define __PTK_FRAMEWORK_SWIFT_KEY0 100
+#define __PTK_FRAMEWORK_SWIFT_KEY1 101
+#define __PTK_FRAMEWORK_SWIFT_KEY2 102
+#define __PTK_FRAMEWORK_SWIFT_KEY3 103
+#define __PTK_FRAMEWORK_SWIFT_KEY4 104
+#define __PTK_FRAMEWORK_SWIFT_KEY5 105
+#define __PTK_FRAMEWORK_SWIFT_KEY6 106
+#define __PTK_FRAMEWORK_SWIFT_KEY7 107
+#define __PTK_FRAMEWORK_SWIFT_KEY8 108
+#define __PTK_FRAMEWORK_SWIFT_KEY9 109
+
+/* Keys 110-115 for libmalloc */
+#define __PTK_LIBMALLOC_KEY0 110
+#define __PTK_LIBMALLOC_KEY1 111
+#define __PTK_LIBMALLOC_KEY2 112
+#define __PTK_LIBMALLOC_KEY3 113
+#define __PTK_LIBMALLOC_KEY4 114
+
+/* Keys 115-120 for libdispatch workgroups */
+#define __PTK_LIBDISPATCH_WORKGROUP_KEY0 115
+#define __PTK_LIBDISPATCH_WORKGROUP_KEY1 116
+#define __PTK_LIBDISPATCH_WORKGROUP_KEY2 117
+#define __PTK_LIBDISPATCH_WORKGROUP_KEY3 118
+#define __PTK_LIBDISPATCH_WORKGROUP_KEY4 119
+
+/* Keys 190 - 194 are for the use of PerfUtils */
+#define __PTK_PERF_UTILS_KEY0 190
+#define __PTK_PERF_UTILS_KEY1 191
+#define __PTK_PERF_UTILS_KEY2 192
+#define __PTK_PERF_UTILS_KEY3 193
+#define __PTK_PERF_UTILS_KEY4 194
+
+/* Keys 210 - 229 are for libSystem usage within the iOS Simulator */
+/* They are offset from their corresponding libSystem keys by 200 */
+#define __PTK_LIBC_SIM_LOCALE_KEY 210
+#define __PTK_LIBC_SIM_TTYNAME_KEY 211
+#define __PTK_LIBC_SIM_LOCALTIME_KEY 212
+#define __PTK_LIBC_SIM_GMTIME_KEY 213
+#define __PTK_LIBC_SIM_GDTOA_BIGINT_KEY 214
+#define __PTK_LIBC_SIM_PARSEFLOAT_KEY 215
+
+__BEGIN_DECLS
+
+extern void *pthread_getspecific(unsigned long);
+extern int pthread_setspecific(unsigned long, const void *);
+/* setup destructor function for static key as it is not created with pthread_key_create() */
+extern int pthread_key_init_np(int, void (*)(void *));
+
+__API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
+extern int _pthread_setspecific_static(unsigned long, void *);
+
+#if PTHREAD_LAYOUT_SPI
+
+/* SPI intended for CoreSymbolication only */
+
+__API_AVAILABLE(macos(10.10), ios(8.0))
+extern const struct pthread_layout_offsets_s {
+ // always add new fields at the end
+ const uint16_t plo_version;
+ // either of the next two fields may be 0; use whichever is set
+ // bytes from pthread_t to base of tsd
+ const uint16_t plo_pthread_tsd_base_offset;
+ // bytes from pthread_t to a pointer to base of tsd
+ const uint16_t plo_pthread_tsd_base_address_offset;
+ const uint16_t plo_pthread_tsd_entry_size;
+} pthread_layout_offsets;
+
+#endif // PTHREAD_LAYOUT_SPI
+
+__header_always_inline int
+_pthread_has_direct_tsd(void)
+{
+#if TARGET_IPHONE_SIMULATOR
+ return 0;
+#else
+ return 1;
+#endif
+}
+
+/* To be used with static constant keys only */
+__header_always_inline void *
+_pthread_getspecific_direct(unsigned long slot)
+{
+#if TARGET_IPHONE_SIMULATOR
+ return pthread_getspecific(slot);
+#else
+ return _os_tsd_get_direct(slot);
+#endif
+}
+
+/* To be used with static constant keys only, assumes destructor is
+ * already setup (with pthread_key_init_np) */
+__header_always_inline int
+_pthread_setspecific_direct(unsigned long slot, void * val)
+{
+#if TARGET_IPHONE_SIMULATOR
+ return _pthread_setspecific_static(slot, val);
+#else
+ return _os_tsd_set_direct(slot, val);
+#endif
+}
+
+__END_DECLS
+
+#endif /* ! __ASSEMBLER__ */
+#endif /* __PTHREAD_TSD_H__ */
--- /dev/null
+/*
+ * Copyright (c) 2007, 2012 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef __PTHREAD_WORKQUEUE_H__
+#define __PTHREAD_WORKQUEUE_H__
+
+#include <stdbool.h>
+#include <sys/cdefs.h>
+#include <sys/event.h>
+#include <Availability.h>
+#include <pthread/pthread.h>
+#include <pthread/qos_private.h>
+
+#define PTHREAD_WORKQUEUE_SPI_VERSION 20170201
+
+/* Feature checking flags, returned by _pthread_workqueue_supported()
+ *
+ * Note: These bits should match the definition of PTHREAD_FEATURE_*
+ * bits defined in libpthread/kern/kern_internal.h */
+
+#define WORKQ_FEATURE_DISPATCHFUNC 0x01 // pthread_workqueue_setdispatch_np is supported (or not)
+#define WORKQ_FEATURE_FINEPRIO 0x02 // fine grained pthread workq priorities
+#define WORKQ_FEATURE_MAINTENANCE 0x10 // QOS class maintenance
+#define WORKQ_FEATURE_KEVENT 0x40 // Support for direct kevent delivery
+#define WORKQ_FEATURE_WORKLOOP 0x80 // Support for direct workloop requests
+
+/* Legacy dispatch priority bands */
+
+#define WORKQ_NUM_PRIOQUEUE 4
+
+#define WORKQ_HIGH_PRIOQUEUE 0 // high priority queue
+#define WORKQ_DEFAULT_PRIOQUEUE 1 // default priority queue
+#define WORKQ_LOW_PRIOQUEUE 2 // low priority queue
+#define WORKQ_BG_PRIOQUEUE 3 // background priority queue
+#define WORKQ_NON_INTERACTIVE_PRIOQUEUE 128 // libdispatch SPI level
+
+/* Legacy dispatch workqueue function flags */
+#define WORKQ_ADDTHREADS_OPTION_OVERCOMMIT 0x00000001
+
+__BEGIN_DECLS
+
+// Legacy callback prototype, used with pthread_workqueue_setdispatch_np
+typedef void (*pthread_workqueue_function_t)(int queue_priority, int options, void *ctxt);
+// New callback prototype, used with pthread_workqueue_init
+typedef void (*pthread_workqueue_function2_t)(pthread_priority_t priority);
+
+// Newer callback prototype, used in conjection with function2 when there are kevents to deliver
+// both parameters are in/out parameters
+#define WORKQ_KEVENT_EVENT_BUFFER_LEN 16
+typedef void (*pthread_workqueue_function_kevent_t)(void **events, int *nevents);
+
+typedef void (*pthread_workqueue_function_workloop_t)(uint64_t *workloop_id, void **events, int *nevents);
+
+#define PTHREAD_WORKQUEUE_CONFIG_VERSION 2
+#define PTHREAD_WORKQUEUE_CONFIG_MIN_SUPPORTED_VERSION 1
+#define PTHREAD_WORKQUEUE_CONFIG_SUPPORTED_FLAGS 0
+struct pthread_workqueue_config {
+ uint32_t flags;
+ uint32_t version;
+ pthread_workqueue_function_kevent_t kevent_cb;
+ pthread_workqueue_function_workloop_t workloop_cb;
+ pthread_workqueue_function2_t workq_cb;
+ uint64_t queue_serialno_offs;
+ uint64_t queue_label_offs;
+};
+
+__API_AVAILABLE(macos(10.15), ios(13.0))
+int
+pthread_workqueue_setup(struct pthread_workqueue_config *cfg, size_t cfg_size);
+
+// Initialises the pthread workqueue subsystem, passing the new-style callback prototype,
+// the dispatchoffset and an unused flags field.
+__API_AVAILABLE(macos(10.10), ios(8.0))
+int
+_pthread_workqueue_init(pthread_workqueue_function2_t func, int offset, int flags);
+
+__API_AVAILABLE(macos(10.11), ios(9.0))
+int
+_pthread_workqueue_init_with_kevent(pthread_workqueue_function2_t queue_func, pthread_workqueue_function_kevent_t kevent_func, int offset, int flags);
+
+__API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
+int
+_pthread_workqueue_init_with_workloop(pthread_workqueue_function2_t queue_func, pthread_workqueue_function_kevent_t kevent_func, pthread_workqueue_function_workloop_t workloop_func, int offset, int flags);
+
+// Non-zero enables kill on current thread, zero disables it.
+__API_AVAILABLE(macos(10.6), ios(3.2))
+int
+__pthread_workqueue_setkill(int);
+
+// Dispatch function to be called when new worker threads are created.
+__API_AVAILABLE(macos(10.8), ios(6.0))
+int
+pthread_workqueue_setdispatch_np(pthread_workqueue_function_t worker_func);
+
+// Dispatch offset to be set in the kernel.
+__API_AVAILABLE(macos(10.9), ios(7.0))
+void
+pthread_workqueue_setdispatchoffset_np(int offset);
+
+// Request additional worker threads.
+__API_AVAILABLE(macos(10.8), ios(6.0))
+int
+pthread_workqueue_addthreads_np(int queue_priority, int options, int numthreads);
+
+// Retrieve the supported pthread feature set
+__API_AVAILABLE(macos(10.10), ios(8.0))
+int
+_pthread_workqueue_supported(void);
+
+// Request worker threads (fine grained priority)
+__API_AVAILABLE(macos(10.10), ios(8.0))
+int
+_pthread_workqueue_addthreads(int numthreads, pthread_priority_t priority);
+
+// Should this thread return to the kernel?
+__API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
+bool
+_pthread_workqueue_should_narrow(pthread_priority_t priority);
+
+__API_AVAILABLE(macos(10.11), ios(9.0))
+int
+_pthread_workqueue_set_event_manager_priority(pthread_priority_t priority);
+
+// Apply a QoS override without allocating userspace memory
+__API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
+int
+_pthread_qos_override_start_direct(mach_port_t thread, pthread_priority_t priority, void *resource);
+
+// Drop a corresponding QoS override made above, if the resource matches
+__API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
+int
+_pthread_qos_override_end_direct(mach_port_t thread, void *resource);
+
+// Apply a QoS override without allocating userspace memory
+__API_DEPRECATED_WITH_REPLACEMENT("_pthread_qos_override_start_direct",
+ macos(10.10, 10.12), ios(8.0, 10.0), tvos(8.0, 10.0), watchos(1.0, 3.0))
+int
+_pthread_override_qos_class_start_direct(mach_port_t thread, pthread_priority_t priority);
+
+// Drop a corresponding QoS override made above.
+__API_DEPRECATED_WITH_REPLACEMENT("_pthread_qos_override_end_direct",
+ macos(10.10, 10.12), ios(8.0, 10.0), tvos(8.0, 10.0), watchos(1.0, 3.0))
+int
+_pthread_override_qos_class_end_direct(mach_port_t thread);
+
+// Apply a QoS override on a given workqueue thread.
+__API_AVAILABLE(macos(10.10), ios(8.0))
+int
+_pthread_workqueue_override_start_direct(mach_port_t thread, pthread_priority_t priority);
+
+// Apply a QoS override on a given workqueue thread.
+__API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
+int
+_pthread_workqueue_override_start_direct_check_owner(mach_port_t thread, pthread_priority_t priority, mach_port_t *ulock_addr);
+
+// Drop all QoS overrides on the current workqueue thread.
+__API_AVAILABLE(macos(10.10), ios(8.0))
+int
+_pthread_workqueue_override_reset(void);
+
+// Apply a QoS override on a given thread (can be non-workqueue as well) with a resource/queue token
+__API_AVAILABLE(macos(10.10.2))
+int
+_pthread_workqueue_asynchronous_override_add(mach_port_t thread, pthread_priority_t priority, void *resource);
+
+// Reset overrides for the given resource for the current thread
+__API_AVAILABLE(macos(10.10.2))
+int
+_pthread_workqueue_asynchronous_override_reset_self(void *resource);
+
+// Reset overrides for all resources for the current thread
+__API_AVAILABLE(macos(10.10.2))
+int
+_pthread_workqueue_asynchronous_override_reset_all_self(void);
+
+__API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
+int
+_pthread_workloop_create(uint64_t workloop_id, uint64_t options, pthread_attr_t *attr);
+
+__API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
+int
+_pthread_workloop_destroy(uint64_t workloop_id);
+
+__END_DECLS
+
+#endif // __PTHREAD_WORKQUEUE_H__
+++ /dev/null
-/*
- * Copyright (c) 2014 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef _QOS_LEGACY_H
-#define _QOS_LEGACY_H
-
-#include_next <pthread/qos.h>
-
-#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
-
-#ifdef __has_include
-#if __has_include(<pthread/qos_private.h>)
-#include <pthread/qos_private.h>
-#endif
-#endif
-
-#endif // __DARWIN_C_LEVEL >= __DARWIN_C_FULL
-
-#endif //_QOS_LEGACY_H
+++ /dev/null
-/*
- * Copyright (c) 2013-2014 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef _QOS_PRIVATE_H
-#define _QOS_PRIVATE_H
-
-#include <pthread/qos.h>
-#include <pthread/priority_private.h>
-#include <sys/qos.h> /* qos_class_t */
-#include <sys/qos_private.h>
-
-#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
-// allow __DARWIN_C_LEVEL to turn off the use of mach_port_t
-#include <mach/port.h>
-#endif
-
-// redeffed here to avoid leaving __QOS_ENUM defined in the public header
-#define __QOS_ENUM(name, type, ...) enum { __VA_ARGS__ }; typedef type name##_t
-#define __QOS_AVAILABLE_10_10
-#define __QOS_AVAILABLE_10_11
-#define __QOS_AVAILABLE_10_12
-
-#if defined(__has_feature) && defined(__has_extension)
-#if __has_feature(objc_fixed_enum) || __has_extension(cxx_strong_enums)
-#undef __QOS_ENUM
-#define __QOS_ENUM(name, type, ...) typedef enum : type { __VA_ARGS__ } name##_t
-#endif
-#if __has_feature(enumerator_attributes)
-#undef __QOS_AVAILABLE_10_10
-#define __QOS_AVAILABLE_10_10 __API_AVAILABLE(macos(10.10), ios(8.0))
-#undef __QOS_AVAILABLE_10_11
-#define __QOS_AVAILABLE_10_11 __API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0), watchos(2.0))
-#undef __QOS_AVAILABLE_10_12
-#define __QOS_AVAILABLE_10_12 __API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
-#undef __QOS_AVAILABLE_10_15_1
-#define __QOS_AVAILABLE_10_15_1 __API_AVAILABLE(macos(10.15.1), ios(13.2), tvos(13.2), watchos(6.2))
-#endif
-#endif
-
-// This enum matches workq_set_self_flags in
-// xnu's workqueue_internal.h.
-__QOS_ENUM(_pthread_set_flags, unsigned int,
- _PTHREAD_SET_SELF_QOS_FLAG __QOS_AVAILABLE_10_10 = 0x1,
- _PTHREAD_SET_SELF_VOUCHER_FLAG __QOS_AVAILABLE_10_10 = 0x2,
- _PTHREAD_SET_SELF_FIXEDPRIORITY_FLAG __QOS_AVAILABLE_10_11 = 0x4,
- _PTHREAD_SET_SELF_TIMESHARE_FLAG __QOS_AVAILABLE_10_11 = 0x8,
- _PTHREAD_SET_SELF_WQ_KEVENT_UNBIND __QOS_AVAILABLE_10_12 = 0x10,
- _PTHREAD_SET_SELF_ALTERNATE_AMX __QOS_AVAILABLE_10_15_1 = 0x20,
-);
-
-#undef __QOS_ENUM
-#undef __QOS_AVAILABLE_10_10
-#undef __QOS_AVAILABLE_10_11
-#undef __QOS_AVAILABLE_10_12
-
-#ifndef KERNEL
-
-__BEGIN_DECLS
-
-/*!
- * @function pthread_set_qos_class_np
- *
- * @abstract
- * Sets the requested QOS class and relative priority of the current thread.
- *
- * @discussion
- * The QOS class and relative priority represent an overall combination of
- * system quality of service attributes on a thread.
- *
- * Subsequent calls to interfaces such as pthread_setschedparam() that are
- * incompatible or in conflict with the QOS class system will unset the QOS
- * class requested with this interface and pthread_get_qos_class_np() will
- * return QOS_CLASS_UNSPECIFIED thereafter. A thread so modified is permanently
- * opted-out of the QOS class system and calls to this function to request a QOS
- * class for such a thread will fail and return EPERM.
- *
- * @param __pthread
- * The current thread as returned by pthread_self().
- * EINVAL will be returned if any other thread is provided.
- *
- * @param __qos_class
- * A QOS class value:
- * - QOS_CLASS_USER_INTERACTIVE
- * - QOS_CLASS_USER_INITIATED
- * - QOS_CLASS_DEFAULT
- * - QOS_CLASS_UTILITY
- * - QOS_CLASS_BACKGROUND
- * - QOS_CLASS_MAINTENANCE
- * EINVAL will be returned if any other value is provided.
- *
- * @param __relative_priority
- * A relative priority within the QOS class. This value is a negative offset
- * from the maximum supported scheduler priority for the given class.
- * EINVAL will be returned if the value is greater than zero or less than
- * QOS_MIN_RELATIVE_PRIORITY.
- *
- * @return
- * Zero if successful, othwerise an errno value.
- */
-__API_DEPRECATED_WITH_REPLACEMENT("pthread_set_qos_class_self_np", macos(10.10, 10.10), ios(8.0, 8.0))
-int
-pthread_set_qos_class_np(pthread_t __pthread,
- qos_class_t __qos_class,
- int __relative_priority);
-
-/* Private interfaces for libdispatch to encode/decode specific values of pthread_priority_t. */
-
-// Encode a class+priority pair into a pthread_priority_t,
-__API_AVAILABLE(macos(10.10), ios(8.0))
-pthread_priority_t
-_pthread_qos_class_encode(qos_class_t qos_class, int relative_priority, unsigned long flags);
-
-// Decode a pthread_priority_t into a class+priority pair.
-__API_AVAILABLE(macos(10.10), ios(8.0))
-qos_class_t
-_pthread_qos_class_decode(pthread_priority_t priority, int *relative_priority, unsigned long *flags);
-
-// Encode a legacy workqueue API priority into a pthread_priority_t. This API
-// is deprecated and can be removed when the simulator no longer uses it.
-__API_DEPRECATED("no longer used", macos(10.10, 10.13), ios(8.0, 11.0))
-pthread_priority_t
-_pthread_qos_class_encode_workqueue(int queue_priority, unsigned long flags);
-
-#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
-
-// Set QoS or voucher, or both, on pthread_self()
-__API_AVAILABLE(macos(10.10), ios(8.0))
-int
-_pthread_set_properties_self(_pthread_set_flags_t flags, pthread_priority_t priority, mach_port_t voucher);
-
-// Set self to fixed priority without disturbing QoS or priority
-__API_AVAILABLE(macos(10.10), ios(8.0))
-int
-pthread_set_fixedpriority_self(void);
-
-// Inverse of pthread_set_fixedpriority_self()
-__API_AVAILABLE(macos(10.10), ios(8.0))
-int
-pthread_set_timeshare_self(void);
-
-// Set self to avoid running on the same AMX as
-// other work in this group.
-// Only allowed on non-workqueue pthreads
-__API_AVAILABLE(macos(10.15.1), ios(13.2), tvos(13.2), watchos(6.2))
-int
-pthread_prefer_alternate_amx_self(void);
-
-/*!
- * @const PTHREAD_MAX_PARALLELISM_PHYSICAL
- * Flag that can be used with pthread_qos_max_parallelism() and
- * pthread_time_constraint_max_parallelism() to ask for a count of physical
- * compute units available for parallelism (default is logical).
- */
-#define PTHREAD_MAX_PARALLELISM_PHYSICAL 0x1
-
-/*!
- * @function pthread_qos_max_parallelism
- *
- * @abstract
- * Returns the number of compute units available for parallel computation at
- * a specified QoS class.
- *
- * @param qos
- * The specified QoS class.
- *
- * @param flags
- * 0 or PTHREAD_MAX_PARALLELISM_PHYSICAL.
- *
- * @return
- * The number of compute units available for parallel computation for the
- * specified QoS, or -1 on failure (with errno set accordingly).
- */
-__API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
-int
-pthread_qos_max_parallelism(qos_class_t qos, unsigned long flags);
-
-/*!
- * @function pthread_time_constraint_max_parallelism()
- *
- * @abstract
- * Returns the number of compute units available for parallel computation on
- * realtime threads.
- *
- * @param flags
- * 0 or PTHREAD_MAX_PARALLELISM_PHYSICAL.
- *
- * @return
- * The number of compute units available for parallel computation on realtime
- * threads, or -1 on failure (with errno set accordingly).
- */
-__API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
-int
-pthread_time_constraint_max_parallelism(unsigned long flags);
-
-#endif // __DARWIN_C_LEVEL >= __DARWIN_C_FULL
-
-__END_DECLS
-
-#endif // KERNEL
-
-#endif //_QOS_PRIVATE_H
+++ /dev/null
-/*
- * Copyright (c) 2003, 2013 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
- * All Rights Reserved
- *
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appears in all copies and
- * that both the copyright notice and this permission notice appear in
- * supporting documentation.
- *
- * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
- * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-/*
- * MkLinux
- */
-
-/*
- * POSIX Threads - IEEE 1003.1c
- */
-
-#ifndef _POSIX_PTHREAD_SPINLOCK_H
-#define _POSIX_PTHREAD_SPINLOCK_H
-
-#include <sys/cdefs.h>
-#include <mach/mach.h>
-#include <libkern/OSAtomic.h>
-
-typedef volatile OSSpinLock pthread_lock_t __deprecated_msg("Use <os/lock.h> instead");
-
-#define LOCK_INIT(l) ((l) = OS_SPINLOCK_INIT)
-#define LOCK_INITIALIZER OS_SPINLOCK_INIT
-
-#define _DO_SPINLOCK_LOCK(v) OSSpinLockLock(v)
-#define _DO_SPINLOCK_UNLOCK(v) OSSpinLockUnlock(v)
-
-#define TRY_LOCK(v) OSSpinLockTry((volatile OSSpinLock *)&(v))
-#define LOCK(v) OSSpinLockLock((volatile OSSpinLock *)&(v))
-#define UNLOCK(v) OSSpinLockUnlock((volatile OSSpinLock *)&(v))
-
-extern void _spin_lock(pthread_lock_t *lockp) __deprecated_msg("Use <os/lock.h> instead");
-extern int _spin_lock_try(pthread_lock_t *lockp) __deprecated_msg("Use <os/lock.h> instead");
-extern void _spin_unlock(pthread_lock_t *lockp) __deprecated_msg("Use <os/lock.h> instead");
-
-extern void spin_lock(pthread_lock_t *lockp) __deprecated_msg("Use <os/lock.h> instead");
-extern int spin_lock_try(pthread_lock_t *lockp) __deprecated_msg("Use <os/lock.h> instead");
-extern void spin_unlock(pthread_lock_t *lockp) __deprecated_msg("Use <os/lock.h> instead");
-
-#endif /* _POSIX_PTHREAD_SPINLOCK_H */
--- /dev/null
+/*
+ * Copyright (c) 2014 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef _QOS_SYS_PRIVATE_H
+#define _QOS_SYS_PRIVATE_H
+
+/*!
+ * @constant QOS_CLASS_MAINTENANCE
+ * @abstract A QOS class which indicates work performed by this thread was not
+ * initiated by the user and that the user may be unaware of the results.
+ * @discussion Such work is requested to run at a priority far below other work
+ * including significant I/O throttling. The use of this QOS class indicates
+ * the work should be run in the most energy and thermally-efficient manner
+ * possible, and may be deferred for a long time in order to preserve
+ * system responsiveness for the user.
+ * This is SPI for use by Spotlight and Time Machine only.
+ */
+#define QOS_CLASS_MAINTENANCE ((qos_class_t)0x05)
+
+#endif //_QOS_SYS_PRIVATE_H
+++ /dev/null
-/*
- * Copyright (c) 2003-2013 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
- * All Rights Reserved
- *
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appears in all copies and
- * that both the copyright notice and this permission notice appear in
- * supporting documentation.
- *
- * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
- * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-/*
- * MkLinux
- */
-
-#ifndef __PTHREAD_TSD_H__
-#define __PTHREAD_TSD_H__
-
-#ifndef __ASSEMBLER__
-
-#include <System/machine/cpu_capabilities.h>
-#include <sys/cdefs.h>
-#include <TargetConditionals.h>
-#include <Availability.h>
-#include <os/tsd.h>
-#include <pthread/spinlock_private.h>
-
-#ifndef __TSD_MACH_THREAD_SELF
-#define __TSD_MACH_THREAD_SELF 3
-#endif
-
-#ifndef __TSD_THREAD_QOS_CLASS
-#define __TSD_THREAD_QOS_CLASS 4
-#endif
-
-#ifndef __TSD_RETURN_TO_KERNEL
-#define __TSD_RETURN_TO_KERNEL 5
-#endif
-
-#ifndef __TSD_PTR_MUNGE
-#define __TSD_PTR_MUNGE 7
-#endif
-
-#ifndef __TSD_MACH_SPECIAL_REPLY
-#define __TSD_MACH_SPECIAL_REPLY 8
-#endif
-
-/* Constant TSD slots for inline pthread_getspecific() usage. */
-
-/* Keys 0 - 9 are for Libsyscall/libplatform usage */
-#define _PTHREAD_TSD_SLOT_PTHREAD_SELF __TSD_THREAD_SELF
-#define _PTHREAD_TSD_SLOT_ERRNO __TSD_ERRNO
-#define _PTHREAD_TSD_SLOT_MIG_REPLY __TSD_MIG_REPLY
-#define _PTHREAD_TSD_SLOT_MACH_THREAD_SELF __TSD_MACH_THREAD_SELF
-#define _PTHREAD_TSD_SLOT_PTHREAD_QOS_CLASS __TSD_THREAD_QOS_CLASS
-#define _PTHREAD_TSD_SLOT_RETURN_TO_KERNEL __TSD_RETURN_TO_KERNEL
-#define _PTHREAD_TSD_SLOT_PTR_MUNGE __TSD_PTR_MUNGE
-#define _PTHREAD_TSD_SLOT_MACH_SPECIAL_REPLY __TSD_MACH_SPECIAL_REPLY
-//#define _PTHREAD_TSD_SLOT_SEMAPHORE_CACHE __TSD_SEMAPHORE_CACHE
-
-/*
- * Windows 64-bit ABI bakes %gs relative accesses into its code in the same
- * range as our TSD keys. To allow some limited interoperability for code
- * targeting that ABI, we leave slots 6 and 11 unused.
- *
- * The Go runtime on x86_64 also uses this because their ABI doesn't reserve a
- * register for the TSD base. They were previously using an arbitrarily chosen
- * dynamic key and relying on being able to get it at runtime, but switched to
- * this slot to avoid issues with that approach. It's assumed that Go and
- * Windows code won't run in the same address space.
- */
-//#define _PTHREAD_TSD_SLOT_RESERVED_WIN64 6
-
-#define _PTHREAD_TSD_RESERVED_SLOT_COUNT _PTHREAD_TSD_RESERVED_SLOT_COUNT
-
-/* Keys 10 - 29 are for Libc/Libsystem internal usage */
-/* used as __pthread_tsd_first + Num */
-#define __PTK_LIBC_LOCALE_KEY 10
-//#define __PTK_LIBC_RESERVED_WIN64 11
-#define __PTK_LIBC_LOCALTIME_KEY 12
-#define __PTK_LIBC_GMTIME_KEY 13
-#define __PTK_LIBC_GDTOA_BIGINT_KEY 14
-#define __PTK_LIBC_PARSEFLOAT_KEY 15
-#define __PTK_LIBC_TTYNAME_KEY 16
-/* for usage by dyld */
-#define __PTK_LIBC_DYLD_Unwind_SjLj_Key 18
-
-/* Keys 20-29 for libdispatch usage */
-#define __PTK_LIBDISPATCH_KEY0 20
-#define __PTK_LIBDISPATCH_KEY1 21
-#define __PTK_LIBDISPATCH_KEY2 22
-#define __PTK_LIBDISPATCH_KEY3 23
-#define __PTK_LIBDISPATCH_KEY4 24
-#define __PTK_LIBDISPATCH_KEY5 25
-#define __PTK_LIBDISPATCH_KEY6 26
-#define __PTK_LIBDISPATCH_KEY7 27
-#define __PTK_LIBDISPATCH_KEY8 28
-#define __PTK_LIBDISPATCH_KEY9 29
-
-/* Keys 30-255 for Non Libsystem usage */
-
-/* Keys 30-39 for Graphic frameworks usage */
-#define _PTHREAD_TSD_SLOT_OPENGL 30 /* backwards compat sake */
-#define __PTK_FRAMEWORK_OPENGL_KEY 30
-#define __PTK_FRAMEWORK_GRAPHICS_KEY1 31
-#define __PTK_FRAMEWORK_GRAPHICS_KEY2 32
-#define __PTK_FRAMEWORK_GRAPHICS_KEY3 33
-#define __PTK_FRAMEWORK_GRAPHICS_KEY4 34
-#define __PTK_FRAMEWORK_GRAPHICS_KEY5 35
-#define __PTK_FRAMEWORK_GRAPHICS_KEY6 36
-#define __PTK_FRAMEWORK_GRAPHICS_KEY7 37
-#define __PTK_FRAMEWORK_GRAPHICS_KEY8 38
-#define __PTK_FRAMEWORK_GRAPHICS_KEY9 39
-
-/* Keys 40-49 for Objective-C runtime usage */
-#define __PTK_FRAMEWORK_OBJC_KEY0 40
-#define __PTK_FRAMEWORK_OBJC_KEY1 41
-#define __PTK_FRAMEWORK_OBJC_KEY2 42
-#define __PTK_FRAMEWORK_OBJC_KEY3 43
-#define __PTK_FRAMEWORK_OBJC_KEY4 44
-#define __PTK_FRAMEWORK_OBJC_KEY5 45
-#define __PTK_FRAMEWORK_OBJC_KEY6 46
-#define __PTK_FRAMEWORK_OBJC_KEY7 47
-#define __PTK_FRAMEWORK_OBJC_KEY8 48
-#define __PTK_FRAMEWORK_OBJC_KEY9 49
-
-/* Keys 50-59 for Core Foundation usage */
-#define __PTK_FRAMEWORK_COREFOUNDATION_KEY0 50
-#define __PTK_FRAMEWORK_COREFOUNDATION_KEY1 51
-#define __PTK_FRAMEWORK_COREFOUNDATION_KEY2 52
-#define __PTK_FRAMEWORK_COREFOUNDATION_KEY3 53
-#define __PTK_FRAMEWORK_COREFOUNDATION_KEY4 54
-#define __PTK_FRAMEWORK_COREFOUNDATION_KEY5 55
-#define __PTK_FRAMEWORK_COREFOUNDATION_KEY6 56
-#define __PTK_FRAMEWORK_COREFOUNDATION_KEY7 57
-#define __PTK_FRAMEWORK_COREFOUNDATION_KEY8 58
-#define __PTK_FRAMEWORK_COREFOUNDATION_KEY9 59
-
-/* Keys 60-69 for Foundation usage */
-#define __PTK_FRAMEWORK_FOUNDATION_KEY0 60
-#define __PTK_FRAMEWORK_FOUNDATION_KEY1 61
-#define __PTK_FRAMEWORK_FOUNDATION_KEY2 62
-#define __PTK_FRAMEWORK_FOUNDATION_KEY3 63
-#define __PTK_FRAMEWORK_FOUNDATION_KEY4 64
-#define __PTK_FRAMEWORK_FOUNDATION_KEY5 65
-#define __PTK_FRAMEWORK_FOUNDATION_KEY6 66
-#define __PTK_FRAMEWORK_FOUNDATION_KEY7 67
-#define __PTK_FRAMEWORK_FOUNDATION_KEY8 68
-#define __PTK_FRAMEWORK_FOUNDATION_KEY9 69
-
-/* Keys 70-79 for Core Animation/QuartzCore usage */
-#define __PTK_FRAMEWORK_QUARTZCORE_KEY0 70
-#define __PTK_FRAMEWORK_QUARTZCORE_KEY1 71
-#define __PTK_FRAMEWORK_QUARTZCORE_KEY2 72
-#define __PTK_FRAMEWORK_QUARTZCORE_KEY3 73
-#define __PTK_FRAMEWORK_QUARTZCORE_KEY4 74
-#define __PTK_FRAMEWORK_QUARTZCORE_KEY5 75
-#define __PTK_FRAMEWORK_QUARTZCORE_KEY6 76
-#define __PTK_FRAMEWORK_QUARTZCORE_KEY7 77
-#define __PTK_FRAMEWORK_QUARTZCORE_KEY8 78
-#define __PTK_FRAMEWORK_QUARTZCORE_KEY9 79
-
-
-/* Keys 80-89 for CoreData */
-#define __PTK_FRAMEWORK_COREDATA_KEY0 80
-#define __PTK_FRAMEWORK_COREDATA_KEY1 81
-#define __PTK_FRAMEWORK_COREDATA_KEY2 82
-#define __PTK_FRAMEWORK_COREDATA_KEY3 83
-#define __PTK_FRAMEWORK_COREDATA_KEY4 84
-#define __PTK_FRAMEWORK_COREDATA_KEY5 85
-#define __PTK_FRAMEWORK_COREDATA_KEY6 86
-#define __PTK_FRAMEWORK_COREDATA_KEY7 87
-#define __PTK_FRAMEWORK_COREDATA_KEY8 88
-#define __PTK_FRAMEWORK_COREDATA_KEY9 89
-
-/* Keys 90-94 for JavaScriptCore Collection */
-#define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0 90
-#define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY1 91
-#define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY2 92
-#define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY3 93
-#define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY4 94
-/* Keys 95 for CoreText */
-#define __PTK_FRAMEWORK_CORETEXT_KEY0 95
-
-/* Keys 100-109 are for the Swift runtime */
-#define __PTK_FRAMEWORK_SWIFT_KEY0 100
-#define __PTK_FRAMEWORK_SWIFT_KEY1 101
-#define __PTK_FRAMEWORK_SWIFT_KEY2 102
-#define __PTK_FRAMEWORK_SWIFT_KEY3 103
-#define __PTK_FRAMEWORK_SWIFT_KEY4 104
-#define __PTK_FRAMEWORK_SWIFT_KEY5 105
-#define __PTK_FRAMEWORK_SWIFT_KEY6 106
-#define __PTK_FRAMEWORK_SWIFT_KEY7 107
-#define __PTK_FRAMEWORK_SWIFT_KEY8 108
-#define __PTK_FRAMEWORK_SWIFT_KEY9 109
-
-/* Keys 190 - 194 are for the use of PerfUtils */
-#define __PTK_PERF_UTILS_KEY0 190
-#define __PTK_PERF_UTILS_KEY1 191
-#define __PTK_PERF_UTILS_KEY2 192
-#define __PTK_PERF_UTILS_KEY3 193
-#define __PTK_PERF_UTILS_KEY4 194
-
-/* Keys 210 - 229 are for libSystem usage within the iOS Simulator */
-/* They are offset from their corresponding libSystem keys by 200 */
-#define __PTK_LIBC_SIM_LOCALE_KEY 210
-#define __PTK_LIBC_SIM_TTYNAME_KEY 211
-#define __PTK_LIBC_SIM_LOCALTIME_KEY 212
-#define __PTK_LIBC_SIM_GMTIME_KEY 213
-#define __PTK_LIBC_SIM_GDTOA_BIGINT_KEY 214
-#define __PTK_LIBC_SIM_PARSEFLOAT_KEY 215
-
-__BEGIN_DECLS
-
-extern void *pthread_getspecific(unsigned long);
-extern int pthread_setspecific(unsigned long, const void *);
-/* setup destructor function for static key as it is not created with pthread_key_create() */
-extern int pthread_key_init_np(int, void (*)(void *));
-
-__API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
-extern int _pthread_setspecific_static(unsigned long, void *);
-
-#if PTHREAD_LAYOUT_SPI
-
-/* SPI intended for CoreSymbolication only */
-
-__API_AVAILABLE(macos(10.10), ios(8.0))
-extern const struct pthread_layout_offsets_s {
- // always add new fields at the end
- const uint16_t plo_version;
- // either of the next two fields may be 0; use whichever is set
- // bytes from pthread_t to base of tsd
- const uint16_t plo_pthread_tsd_base_offset;
- // bytes from pthread_t to a pointer to base of tsd
- const uint16_t plo_pthread_tsd_base_address_offset;
- const uint16_t plo_pthread_tsd_entry_size;
-} pthread_layout_offsets;
-
-#endif // PTHREAD_LAYOUT_SPI
-
-__header_always_inline int
-_pthread_has_direct_tsd(void)
-{
-#if TARGET_IPHONE_SIMULATOR
- return 0;
-#else
- return 1;
-#endif
-}
-
-/* To be used with static constant keys only */
-__header_always_inline void *
-_pthread_getspecific_direct(unsigned long slot)
-{
-#if TARGET_IPHONE_SIMULATOR
- return pthread_getspecific(slot);
-#else
- return _os_tsd_get_direct(slot);
-#endif
-}
-
-/* To be used with static constant keys only, assumes destructor is
- * already setup (with pthread_key_init_np) */
-__header_always_inline int
-_pthread_setspecific_direct(unsigned long slot, void * val)
-{
-#if TARGET_IPHONE_SIMULATOR
- return _pthread_setspecific_static(slot, val);
-#else
- return _os_tsd_set_direct(slot, val);
-#endif
-}
-
-__END_DECLS
-
-#endif /* ! __ASSEMBLER__ */
-#endif /* __PTHREAD_TSD_H__ */
+++ /dev/null
-/*
- * Copyright (c) 2007, 2012 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef __PTHREAD_WORKQUEUE_H__
-#define __PTHREAD_WORKQUEUE_H__
-
-#include <stdbool.h>
-#include <sys/cdefs.h>
-#include <sys/event.h>
-#include <Availability.h>
-#include <pthread/pthread.h>
-#include <pthread/qos.h>
-#ifndef _PTHREAD_BUILDING_PTHREAD_
-#include <pthread/qos_private.h>
-#endif
-
-#define PTHREAD_WORKQUEUE_SPI_VERSION 20170201
-
-/* Feature checking flags, returned by _pthread_workqueue_supported()
- *
- * Note: These bits should match the definition of PTHREAD_FEATURE_*
- * bits defined in libpthread/kern/kern_internal.h */
-
-#define WORKQ_FEATURE_DISPATCHFUNC 0x01 // pthread_workqueue_setdispatch_np is supported (or not)
-#define WORKQ_FEATURE_FINEPRIO 0x02 // fine grained pthread workq priorities
-#define WORKQ_FEATURE_MAINTENANCE 0x10 // QOS class maintenance
-#define WORKQ_FEATURE_KEVENT 0x40 // Support for direct kevent delivery
-#define WORKQ_FEATURE_WORKLOOP 0x80 // Support for direct workloop requests
-
-/* Legacy dispatch priority bands */
-
-#define WORKQ_NUM_PRIOQUEUE 4
-
-#define WORKQ_HIGH_PRIOQUEUE 0 // high priority queue
-#define WORKQ_DEFAULT_PRIOQUEUE 1 // default priority queue
-#define WORKQ_LOW_PRIOQUEUE 2 // low priority queue
-#define WORKQ_BG_PRIOQUEUE 3 // background priority queue
-#define WORKQ_NON_INTERACTIVE_PRIOQUEUE 128 // libdispatch SPI level
-
-/* Legacy dispatch workqueue function flags */
-#define WORKQ_ADDTHREADS_OPTION_OVERCOMMIT 0x00000001
-
-__BEGIN_DECLS
-
-// Legacy callback prototype, used with pthread_workqueue_setdispatch_np
-typedef void (*pthread_workqueue_function_t)(int queue_priority, int options, void *ctxt);
-// New callback prototype, used with pthread_workqueue_init
-typedef void (*pthread_workqueue_function2_t)(pthread_priority_t priority);
-
-// Newer callback prototype, used in conjection with function2 when there are kevents to deliver
-// both parameters are in/out parameters
-#define WORKQ_KEVENT_EVENT_BUFFER_LEN 16
-typedef void (*pthread_workqueue_function_kevent_t)(void **events, int *nevents);
-
-typedef void (*pthread_workqueue_function_workloop_t)(uint64_t *workloop_id, void **events, int *nevents);
-
-#define PTHREAD_WORKQUEUE_CONFIG_VERSION 2
-#define PTHREAD_WORKQUEUE_CONFIG_MIN_SUPPORTED_VERSION 1
-#define PTHREAD_WORKQUEUE_CONFIG_SUPPORTED_FLAGS 0
-struct pthread_workqueue_config {
- uint32_t flags;
- uint32_t version;
- pthread_workqueue_function_kevent_t kevent_cb;
- pthread_workqueue_function_workloop_t workloop_cb;
- pthread_workqueue_function2_t workq_cb;
- uint64_t queue_serialno_offs;
- uint64_t queue_label_offs;
-};
-
-__API_AVAILABLE(macos(10.15), ios(13.0))
-int
-pthread_workqueue_setup(struct pthread_workqueue_config *cfg, size_t cfg_size);
-
-// Initialises the pthread workqueue subsystem, passing the new-style callback prototype,
-// the dispatchoffset and an unused flags field.
-__API_AVAILABLE(macos(10.10), ios(8.0))
-int
-_pthread_workqueue_init(pthread_workqueue_function2_t func, int offset, int flags);
-
-__API_AVAILABLE(macos(10.11), ios(9.0))
-int
-_pthread_workqueue_init_with_kevent(pthread_workqueue_function2_t queue_func, pthread_workqueue_function_kevent_t kevent_func, int offset, int flags);
-
-__API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
-int
-_pthread_workqueue_init_with_workloop(pthread_workqueue_function2_t queue_func, pthread_workqueue_function_kevent_t kevent_func, pthread_workqueue_function_workloop_t workloop_func, int offset, int flags);
-
-// Non-zero enables kill on current thread, zero disables it.
-__API_AVAILABLE(macos(10.6), ios(3.2))
-int
-__pthread_workqueue_setkill(int);
-
-// Dispatch function to be called when new worker threads are created.
-__API_AVAILABLE(macos(10.8), ios(6.0))
-int
-pthread_workqueue_setdispatch_np(pthread_workqueue_function_t worker_func);
-
-// Dispatch offset to be set in the kernel.
-__API_AVAILABLE(macos(10.9), ios(7.0))
-void
-pthread_workqueue_setdispatchoffset_np(int offset);
-
-// Request additional worker threads.
-__API_AVAILABLE(macos(10.8), ios(6.0))
-int
-pthread_workqueue_addthreads_np(int queue_priority, int options, int numthreads);
-
-// Retrieve the supported pthread feature set
-__API_AVAILABLE(macos(10.10), ios(8.0))
-int
-_pthread_workqueue_supported(void);
-
-// Request worker threads (fine grained priority)
-__API_AVAILABLE(macos(10.10), ios(8.0))
-int
-_pthread_workqueue_addthreads(int numthreads, pthread_priority_t priority);
-
-// Should this thread return to the kernel?
-__API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
-bool
-_pthread_workqueue_should_narrow(pthread_priority_t priority);
-
-__API_AVAILABLE(macos(10.11), ios(9.0))
-int
-_pthread_workqueue_set_event_manager_priority(pthread_priority_t priority);
-
-// Apply a QoS override without allocating userspace memory
-__API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
-int
-_pthread_qos_override_start_direct(mach_port_t thread, pthread_priority_t priority, void *resource);
-
-// Drop a corresponding QoS override made above, if the resource matches
-__API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
-int
-_pthread_qos_override_end_direct(mach_port_t thread, void *resource);
-
-// Apply a QoS override without allocating userspace memory
-__API_DEPRECATED_WITH_REPLACEMENT("_pthread_qos_override_start_direct",
- macos(10.10, 10.12), ios(8.0, 10.0), tvos(8.0, 10.0), watchos(1.0, 3.0))
-int
-_pthread_override_qos_class_start_direct(mach_port_t thread, pthread_priority_t priority);
-
-// Drop a corresponding QoS override made above.
-__API_DEPRECATED_WITH_REPLACEMENT("_pthread_qos_override_end_direct",
- macos(10.10, 10.12), ios(8.0, 10.0), tvos(8.0, 10.0), watchos(1.0, 3.0))
-int
-_pthread_override_qos_class_end_direct(mach_port_t thread);
-
-// Apply a QoS override on a given workqueue thread.
-__API_AVAILABLE(macos(10.10), ios(8.0))
-int
-_pthread_workqueue_override_start_direct(mach_port_t thread, pthread_priority_t priority);
-
-// Apply a QoS override on a given workqueue thread.
-__API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
-int
-_pthread_workqueue_override_start_direct_check_owner(mach_port_t thread, pthread_priority_t priority, mach_port_t *ulock_addr);
-
-// Drop all QoS overrides on the current workqueue thread.
-__API_AVAILABLE(macos(10.10), ios(8.0))
-int
-_pthread_workqueue_override_reset(void);
-
-// Apply a QoS override on a given thread (can be non-workqueue as well) with a resource/queue token
-__API_AVAILABLE(macos(10.10.2))
-int
-_pthread_workqueue_asynchronous_override_add(mach_port_t thread, pthread_priority_t priority, void *resource);
-
-// Reset overrides for the given resource for the current thread
-__API_AVAILABLE(macos(10.10.2))
-int
-_pthread_workqueue_asynchronous_override_reset_self(void *resource);
-
-// Reset overrides for all resources for the current thread
-__API_AVAILABLE(macos(10.10.2))
-int
-_pthread_workqueue_asynchronous_override_reset_all_self(void);
-
-__API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
-int
-_pthread_workloop_create(uint64_t workloop_id, uint64_t options, pthread_attr_t *attr);
-
-__API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
-int
-_pthread_workloop_destroy(uint64_t workloop_id);
-
-__END_DECLS
-
-#endif // __PTHREAD_WORKQUEUE_H__
+++ /dev/null
-/*
- * Copyright (c) 2013, 2016 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef __PTHREAD_INTROSPECTION__
-#define __PTHREAD_INTROSPECTION__
-
-#include <sys/cdefs.h>
-#include <pthread/pthread.h>
-#include <Availability.h>
-
-/*!
- * @header
- *
- * @abstract
- * Introspection API for libpthread.
- *
- * This should only be used for introspection and debugging tools. Do not rely
- * on it in shipping code.
- */
-
-__BEGIN_DECLS
-
-/*!
- * @typedef pthread_introspection_hook_t
- *
- * @abstract
- * A function pointer called at various points in a PThread's lifetime. The
- * function must be able to be called in contexts with invalid thread state.
- *
- * @param event
- * One of the events in pthread_introspection_event_t.
- *
- * @param thread
- * pthread_t associated with the event.
- *
- * @param addr
- * Address associated with the event, e.g. stack address.
- *
- * @param size
- * Size associated with the event, e.g. stack size.
- */
-typedef void (*pthread_introspection_hook_t)(unsigned int event,
- pthread_t thread, void *addr, size_t size);
-
-/*!
- * @enum pthread_introspection_event_t
- * Events sent by libpthread about threads lifetimes.
- *
- * @const PTHREAD_INTROSPECTION_THREAD_CREATE
- * The specified pthread_t was created, and there will be a paired
- * PTHREAD_INTROSPECTION_THREAD_DESTROY event. However, there may not be
- * a START/TERMINATE pair of events for this pthread_t.
- *
- * Starting with macOS 10.14, and iOS 12, this event is always sent before
- * PTHREAD_INTROSPECTION_THREAD_START is sent. This event is however not sent
- * for the main thread.
- *
- * This event may not be sent from the context of the passed in pthread_t.
- *
- * Note that all properties of this thread may not be functional yet, and it is
- * not permitted to call functions on this thread past observing its address.
- *
- * @const PTHREAD_INTROSPECTION_THREAD_START
- * Thread has started and its stack was allocated. There will be a matching
- * PTHREAD_INTROSPECTION_THREAD_TERMINATE event.
- *
- * This event is always sent from the context of the passed in pthread_t.
- *
- * @const PTHREAD_INTROSPECTION_THREAD_TERMINATE
- * Thread is about to be terminated and stack will be deallocated. This always
- * matches a PTHREAD_INTROSPECTION_THREAD_START event.
- *
- * This event is always sent from the context of the passed in pthread_t.
- *
- * @const PTHREAD_INTROSPECTION_THREAD_DESTROY
- * pthread_t is about to be destroyed. This always matches
- * a PTHREAD_INTROSPECTION_THREAD_CREATE event, but there may not have been
- * a START/TERMINATE pair of events for this pthread_t.
- *
- * This event may not be sent from the context of the passed in pthread_t.
- */
-enum {
- PTHREAD_INTROSPECTION_THREAD_CREATE = 1,
- PTHREAD_INTROSPECTION_THREAD_START,
- PTHREAD_INTROSPECTION_THREAD_TERMINATE,
- PTHREAD_INTROSPECTION_THREAD_DESTROY,
-};
-
-/*!
- * @function pthread_introspection_hook_install
- *
- * @abstract
- * Install introspection hook function into libpthread.
- *
- * @discussion
- * The caller is responsible for implementing chaining to the hook that was
- * previously installed (if any).
- *
- * @param hook
- * Pointer to hook function.
- *
- * @result
- * Previously installed hook function or NULL.
- */
-
-__API_AVAILABLE(macos(10.9), ios(7.0))
-__attribute__((__nonnull__, __warn_unused_result__))
-extern pthread_introspection_hook_t
-pthread_introspection_hook_install(pthread_introspection_hook_t hook);
-
-__END_DECLS
-
-#endif
+++ /dev/null
-/*
- * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
- * All Rights Reserved
- *
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appears in all copies and
- * that both the copyright notice and this permission notice appear in
- * supporting documentation.
- *
- * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
- * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-/*
- * MkLinux
- */
-
-/*
- * POSIX Threads - IEEE 1003.1c
- */
-
-#ifndef _PTHREAD_H
-#define _PTHREAD_H
-
-#include <_types.h>
-#ifndef __POSIX_LIB__
-#include <pthread/pthread_impl.h>
-#endif
-#include <pthread/sched.h>
-#include <time.h>
-#include <sys/_pthread/_pthread_types.h>
-#include <sys/_pthread/_pthread_attr_t.h>
-#include <sys/_pthread/_pthread_cond_t.h>
-#include <sys/_pthread/_pthread_condattr_t.h>
-#include <sys/_pthread/_pthread_key_t.h>
-#include <sys/_pthread/_pthread_mutex_t.h>
-#include <sys/_pthread/_pthread_mutexattr_t.h>
-#include <sys/_pthread/_pthread_once_t.h>
-#include <sys/_pthread/_pthread_rwlock_t.h>
-#include <sys/_pthread/_pthread_rwlockattr_t.h>
-#include <sys/_pthread/_pthread_t.h>
-
-#include <pthread/qos.h>
-
-#if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE) || defined(__cplusplus)
-
-#include <sys/_types/_mach_port_t.h>
-#include <sys/_types/_sigset_t.h>
-
-#endif /* (!_POSIX_C_SOURCE && !_XOPEN_SOURCE) || _DARWIN_C_SOURCE || __cplusplus */
-
-/*
- * These symbols indicate which [optional] features are available
- * They can be tested at compile time via '#ifdef XXX'
- * The way to check for pthreads is like so:
-
- * #include <unistd.h>
- * #ifdef _POSIX_THREADS
- * #include <pthread.h>
- * #endif
-
- */
-
-/* These will be moved to unistd.h */
-
-/*
- * Note: These data structures are meant to be opaque. Only enough
- * structure is exposed to support initializers.
- * All of the typedefs will be moved to <sys/types.h>
- */
-
-#include <sys/cdefs.h>
-#include <Availability.h>
-
-#if __has_feature(assume_nonnull)
-_Pragma("clang assume_nonnull begin")
-#endif
-__BEGIN_DECLS
-/*
- * Threads
- */
-
-
-/*
- * Cancel cleanup handler management. Note, since these are implemented as macros,
- * they *MUST* occur in matched pairs!
- */
-
-#define pthread_cleanup_push(func, val) \
- { \
- struct __darwin_pthread_handler_rec __handler; \
- pthread_t __self = pthread_self(); \
- __handler.__routine = func; \
- __handler.__arg = val; \
- __handler.__next = __self->__cleanup_stack; \
- __self->__cleanup_stack = &__handler;
-
-#define pthread_cleanup_pop(execute) \
- /* Note: 'handler' must be in this same lexical context! */ \
- __self->__cleanup_stack = __handler.__next; \
- if (execute) (__handler.__routine)(__handler.__arg); \
- }
-
-/*
- * Thread attributes
- */
-
-#define PTHREAD_CREATE_JOINABLE 1
-#define PTHREAD_CREATE_DETACHED 2
-
-#define PTHREAD_INHERIT_SCHED 1
-#define PTHREAD_EXPLICIT_SCHED 2
-
-#define PTHREAD_CANCEL_ENABLE 0x01 /* Cancel takes place at next cancellation point */
-#define PTHREAD_CANCEL_DISABLE 0x00 /* Cancel postponed */
-#define PTHREAD_CANCEL_DEFERRED 0x02 /* Cancel waits until cancellation point */
-#define PTHREAD_CANCEL_ASYNCHRONOUS 0x00 /* Cancel occurs immediately */
-
-/* Value returned from pthread_join() when a thread is canceled */
-#define PTHREAD_CANCELED ((void *) 1)
-
-/* We only support PTHREAD_SCOPE_SYSTEM */
-#define PTHREAD_SCOPE_SYSTEM 1
-#define PTHREAD_SCOPE_PROCESS 2
-
-#define PTHREAD_PROCESS_SHARED 1
-#define PTHREAD_PROCESS_PRIVATE 2
-
-/*
- * Mutex protocol attributes
- */
-#define PTHREAD_PRIO_NONE 0
-#define PTHREAD_PRIO_INHERIT 1
-#define PTHREAD_PRIO_PROTECT 2
-
-/*
- * Mutex type attributes
- */
-#define PTHREAD_MUTEX_NORMAL 0
-#define PTHREAD_MUTEX_ERRORCHECK 1
-#define PTHREAD_MUTEX_RECURSIVE 2
-#define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL
-
-/*
- * Mutex policy attributes
- */
-#define PTHREAD_MUTEX_POLICY_FAIRSHARE_NP 1
-#define PTHREAD_MUTEX_POLICY_FIRSTFIT_NP 3
-
-/*
- * RWLock variables
- */
-#define PTHREAD_RWLOCK_INITIALIZER {_PTHREAD_RWLOCK_SIG_init, {0}}
-
-/*
- * Mutex variables
- */
-#define PTHREAD_MUTEX_INITIALIZER {_PTHREAD_MUTEX_SIG_init, {0}}
-
-/* <rdar://problem/10854763> */
-#if ((__MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000)) || defined(__DRIVERKIT_VERSION_MIN_REQUIRED)
-# if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE)
-# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER {_PTHREAD_ERRORCHECK_MUTEX_SIG_init, {0}}
-# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER {_PTHREAD_RECURSIVE_MUTEX_SIG_init, {0}}
-# endif /* (!_POSIX_C_SOURCE && !_XOPEN_SOURCE) || _DARWIN_C_SOURCE */
-#endif
-
-/* <rdar://problem/25944576> */
-#define _PTHREAD_SWIFT_IMPORTER_NULLABILITY_COMPAT \
- defined(SWIFT_CLASS_EXTRA) && (!defined(SWIFT_SDK_OVERLAY_PTHREAD_EPOCH) || (SWIFT_SDK_OVERLAY_PTHREAD_EPOCH < 1))
-
-/*
- * Condition variable attributes
- */
-
-/*
- * Condition variables
- */
-
-#define PTHREAD_COND_INITIALIZER {_PTHREAD_COND_SIG_init, {0}}
-
-/*
- * Initialization control (once) variables
- */
-
-#define PTHREAD_ONCE_INIT {_PTHREAD_ONCE_SIG_init, {0}}
-
-/*
- * Prototypes for all PTHREAD interfaces
- */
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_atfork(void (* _Nullable)(void), void (* _Nullable)(void),
- void (* _Nullable)(void));
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_destroy(pthread_attr_t *);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_getdetachstate(const pthread_attr_t *, int *);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_getguardsize(const pthread_attr_t * __restrict, size_t * __restrict);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_getinheritsched(const pthread_attr_t * __restrict, int * __restrict);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_getschedparam(const pthread_attr_t * __restrict,
- struct sched_param * __restrict);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_getschedpolicy(const pthread_attr_t * __restrict, int * __restrict);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_getscope(const pthread_attr_t * __restrict, int * __restrict);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_getstack(const pthread_attr_t * __restrict,
- void * _Nullable * _Nonnull __restrict, size_t * __restrict);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_getstackaddr(const pthread_attr_t * __restrict,
- void * _Nullable * _Nonnull __restrict);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_getstacksize(const pthread_attr_t * __restrict, size_t * __restrict);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_init(pthread_attr_t *);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_setdetachstate(pthread_attr_t *, int);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_setguardsize(pthread_attr_t *, size_t);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_setinheritsched(pthread_attr_t *, int);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_setschedparam(pthread_attr_t * __restrict,
- const struct sched_param * __restrict);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_setschedpolicy(pthread_attr_t *, int);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_setscope(pthread_attr_t *, int);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_setstack(pthread_attr_t *, void *, size_t);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_setstackaddr(pthread_attr_t *, void *);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_attr_setstacksize(pthread_attr_t *, size_t);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_cancel(pthread_t) __DARWIN_ALIAS(pthread_cancel);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_cond_broadcast(pthread_cond_t *);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_cond_destroy(pthread_cond_t *);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_cond_init(
- pthread_cond_t * __restrict,
- const pthread_condattr_t * _Nullable __restrict)
- __DARWIN_ALIAS(pthread_cond_init);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_cond_signal(pthread_cond_t *);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_cond_timedwait(
- pthread_cond_t * __restrict, pthread_mutex_t * __restrict,
- const struct timespec * _Nullable __restrict)
- __DARWIN_ALIAS_C(pthread_cond_timedwait);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_cond_wait(pthread_cond_t * __restrict,
- pthread_mutex_t * __restrict) __DARWIN_ALIAS_C(pthread_cond_wait);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_condattr_destroy(pthread_condattr_t *);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_condattr_init(pthread_condattr_t *);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_condattr_getpshared(const pthread_condattr_t * __restrict,
- int * __restrict);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_condattr_setpshared(pthread_condattr_t *, int);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-#if !_PTHREAD_SWIFT_IMPORTER_NULLABILITY_COMPAT
-int pthread_create(pthread_t _Nullable * _Nonnull __restrict,
- const pthread_attr_t * _Nullable __restrict,
- void * _Nullable (* _Nonnull)(void * _Nullable),
- void * _Nullable __restrict);
-#else
-int pthread_create(pthread_t * __restrict,
- const pthread_attr_t * _Nullable __restrict,
- void *(* _Nonnull)(void *), void * _Nullable __restrict);
-#endif // _PTHREAD_SWIFT_IMPORTER_NULLABILITY_COMPAT
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_detach(pthread_t);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_equal(pthread_t _Nullable, pthread_t _Nullable);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-void pthread_exit(void * _Nullable) __dead2;
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_getconcurrency(void);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_getschedparam(pthread_t , int * _Nullable __restrict,
- struct sched_param * _Nullable __restrict);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-void* _Nullable pthread_getspecific(pthread_key_t);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_join(pthread_t , void * _Nullable * _Nullable)
- __DARWIN_ALIAS_C(pthread_join);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_key_create(pthread_key_t *, void (* _Nullable)(void *));
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_key_delete(pthread_key_t);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_mutex_destroy(pthread_mutex_t *);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_mutex_getprioceiling(const pthread_mutex_t * __restrict,
- int * __restrict);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_mutex_init(pthread_mutex_t * __restrict,
- const pthread_mutexattr_t * _Nullable __restrict);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_mutex_lock(pthread_mutex_t *);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_mutex_setprioceiling(pthread_mutex_t * __restrict, int,
- int * __restrict);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_mutex_trylock(pthread_mutex_t *);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_mutex_unlock(pthread_mutex_t *);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_mutexattr_destroy(pthread_mutexattr_t *) __DARWIN_ALIAS(pthread_mutexattr_destroy);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t * __restrict,
- int * __restrict);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_mutexattr_getprotocol(const pthread_mutexattr_t * __restrict,
- int * __restrict);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_mutexattr_getpshared(const pthread_mutexattr_t * __restrict,
- int * __restrict);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_mutexattr_gettype(const pthread_mutexattr_t * __restrict,
- int * __restrict);
-
-__API_AVAILABLE(macos(10.13.4), ios(11.3), watchos(4.3), tvos(11.3))
-int pthread_mutexattr_getpolicy_np(const pthread_mutexattr_t * __restrict,
- int * __restrict);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_mutexattr_init(pthread_mutexattr_t *);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *, int);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_mutexattr_setprotocol(pthread_mutexattr_t *, int);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
-
-__API_AVAILABLE(macos(10.7), ios(5.0))
-int pthread_mutexattr_setpolicy_np(pthread_mutexattr_t *, int);
-
-__SWIFT_UNAVAILABLE_MSG("Use lazily initialized globals instead")
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_once(pthread_once_t *, void (* _Nonnull)(void));
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_rwlock_destroy(pthread_rwlock_t * ) __DARWIN_ALIAS(pthread_rwlock_destroy);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_rwlock_init(pthread_rwlock_t * __restrict,
- const pthread_rwlockattr_t * _Nullable __restrict)
- __DARWIN_ALIAS(pthread_rwlock_init);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_rwlock_rdlock(pthread_rwlock_t *) __DARWIN_ALIAS(pthread_rwlock_rdlock);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_rwlock_tryrdlock(pthread_rwlock_t *) __DARWIN_ALIAS(pthread_rwlock_tryrdlock);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_rwlock_trywrlock(pthread_rwlock_t *) __DARWIN_ALIAS(pthread_rwlock_trywrlock);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_rwlock_wrlock(pthread_rwlock_t *) __DARWIN_ALIAS(pthread_rwlock_wrlock);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_rwlock_unlock(pthread_rwlock_t *) __DARWIN_ALIAS(pthread_rwlock_unlock);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_rwlockattr_destroy(pthread_rwlockattr_t *);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t * __restrict,
- int * __restrict);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_rwlockattr_init(pthread_rwlockattr_t *);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-pthread_t pthread_self(void);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_setcancelstate(int , int * _Nullable)
- __DARWIN_ALIAS(pthread_setcancelstate);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_setcanceltype(int , int * _Nullable)
- __DARWIN_ALIAS(pthread_setcanceltype);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_setconcurrency(int);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_setschedparam(pthread_t, int, const struct sched_param *);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_setspecific(pthread_key_t , const void * _Nullable);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-void pthread_testcancel(void) __DARWIN_ALIAS(pthread_testcancel);
-
-#if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE) || defined(__cplusplus)
-
-/* returns non-zero if pthread_create or cthread_fork have been called */
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_is_threaded_np(void);
-
-__API_AVAILABLE(macos(10.6), ios(3.2))
-int pthread_threadid_np(pthread_t _Nullable,__uint64_t* _Nullable);
-
-/*SPI to set and get pthread name*/
-__API_AVAILABLE(macos(10.6), ios(3.2))
-int pthread_getname_np(pthread_t,char*,size_t);
-
-__API_AVAILABLE(macos(10.6), ios(3.2))
-int pthread_setname_np(const char*);
-
-/* returns non-zero if the current thread is the main thread */
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_main_np(void);
-
-/* return the mach thread bound to the pthread */
-__API_AVAILABLE(macos(10.4), ios(2.0))
-mach_port_t pthread_mach_thread_np(pthread_t);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-size_t pthread_get_stacksize_np(pthread_t);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-void* pthread_get_stackaddr_np(pthread_t);
-
-/* Like pthread_cond_signal(), but only wake up the specified pthread */
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_cond_signal_thread_np(pthread_cond_t *, pthread_t _Nullable);
-
-/* Like pthread_cond_timedwait, but use a relative timeout */
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_cond_timedwait_relative_np(pthread_cond_t *, pthread_mutex_t *,
- const struct timespec * _Nullable);
-
-/* Like pthread_create(), but leaves the thread suspended */
-__API_AVAILABLE(macos(10.4), ios(2.0))
-#if !_PTHREAD_SWIFT_IMPORTER_NULLABILITY_COMPAT
-int pthread_create_suspended_np(
- pthread_t _Nullable * _Nonnull, const pthread_attr_t * _Nullable,
- void * _Nullable (* _Nonnull)(void * _Nullable), void * _Nullable);
-#else
-int pthread_create_suspended_np(pthread_t *, const pthread_attr_t * _Nullable,
- void *(* _Nonnull)(void *), void * _Nullable);
-#endif
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_kill(pthread_t, int);
-
-__API_AVAILABLE(macos(10.5), ios(2.0))
-_Nullable pthread_t pthread_from_mach_thread_np(mach_port_t);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-int pthread_sigmask(int, const sigset_t * _Nullable, sigset_t * _Nullable)
- __DARWIN_ALIAS(pthread_sigmask);
-
-__API_AVAILABLE(macos(10.4), ios(2.0))
-void pthread_yield_np(void);
-
-#endif /* (!_POSIX_C_SOURCE && !_XOPEN_SOURCE) || _DARWIN_C_SOURCE || __cplusplus */
-__END_DECLS
-#if __has_feature(assume_nonnull)
-_Pragma("clang assume_nonnull end")
-#endif
-
-#endif /* _PTHREAD_H */
+++ /dev/null
-/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef _PTHREAD_IMPL_H_
-#define _PTHREAD_IMPL_H_
-/*
- * Internal implementation details
- */
-
-/* This whole header file will disappear, so don't depend on it... */
-
-#if __has_feature(assume_nonnull)
-_Pragma("clang assume_nonnull begin")
-#endif
-
-#ifndef __POSIX_LIB__
-
-/*
- * [Internal] data structure signatures
- */
-#define _PTHREAD_MUTEX_SIG_init 0x32AAABA7
-
-#define _PTHREAD_ERRORCHECK_MUTEX_SIG_init 0x32AAABA1
-#define _PTHREAD_RECURSIVE_MUTEX_SIG_init 0x32AAABA2
-#define _PTHREAD_FIRSTFIT_MUTEX_SIG_init 0x32AAABA3
-
-#define _PTHREAD_COND_SIG_init 0x3CB0B1BB
-#define _PTHREAD_ONCE_SIG_init 0x30B1BCBA
-#define _PTHREAD_RWLOCK_SIG_init 0x2DA8B3B4
-
-/*
- * POSIX scheduling policies
- */
-#define SCHED_OTHER 1
-#define SCHED_FIFO 4
-#define SCHED_RR 2
-
-#define __SCHED_PARAM_SIZE__ 4
-
-#endif /* __POSIX_LIB__ */
-
-#if __has_feature(assume_nonnull)
-_Pragma("clang assume_nonnull end")
-#endif
-
-#endif /* _PTHREAD_IMPL_H_ */
+++ /dev/null
-/*
- * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
- * All Rights Reserved
- *
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appears in all copies and
- * that both the copyright notice and this permission notice appear in
- * supporting documentation.
- *
- * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
- * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-/*
- * MkLinux
- */
-
-/*
- * Extension SPIs; installed to /usr/include.
- */
-
-#ifndef _PTHREAD_SPIS_H
-#define _PTHREAD_SPIS_H
-
-
-#include <pthread/pthread.h>
-
-#if __has_feature(assume_nonnull)
-_Pragma("clang assume_nonnull begin")
-#endif
-__BEGIN_DECLS
-
-#if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE)
-/* firstfit */
-#define PTHREAD_FIRSTFIT_MUTEX_INITIALIZER {_PTHREAD_FIRSTFIT_MUTEX_SIG_init, {0}}
-
-/*
- * Mutex attributes
- */
-#define _PTHREAD_MUTEX_POLICY_NONE PTHREAD_MUTEX_POLICY_NONE
-#define _PTHREAD_MUTEX_POLICY_FAIRSHARE PTHREAD_MUTEX_POLICY_FAIRSHARE_NP
-#define _PTHREAD_MUTEX_POLICY_FIRSTFIT PTHREAD_MUTEX_POLICY_FIRSTFIT_NP
-
-#endif /* (!_POSIX_C_SOURCE && !_XOPEN_SOURCE) || _DARWIN_C_SOURCE */
-
-__API_AVAILABLE(macos(10.11))
-void _pthread_mutex_enable_legacy_mode(void);
-
-/*
- * A version of pthread_create that is safely callable from an injected mach thread.
- *
- * The _create introspection hook will not fire for threads created from this function.
- *
- * It is not safe to call this function concurrently.
- */
-__API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
-#if !_PTHREAD_SWIFT_IMPORTER_NULLABILITY_COMPAT
-int pthread_create_from_mach_thread(
- pthread_t _Nullable * _Nonnull __restrict,
- const pthread_attr_t * _Nullable __restrict,
- void * _Nullable (* _Nonnull)(void * _Nullable),
- void * _Nullable __restrict);
-#else
-int pthread_create_from_mach_thread(pthread_t * __restrict,
- const pthread_attr_t * _Nullable __restrict,
- void *(* _Nonnull)(void *), void * _Nullable __restrict);
-#endif
-
-
-__END_DECLS
-#if __has_feature(assume_nonnull)
-_Pragma("clang assume_nonnull end")
-#endif
-
-#endif /* _PTHREAD_SPIS_H */
+++ /dev/null
-/*
- * Copyright (c) 2013-2014 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef _PTHREAD_QOS_H
-#define _PTHREAD_QOS_H
-
-#include <sys/cdefs.h>
-#include <sys/_pthread/_pthread_attr_t.h> /* pthread_attr_t */
-#include <sys/_pthread/_pthread_t.h> /* pthread_t */
-#include <Availability.h>
-
-#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
-
-#include <sys/qos.h>
-
-#ifndef KERNEL
-
-#if __has_feature(assume_nonnull)
-_Pragma("clang assume_nonnull begin")
-#endif
-__BEGIN_DECLS
-
-/*!
- * @function pthread_attr_set_qos_class_np
- *
- * @abstract
- * Sets the QOS class and relative priority of a pthread attribute structure
- * which may be used to specify the requested QOS class of newly created
- * threads.
- *
- * @discussion
- * The QOS class and relative priority represent an overall combination of
- * system quality of service attributes on a thread.
- *
- * Subsequent calls to interfaces such as pthread_attr_setschedparam() that are
- * incompatible or in conflict with the QOS class system will unset the QOS
- * class requested with this interface and pthread_attr_get_qos_class_np() will
- * return QOS_CLASS_UNSPECIFIED.
- *
- * @param __attr
- * The pthread attribute structure to modify.
- *
- * @param __qos_class
- * A QOS class value:
- * - QOS_CLASS_USER_INTERACTIVE
- * - QOS_CLASS_USER_INITIATED
- * - QOS_CLASS_DEFAULT
- * - QOS_CLASS_UTILITY
- * - QOS_CLASS_BACKGROUND
- * EINVAL will be returned if any other value is provided.
- *
- * @param __relative_priority
- * A relative priority within the QOS class. This value is a negative offset
- * from the maximum supported scheduler priority for the given class.
- * EINVAL will be returned if the value is greater than zero or less than
- * QOS_MIN_RELATIVE_PRIORITY.
- *
- * @return
- * Zero if successful, otherwise an errno value.
- */
-__API_AVAILABLE(macos(10.10), ios(8.0))
-int
-pthread_attr_set_qos_class_np(pthread_attr_t *__attr,
- qos_class_t __qos_class, int __relative_priority);
-
-/*!
- * @function pthread_attr_get_qos_class_np
- *
- * @abstract
- * Gets the QOS class and relative priority of a pthread attribute structure.
- *
- * @param __attr
- * The pthread attribute structure to inspect.
- *
- * @param __qos_class
- * On output, a QOS class value:
- * - QOS_CLASS_USER_INTERACTIVE
- * - QOS_CLASS_USER_INITIATED
- * - QOS_CLASS_DEFAULT
- * - QOS_CLASS_UTILITY
- * - QOS_CLASS_BACKGROUND
- * - QOS_CLASS_UNSPECIFIED
- * This value may be NULL in which case no value is returned.
- *
- * @param __relative_priority
- * On output, a relative priority offset within the QOS class.
- * This value may be NULL in which case no value is returned.
- *
- * @return
- * Zero if successful, otherwise an errno value.
- */
-__API_AVAILABLE(macos(10.10), ios(8.0))
-int
-pthread_attr_get_qos_class_np(pthread_attr_t * __restrict __attr,
- qos_class_t * _Nullable __restrict __qos_class,
- int * _Nullable __restrict __relative_priority);
-
-/*!
- * @function pthread_set_qos_class_self_np
- *
- * @abstract
- * Sets the requested QOS class and relative priority of the current thread.
- *
- * @discussion
- * The QOS class and relative priority represent an overall combination of
- * system quality of service attributes on a thread.
- *
- * Subsequent calls to interfaces such as pthread_setschedparam() that are
- * incompatible or in conflict with the QOS class system will unset the QOS
- * class requested with this interface and pthread_get_qos_class_np() will
- * return QOS_CLASS_UNSPECIFIED thereafter. A thread so modified is permanently
- * opted-out of the QOS class system and calls to this function to request a QOS
- * class for such a thread will fail and return EPERM.
- *
- * @param __qos_class
- * A QOS class value:
- * - QOS_CLASS_USER_INTERACTIVE
- * - QOS_CLASS_USER_INITIATED
- * - QOS_CLASS_DEFAULT
- * - QOS_CLASS_UTILITY
- * - QOS_CLASS_BACKGROUND
- * EINVAL will be returned if any other value is provided.
- *
- * @param __relative_priority
- * A relative priority within the QOS class. This value is a negative offset
- * from the maximum supported scheduler priority for the given class.
- * EINVAL will be returned if the value is greater than zero or less than
- * QOS_MIN_RELATIVE_PRIORITY.
- *
- * @return
- * Zero if successful, otherwise an errno value.
- */
-__API_AVAILABLE(macos(10.10), ios(8.0))
-int
-pthread_set_qos_class_self_np(qos_class_t __qos_class,
- int __relative_priority);
-
-/*!
- * @function pthread_get_qos_class_np
- *
- * @abstract
- * Gets the requested QOS class and relative priority of a thread.
- *
- * @param __pthread
- * The target thread to inspect.
- *
- * @param __qos_class
- * On output, a QOS class value:
- * - QOS_CLASS_USER_INTERACTIVE
- * - QOS_CLASS_USER_INITIATED
- * - QOS_CLASS_DEFAULT
- * - QOS_CLASS_UTILITY
- * - QOS_CLASS_BACKGROUND
- * - QOS_CLASS_UNSPECIFIED
- * This value may be NULL in which case no value is returned.
- *
- * @param __relative_priority
- * On output, a relative priority offset within the QOS class.
- * This value may be NULL in which case no value is returned.
- *
- * @return
- * Zero if successful, otherwise an errno value.
- */
-__API_AVAILABLE(macos(10.10), ios(8.0))
-int
-pthread_get_qos_class_np(pthread_t __pthread,
- qos_class_t * _Nullable __restrict __qos_class,
- int * _Nullable __restrict __relative_priority);
-
-/*!
- * @typedef pthread_override_t
- *
- * @abstract
- * An opaque object representing a QOS class override of a thread.
- *
- * @discussion
- * A QOS class override of a target thread expresses that an item of pending
- * work classified with a specific QOS class and relative priority depends on
- * the completion of the work currently being executed by the thread (e.g. due
- * to ordering requirements).
- *
- * While overrides are in effect, the target thread will execute at the maximum
- * QOS class and relative priority of all overrides and of the QOS class
- * requested by the thread itself.
- *
- * A QOS class override does not modify the target thread's requested QOS class
- * value and the effect of an override is not visible to the qos_class_self()
- * and pthread_get_qos_class_np() interfaces.
- */
-
-typedef struct pthread_override_s* pthread_override_t;
-
-/*!
- * @function pthread_override_qos_class_start_np
- *
- * @abstract
- * Starts a QOS class override of the specified target thread.
- *
- * @discussion
- * Starting a QOS class override of the specified target thread expresses that
- * an item of pending work classified with the specified QOS class and relative
- * priority depends on the completion of the work currently being executed by
- * the thread (e.g. due to ordering requirements).
- *
- * While overrides are in effect, the specified target thread will execute at
- * the maximum QOS class and relative priority of all overrides and of the QOS
- * class requested by the thread itself.
- *
- * Starting a QOS class override does not modify the target thread's requested
- * QOS class value and the effect of an override is not visible to the
- * qos_class_self() and pthread_get_qos_class_np() interfaces.
- *
- * The returned newly allocated override object is intended to be associated
- * with the item of pending work in question. Once the dependency has been
- * satisfied and enabled that work to begin executing, the QOS class override
- * must be ended by passing the associated override object to
- * pthread_override_qos_class_end_np(). Failure to do so will result in the
- * associated resources to be leaked and the target thread to be permanently
- * executed at an inappropriately elevated QOS class.
- *
- * @param __pthread
- * The target thread to modify.
- *
- * @param __qos_class
- * A QOS class value:
- * - QOS_CLASS_USER_INTERACTIVE
- * - QOS_CLASS_USER_INITIATED
- * - QOS_CLASS_DEFAULT
- * - QOS_CLASS_UTILITY
- * - QOS_CLASS_BACKGROUND
- * NULL will be returned if any other value is provided.
- *
- * @param __relative_priority
- * A relative priority within the QOS class. This value is a negative offset
- * from the maximum supported scheduler priority for the given class.
- * NULL will be returned if the value is greater than zero or less than
- * QOS_MIN_RELATIVE_PRIORITY.
- *
- * @return
- * A newly allocated override object if successful, or NULL if the override
- * could not be started.
- */
-__API_AVAILABLE(macos(10.10), ios(8.0))
-pthread_override_t
-pthread_override_qos_class_start_np(pthread_t __pthread,
- qos_class_t __qos_class, int __relative_priority);
-
-/*!
- * @function pthread_override_qos_class_end_np
- *
- * @abstract
- * Ends a QOS class override.
- *
- * @discussion
- * Passing an override object returned by pthread_override_qos_class_start_np()
- * ends the QOS class override started by that call and deallocates all
- * associated resources as well as the override object itself.
- *
- * The thread starting and the thread ending a QOS class override need not be
- * identical. If the thread ending the override is the the target thread of the
- * override itself, it should take care to elevate its requested QOS class
- * appropriately with pthread_set_qos_class_self_np() before ending the
- * override.
- *
- * @param __override
- * An override object returned by pthread_override_qos_class_start_np().
- *
- * @return
- * Zero if successful, otherwise an errno value.
- */
-__API_AVAILABLE(macos(10.10), ios(8.0))
-int
-pthread_override_qos_class_end_np(pthread_override_t __override);
-
-__END_DECLS
-#if __has_feature(assume_nonnull)
-_Pragma("clang assume_nonnull end")
-#endif
-
-#endif // KERNEL
-
-#endif // __DARWIN_C_LEVEL >= __DARWIN_C_FULL
-
-#endif // _PTHREAD_QOS_H
+++ /dev/null
-/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef _SCHED_H_
-#define _SCHED_H_
-
-#include <sys/cdefs.h>
-#include <pthread_impl.h>
-
-__BEGIN_DECLS
-/*
- * Scheduling paramters
- */
-#ifndef __POSIX_LIB__
-struct sched_param { int sched_priority; char __opaque[__SCHED_PARAM_SIZE__]; };
-#endif
-
-extern int sched_yield(void);
-extern int sched_get_priority_min(int);
-extern int sched_get_priority_max(int);
-__END_DECLS
-
-#endif /* _SCHED_H_ */
-
+++ /dev/null
-/*
- * Copyright (c) 2014 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef _PTHREAD_SPAWN_H
-#define _PTHREAD_SPAWN_H
-
-/*!
- * @group posix_spawn QOS class support
- * Apple extensions to posix_spawn(2) and posix_spawnp(2)
- */
-
-#include <pthread/pthread.h>
-#include <spawn.h>
-
-__BEGIN_DECLS
-
-/*!
- * @function posix_spawnattr_set_qos_class_np
- *
- * @abstract
- * Sets the QOS class property of a posix_spawn attributes object, which may be
- * used to specify the QOS class a process should be spawned with.
- *
- * @discussion
- * The QOS class specified at the time of process spawn determines both the
- * initial requested QOS class of the main thread in the new process, and the
- * interpretation by the system of all QOS class values requested by threads in
- * the process.
- *
- * @param __attr
- * The spawn attributes object to modify.
- *
- * @param __qos_class
- * A QOS class value:
- * - QOS_CLASS_UTILITY
- * - QOS_CLASS_BACKGROUND
- * EINVAL will be returned if any other value is provided.
- *
- * @return
- * Zero if successful, otherwise an errno value.
- */
-__API_AVAILABLE(macos(10.10), ios(8.0))
-int
-posix_spawnattr_set_qos_class_np(posix_spawnattr_t * __restrict __attr,
- qos_class_t __qos_class);
-
-/*!
- * @function posix_spawnattr_get_qos_class_np
- *
- * @abstract
- * Gets the QOS class property of a posix_spawn attributes object.
- *
- * @param __attr
- * The spawn attributes object to inspect.
- *
- * @param __qos_class
- * On output, a QOS class value:
- * - QOS_CLASS_UTILITY
- * - QOS_CLASS_BACKGROUND
- * - QOS_CLASS_UNSPECIFIED
- *
- * @return
- * Zero if successful, otherwise an errno value.
- */
-__API_AVAILABLE(macos(10.10), ios(8.0))
-int
-posix_spawnattr_get_qos_class_np(const posix_spawnattr_t *__restrict __attr,
- qos_class_t * __restrict __qos_class);
-
-__END_DECLS
-
-#endif // _PTHREAD_SPAWN_H
+++ /dev/null
-/*
- * Copyright (c) 2018 Apple Inc. All rights reserved.
- *
- * @APPLE_APACHE_LICENSE_HEADER_START@
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @APPLE_APACHE_LICENSE_HEADER_END@
- */
-
-#ifndef __PTHREAD_STACK_NP__
-#define __PTHREAD_STACK_NP__
-
-#include <Availability.h>
-#include <sys/cdefs.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <os/base.h>
-
-OS_ASSUME_NONNULL_BEGIN
-
-/*! @header
- * Low-level API to introspect thread stacks.
- */
-
-__BEGIN_DECLS
-
-/*!
- * @function pthread_stack_frame_decode_np
- *
- * @abstract
- * Decodes the return address and the next stack frame address
- * from the given stack frame address.
- *
- * @discussion
- * Validation of the frame address is not performed by this function.
- * The caller is responsible for making sure the frame address is valid,
- * for example using pthread_get_stackaddr_np() and pthread_get_stacksize_np().
- *
- * @param frame_addr
- * A valid stack frame address such as __builtin_frame_address(0) or the return
- * value of a previous call to pthread_stack_frame_decode_np().
- *
- * @param return_addr
- * An optional out paramter that will be filled with the return address stored
- * at the specified stack frame.
- *
- * @returns
- * This returns the next frame address stored at the specified stack frame.
- */
-__OSX_AVAILABLE(10.14) __IOS_AVAILABLE(12.0)
-__TVOS_AVAILABLE(12.0) __WATCHOS_AVAILABLE(5.0)
-uintptr_t
-pthread_stack_frame_decode_np(uintptr_t frame_addr,
- uintptr_t *_Nullable return_addr);
-
-__END_DECLS
-
-OS_ASSUME_NONNULL_END
-
-#endif // __PTHREAD_STACK_NP__
--- /dev/null
+/*
+ * Copyright (c) 2019 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef __LIBPTHREAD_EXPORTS_INTERNAL_H__
+#define __LIBPTHREAD_EXPORTS_INTERNAL_H__
+
+/*!
+ * @file exports_internal.h
+ *
+ * @brief
+ * This file has prototypes for symbols / functions that are exported
+ * without a public header.
+ *
+ * @discussion
+ * This header is also fed to TAPI and needs to work without internal.h
+ */
+
+#include <os/base.h>
+#include <mach/mach.h>
+#include <pthread.h>
+
+struct ProgramVars;
+
+OS_EXPORT int __is_threaded;
+
+OS_EXPORT const int __unix_conforming;
+
+OS_EXPORT
+void
+_pthread_set_self(pthread_t);
+
+OS_EXPORT
+pthread_t
+_pthread_self(void);
+
+OS_EXPORT
+int
+__pthread_init(const struct _libpthread_functions *pthread_funcs,
+ const char *envp[], const char *apple[],
+ const struct ProgramVars *vars);
+
+OS_EXPORT OS_NORETURN
+void
+thread_start(pthread_t self, mach_port_t kport,
+ void *(*fun)(void *), void *arg,
+ size_t stacksize, unsigned int flags); // trampoline into _pthread_start
+
+OS_EXPORT OS_NORETURN
+void
+_pthread_start(pthread_t thread, mach_port_t kport,
+ void *(*fun)(void *), void *arg,
+ size_t stacksize, unsigned int flags);
+
+OS_EXPORT OS_NORETURN
+void
+start_wqthread(pthread_t self, mach_port_t kport,
+ void *stackaddr, void *unused, int reuse); // trampoline into _start_wqthread
+
+OS_EXPORT
+void
+_pthread_wqthread(pthread_t self, mach_port_t kport,
+ void *stackaddr, void *keventlist, int flags, int nkevents);
+
+#if defined(__x86_64__) || defined(__i386__) || defined(__arm64__)
+OS_EXPORT
+void
+___chkstk_darwin(void);
+
+OS_EXPORT
+void
+thread_chkstk_darwin(void);
+#endif // defined(__x86_64__) || defined(__i386__) || defined(__arm64__)
+
+#pragma mark - exports with prototypes from not in libpthread
+
+OS_EXPORT
+int
+sigwait(const sigset_t *, int *) __DARWIN_ALIAS_C(sigwait);
+
+#pragma mark - shared with libsystem_kernel.dylib
+/* Note: these can't use _pthread_malloc / _pthread_free unconditionally */
+
+OS_EXPORT
+void
+_pthread_clear_qos_tsd(mach_port_t kport);
+
+OS_EXPORT
+void
+_pthread_exit_if_canceled(int error);
+
+#pragma mark - atfork libSystem integration
+
+OS_EXPORT void _pthread_atfork_prepare_handlers(void);
+OS_EXPORT void _pthread_atfork_prepare(void);
+OS_EXPORT void _pthread_atfork_parent(void);
+OS_EXPORT void _pthread_atfork_parent_handlers(void);
+OS_EXPORT void _pthread_atfork_child(void);
+OS_EXPORT void _pthread_atfork_child_handlers(void);
+OS_EXPORT void _pthread_fork_prepare(void);
+OS_EXPORT void _pthread_fork_parent(void);
+OS_EXPORT void _pthread_fork_child(void);
+OS_EXPORT void _pthread_fork_child_postinit(void);
+
+#pragma mark - TAPI
+#ifdef __clang_tapi__
+
+#define declare_symbol(s) OS_EXPORT void __tapi_##s(void) asm("_" #s)
+
+#if TARGET_OS_OSX && defined(__i386__)
+// TAPI will see the $UNIX2003 redirected symbols
+declare_symbol(pthread_cancel);
+declare_symbol(pthread_cond_init);
+declare_symbol(pthread_cond_timedwait);
+declare_symbol(pthread_cond_wait);
+declare_symbol(pthread_join);
+declare_symbol(pthread_mutexattr_destroy);
+declare_symbol(pthread_rwlock_destroy);
+declare_symbol(pthread_rwlock_init);
+declare_symbol(pthread_rwlock_rdlock);
+declare_symbol(pthread_rwlock_tryrdlock);
+declare_symbol(pthread_rwlock_trywrlock);
+declare_symbol(pthread_rwlock_unlock);
+declare_symbol(pthread_rwlock_wrlock);
+declare_symbol(pthread_setcancelstate);
+declare_symbol(pthread_setcanceltype);
+declare_symbol(pthread_sigmask);
+declare_symbol(pthread_testcancel);
+declare_symbol(sigwait);
+// TAPI will see the $NOCANCEL$UNIX2003 redirected symbols
+declare_symbol(pthread_cond_timedwait$UNIX2003);
+declare_symbol(pthread_cond_wait$UNIX2003);
+declare_symbol(pthread_join$UNIX2003);
+declare_symbol(sigwait$UNIX2003);
+#else
+// TAPI will see the $NOCANCEL redirected symbols
+declare_symbol(pthread_cond_timedwait);
+declare_symbol(pthread_cond_wait);
+declare_symbol(pthread_join);
+declare_symbol(sigwait);
+#endif
+
+#undef declare_symbol
+
+#endif // __clang_tapi__
+#endif // __LIBPTHREAD_EXPORTS_INTERNAL_H__
--- /dev/null
+/*
+ * Copyright (c) 2019 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef __LIBPTHREAD_IMPORTS_INTERNAL_H__
+#define __LIBPTHREAD_IMPORTS_INTERNAL_H__
+
+/*!
+ * @file imports_internal.h
+ *
+ * @brief
+ * This file lists prototypes that do not have a header on the system,
+ * like syscalls, that we need to import in pthread.
+ */
+
+#include <os/base.h>
+#include <mach/mach.h>
+#include <sys/time.h>
+#include <stack_logging.h>
+
+extern boolean_t swtch_pri(int);
+
+// Defined in libsyscall; initialized in libmalloc
+extern malloc_logger_t *__syscall_logger;
+
+// syscalls
+
+extern uint32_t __psynch_mutexwait(pthread_mutex_t *mutex, uint32_t mgen, uint32_t ugen, uint64_t tid, uint32_t flags);
+extern uint32_t __psynch_mutexdrop(pthread_mutex_t *mutex, uint32_t mgen, uint32_t ugen, uint64_t tid, uint32_t flags);
+
+extern uint32_t __psynch_cvbroad(pthread_cond_t *cv, uint64_t cvlsgen, uint64_t cvudgen, uint32_t flags, pthread_mutex_t *mutex, uint64_t mugen, uint64_t tid);
+extern uint32_t __psynch_cvsignal(pthread_cond_t *cv, uint64_t cvlsgen, uint32_t cvugen, int thread_port, pthread_mutex_t *mutex, uint64_t mugen, uint64_t tid, uint32_t flags);
+extern uint32_t __psynch_cvwait(pthread_cond_t *cv, uint64_t cvlsgen, uint32_t cvugen, pthread_mutex_t *mutex, uint64_t mugen, uint32_t flags, int64_t sec, uint32_t nsec);
+extern uint32_t __psynch_cvclrprepost(void *cv, uint32_t cvgen, uint32_t cvugen, uint32_t cvsgen, uint32_t prepocnt, uint32_t preposeq, uint32_t flags);
+
+extern uint32_t __psynch_rw_longrdlock(pthread_rwlock_t *rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
+extern uint32_t __psynch_rw_yieldwrlock(pthread_rwlock_t *rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
+extern int __psynch_rw_downgrade(pthread_rwlock_t *rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
+extern uint32_t __psynch_rw_upgrade(pthread_rwlock_t *rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
+extern uint32_t __psynch_rw_rdlock(pthread_rwlock_t *rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
+extern uint32_t __psynch_rw_wrlock(pthread_rwlock_t *rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
+extern uint32_t __psynch_rw_unlock(pthread_rwlock_t *rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
+extern uint32_t __psynch_rw_unlock2(pthread_rwlock_t *rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
+
+extern uint32_t __bsdthread_ctl(uintptr_t cmd, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3);
+extern pthread_t __bsdthread_create(void *(*func)(void *), void *func_arg, void *stack, pthread_t thread, unsigned int flags);
+extern int __bsdthread_register(void (*)(pthread_t, mach_port_t, void *(*)(void *), void *, size_t, unsigned int), void (*)(pthread_t, mach_port_t, void *, void *, int), int,void (*)(pthread_t, mach_port_t, void *(*)(void *), void *, size_t, unsigned int), int32_t *,__uint64_t);
+extern int __bsdthread_terminate(void *freeaddr, size_t freesize, mach_port_t kport, mach_port_t joinsem);
+
+extern uint64_t __thread_selfid(void);
+extern int __disable_threadsignal(int);
+
+extern int __pthread_canceled(int);
+extern int __pthread_chdir(const char *path);
+extern int __pthread_fchdir(int fd);
+extern int __pthread_kill(mach_port_t, int);
+extern int __pthread_markcancel(mach_port_t);
+extern int __pthread_sigmask(int, const sigset_t *, sigset_t *);
+
+extern int __gettimeofday(struct timeval *, struct timezone *);
+extern void __exit(int) __attribute__((noreturn));
+extern int __proc_info(int callnum, int pid, int flavor, uint64_t arg, void *buffer, int buffersize);
+extern int __semwait_signal_nocancel(int, int, int, int, __int64_t, __int32_t);
+extern int __sigwait(const sigset_t *set, int *sig);
+extern int __sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
+
+
+#endif // __LIBPTHREAD_IMPORTS_INTERNAL_H__
--- /dev/null
+/*
+ * Copyright (c) 2019 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef __LIBPTHREAD_INLINE_INTERNAL_H__
+#define __LIBPTHREAD_INLINE_INTERNAL_H__
+
+/*!
+ * @file inline_internal.h
+ *
+ * @brief
+ * This file exposes inline helpers that are generally useful in libpthread.
+ */
+
+#define PTHREAD_INTERNAL_CRASH(c, x) OS_BUG_INTERNAL(c, "LIBPTHREAD", x)
+#define PTHREAD_CLIENT_CRASH(c, x) OS_BUG_CLIENT(c, "LIBPTHREAD", x)
+#ifdef DEBUG
+#define PTHREAD_DEBUG_ASSERT(b) \
+ do { \
+ if (os_unlikely(!(b))) { \
+ PTHREAD_INTERNAL_CRASH(0, "Assertion failed: " #b); \
+ } \
+ } while (0)
+#else
+#define PTHREAD_DEBUG_ASSERT(b) ((void)0)
+#endif
+
+#pragma mark _pthread_mutex_check_signature
+
+OS_ALWAYS_INLINE
+static inline bool
+_pthread_mutex_check_signature_fast(pthread_mutex_t *mutex)
+{
+ return (mutex->sig == _PTHREAD_MUTEX_SIG_fast);
+}
+
+OS_ALWAYS_INLINE
+static inline bool
+_pthread_mutex_check_signature(const pthread_mutex_t *mutex)
+{
+ // TODO: PTHREAD_STRICT candidate
+ return ((mutex->sig & _PTHREAD_MUTEX_SIG_MASK) == _PTHREAD_MUTEX_SIG_CMP);
+}
+
+OS_ALWAYS_INLINE
+static inline bool
+_pthread_mutex_check_signature_init(const pthread_mutex_t *mutex)
+{
+ return ((mutex->sig & _PTHREAD_MUTEX_SIG_init_MASK) ==
+ _PTHREAD_MUTEX_SIG_init_CMP);
+}
+
+#pragma mark pthread mutex accessors
+
+OS_ALWAYS_INLINE
+static inline bool
+_pthread_mutex_uses_ulock(pthread_mutex_t *mutex)
+{
+ return mutex->mtxopts.options.ulock;
+}
+
+#pragma mark _pthread_rwlock_check_signature
+
+OS_ALWAYS_INLINE
+static inline bool
+_pthread_rwlock_check_signature(const pthread_rwlock_t *rwlock)
+{
+ return (rwlock->sig == _PTHREAD_RWLOCK_SIG);
+}
+
+OS_ALWAYS_INLINE
+static inline bool
+_pthread_rwlock_check_signature_init(const pthread_rwlock_t *rwlock)
+{
+ return (rwlock->sig == _PTHREAD_RWLOCK_SIG_init);
+}
+
+#pragma mark unfair lock wrappers
+
+#define _PTHREAD_LOCK_INITIALIZER OS_UNFAIR_LOCK_INIT
+#define _PTHREAD_LOCK_OPTIONS \
+ (OS_UNFAIR_LOCK_DATA_SYNCHRONIZATION | OS_UNFAIR_LOCK_ADAPTIVE_SPIN)
+
+OS_ALWAYS_INLINE
+static inline void
+_pthread_lock_init(os_unfair_lock_t lock)
+{
+ *lock = _PTHREAD_LOCK_INITIALIZER;
+}
+
+OS_OVERLOADABLE OS_ALWAYS_INLINE
+static inline void
+_pthread_lock_lock(os_unfair_lock_t lock)
+{
+#if OS_UNFAIR_LOCK_INLINE
+ os_unfair_lock_lock_with_options_inline(lock, _PTHREAD_LOCK_OPTIONS);
+#else
+ os_unfair_lock_lock_with_options(lock, _PTHREAD_LOCK_OPTIONS);
+#endif
+}
+
+OS_OVERLOADABLE OS_ALWAYS_INLINE
+static inline void
+_pthread_lock_lock(os_unfair_lock_t lock, mach_port_t mts)
+{
+#if OS_UNFAIR_LOCK_INLINE
+ os_unfair_lock_lock_no_tsd_inline(lock, _PTHREAD_LOCK_OPTIONS, mts);
+#else
+ os_unfair_lock_lock_no_tsd(lock, _PTHREAD_LOCK_OPTIONS, mts);
+#endif
+}
+
+OS_OVERLOADABLE OS_ALWAYS_INLINE
+static inline void
+_pthread_lock_unlock(os_unfair_lock_t lock)
+{
+#if OS_UNFAIR_LOCK_INLINE
+ os_unfair_lock_unlock_inline(lock);
+#else
+ os_unfair_lock_unlock(lock);
+#endif
+}
+
+OS_OVERLOADABLE OS_ALWAYS_INLINE
+static inline void
+_pthread_lock_unlock(os_unfair_lock_t lock, mach_port_t mts)
+{
+#if OS_UNFAIR_LOCK_INLINE
+ os_unfair_lock_unlock_no_tsd_inline(lock, mts);
+#else
+ os_unfair_lock_unlock_no_tsd(lock, mts);
+#endif
+}
+
+#pragma mark pthread accessors
+
+// Internal references to pthread_self() use TSD slot 0 directly.
+#define pthread_self() _pthread_self_direct()
+
+// Internal references to errno use TSD slot 1 directly.
+#undef errno
+#define errno (*_pthread_errno_address_direct())
+
+#define _pthread_tsd_slot(th, name) \
+ (*(_PTHREAD_TSD_SLOT_##name##_TYPE *)(uintptr_t *)&(th)->tsd[_PTHREAD_TSD_SLOT_##name])
+
+OS_ALWAYS_INLINE
+static inline void
+_pthread_validate_signature(pthread_t thread)
+{
+ pthread_t th = (pthread_t)(thread->sig ^ _pthread_ptr_munge_token);
+#if __has_feature(ptrauth_calls)
+ th = ptrauth_auth_data(th, ptrauth_key_process_dependent_data,
+ ptrauth_string_discriminator("pthread.signature"));
+#endif
+ if (os_unlikely(th != thread)) {
+ /* OS_REASON_LIBSYSTEM_CODE_PTHREAD_CORRUPTION == 4 */
+ abort_with_reason(OS_REASON_LIBSYSTEM, 4, "pthread_t was corrupted", 0);
+ }
+}
+
+OS_ALWAYS_INLINE
+static inline void
+_pthread_init_signature(pthread_t thread)
+{
+ pthread_t th = thread;
+#if __has_feature(ptrauth_calls)
+ th = ptrauth_sign_unauthenticated(th, ptrauth_key_process_dependent_data,
+ ptrauth_string_discriminator("pthread.signature"));
+#endif
+ thread->sig = (uintptr_t)th ^ _pthread_ptr_munge_token;
+}
+
+/*
+ * ALWAYS called without list lock and return with list lock held on success
+ *
+ * This weird calling convention exists because this function will sometimes
+ * drop the lock, and it's best callers don't have to remember this.
+ */
+OS_ALWAYS_INLINE
+static inline bool
+_pthread_validate_thread_and_list_lock(pthread_t thread)
+{
+ pthread_t p;
+ if (thread == NULL) return false;
+ _pthread_lock_lock(&_pthread_list_lock);
+ TAILQ_FOREACH(p, &__pthread_head, tl_plist) {
+ if (p != thread) continue;
+ _pthread_validate_signature(p);
+ return true;
+ }
+ _pthread_lock_unlock(&_pthread_list_lock);
+
+ return false;
+}
+
+OS_ALWAYS_INLINE
+static inline bool
+_pthread_is_valid(pthread_t thread, mach_port_t *portp)
+{
+ mach_port_t kport = MACH_PORT_NULL;
+ bool valid;
+
+ if (thread == pthread_self()) {
+ _pthread_validate_signature(thread);
+ valid = true;
+ kport = _pthread_tsd_slot(thread, MACH_THREAD_SELF);
+ } else if (!_pthread_validate_thread_and_list_lock(thread)) {
+ valid = false;
+ } else {
+ kport = _pthread_tsd_slot(thread, MACH_THREAD_SELF);
+ valid = true;
+ _pthread_lock_unlock(&_pthread_list_lock);
+ }
+
+ if (portp != NULL) {
+ *portp = kport;
+ }
+ return valid;
+}
+
+OS_ALWAYS_INLINE OS_CONST
+static inline pthread_globals_t
+_pthread_globals(void)
+{
+ return os_alloc_once(OS_ALLOC_ONCE_KEY_LIBSYSTEM_PTHREAD,
+ sizeof(struct pthread_globals_s), NULL);
+}
+
+#endif // __LIBPTHREAD_INLINE_INTERNAL_H__
#ifndef _POSIX_PTHREAD_INTERNALS_H
#define _POSIX_PTHREAD_INTERNALS_H
-#define _PTHREAD_BUILDING_PTHREAD_
-
-// suppress pthread_attr_t typedef in sys/signal.h
-#define _PTHREAD_ATTR_T
-struct _pthread_attr_t; /* forward reference */
-typedef struct _pthread_attr_t pthread_attr_t;
+#ifndef PTHREAD_LAYOUT_SPI
+#define PTHREAD_LAYOUT_SPI 1
+#endif
-#include <_simple.h>
-#include <assert.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <errno.h>
#include <TargetConditionals.h>
-#include <mach/mach.h>
-#include <mach/mach_error.h>
-#include <sys/queue.h>
-#include <sys/reason.h>
-#include <pthread/bsdthread_private.h>
-#include <pthread/workqueue_syscalls.h>
-
-#define __OS_EXPOSE_INTERNALS__ 1
-#include <os/internal/internal_shared.h>
-#include <os/once_private.h>
-#include <os/reason_private.h>
#if TARGET_IPHONE_SIMULATOR
#error Unsupported target
#endif
+#include "types_internal.h" // has to come first as it hides the SDK types
+#include "offsets_internal.h" // included to validate the offsets at build time
-#define PTHREAD_INTERNAL_CRASH(c, x) do { \
- _os_set_crash_log_cause_and_message((c), \
- "BUG IN LIBPTHREAD: " x); \
- __builtin_trap(); \
- } while (0)
-
-#define PTHREAD_CLIENT_CRASH(c, x) do { \
- _os_set_crash_log_cause_and_message((c), \
- "BUG IN CLIENT OF LIBPTHREAD: " x); \
- __builtin_trap(); \
- } while (0)
-
-#ifndef __POSIX_LIB__
-#define __POSIX_LIB__
-#endif
-
-#ifndef PTHREAD_LAYOUT_SPI
-#define PTHREAD_LAYOUT_SPI 1
-#endif
-
-#include "posix_sched.h"
-#include "tsd_private.h"
-#include "spinlock_private.h"
-
-#define PTHREAD_EXPORT extern __attribute__((visibility("default")))
-#define PTHREAD_EXTERN extern
-#define PTHREAD_NOEXPORT __attribute__((visibility("hidden")))
-#define PTHREAD_NOEXPORT_VARIANT
-#define PTHREAD_NORETURN __attribute__((__noreturn__))
-#define PTHREAD_ALWAYS_INLINE __attribute__((always_inline))
-#define PTHREAD_NOINLINE __attribute__((noinline))
-#define PTHREAD_WEAK __attribute__((weak))
-#define PTHREAD_USED __attribute__((used))
-#define PTHREAD_NOT_TAIL_CALLED __attribute__((__not_tail_called__))
+#include <_simple.h>
+#include <platform/string.h>
+#include <platform/compat.h>
+#include <sys/ulock.h>
+#include <sys/reason.h>
-#define OS_UNFAIR_LOCK_INLINE 1
+#include <os/alloc_once_private.h>
+#include <os/atomic_private.h>
+#include <os/crashlog_private.h>
#include <os/lock_private.h>
-typedef os_unfair_lock _pthread_lock;
-#define _PTHREAD_LOCK_INITIALIZER OS_UNFAIR_LOCK_INIT
-#define _PTHREAD_LOCK_INIT(lock) ((lock) = (_pthread_lock)_PTHREAD_LOCK_INITIALIZER)
-#define _PTHREAD_LOCK(lock) os_unfair_lock_lock_with_options_inline(&(lock), OS_UNFAIR_LOCK_DATA_SYNCHRONIZATION)
-#define _PTHREAD_LOCK_FROM_MACH_THREAD(lock) os_unfair_lock_lock_inline_no_tsd_4libpthread(&(lock))
-#define _PTHREAD_UNLOCK(lock) os_unfair_lock_unlock_inline(&(lock))
-#define _PTHREAD_UNLOCK_FROM_MACH_THREAD(lock) os_unfair_lock_unlock_inline_no_tsd_4libpthread(&(lock))
-
-#define _PTHREAD_POLICY_IS_FIXEDPRI(x) ((x) == SCHED_RR || (x) == SCHED_FIFO)
-
-extern int __is_threaded;
-extern int __unix_conforming;
-PTHREAD_NOEXPORT
-extern uintptr_t _pthread_ptr_munge_token;
-
-// List of all pthreads in the process.
-TAILQ_HEAD(__pthread_list, _pthread);
-PTHREAD_NOEXPORT extern struct __pthread_list __pthread_head;
-
-// Lock protects access to above list.
-PTHREAD_NOEXPORT extern _pthread_lock _pthread_list_lock;
-
-PTHREAD_NOEXPORT extern uint32_t _main_qos;
-
-#if PTHREAD_DEBUG_LOG
-#include <mach/mach_time.h>
-PTHREAD_NOEXPORT extern int _pthread_debuglog;
-PTHREAD_NOEXPORT extern uint64_t _pthread_debugstart;
-#endif
-
-/*
- * Compiled-in limits
- */
-#if TARGET_OS_EMBEDDED
-#define _EXTERNAL_POSIX_THREAD_KEYS_MAX 256
-#define _INTERNAL_POSIX_THREAD_KEYS_MAX 256
-#define _INTERNAL_POSIX_THREAD_KEYS_END 512
-#else
-#define _EXTERNAL_POSIX_THREAD_KEYS_MAX 512
-#define _INTERNAL_POSIX_THREAD_KEYS_MAX 256
-#define _INTERNAL_POSIX_THREAD_KEYS_END 768
-#endif
-
-#if defined(__arm64__)
-/* Pull the pthread_t into the same page as the top of the stack so we dirty one less page.
- * <rdar://problem/19941744> The _pthread struct at the top of the stack shouldn't be page-aligned
- */
-#define PTHREAD_T_OFFSET (12*1024)
-#else
-#define PTHREAD_T_OFFSET 0
-#endif
-
-#define MAXTHREADNAMESIZE 64
-#define _PTHREAD_T
-typedef struct _pthread {
- //
- // ABI - These fields are externally known as struct _opaque_pthread_t.
- //
- long sig;
- struct __darwin_pthread_handler_rec *__cleanup_stack;
-
- //
- // SPI - These fields are private.
- //
-
- //
- // Fields protected by _pthread_list_lock
- //
-
- TAILQ_ENTRY(_pthread) tl_plist; // global thread list [aligned]
- struct pthread_join_context_s *tl_join_ctx;
- void *tl_exit_value;
- uint32_t tl_policy:8,
- tl_joinable:1,
- tl_joiner_cleans_up:1,
- tl_has_custom_stack:1,
- __tl_pad:21;
- // MACH_PORT_NULL if no joiner
- // tsd[_PTHREAD_TSD_SLOT_MACH_THREAD_SELF] when has a joiner
- // MACH_PORT_DEAD if the thread exited
- uint32_t tl_exit_gate;
- struct sched_param tl_param;
- void *__unused_padding;
-
- //
- // Fields protected by pthread_t::lock
- //
-
- _pthread_lock lock;
- uint16_t max_tsd_key;
- uint16_t inherit:8,
- kernalloc:1,
- schedset:1,
- wqthread:1,
- wqkillset:1,
- __flags_pad:4;
-
- char pthread_name[MAXTHREADNAMESIZE]; // includes NUL [aligned]
-
- void *(*fun)(void *); // thread start routine
- void *arg; // thread start routine argument
- int wq_nevents; // wqthreads (workloop / kevent)
- bool wq_outsideqos;
- uint8_t canceled; // 4597450 set if conformant cancelation happened
- uint16_t cancel_state; // whether the thread can be canceled [atomic]
- errno_t cancel_error;
- errno_t err_no; // thread-local errno
-
- void *stackaddr; // base of the stack (page aligned)
- void *stackbottom; // stackaddr - stacksize
- void *freeaddr; // stack/thread allocation base address
- size_t freesize; // stack/thread allocation size
- size_t guardsize; // guard page size in bytes
-
- // tsd-base relative accessed elements
- __attribute__((aligned(8)))
- uint64_t thread_id; // 64-bit unique thread id
-
- /* Thread Specific Data slots
- *
- * The offset of this field from the start of the structure is difficult to
- * change on OS X because of a thorny bitcompat issue: mono has hard coded
- * the value into their source. Newer versions of mono will fall back to
- * scanning to determine it at runtime, but there's lots of software built
- * with older mono that won't. We will have to break them someday...
- */
- __attribute__ ((aligned (16)))
- void *tsd[_EXTERNAL_POSIX_THREAD_KEYS_MAX + _INTERNAL_POSIX_THREAD_KEYS_MAX];
-} *pthread_t;
-
-#define _PTHREAD_ATTR_REFILLMS_MAX ((2<<24) - 1)
-struct _pthread_attr_t {
- long sig;
- size_t guardsize; // size in bytes of stack overflow guard area
- void *stackaddr; // stack base; vm_page_size aligned
- size_t stacksize; // stack size; multiple of vm_page_size and >= PTHREAD_STACK_MIN
- union {
- struct sched_param param; // [aligned]
- unsigned long qosclass; // pthread_priority_t
- };
- uint32_t
- detached:8,
- inherit:8,
- policy:8,
- schedset:1,
- qosset:1,
- policyset:1,
- cpupercentset:1,
- defaultguardpage:1,
- unused:3;
- uint32_t
- cpupercent:8,
- refillms:24;
-#if defined(__LP64__)
- uint32_t _reserved[4];
-#else
- uint32_t _reserved[2];
-#endif
-};
-
-/*
- * Mutex attributes
- */
-
-#define _PTHREAD_MUTEXATTR_T
-typedef struct {
- long sig;
- int prioceiling;
- uint32_t protocol:2,
- type:2,
- pshared:2,
- opt:3,
- unused:23;
-} pthread_mutexattr_t;
-
-struct _pthread_mutex_options {
- uint32_t protocol:2,
- type:2,
- pshared:2,
- policy:3,
- hold:2,
- misalign:1,
- notify:1,
- mutex:1,
- unused:2,
- lock_count:16;
-};
-//
-#define _PTHREAD_MUTEX_POLICY_LAST (PTHREAD_MUTEX_POLICY_FIRSTFIT_NP + 1)
-#define _PTHREAD_MTX_OPT_POLICY_FAIRSHARE 1
-#define _PTHREAD_MTX_OPT_POLICY_FIRSTFIT 2
-#define _PTHREAD_MTX_OPT_POLICY_DEFAULT _PTHREAD_MTX_OPT_POLICY_FIRSTFIT
-// The following _pthread_mutex_options defintions exist in synch_internal.h
-// such that the kernel extension can test for flags. They must be kept in
-// sync with the bit values in the struct above.
-// _PTHREAD_MTX_OPT_PSHARED 0x010
-// _PTHREAD_MTX_OPT_NOTIFY 0x1000
-// _PTHREAD_MTX_OPT_MUTEX 0x2000
-
-// The fixed mask is used to mask out portions of the mutex options that
-// change on a regular basis (notify, lock_count).
-#define _PTHREAD_MTX_OPT_FIXED_MASK 0x27ff
-
-typedef struct {
- long sig;
- _pthread_lock lock;
- union {
- uint32_t value;
- struct _pthread_mutex_options options;
- } mtxopts;
- int16_t prioceiling;
- int16_t priority;
-#if defined(__LP64__)
- uint32_t _pad;
-#endif
- uint32_t m_tid[2]; // thread id of thread that has mutex locked
- uint32_t m_seq[2]; // mutex sequence id
- uint32_t m_mis[2]; // for misaligned locks m_tid/m_seq will span into here
-#if defined(__LP64__)
- uint32_t _reserved[4];
-#else
- uint32_t _reserved[1];
-#endif
-} _pthread_mutex;
-
-
-#define _PTHREAD_CONDATTR_T
-typedef struct {
- long sig;
- uint32_t pshared:2,
- unsupported:30;
-} pthread_condattr_t;
-
-
-typedef struct {
- long sig;
- _pthread_lock lock;
- uint32_t unused:29,
- misalign:1,
- pshared:2;
- _pthread_mutex *busy;
- uint32_t c_seq[3];
-#if defined(__LP64__)
- uint32_t _reserved[3];
-#endif
-} _pthread_cond;
-
-
-#define _PTHREAD_ONCE_T
-typedef struct {
- long sig;
- os_once_t once;
-} pthread_once_t;
-
-
-#define _PTHREAD_RWLOCKATTR_T
-typedef struct {
- long sig;
- int pshared;
-#if defined(__LP64__)
- uint32_t _reserved[3];
-#else
- uint32_t _reserved[2];
-#endif
-} pthread_rwlockattr_t;
-
+#include <os/overflow.h>
+#include <os/reason_private.h>
+#include <os/semaphore_private.h>
-typedef struct {
- long sig;
- _pthread_lock lock;
- uint32_t unused:29,
- misalign:1,
- pshared:2;
- uint32_t rw_flags;
-#if defined(__LP64__)
- uint32_t _pad;
-#endif
- uint32_t rw_tid[2]; // thread id of thread that has exclusive (write) lock
- uint32_t rw_seq[4]; // rw sequence id (at 128-bit aligned boundary)
- uint32_t rw_mis[4]; // for misaligned locks rw_seq will span into here
-#if defined(__LP64__)
- uint32_t _reserved[34];
-#else
- uint32_t _reserved[18];
-#endif
-} _pthread_rwlock;
+#include <pthread/bsdthread_private.h>
+#include <pthread/workqueue_syscalls.h>
#include "pthread.h"
#include "pthread_spis.h"
+#include "pthread/private.h"
+#include "pthread/dependency_private.h"
+#include "pthread/spinlock_private.h"
+#include "pthread/workqueue_private.h"
+#include "pthread/introspection_private.h"
+#include "pthread/qos_private.h"
+#include "pthread/tsd_private.h"
+#include "pthread/stack_np.h"
+
+#include "imports_internal.h"
+#include "prototypes_internal.h"
+#include "exports_internal.h"
+#include "inline_internal.h"
-_Static_assert(sizeof(_pthread_mutex) == sizeof(pthread_mutex_t),
- "Incorrect _pthread_mutex structure size");
-
-_Static_assert(sizeof(_pthread_rwlock) == sizeof(pthread_rwlock_t),
- "Incorrect _pthread_rwlock structure size");
-
-// Internal references to pthread_self() use TSD slot 0 directly.
-__header_always_inline __pure2 pthread_t
-_pthread_self_direct(void)
-{
-#if TARGET_OS_SIMULATOR || defined(__i386__) || defined(__x86_64__)
- return (pthread_t)_pthread_getspecific_direct(_PTHREAD_TSD_SLOT_PTHREAD_SELF);
-#elif defined(__arm__) || defined(__arm64__)
- uintptr_t tsd_base = (uintptr_t)_os_tsd_get_base();
- return (pthread_t)(tsd_base - offsetof(struct _pthread, tsd));
-#else
-#error unsupported architecture
-#endif
-}
-#define pthread_self() _pthread_self_direct()
-
-PTHREAD_ALWAYS_INLINE
-inline static uint64_t __attribute__((__pure__))
-_pthread_selfid_direct(void)
-{
- return (_pthread_self_direct())->thread_id;
-}
-
-#define _PTHREAD_DEFAULT_INHERITSCHED PTHREAD_INHERIT_SCHED
-#define _PTHREAD_DEFAULT_PROTOCOL PTHREAD_PRIO_NONE
-#define _PTHREAD_DEFAULT_PRIOCEILING 0
-#define _PTHREAD_DEFAULT_POLICY SCHED_OTHER
-#define _PTHREAD_DEFAULT_STACKSIZE 0x80000 /* 512K */
-#define _PTHREAD_DEFAULT_PSHARED PTHREAD_PROCESS_PRIVATE
-
-#define _PTHREAD_NO_SIG 0x00000000
-#define _PTHREAD_MUTEX_ATTR_SIG 0x4D545841 /* 'MTXA' */
-#define _PTHREAD_MUTEX_SIG 0x4D555458 /* 'MUTX' */
-#define _PTHREAD_MUTEX_SIG_fast 0x4D55545A /* 'MUTZ' */
-#define _PTHREAD_MUTEX_SIG_MASK 0xfffffffd
-#define _PTHREAD_MUTEX_SIG_CMP 0x4D555458 /* _PTHREAD_MUTEX_SIG & _PTHREAD_MUTEX_SIG_MASK */
-#define _PTHREAD_MUTEX_SIG_init 0x32AAABA7 /* [almost] ~'MUTX' */
-#define _PTHREAD_ERRORCHECK_MUTEX_SIG_init 0x32AAABA1
-#define _PTHREAD_RECURSIVE_MUTEX_SIG_init 0x32AAABA2
-#define _PTHREAD_FIRSTFIT_MUTEX_SIG_init 0x32AAABA3
-#define _PTHREAD_MUTEX_SIG_init_MASK 0xfffffff0
-#define _PTHREAD_MUTEX_SIG_init_CMP 0x32AAABA0
-#define _PTHREAD_COND_ATTR_SIG 0x434E4441 /* 'CNDA' */
-#define _PTHREAD_COND_SIG 0x434F4E44 /* 'COND' */
-#define _PTHREAD_COND_SIG_init 0x3CB0B1BB /* [almost] ~'COND' */
-#define _PTHREAD_ATTR_SIG 0x54484441 /* 'THDA' */
-#define _PTHREAD_ONCE_SIG 0x4F4E4345 /* 'ONCE' */
-#define _PTHREAD_ONCE_SIG_init 0x30B1BCBA /* [almost] ~'ONCE' */
-#define _PTHREAD_SIG 0x54485244 /* 'THRD' */
-#define _PTHREAD_RWLOCK_ATTR_SIG 0x52574C41 /* 'RWLA' */
-#define _PTHREAD_RWLOCK_SIG 0x52574C4B /* 'RWLK' */
-#define _PTHREAD_RWLOCK_SIG_init 0x2DA8B3B4 /* [almost] ~'RWLK' */
-
-
-#define _PTHREAD_KERN_COND_SIG 0x12345678 /* */
-#define _PTHREAD_KERN_MUTEX_SIG 0x34567812 /* */
-#define _PTHREAD_KERN_RWLOCK_SIG 0x56781234 /* */
-
-#if defined(DEBUG)
-#define _PTHREAD_MUTEX_OWNER_SELF pthread_self()
-#else
-#define _PTHREAD_MUTEX_OWNER_SELF (pthread_t)0x12141968
-#endif
-#define _PTHREAD_MUTEX_OWNER_SWITCHING (pthread_t)(~0)
-
-#define _PTHREAD_CANCEL_STATE_MASK 0x01
-#define _PTHREAD_CANCEL_TYPE_MASK 0x02
-#define _PTHREAD_CANCEL_PENDING 0x10 /* pthread_cancel() has been called for this thread */
-
-extern boolean_t swtch_pri(int);
-
+#include "pthread.h"
+#include "pthread_spis.h"
+#include "inline_internal.h"
#include "kern/kern_internal.h"
-/* Prototypes. */
-
-/* Internal globals. */
-PTHREAD_NOEXPORT void _pthread_tsd_cleanup(pthread_t self);
-
-PTHREAD_NOEXPORT int _pthread_mutex_droplock(_pthread_mutex *mutex, uint32_t * flagp, uint32_t ** pmtxp, uint32_t * mgenp, uint32_t * ugenp);
-
-/* internally redirected upcalls. */
-PTHREAD_NOEXPORT void* malloc(size_t);
-PTHREAD_NOEXPORT void free(void*);
-
-/* syscall interfaces */
-extern uint32_t __psynch_mutexwait(_pthread_mutex * mutex, uint32_t mgen, uint32_t ugen, uint64_t tid, uint32_t flags);
-extern uint32_t __psynch_mutexdrop(_pthread_mutex * mutex, uint32_t mgen, uint32_t ugen, uint64_t tid, uint32_t flags);
-
-extern uint32_t __psynch_cvbroad(pthread_cond_t * cv, uint64_t cvlsgen, uint64_t cvudgen, uint32_t flags, pthread_mutex_t * mutex, uint64_t mugen, uint64_t tid);
-extern uint32_t __psynch_cvsignal(pthread_cond_t * cv, uint64_t cvlsgen, uint32_t cvugen, int thread_port, pthread_mutex_t * mutex, uint64_t mugen, uint64_t tid, uint32_t flags);
-extern uint32_t __psynch_cvwait(pthread_cond_t * cv, uint64_t cvlsgen, uint32_t cvugen, pthread_mutex_t * mutex, uint64_t mugen, uint32_t flags, int64_t sec, uint32_t nsec);
-extern uint32_t __psynch_cvclrprepost(void * cv, uint32_t cvgen, uint32_t cvugen, uint32_t cvsgen, uint32_t prepocnt, uint32_t preposeq, uint32_t flags);
-extern uint32_t __psynch_rw_longrdlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
-extern uint32_t __psynch_rw_yieldwrlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
-extern int __psynch_rw_downgrade(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
-extern uint32_t __psynch_rw_upgrade(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
-extern uint32_t __psynch_rw_rdlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
-extern uint32_t __psynch_rw_wrlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
-extern uint32_t __psynch_rw_unlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
-extern uint32_t __psynch_rw_unlock2(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
-extern uint32_t __bsdthread_ctl(uintptr_t cmd, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3);
-
-PTHREAD_EXTERN
-int
-__proc_info(int callnum, int pid, int flavor, uint64_t arg, void * buffer, int buffersize);
-
-PTHREAD_NOEXPORT
-void
-_pthread_deallocate(pthread_t t, bool from_mach_thread);
-
-PTHREAD_NOEXPORT
-thread_qos_t
-_pthread_qos_class_to_thread_qos(qos_class_t qos);
-
-PTHREAD_NOEXPORT
-void
-_pthread_set_main_qos(pthread_priority_t qos);
-
-PTHREAD_NOEXPORT
-void
-_pthread_key_global_init(const char *envp[]);
-
-PTHREAD_NOEXPORT
-void
-_pthread_mutex_global_init(const char *envp[], struct _pthread_registration_data *registration_data);
-
-PTHREAD_EXPORT
-void
-_pthread_start(pthread_t self, mach_port_t kport, void *(*fun)(void *), void * funarg, size_t stacksize, unsigned int flags);
-
-PTHREAD_EXPORT
-void
-_pthread_wqthread(pthread_t self, mach_port_t kport, void *stackaddr, void *keventlist, int flags, int nkevents);
-
-PTHREAD_NOEXPORT
-void
-_pthread_main_thread_init(pthread_t p);
-
-PTHREAD_NOEXPORT
-void
-_pthread_main_thread_postfork_init(pthread_t p);
-
-PTHREAD_NOEXPORT
-void
-_pthread_bsdthread_init(struct _pthread_registration_data *data);
-
-PTHREAD_NOEXPORT_VARIANT
-void
-_pthread_clear_qos_tsd(mach_port_t thread_port);
-
-#define PTHREAD_CONFORM_DARWIN_LEGACY 0
-#define PTHREAD_CONFORM_UNIX03_NOCANCEL 1
-#define PTHREAD_CONFORM_UNIX03_CANCELABLE 2
-
-PTHREAD_NOEXPORT_VARIANT
-void
-_pthread_testcancel(int conforming);
-
-PTHREAD_EXPORT
-void
-_pthread_exit_if_canceled(int error);
-
-PTHREAD_NOEXPORT
-void
-_pthread_markcancel_if_canceled(pthread_t thread, mach_port_t kport);
-
-PTHREAD_NOEXPORT
-void
-_pthread_setcancelstate_exit(pthread_t self, void *value_ptr);
-
-PTHREAD_NOEXPORT
-semaphore_t
-_pthread_joiner_prepost_wake(pthread_t thread);
-
-PTHREAD_ALWAYS_INLINE
-static inline mach_port_t
-_pthread_kernel_thread(pthread_t t)
-{
- return t->tsd[_PTHREAD_TSD_SLOT_MACH_THREAD_SELF];
-}
-
-PTHREAD_ALWAYS_INLINE
-static inline void
-_pthread_set_kernel_thread(pthread_t t, mach_port_t p)
-{
- t->tsd[_PTHREAD_TSD_SLOT_MACH_THREAD_SELF] = p;
-}
-
-#ifdef DEBUG
-#define PTHREAD_DEBUG_ASSERT(b) \
- do { \
- if (os_unlikely(!(b))) { \
- PTHREAD_INTERNAL_CRASH(0, "Assertion failed: " #b); \
- } \
- } while (0)
-#else
-#define PTHREAD_DEBUG_ASSERT(b) ((void)0)
-#endif
-
-#include <os/semaphore_private.h>
-#include <os/alloc_once_private.h>
-
-struct pthread_atfork_entry {
- void (*prepare)(void);
- void (*parent)(void);
- void (*child)(void);
-};
-
-#define PTHREAD_ATFORK_INLINE_MAX 10
-#define PTHREAD_ATFORK_MAX (vm_page_size/sizeof(struct pthread_atfork_entry))
-
-struct pthread_globals_s {
- // atfork.c
- pthread_t psaved_self;
- _pthread_lock psaved_self_global_lock;
- _pthread_lock pthread_atfork_lock;
-
- size_t atfork_count;
- struct pthread_atfork_entry atfork_storage[PTHREAD_ATFORK_INLINE_MAX];
- struct pthread_atfork_entry *atfork;
- uint16_t qmp_logical[THREAD_QOS_LAST];
- uint16_t qmp_physical[THREAD_QOS_LAST];
-
-};
-typedef struct pthread_globals_s *pthread_globals_t;
-
-__attribute__((__pure__))
-static inline pthread_globals_t
-_pthread_globals(void)
-{
- return os_alloc_once(OS_ALLOC_ONCE_KEY_LIBSYSTEM_PTHREAD,
- sizeof(struct pthread_globals_s),
- NULL);
-}
-
-#pragma mark _pthread_mutex_check_signature
-
-PTHREAD_ALWAYS_INLINE
-static inline bool
-_pthread_mutex_check_signature_fast(_pthread_mutex *mutex)
-{
- return (mutex->sig == _PTHREAD_MUTEX_SIG_fast);
-}
-
-PTHREAD_ALWAYS_INLINE
-static inline bool
-_pthread_mutex_check_signature(_pthread_mutex *mutex)
-{
- return ((mutex->sig & _PTHREAD_MUTEX_SIG_MASK) == _PTHREAD_MUTEX_SIG_CMP);
-}
-
-PTHREAD_ALWAYS_INLINE
-static inline bool
-_pthread_mutex_check_signature_init(_pthread_mutex *mutex)
-{
- return ((mutex->sig & _PTHREAD_MUTEX_SIG_init_MASK) ==
- _PTHREAD_MUTEX_SIG_init_CMP);
-}
-
-#pragma mark _pthread_rwlock_check_signature
-
-PTHREAD_ALWAYS_INLINE
-static inline bool
-_pthread_rwlock_check_signature(_pthread_rwlock *rwlock)
-{
- return (rwlock->sig == _PTHREAD_RWLOCK_SIG);
-}
-
-PTHREAD_ALWAYS_INLINE
-static inline bool
-_pthread_rwlock_check_signature_init(_pthread_rwlock *rwlock)
-{
- return (rwlock->sig == _PTHREAD_RWLOCK_SIG_init);
-}
-
-PTHREAD_ALWAYS_INLINE
-static inline void
-_pthread_validate_signature(pthread_t thread)
-{
- pthread_t th = (pthread_t)(thread->sig ^ _pthread_ptr_munge_token);
-#if __has_feature(ptrauth_calls)
- th = ptrauth_auth_data(th, ptrauth_key_process_dependent_data,
- ptrauth_string_discriminator("pthread.signature"));
-#endif
- if (os_unlikely(th != thread)) {
- /* OS_REASON_LIBSYSTEM_CODE_PTHREAD_CORRUPTION == 4 */
- abort_with_reason(OS_REASON_LIBSYSTEM, 4, "pthread_t was corrupted", 0);
- }
-}
-
-PTHREAD_ALWAYS_INLINE
-static inline void
-_pthread_init_signature(pthread_t thread)
-{
- pthread_t th = thread;
-#if __has_feature(ptrauth_calls)
- th = ptrauth_sign_unauthenticated(th, ptrauth_key_process_dependent_data,
- ptrauth_string_discriminator("pthread.signature"));
-#endif
- thread->sig = (uintptr_t)th ^ _pthread_ptr_munge_token;
-}
-
-/*
- * ALWAYS called without list lock and return with list lock held on success
- *
- * This weird calling convention exists because this function will sometimes
- * drop the lock, and it's best callers don't have to remember this.
- */
-PTHREAD_ALWAYS_INLINE
-static inline bool
-_pthread_validate_thread_and_list_lock(pthread_t thread)
-{
- pthread_t p;
- if (thread == NULL) return false;
- _PTHREAD_LOCK(_pthread_list_lock);
- TAILQ_FOREACH(p, &__pthread_head, tl_plist) {
- if (p != thread) continue;
- _pthread_validate_signature(p);
- return true;
- }
- _PTHREAD_UNLOCK(_pthread_list_lock);
-
- return false;
-}
-
-PTHREAD_ALWAYS_INLINE
-static inline bool
-_pthread_is_valid(pthread_t thread, mach_port_t *portp)
-{
- mach_port_t kport = MACH_PORT_NULL;
- bool valid;
-
- if (thread == pthread_self()) {
- _pthread_validate_signature(thread);
- valid = true;
- kport = _pthread_kernel_thread(thread);
- } else if (!_pthread_validate_thread_and_list_lock(thread)) {
- valid = false;
- } else {
- kport = _pthread_kernel_thread(thread);
- valid = true;
- _PTHREAD_UNLOCK(_pthread_list_lock);
- }
-
- if (portp != NULL) {
- *portp = kport;
- }
- return valid;
-}
-
-PTHREAD_ALWAYS_INLINE
-static inline void*
-_pthread_atomic_xchg_ptr_inline(void **p, void *v)
-{
- return os_atomic_xchg(p, v, seq_cst);
-}
-
-PTHREAD_ALWAYS_INLINE
-static inline uint32_t
-_pthread_atomic_xchg_uint32_relaxed_inline(uint32_t *p,uint32_t v)
-{
- return os_atomic_xchg(p, v, relaxed);
-}
-
-#define _pthread_atomic_xchg_ptr(p, v) \
- _pthread_atomic_xchg_ptr_inline(p, v)
-#define _pthread_atomic_xchg_uint32_relaxed(p, v) \
- _pthread_atomic_xchg_uint32_relaxed_inline(p, v)
#endif /* _POSIX_PTHREAD_INTERNALS_H */
+++ /dev/null
-/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
- * All Rights Reserved
- *
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appears in all copies and
- * that both the copyright notice and this permission notice appear in
- * supporting documentation.
- *
- * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
- * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-/*
- * MkLinux
- */
-
-/*
- * This program will generate the stuff necessary to "publish" the POSIX
- * header <pthread.h> in a machine dependent fashion.
- */
-
-#include <pthread_internals.h>
-#include <stdio.h>
-
-int
-main(void)
-{
- printf("#ifndef _PTHREAD_IMPL_H_\n");
- printf("#define _PTHREAD_IMPL_H_\n");
- printf("/*\n");
- printf(" * Internal implementation details\n");
- printf(" */\n");
- printf("\n");
- printf("#define __PTHREAD_SIZE__ %zd\n", sizeof(struct _pthread)-sizeof(long));
- printf("#define __PTHREAD_ATTR_SIZE__ %zd\n", sizeof(pthread_attr_t)-sizeof(long));
- printf("#define __PTHREAD_MUTEXATTR_SIZE__ %zd\n", sizeof(pthread_mutexattr_t)-sizeof(long));
- printf("#define __PTHREAD_MUTEX_SIZE__ %zd\n", sizeof(pthread_mutex_t)-sizeof(long));
- printf("#define __PTHREAD_CONDATTR_SIZE__ %zd\n", sizeof(pthread_condattr_t)-sizeof(long));
- printf("#define __PTHREAD_COND_SIZE__ %zd\n", sizeof(pthread_cond_t)-sizeof(long));
- printf("#define __PTHREAD_ONCE_SIZE__ %zd\n", sizeof(pthread_once_t)-sizeof(long));
- printf("#define __PTHREAD_sig_OFFSET__ %zd\n", offsetof(struct _pthread, sig));
- printf("#define __PTHREAD_cleanup_stack_OFFSET__ %zd\n", offsetof(struct _pthread, __cleanup_stack));
- printf("#define __PTHREAD_guardsize_OFFSET__ %zd\n", offsetof(struct _pthread, guardsize));
- printf("#define __PTHREAD_param_OFFSET__ %zd\n", offsetof(struct _pthread, param));
- printf("#define __PTHREAD_mutexes_OFFSET__ %zd\n", offsetof(struct _pthread, mutexes));
- printf("#define __PTHREAD_joiner_OFFSET__ %zd\n", offsetof(struct _pthread, joiner));
- printf("#define __PTHREAD_exit_value_OFFSET__ %zd\n", offsetof(struct _pthread, exit_value));
- printf("#define __PTHREAD_death_OFFSET__ %zd\n", offsetof(struct _pthread, death));
- printf("#define __PTHREAD_kernel_thread_OFFSET__ %zd\n", offsetof(struct _pthread, kernel_thread));
- printf("#define __PTHREAD_fun_OFFSET__ %zd\n", offsetof(struct _pthread, fun));
- printf("#define __PTHREAD_arg_OFFSET__ %zd\n", offsetof(struct _pthread, arg));
- printf("#define __PTHREAD_cancel_state_OFFSET__ %zd\n", offsetof(struct _pthread, cancel_state));
- printf("#define __PTHREAD_err_no_OFFSET__ %zd\n", offsetof(struct _pthread, err_no));
- printf("#define __PTHREAD_tsd_OFFSET__ %zd\n", offsetof(struct _pthread, tsd));
- printf("#define __PTHREAD_stackaddr_OFFSET__ %zd\n", offsetof(struct _pthread, stackaddr));
- printf("#define __PTHREAD_stacksize_OFFSET__ %zd\n", offsetof(struct _pthread, stacksize));
- printf("#define __PTHREAD_reply_port_OFFSET__ %zd\n", offsetof(struct _pthread, reply_port));
- printf("#define __PTHREAD_cthread_self_OFFSET__ %zd\n", offsetof(struct _pthread, cthread_self));
- printf("#define __PTHREAD_freeStackOnExit_OFFSET__ %zd\n", offsetof(struct _pthread, freeStackOnExit));
- printf("#define __PTHREAD_plist_OFFSET__ %zd\n", offsetof(struct _pthread, plist));
- printf("/*\n");
- printf(" * [Internal] data structure signatures\n");
- printf(" */\n");
- printf("#define _PTHREAD_MUTEX_SIG_init 0x%08X\n", _PTHREAD_MUTEX_SIG_init);
- printf("#define _PTHREAD_COND_SIG_init 0x%08X\n", _PTHREAD_COND_SIG_init);
- printf("#define _PTHREAD_ONCE_SIG_init 0x%08X\n", _PTHREAD_ONCE_SIG_init);
- printf("/*\n");
- printf(" * POSIX scheduling policies \n");
- printf(" */\n");
- printf("#define SCHED_OTHER %d\n", SCHED_OTHER);
- printf("#define SCHED_FIFO %d\n", SCHED_FIFO);
- printf("#define SCHED_RR %d\n", SCHED_RR);
- printf("\n");
- printf("#define __SCHED_PARAM_SIZE__ %ld\n", (long) sizeof(struct sched_param)-sizeof(int));
- printf("\n");
- printf("#endif _PTHREAD_IMPL_H_\n");
-
- exit(0);
-}
+++ /dev/null
-/*
- * Copyright (c) 2018 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef _POSIX_PTHREAD_OFFSETS_H
-#define _POSIX_PTHREAD_OFFSETS_H
-
-#ifndef __ASSEMBLER__
-#define check_backward_offset(field, value) \
- _Static_assert(offsetof(struct _pthread, tsd) + value == \
- offsetof(struct _pthread, field), #value " is correct")
-#define check_forward_offset(field, value) \
- _Static_assert(offsetof(struct _pthread, field) == value, \
- #value " is correct")
-#else
-#define check_backward_offset(field, value)
-#define check_forward_offset(field, value)
-#endif // __ASSEMBLER__
-
-#if defined(__i386__)
-#define _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET 140
-#define _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET 144
-#elif __LP64__
-#define _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET -48
-#define _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET -40
-#else
-#define _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET -36
-#define _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET -32
-#endif
-
-#if defined(__i386__)
-check_forward_offset(stackaddr, _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET);
-check_forward_offset(stackbottom, _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET);
-#else
-check_backward_offset(stackaddr, _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET);
-check_backward_offset(stackbottom, _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET);
-#endif
-
-#endif /* _POSIX_PTHREAD_OFFSETS_H */
--- /dev/null
+/*
+ * Copyright (c) 2018 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef _POSIX_PTHREAD_OFFSETS_H
+#define _POSIX_PTHREAD_OFFSETS_H
+
+#if defined(__i386__)
+#define _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET 140
+#define _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET 144
+#elif __LP64__
+#define _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET -48
+#define _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET -40
+#else
+#define _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET -36
+#define _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET -32
+#endif
+
+#ifndef __ASSEMBLER__
+#include "pthread/private.h" // for other _PTHREAD_STRUCT_DIRECT_*_OFFSET
+
+#define check_backward_offset(field, value) \
+ _Static_assert(offsetof(struct pthread_s, tsd) + value == \
+ offsetof(struct pthread_s, field), #value " is correct")
+#define check_forward_offset(field, value) \
+ _Static_assert(offsetof(struct pthread_s, field) == value, \
+ #value " is correct")
+
+check_forward_offset(tsd, _PTHREAD_STRUCT_DIRECT_TSD_OFFSET);
+check_backward_offset(thread_id, _PTHREAD_STRUCT_DIRECT_THREADID_OFFSET);
+#if defined(__i386__)
+check_forward_offset(stackaddr, _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET);
+check_forward_offset(stackbottom, _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET);
+#else
+check_backward_offset(stackaddr, _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET);
+check_backward_offset(stackbottom, _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET);
+#endif
+
+#endif // __ASSEMBLER__
+
+#endif /* _POSIX_PTHREAD_OFFSETS_H */
--- /dev/null
+/*
+ * Copyright (c) 2019 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef __LIBPTHREAD_PROTOTYPES_INTERNAL_H__
+#define __LIBPTHREAD_PROTOTYPES_INTERNAL_H__
+
+/*!
+ * @file prototypes_internal.h
+ *
+ * @brief
+ * This file has prototypes for symbols / functions private to libpthread.
+ */
+
+#define PTHREAD_NOEXPORT __attribute__((visibility("hidden")))
+#define PTHREAD_NOEXPORT_VARIANT
+
+
+#pragma GCC visibility push(hidden)
+
+/*!
+ * @macro main_thread()
+ *
+ * @brief
+ * Returns a pointer to the main thread.
+ *
+ * @discussion
+ * The main thread structure really lives in dyld,
+ * and when __pthread_init() is called, its pointer will be discovered
+ * and stashed in _main_thread_ptr which libpthread uses.
+ */
+#if VARIANT_DYLD
+extern struct pthread_s _main_thread;
+#define main_thread() (&_main_thread)
+#define __pthread_mutex_default_opt_policy _PTHREAD_MTX_OPT_POLICY_DEFAULT
+#define __pthread_mutex_use_ulock _PTHREAD_MTX_OPT_ULOCK_DEFAULT
+#define __pthread_mutex_ulock_adaptive_spin _PTHREAD_MTX_OPT_ADAPTIVE_DEFAULT
+#else // VARIANT_DYLD
+extern pthread_t _main_thread_ptr;
+#define main_thread() (_main_thread_ptr)
+extern void *(*_pthread_malloc)(size_t);
+extern void (*_pthread_free)(void *);
+extern int __pthread_mutex_default_opt_policy;
+extern bool __pthread_mutex_use_ulock;
+extern bool __pthread_mutex_ulock_adaptive_spin;
+#endif // VARIANT_DYLD
+
+extern struct __pthread_list __pthread_head; // List of all pthreads in the process.
+extern _pthread_lock _pthread_list_lock; // Lock protects access to above list.
+extern uint32_t _main_qos;
+extern uintptr_t _pthread_ptr_munge_token;
+
+#if PTHREAD_DEBUG_LOG
+#include <mach/mach_time.h>
+extern int _pthread_debuglog;
+extern uint64_t _pthread_debugstart;
+#endif
+
+/* pthread.c */
+void _pthread_deallocate(pthread_t t, bool from_mach_thread);
+void _pthread_main_thread_init(pthread_t p);
+void _pthread_main_thread_postfork_init(pthread_t p);
+void _pthread_bsdthread_init(struct _pthread_registration_data *data);
+void *_pthread_atomic_xchg_ptr(void **p, void *v);
+uint32_t _pthread_atomic_xchg_uint32_relaxed(uint32_t *p, uint32_t v);
+
+/* pthread_cancelable.c */
+void _pthread_markcancel_if_canceled(pthread_t thread, mach_port_t kport);
+void _pthread_setcancelstate_exit(pthread_t self, void *value_ptr);
+semaphore_t _pthread_joiner_prepost_wake(pthread_t thread);
+int _pthread_join(pthread_t thread, void **value_ptr, pthread_conformance_t);
+
+/* pthread_cond.c */
+int _pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex,
+ const struct timespec *abstime, int isRelative, pthread_conformance_t);
+int _pthread_mutex_droplock(pthread_mutex_t *mutex, uint32_t *flagp,
+ uint32_t **pmtxp, uint32_t *mgenp, uint32_t *ugenp);
+
+/* pthread_dependency.c */
+void _pthread_dependency_fulfill_slow(pthread_dependency_t *pr, uint32_t old);
+
+/* pthread_mutex.c */
+OS_COLD OS_NORETURN
+int _pthread_mutex_corruption_abort(pthread_mutex_t *mutex);
+int _pthread_mutex_fairshare_lock_slow(pthread_mutex_t *mutex, bool trylock);
+int _pthread_mutex_fairshare_unlock_slow(pthread_mutex_t *mutex);
+int _pthread_mutex_ulock_lock(pthread_mutex_t *mutex, bool trylock);
+int _pthread_mutex_ulock_unlock(pthread_mutex_t *mutex);
+int _pthread_mutex_firstfit_lock_slow(pthread_mutex_t *mutex, bool trylock);
+int _pthread_mutex_firstfit_unlock_slow(pthread_mutex_t *mutex);
+int _pthread_mutex_lock_init_slow(pthread_mutex_t *mutex, bool trylock);
+void _pthread_mutex_global_init(const char *envp[], struct _pthread_registration_data *registration_data);
+
+/* pthread_rwlock.c */
+enum rwlock_seqfields;
+int _pthread_rwlock_lock_slow(pthread_rwlock_t *rwlock, bool readlock, bool trylock);
+int _pthread_rwlock_unlock_slow(pthread_rwlock_t *rwlock, enum rwlock_seqfields updated_seqfields);
+
+/* pthread_tsd.c */
+void _pthread_tsd_cleanup(pthread_t self);
+void _pthread_key_global_init(const char *envp[]);
+
+/* qos.c */
+thread_qos_t _pthread_qos_class_to_thread_qos(qos_class_t qos);
+void _pthread_set_main_qos(pthread_priority_t qos);
+
+#pragma GCC visibility pop
+
+#endif // __LIBPTHREAD_PROTOTYPES_INTERNAL_H__
* POSIX Pthread Library
*/
-#include "resolver.h"
#include "internal.h"
-#include "private.h"
-#include "workqueue_private.h"
-#include "introspection_private.h"
-#include "qos_private.h"
-#include "tsd_private.h"
-#include "pthread/stack_np.h"
-#include "offsets.h" // included to validate the offsets at build time
#include <stdlib.h>
#include <errno.h>
#if __has_include(<ptrauth.h>)
#include <ptrauth.h>
#endif // __has_include(<ptrauth.h>)
-
-#include <_simple.h>
-#include <platform/string.h>
-#include <platform/compat.h>
-
-#include <stack_logging.h>
-
-// Defined in libsyscall; initialized in libmalloc
-extern malloc_logger_t *__syscall_logger;
-
-extern int __sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
- void *newp, size_t newlen);
-extern void __exit(int) __attribute__((noreturn));
-extern int __pthread_kill(mach_port_t, int);
-
-extern void _pthread_joiner_wake(pthread_t thread);
-
-#if !VARIANT_DYLD
-PTHREAD_NOEXPORT extern struct _pthread *_main_thread_ptr;
-#define main_thread() (_main_thread_ptr)
-#endif // VARIANT_DYLD
+#include <os/thread_self_restrict.h>
+#include <os/tsd.h>
// Default stack size is 512KB; independent of the main thread's stack size.
#define DEFAULT_STACK_SIZE (size_t)(512 * 1024)
-
//
// Global constants
//
* start of the next page. There's also one page worth of allocation
* below stacksize for the guard page. <rdar://problem/19941744>
*/
-#define PTHREAD_SIZE ((size_t)mach_vm_round_page(sizeof(struct _pthread)))
+#define PTHREAD_SIZE ((size_t)mach_vm_round_page(sizeof(struct pthread_s)))
#define PTHREAD_ALLOCADDR(stackaddr, stacksize) ((stackaddr - stacksize) - vm_page_size)
#define PTHREAD_ALLOCSIZE(stackaddr, stacksize) ((round_page((uintptr_t)stackaddr) + PTHREAD_SIZE) - (uintptr_t)PTHREAD_ALLOCADDR(stackaddr, stacksize))
const struct pthread_layout_offsets_s pthread_layout_offsets = {
.plo_version = 1,
- .plo_pthread_tsd_base_offset = offsetof(struct _pthread, tsd),
+ .plo_pthread_tsd_base_offset = offsetof(struct pthread_s, tsd),
.plo_pthread_tsd_base_address_offset = 0,
- .plo_pthread_tsd_entry_size = sizeof(((struct _pthread *)NULL)->tsd[0]),
+ .plo_pthread_tsd_entry_size = sizeof(((struct pthread_s *)NULL)->tsd[0]),
};
#endif // PTHREAD_LAYOUT_SPI
// This global should be used (carefully) by anyone needing to know if a
// pthread (other than the main thread) has been created.
int __is_threaded = 0;
-int __unix_conforming = 0;
+const int __unix_conforming = 1; // we're always conformant, but it's exported
//
// Global internal variables
#if VARIANT_DYLD
// The main thread's pthread_t
-struct _pthread _main_thread __attribute__((aligned(64))) = { };
-#define main_thread() (&_main_thread)
+struct pthread_s _main_thread OS_ALIGNED(64);
#else // VARIANT_DYLD
-struct _pthread *_main_thread_ptr;
+pthread_t _main_thread_ptr;
+void *(*_pthread_malloc)(size_t);
+void (*_pthread_free)(void *);
#endif // VARIANT_DYLD
#if PTHREAD_DEBUG_LOG
uintptr_t _pthread_ptr_munge_token;
static void (*exitf)(int) = __exit;
-#if !VARIANT_DYLD
-static void *(*_pthread_malloc)(size_t) = NULL;
-static void (*_pthread_free)(void *) = NULL;
-#endif // !VARIANT_DYLD
// work queue support data
-PTHREAD_NORETURN
+OS_NORETURN OS_COLD
static void
__pthread_invalid_keventfunction(void **events, int *nevents)
{
PTHREAD_CLIENT_CRASH(0, "Invalid kqworkq setup");
}
-PTHREAD_NORETURN
+OS_NORETURN OS_COLD
static void
__pthread_invalid_workloopfunction(uint64_t *workloop_id, void **events, int *nevents)
{
#endif // VARIANT_DYLD
static inline void _pthread_set_self_internal(pthread_t);
-static void _pthread_dealloc_reply_port(pthread_t t);
-static void _pthread_dealloc_special_reply_port(pthread_t t);
-
static inline void __pthread_started_thread(pthread_t t);
static void _pthread_exit(pthread_t self, void *value_ptr) __dead2;
static inline void _pthread_introspection_thread_terminate(pthread_t t);
static inline void _pthread_introspection_thread_destroy(pthread_t t);
-extern void _pthread_set_self(pthread_t);
-extern void start_wqthread(pthread_t self, mach_port_t kport, void *stackaddr, void *unused, int reuse); // trampoline into _pthread_wqthread
-extern void thread_start(pthread_t self, mach_port_t kport, void *(*fun)(void *), void * funarg, size_t stacksize, unsigned int flags); // trampoline into _pthread_start
-
/*
* Flags filed passed to bsdthread_create and back in pthread_start
* 31 <---------------------------------> 0
#define PTHREAD_START_POLICY_MASK 0xff
#define PTHREAD_START_IMPORTANCE_MASK 0xffff
-extern pthread_t __bsdthread_create(void *(*func)(void *), void * func_arg, void * stack, pthread_t thread, unsigned int flags);
-extern int __bsdthread_register(void (*)(pthread_t, mach_port_t, void *(*)(void *), void *, size_t, unsigned int), void (*)(pthread_t, mach_port_t, void *, void *, int), int,void (*)(pthread_t, mach_port_t, void *(*)(void *), void *, size_t, unsigned int), int32_t *,__uint64_t);
-extern int __bsdthread_terminate(void * freeaddr, size_t freesize, mach_port_t kport, mach_port_t joinsem);
-extern __uint64_t __thread_selfid( void );
-
-#if __LP64__
-_Static_assert(offsetof(struct _pthread, tsd) == 224, "TSD LP64 offset");
-#else
-_Static_assert(offsetof(struct _pthread, tsd) == 176, "TSD ILP32 offset");
-#endif
-_Static_assert(offsetof(struct _pthread, tsd) + _PTHREAD_STRUCT_DIRECT_THREADID_OFFSET
- == offsetof(struct _pthread, thread_id),
- "_PTHREAD_STRUCT_DIRECT_THREADID_OFFSET is correct");
-
#pragma mark pthread attrs
-_Static_assert(sizeof(struct _pthread_attr_t) == sizeof(__darwin_pthread_attr_t),
- "internal pthread_attr_t == external pthread_attr_t");
-
int
pthread_attr_destroy(pthread_attr_t *attr)
{
return ret;
}
-static PTHREAD_ALWAYS_INLINE void
+static OS_ALWAYS_INLINE void
_pthread_attr_get_schedparam(const pthread_attr_t *attr,
struct sched_param *param)
{
return ret;
}
+#define _PTHREAD_POLICY_IS_FIXEDPRI(x) ((x) == SCHED_RR || (x) == SCHED_FIFO)
+
int
pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
{
{
int ret = EINVAL;
if (attr->sig == _PTHREAD_ATTR_SIG &&
- ((uintptr_t)stackaddr % vm_page_size) == 0) {
+ ((mach_vm_address_t)stackaddr & vm_page_mask) == 0) {
attr->stackaddr = stackaddr;
attr->defaultguardpage = false;
attr->guardsize = 0;
int
pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
{
+#if TARGET_OS_OSX
+ // If the caller is doing something reasonable, help them out.
+ if (stacksize % 0x1000 == 0) {
+ stacksize = round_page(stacksize);
+ }
+#endif // TARGET_OS_OSX
+
int ret = EINVAL;
if (attr->sig == _PTHREAD_ATTR_SIG &&
- (stacksize % vm_page_size) == 0 &&
+ ((stacksize & vm_page_mask) == 0) &&
stacksize >= PTHREAD_STACK_MIN) {
attr->stacksize = stacksize;
ret = 0;
{
int ret = EINVAL;
if (attr->sig == _PTHREAD_ATTR_SIG &&
- ((uintptr_t)stackaddr % vm_page_size) == 0 &&
- (stacksize % vm_page_size) == 0 &&
+ (((mach_vm_address_t)stackaddr & vm_page_mask) == 0) &&
+ ((stacksize & vm_page_mask) == 0) &&
stacksize >= PTHREAD_STACK_MIN) {
attr->stackaddr = (void *)((uintptr_t)stackaddr + stacksize);
attr->stacksize = stacksize;
int
pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
{
+#if TARGET_OS_OSX
+ // If the caller is doing something reasonable, help them out.
+ if (guardsize % 0x1000 == 0) {
+ guardsize = round_page(guardsize);
+ }
+#endif // TARGET_OS_OSX
+
int ret = EINVAL;
- if (attr->sig == _PTHREAD_ATTR_SIG && (guardsize % vm_page_size) == 0) {
+ if (attr->sig == _PTHREAD_ATTR_SIG &&
+ (guardsize & vm_page_mask) == 0) {
/* Guardsize of 0 is valid, means no guard */
attr->defaultguardpage = false;
attr->guardsize = guardsize;
PTHREAD_CLIENT_CRASH(attrs->stacksize, "Stack size in attrs is too small");
}
- if (os_unlikely(((uintptr_t)attrs->stackaddr % vm_page_size) != 0)) {
- PTHREAD_CLIENT_CRASH(attrs->stacksize, "Unaligned stack addr in attrs");
+ if (os_unlikely((mach_vm_address_t)attrs->stackaddr & vm_page_mask)) {
+ PTHREAD_CLIENT_CRASH(attrs->stackaddr, "Unaligned stack addr in attrs");
}
// Allocate a pthread structure if necessary
// the allocations. <rdar://36418708>
int eventTypeFlags = stack_logging_type_vm_allocate;
__syscall_logger(eventTypeFlags | VM_MAKE_TAG(VM_MEMORY_STACK),
- (uintptr_t)mach_task_self(), (uintptr_t)allocsize, 0,
- (uintptr_t)allocaddr, 0);
+ (uintptr_t)mach_task_self(), (uintptr_t)allocsize, 0,
+ (uintptr_t)allocaddr, 0);
}
// The stack grows down.
return t;
}
-PTHREAD_NOINLINE
+OS_NOINLINE
void
_pthread_deallocate(pthread_t t, bool from_mach_thread)
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreturn-stack-address"
-PTHREAD_NOINLINE
+OS_NOINLINE
static void*
_pthread_current_stack_address(void)
{
#pragma clang diagnostic pop
-void
+static void
_pthread_joiner_wake(pthread_t thread)
{
uint32_t *exit_gate = &thread->tl_exit_gate;
}
}
+static void
+_pthread_dealloc_reply_port(pthread_t self)
+{
+ mach_port_t port = _pthread_tsd_slot(self, MIG_REPLY);
+ if (port != MACH_PORT_NULL) {
+ // this will also set the TSD to MACH_PORT_NULL
+ mig_dealloc_reply_port(port);
+ }
+}
+
+static void
+_pthread_dealloc_special_reply_port(pthread_t self)
+{
+ mach_port_t port = _pthread_tsd_slot(self, MACH_SPECIAL_REPLY);
+ if (port != MACH_PORT_NULL) {
+ _pthread_tsd_slot(self, MACH_SPECIAL_REPLY) = MACH_PORT_NULL;
+ thread_destruct_special_reply_port(port, THREAD_SPECIAL_REPLY_PORT_ALL);
+ }
+}
+
// Terminates the thread if called from the currently running thread.
-PTHREAD_NORETURN PTHREAD_NOINLINE PTHREAD_NOT_TAIL_CALLED
+OS_NORETURN OS_NOINLINE OS_NOT_TAIL_CALLED
static void
_pthread_terminate(pthread_t t, void *exit_value)
{
freesize_stack = 0;
}
- mach_port_t kport = _pthread_kernel_thread(t);
+ mach_port_t kport = _pthread_tsd_slot(t, MACH_THREAD_SELF);
bool keep_thread_struct = false, needs_wake = false;
semaphore_t custom_stack_sema = MACH_PORT_NULL;
_pthread_dealloc_special_reply_port(t);
_pthread_dealloc_reply_port(t);
- _PTHREAD_LOCK(_pthread_list_lock);
+ _pthread_lock_lock(&_pthread_list_lock);
// This piece of code interacts with pthread_join. It will always:
// - set tl_exit_gate to MACH_PORT_DEAD (thread exited)
TAILQ_REMOVE(&__pthread_head, t, tl_plist);
}
- _PTHREAD_UNLOCK(_pthread_list_lock);
+ _pthread_lock_unlock(&_pthread_list_lock);
if (needs_wake) {
// When we found a waiter, we want to drop the very contended list lock
// - the exiting thread tries to set tl_joiner_cleans_up to true
// Whoever does it first commits the other guy to cleanup the pthread_t
_pthread_joiner_wake(t);
- _PTHREAD_LOCK(_pthread_list_lock);
+ _pthread_lock_lock(&_pthread_list_lock);
if (t->tl_join_ctx) {
t->tl_joiner_cleans_up = true;
keep_thread_struct = true;
}
- _PTHREAD_UNLOCK(_pthread_list_lock);
+ _pthread_lock_unlock(&_pthread_list_lock);
}
//
PTHREAD_INTERNAL_CRASH(t, "thread didn't terminate");
}
-PTHREAD_NORETURN
+OS_NORETURN
static void
_pthread_terminate_invoke(pthread_t t, void *exit_value)
{
#pragma mark pthread start / body
-PTHREAD_NORETURN
void
_pthread_start(pthread_t self, mach_port_t kport,
__unused void *(*fun)(void *), __unused void *arg,
"thread_set_tsd_base() wasn't called by the kernel");
}
PTHREAD_DEBUG_ASSERT(MACH_PORT_VALID(kport));
- PTHREAD_DEBUG_ASSERT(_pthread_kernel_thread(self) == kport);
+ PTHREAD_DEBUG_ASSERT(_pthread_tsd_slot(self, MACH_THREAD_SELF) == kport);
_pthread_validate_signature(self);
_pthread_markcancel_if_canceled(self, kport);
_pthread_exit(self, (self->fun)(self->arg));
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline void
_pthread_struct_init(pthread_t t, const pthread_attr_t *attrs,
void *stackaddr, size_t stacksize, void *freeaddr, size_t freesize)
{
_pthread_init_signature(t);
- t->tsd[_PTHREAD_TSD_SLOT_PTHREAD_SELF] = t;
- t->tsd[_PTHREAD_TSD_SLOT_ERRNO] = &t->err_no;
+ _pthread_tsd_slot(t, PTHREAD_SELF) = t;
+ _pthread_tsd_slot(t, ERRNO) = &t->err_no;
if (attrs->schedset == 0) {
- t->tsd[_PTHREAD_TSD_SLOT_PTHREAD_QOS_CLASS] = attrs->qosclass;
+ _pthread_tsd_slot(t, PTHREAD_QOS_CLASS) = attrs->qosclass;
} else {
- t->tsd[_PTHREAD_TSD_SLOT_PTHREAD_QOS_CLASS] =
+ _pthread_tsd_slot(t, PTHREAD_QOS_CLASS) =
_pthread_unspecified_priority();
}
- t->tsd[_PTHREAD_TSD_SLOT_PTR_MUNGE] = _pthread_ptr_munge_token;
+ _pthread_tsd_slot(t, PTR_MUNGE) = _pthread_ptr_munge_token;
t->tl_has_custom_stack = (attrs->stackaddr != NULL);
- _PTHREAD_LOCK_INIT(t->lock);
+ _pthread_lock_init(&t->lock);
t->stackaddr = stackaddr;
t->stackbottom = stackaddr - stacksize;
#pragma mark pthread public interface
-/* Need to deprecate this in future */
-int
-_pthread_is_threaded(void)
-{
- return __is_threaded;
-}
-
/* Non portable public api to know whether this process has(had) atleast one thread
* apart from main thread. There could be race if there is a thread in the process of
* creation at the time of call . It does not tell whether there are more than one thread
return __is_threaded;
}
-
-PTHREAD_NOEXPORT_VARIANT
mach_port_t
pthread_mach_thread_np(pthread_t t)
{
return kport;
}
-PTHREAD_NOEXPORT_VARIANT
pthread_t
pthread_from_mach_thread_np(mach_port_t kernel_thread)
{
- struct _pthread *p = NULL;
+ pthread_t p = NULL;
/* No need to wait as mach port is already known */
- _PTHREAD_LOCK(_pthread_list_lock);
+ _pthread_lock_lock(&_pthread_list_lock);
TAILQ_FOREACH(p, &__pthread_head, tl_plist) {
- if (_pthread_kernel_thread(p) == kernel_thread) {
+ if (_pthread_tsd_slot(p, MACH_THREAD_SELF) == kernel_thread) {
break;
}
}
- _PTHREAD_UNLOCK(_pthread_list_lock);
+ _pthread_lock_unlock(&_pthread_list_lock);
return p;
}
-PTHREAD_NOEXPORT_VARIANT
size_t
pthread_get_stacksize_np(pthread_t t)
{
if (_pthread_validate_thread_and_list_lock(t)) {
size = t->stackaddr - t->stackbottom;;
- _PTHREAD_UNLOCK(_pthread_list_lock);
+ _pthread_lock_unlock(&_pthread_list_lock);
}
out:
return size ? size : DEFAULT_STACK_SIZE;
}
-PTHREAD_NOEXPORT_VARIANT
void *
pthread_get_stackaddr_np(pthread_t t)
{
}
void *addr = t->stackaddr;
- _PTHREAD_UNLOCK(_pthread_list_lock);
+ _pthread_lock_unlock(&_pthread_list_lock);
return addr;
}
-
-static mach_port_t
-_pthread_reply_port(pthread_t t)
-{
- void *p;
- if (t == NULL) {
- p = _pthread_getspecific_direct(_PTHREAD_TSD_SLOT_MIG_REPLY);
- } else {
- p = t->tsd[_PTHREAD_TSD_SLOT_MIG_REPLY];
- }
- return (mach_port_t)(uintptr_t)p;
-}
-
-static void
-_pthread_set_reply_port(pthread_t t, mach_port_t reply_port)
-{
- void *p = (void *)(uintptr_t)reply_port;
- if (t == NULL) {
- _pthread_setspecific_direct(_PTHREAD_TSD_SLOT_MIG_REPLY, p);
- } else {
- t->tsd[_PTHREAD_TSD_SLOT_MIG_REPLY] = p;
- }
-}
-
-static void
-_pthread_dealloc_reply_port(pthread_t t)
-{
- mach_port_t reply_port = _pthread_reply_port(t);
- if (reply_port != MACH_PORT_NULL) {
- mig_dealloc_reply_port(reply_port);
- }
-}
-
-static mach_port_t
-_pthread_special_reply_port(pthread_t t)
-{
- void *p;
- if (t == NULL) {
- p = _pthread_getspecific_direct(_PTHREAD_TSD_SLOT_MACH_SPECIAL_REPLY);
- } else {
- p = t->tsd[_PTHREAD_TSD_SLOT_MACH_SPECIAL_REPLY];
- }
- return (mach_port_t)(uintptr_t)p;
-}
-
-static void
-_pthread_dealloc_special_reply_port(pthread_t t)
-{
- mach_port_t special_reply_port = _pthread_special_reply_port(t);
- if (special_reply_port != MACH_PORT_NULL) {
- thread_destruct_special_reply_port(special_reply_port,
- THREAD_SPECIAL_REPLY_PORT_ALL);
- }
-}
-
pthread_t
pthread_main_thread_np(void)
{
return pthread_self() == main_thread();
}
-
static int
_pthread_threadid_slow(pthread_t thread, uint64_t *thread_id)
{
unsigned int info_count = THREAD_IDENTIFIER_INFO_COUNT;
- mach_port_t thport = _pthread_kernel_thread(thread);
+ mach_port_t thport = _pthread_tsd_slot(thread, MACH_THREAD_SELF);
struct thread_identifier_info info;
kern_return_t kr;
(thread_info_t)&info, &info_count);
if (kr == KERN_SUCCESS && info.thread_id) {
*thread_id = info.thread_id;
+#if __LP64__
os_atomic_store(&thread->thread_id, info.thread_id, relaxed);
+#else
+ os_atomic_store_wide(&thread->thread_id, info.thread_id, relaxed);
+#endif
return 0;
}
return EINVAL;
* thread's thread_id. So folks don't have to call pthread_self, in addition to
* us doing it, if they just want their thread_id.
*/
-PTHREAD_NOEXPORT_VARIANT
int
pthread_threadid_np(pthread_t thread, uint64_t *thread_id)
{
} else if (!_pthread_validate_thread_and_list_lock(thread)) {
res = ESRCH;
} else {
+#if __LP64__
*thread_id = os_atomic_load(&thread->thread_id, relaxed);
+#else
+ *thread_id = os_atomic_load_wide(&thread->thread_id, relaxed);
+#endif
if (os_unlikely(*thread_id == 0)) {
// there is a race at init because the thread sets its own TID.
// correct this by asking mach
res = _pthread_threadid_slow(thread, thread_id);
}
- _PTHREAD_UNLOCK(_pthread_list_lock);
+ _pthread_lock_unlock(&_pthread_list_lock);
}
return res;
}
-PTHREAD_NOEXPORT_VARIANT
+int
+pthread_cpu_number_np(size_t *cpu_id)
+{
+ if (cpu_id == NULL) {
+ errno = EINVAL;
+ return errno;
+ }
+
+ *cpu_id = _os_cpu_number();
+ return 0;
+}
+
int
pthread_getname_np(pthread_t thread, char *threadname, size_t len)
{
}
strlcpy(threadname, thread->pthread_name, len);
- _PTHREAD_UNLOCK(_pthread_list_lock);
+ _pthread_lock_unlock(&_pthread_list_lock);
return 0;
}
-
int
pthread_setname_np(const char *name)
{
_pthread_validate_signature(self);
- /* protytype is in pthread_internals.h */
res = __proc_info(5, getpid(), 2, (uint64_t)0, (void*)name, (int)len);
if (res == 0) {
if (len > 0) {
}
-PTHREAD_ALWAYS_INLINE
-static inline void
-__pthread_add_thread(pthread_t t, bool from_mach_thread)
+void
+pthread_jit_write_protect_np(int enable)
{
- if (from_mach_thread) {
- _PTHREAD_LOCK_FROM_MACH_THREAD(_pthread_list_lock);
- } else {
- _PTHREAD_LOCK(_pthread_list_lock);
- }
+ if (!os_thread_self_restrict_rwx_is_supported()) {
+ return;
+ }
+
+ if (enable) {
+ os_thread_self_restrict_rwx_to_rx();
+ } else {
+ os_thread_self_restrict_rwx_to_rw();
+ }
+}
+
+int pthread_jit_write_protect_supported_np()
+{
+ return os_thread_self_restrict_rwx_is_supported();
+}
+OS_ALWAYS_INLINE
+static inline void
+__pthread_add_thread(pthread_t t, mach_port_t self, bool from_mach_thread)
+{
+ _pthread_lock_lock(&_pthread_list_lock, self);
TAILQ_INSERT_TAIL(&__pthread_head, t, tl_plist);
_pthread_count++;
-
- if (from_mach_thread) {
- _PTHREAD_UNLOCK_FROM_MACH_THREAD(_pthread_list_lock);
- } else {
- _PTHREAD_UNLOCK(_pthread_list_lock);
- }
+ _pthread_lock_unlock(&_pthread_list_lock, self);
if (!from_mach_thread) {
// PR-26275485: Mach threads will likely crash trying to run
}
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline void
-__pthread_undo_add_thread(pthread_t t, bool from_mach_thread)
+__pthread_undo_add_thread(pthread_t t, mach_port_t self)
{
- if (from_mach_thread) {
- _PTHREAD_LOCK_FROM_MACH_THREAD(_pthread_list_lock);
- } else {
- _PTHREAD_LOCK(_pthread_list_lock);
- }
-
+ _pthread_lock_lock(&_pthread_list_lock, self);
TAILQ_REMOVE(&__pthread_head, t, tl_plist);
_pthread_count--;
-
- if (from_mach_thread) {
- _PTHREAD_UNLOCK_FROM_MACH_THREAD(_pthread_list_lock);
- } else {
- _PTHREAD_UNLOCK(_pthread_list_lock);
- }
+ _pthread_lock_unlock(&_pthread_list_lock, self);
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline void
__pthread_started_thread(pthread_t t)
{
- mach_port_t kport = _pthread_kernel_thread(t);
+ mach_port_t kport = _pthread_tsd_slot(t, MACH_THREAD_SELF);
if (os_unlikely(!MACH_PORT_VALID(kport))) {
PTHREAD_CLIENT_CRASH(kport,
"Unable to allocate thread port, possible port leak");
pthread_t t = NULL;
void *stack = NULL;
bool from_mach_thread = (create_flags & _PTHREAD_CREATE_FROM_MACH_THREAD);
+ mach_port_t self_kport;
+ int rc = 0;
if (attrs == NULL) {
attrs = &_pthread_attr_default;
__is_threaded = 1;
- t =_pthread_allocate(attrs, &stack, from_mach_thread);
+ t = _pthread_allocate(attrs, &stack, from_mach_thread);
if (t == NULL) {
return EAGAIN;
}
+ if (os_unlikely(from_mach_thread)) {
+ self_kport = mach_thread_self();
+ } else {
+ self_kport = _pthread_mach_thread_self_direct();
+ }
+
t->arg = arg;
t->fun = start_routine;
- __pthread_add_thread(t, from_mach_thread);
+ __pthread_add_thread(t, self_kport, from_mach_thread);
if (__bsdthread_create(start_routine, arg, stack, t, flags) ==
(pthread_t)-1) {
PTHREAD_CLIENT_CRASH(0,
"Unable to allocate thread port, possible port leak");
}
- __pthread_undo_add_thread(t, from_mach_thread);
+ __pthread_undo_add_thread(t, self_kport);
_pthread_deallocate(t, from_mach_thread);
- return EAGAIN;
+ t = NULL;
+ rc = EAGAIN;
+ }
+ if (from_mach_thread) {
+ mach_port_deallocate(mach_task_self(), self_kport);
}
// n.b. if a thread is created detached and exits, t will be invalid
*thread = t;
- return 0;
+ return rc;
}
int
return _pthread_create(thread, attr, start_routine, arg, flags);
}
-
-PTHREAD_NOEXPORT_VARIANT
int
pthread_detach(pthread_t thread)
{
wake = true;
}
}
- _PTHREAD_UNLOCK(_pthread_list_lock);
+ _pthread_lock_unlock(&_pthread_list_lock);
if (join) {
pthread_join(thread, NULL);
return res;
}
-PTHREAD_NOEXPORT_VARIANT
int
pthread_kill(pthread_t th, int sig)
{
return ret;
}
-PTHREAD_NOEXPORT_VARIANT
int
__pthread_workqueue_setkill(int enable)
{
}
}
-
-/* For compatibility... */
-
-pthread_t
-_pthread_self(void)
-{
- return pthread_self();
-}
-
/*
* Terminate a thread.
*/
-extern int __disable_threadsignal(int);
-PTHREAD_NORETURN
+OS_NORETURN
static void
_pthread_exit(pthread_t self, void *exit_value)
{
_pthread_exit(self, exit_value);
}
+int
+pthread_self_is_exiting_np(void)
+{
+ return (os_atomic_load(&pthread_self()->cancel_state, relaxed) &
+ _PTHREAD_CANCEL_EXITING) != 0;
+}
-PTHREAD_NOEXPORT_VARIANT
int
pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param)
{
if (policy) *policy = thread->tl_policy;
if (param) *param = thread->tl_param;
- _PTHREAD_UNLOCK(_pthread_list_lock);
+ _pthread_lock_unlock(&_pthread_list_lock);
return 0;
}
-
-
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline int
pthread_setschedparam_internal(pthread_t thread, mach_port_t kport, int policy,
const struct sched_param *param)
mach_msg_type_number_t count;
kern_return_t ret;
+ if (os_unlikely(thread->wqthread)) {
+ return ENOTSUP;
+ }
+
switch (policy) {
- case SCHED_OTHER:
- bases.ts.base_priority = param->sched_priority;
- base = (policy_base_t)&bases.ts;
- count = POLICY_TIMESHARE_BASE_COUNT;
- break;
- case SCHED_FIFO:
- bases.fifo.base_priority = param->sched_priority;
- base = (policy_base_t)&bases.fifo;
- count = POLICY_FIFO_BASE_COUNT;
- break;
- case SCHED_RR:
- bases.rr.base_priority = param->sched_priority;
- /* quantum isn't public yet */
- bases.rr.quantum = param->quantum;
- base = (policy_base_t)&bases.rr;
- count = POLICY_RR_BASE_COUNT;
- break;
- default:
- return EINVAL;
+ case SCHED_OTHER:
+ bases.ts.base_priority = param->sched_priority;
+ base = (policy_base_t)&bases.ts;
+ count = POLICY_TIMESHARE_BASE_COUNT;
+ break;
+ case SCHED_FIFO:
+ bases.fifo.base_priority = param->sched_priority;
+ base = (policy_base_t)&bases.fifo;
+ count = POLICY_FIFO_BASE_COUNT;
+ break;
+ case SCHED_RR:
+ bases.rr.base_priority = param->sched_priority;
+ /* quantum isn't public yet */
+ bases.rr.quantum = param->quantum;
+ base = (policy_base_t)&bases.rr;
+ count = POLICY_RR_BASE_COUNT;
+ break;
+ default:
+ return EINVAL;
}
ret = thread_policy(kport, policy, base, count, TRUE);
return (ret != KERN_SUCCESS) ? EINVAL : 0;
}
-PTHREAD_NOEXPORT_VARIANT
int
pthread_setschedparam(pthread_t t, int policy, const struct sched_param *param)
{
// since the main thread will not get de-allocated from underneath us
if (t == pthread_self() || t == main_thread()) {
_pthread_validate_signature(t);
- kport = _pthread_kernel_thread(t);
+ kport = _pthread_tsd_slot(t, MACH_THREAD_SELF);
} else {
bypass = 0;
if (!_pthread_is_valid(t, &kport)) {
if (res) return res;
if (bypass) {
- _PTHREAD_LOCK(_pthread_list_lock);
+ _pthread_lock_lock(&_pthread_list_lock);
} else if (!_pthread_validate_thread_and_list_lock(t)) {
// Ensure the thread is still valid.
return ESRCH;
t->tl_policy = policy;
t->tl_param = *param;
- _PTHREAD_UNLOCK(_pthread_list_lock);
+ _pthread_lock_unlock(&_pthread_list_lock);
return 0;
}
-
int
sched_get_priority_min(int policy)
{
return (t1 == t2);
}
-/*
- * Force LLVM not to optimise this to a call to __pthread_set_self, if it does
- * then _pthread_set_self won't be bound when secondary threads try and start up.
- */
-PTHREAD_NOINLINE
+OS_NOINLINE
void
_pthread_set_self(pthread_t p)
{
// _pthread_set_self_dyld is noinline+noexport to allow the option for
// static libsyscall to adopt this as the entry point from mach_init if
// desired
-PTHREAD_NOINLINE PTHREAD_NOEXPORT
-void
+OS_NOINLINE
+static void
_pthread_set_self_dyld(void)
{
pthread_t p = main_thread();
// this, TSD access will fail and crash if it uses bits of Libc prior to
// library initialization. __pthread_init will finish the initialization
// during library init.
- p->tsd[_PTHREAD_TSD_SLOT_PTHREAD_SELF] = p;
- p->tsd[_PTHREAD_TSD_SLOT_ERRNO] = &p->err_no;
+ _pthread_tsd_slot(p, PTHREAD_SELF) = p;
+ _pthread_tsd_slot(p, ERRNO) = &p->err_no;
_thread_set_tsd_base(&p->tsd[0]);
}
#endif // VARIANT_DYLD
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline void
_pthread_set_self_internal(pthread_t p)
{
+#if __LP64__
os_atomic_store(&p->thread_id, __thread_selfid(), relaxed);
+#else
+ os_atomic_store_wide(&p->thread_id, __thread_selfid(), relaxed);
+#endif
if (os_unlikely(p->thread_id == -1ull)) {
PTHREAD_INTERNAL_CRASH(0, "failed to set thread_id");
}
}
-
// <rdar://problem/28984807> pthread_once should have an acquire barrier
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline void
_os_once_acquire(os_once_t *predicate, void *context, os_function_t function)
{
ctx->pthread_once->sig = _PTHREAD_ONCE_SIG;
}
-PTHREAD_NOEXPORT_VARIANT
int
pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
{
return 0;
}
-
int
pthread_getconcurrency(void)
{
return 0;
}
-#if !defined(VARIANT_STATIC)
-void *
-malloc(size_t sz)
-{
- if (_pthread_malloc) {
- return _pthread_malloc(sz);
- } else {
- return NULL;
- }
-}
-
-void
-free(void *p)
-{
- if (_pthread_free) {
- _pthread_free(p);
- }
-}
-#endif // VARIANT_STATIC
-
/*
* Perform package initialization - called automatically when application starts
*/
-struct ProgramVars; /* forward reference */
#if !VARIANT_DYLD
static unsigned long
token = _pthread_strtoul(p, &s, 16);
bzero((char *)p, strlen(p));
}
+ /*
+ * In DEBUG we allow the environment variable to override the kernel
+ * security setting, including setting it to 0 which is helpful during
+ * debugging sessions.
+ *
+ * For other cases, the token must be set by the kernel or the environment
+ * variable to a non 0 value.
+ */
#if !DEBUG
if (!token) {
#endif
if (!token) {
PTHREAD_INTERNAL_CRASH(token, "Token from the kernel is 0");
}
-#endif // DEBUG
+#endif // !DEBUG
_pthread_ptr_munge_token = token;
// we need to refresh the main thread signature now that we changed
// libpthread.a in dyld "owns" the main thread structure itself and sets
// up the tsd to point to it. So take the pthread_self() from there
// and make it our main thread point.
- pthread_t thread = (pthread_t)_pthread_getspecific_direct(
- _PTHREAD_TSD_SLOT_PTHREAD_SELF);
+ pthread_t thread = _pthread_self_direct();
if (os_unlikely(thread == NULL)) {
PTHREAD_INTERNAL_CRASH(0, "PTHREAD_SELF TSD not initialized");
}
}
#endif // !VARIANT_DYLD
-PTHREAD_NOEXPORT void
+void
_pthread_main_thread_init(pthread_t p)
{
TAILQ_INIT(&__pthread_head);
- _PTHREAD_LOCK_INIT(_pthread_list_lock);
- _PTHREAD_LOCK_INIT(p->lock);
- _pthread_set_kernel_thread(p, mach_thread_self());
- _pthread_set_reply_port(p, mach_reply_port());
+ _pthread_lock_init(&_pthread_list_lock);
+ _pthread_lock_init(&p->lock);
p->__cleanup_stack = NULL;
p->tl_join_ctx = NULL;
p->tl_exit_gate = MACH_PORT_NULL;
- p->tsd[__TSD_SEMAPHORE_CACHE] = (void*)(uintptr_t)SEMAPHORE_NULL;
- p->tsd[__TSD_MACH_SPECIAL_REPLY] = 0;
+ _pthread_tsd_slot(p, MACH_THREAD_SELF) = mach_thread_self();
+ _pthread_tsd_slot(p, MIG_REPLY) = mach_reply_port();
+ _pthread_tsd_slot(p, MACH_SPECIAL_REPLY) = MACH_PORT_NULL;
+ _pthread_tsd_slot(p, SEMAPHORE_CACHE) = SEMAPHORE_NULL;
// Initialize the list of threads with the new main thread.
TAILQ_INSERT_HEAD(&__pthread_head, p, tl_plist);
_pthread_introspection_thread_start(p);
}
-PTHREAD_NOEXPORT
void
_pthread_main_thread_postfork_init(pthread_t p)
{
return 0;
}
-// XXX remove
-void
-cthread_yield(void)
-{
- sched_yield();
-}
-
-void
-pthread_yield_np(void)
-{
- sched_yield();
-}
-
// Libsystem knows about this symbol and exports it to libsyscall
int
pthread_current_stack_contains_np(const void *addr, size_t length)
return stack_base <= begin && end <= stack_top;
}
-
-
// Libsystem knows about this symbol and exports it to libsyscall
-PTHREAD_NOEXPORT_VARIANT
+
void
-_pthread_clear_qos_tsd(mach_port_t thread_port)
+_pthread_clear_qos_tsd(mach_port_t port)
{
- if (thread_port == MACH_PORT_NULL || (uintptr_t)_pthread_getspecific_direct(_PTHREAD_TSD_SLOT_MACH_THREAD_SELF) == thread_port) {
+ pthread_priority_t pp = _pthread_unspecified_priority();
+
+ if (port == MACH_PORT_NULL || _pthread_mach_thread_self_direct() == port) {
/* Clear the current thread's TSD, that can be done inline. */
- _pthread_setspecific_direct(_PTHREAD_TSD_SLOT_PTHREAD_QOS_CLASS,
- _pthread_unspecified_priority());
+ _pthread_setspecific_direct(_PTHREAD_TSD_SLOT_PTHREAD_QOS_CLASS, pp);
} else {
pthread_t p;
- _PTHREAD_LOCK(_pthread_list_lock);
+ _pthread_lock_lock(&_pthread_list_lock);
TAILQ_FOREACH(p, &__pthread_head, tl_plist) {
- mach_port_t kp = _pthread_kernel_thread(p);
- if (thread_port == kp) {
- p->tsd[_PTHREAD_TSD_SLOT_PTHREAD_QOS_CLASS] =
- _pthread_unspecified_priority();
+ mach_port_t kp = _pthread_tsd_slot(p, MACH_THREAD_SELF);
+ if (port == kp) {
+ _pthread_tsd_slot(p, PTHREAD_QOS_CLASS) = pp;
break;
}
}
- _PTHREAD_UNLOCK(_pthread_list_lock);
+ _pthread_lock_unlock(&_pthread_list_lock);
}
}
-
#pragma mark pthread/stack_np.h public interface
-
#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__arm64__)
#if __ARM64_ARCH_8_32__
/*
return (uintptr_t)frame->frame_addr_next;
}
-
#pragma mark pthread workqueue support routines
-
-PTHREAD_NOEXPORT void
+void
_pthread_bsdthread_init(struct _pthread_registration_data *data)
{
bzero(data, sizeof(*data));
data->version = sizeof(struct _pthread_registration_data);
data->dispatch_queue_offset = __PTK_LIBDISPATCH_KEY0 * sizeof(void *);
data->return_to_kernel_offset = __TSD_RETURN_TO_KERNEL * sizeof(void *);
- data->tsd_offset = offsetof(struct _pthread, tsd);
+ data->tsd_offset = offsetof(struct pthread_s, tsd);
data->mach_thread_self_offset = __TSD_MACH_THREAD_SELF * sizeof(void *);
+ data->joinable_offset_bits = CHAR_BIT * (offsetof(struct pthread_s, tl_policy) + 1);
int rv = __bsdthread_register(thread_start, start_wqthread, (int)PTHREAD_SIZE,
(void*)data, (uintptr_t)sizeof(*data), data->dispatch_queue_offset);
if (_pthread_priority_thread_qos(main_qos) != THREAD_QOS_UNSPECIFIED) {
_pthread_set_main_qos(main_qos);
- main_thread()->tsd[_PTHREAD_TSD_SLOT_PTHREAD_QOS_CLASS] = main_qos;
+ _pthread_tsd_slot(main_thread(), PTHREAD_QOS_CLASS) = main_qos;
}
if (data->stack_addr_hint) {
}
}
-PTHREAD_NOINLINE
+OS_NOINLINE
static void
_pthread_wqthread_legacy_worker_wrap(pthread_priority_t pp)
{
PTHREAD_INTERNAL_CRASH(pp, "Invalid pthread priority for the legacy interface");
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline pthread_priority_t
_pthread_wqthread_priority(int flags)
{
return pp;
}
-PTHREAD_NOINLINE
+OS_NOINLINE
static void
_pthread_wqthread_setup(pthread_t self, mach_port_t kport, void *stacklowaddr,
int flags)
PTHREAD_ALLOCADDR(stackaddr, stacksize),
PTHREAD_ALLOCSIZE(stackaddr, stacksize));
- _pthread_set_kernel_thread(self, kport);
+ _pthread_tsd_slot(self, MACH_THREAD_SELF) = kport;
self->wqthread = 1;
self->wqkillset = 0;
self->tl_joinable = false;
"thread_set_tsd_base() wasn't called by the kernel");
}
_pthread_set_self_internal(self);
- __pthread_add_thread(self, false);
+ __pthread_add_thread(self, kport, false);
__pthread_started_thread(self);
}
-PTHREAD_NORETURN PTHREAD_NOINLINE
+OS_NORETURN OS_NOINLINE
static void
_pthread_wqthread_exit(pthread_t self)
{
- pthread_priority_t pp;
+ const thread_qos_t WORKQ_THREAD_QOS_CLEANUP = THREAD_QOS_LEGACY;
+ pthread_priority_t pp = _pthread_tsd_slot(self, PTHREAD_QOS_CLASS);
thread_qos_t qos;
- pp = (pthread_priority_t)self->tsd[_PTHREAD_TSD_SLOT_PTHREAD_QOS_CLASS];
qos = _pthread_priority_thread_qos(pp);
if (qos == THREAD_QOS_UNSPECIFIED || qos > WORKQ_THREAD_QOS_CLEANUP) {
// Reset QoS to something low for the cleanup process
pp = _pthread_priority_make_from_thread_qos(WORKQ_THREAD_QOS_CLEANUP, 0, 0);
- self->tsd[_PTHREAD_TSD_SLOT_PTHREAD_QOS_CLASS] = (void *)pp;
+ _pthread_tsd_slot(self, PTHREAD_QOS_CLASS) = pp;
}
_pthread_exit(self, NULL);
*/
}
-
#pragma mark pthread workqueue API for libdispatch
-
_Static_assert(WORKQ_KEVENT_EVENT_BUFFER_LEN == WQ_KEVENT_LIST_LEN,
"Kernel and userland should agree on the event list size");
}
switch (cfg->version) {
- case 1:
- min_size = offsetof(struct pthread_workqueue_config, queue_label_offs);
- break;
- case 2:
- min_size = sizeof(struct pthread_workqueue_config);
- break;
- default:
- return EINVAL;
- }
+ case 1:
+ min_size = offsetof(struct pthread_workqueue_config, queue_label_offs);
+ break;
+ case 2:
+ min_size = sizeof(struct pthread_workqueue_config);
+ break;
+ default:
+ return EINVAL;
+ }
if (!cfg || cfg_size < min_size) {
return EINVAL;
return res;
}
-
#pragma mark Introspection SPI for libpthread.
-
static pthread_introspection_hook_t _pthread_introspection_hook;
pthread_introspection_hook_t
return prev;
}
-PTHREAD_NOINLINE
+static inline void
+_pthread_introspection_call_hook(unsigned int event,
+ pthread_t thread, void *addr, size_t size)
+{
+ pthread_t self = pthread_self();
+ uint16_t old = self->introspection;
+ self->introspection = (uint16_t)event;
+ _pthread_introspection_hook(event, thread, addr, size);
+ self->introspection = old;
+}
+
+OS_NOINLINE
static void
_pthread_introspection_hook_callout_thread_create(pthread_t t)
{
- _pthread_introspection_hook(PTHREAD_INTROSPECTION_THREAD_CREATE, t, t,
+ _pthread_introspection_call_hook(PTHREAD_INTROSPECTION_THREAD_CREATE, t, t,
PTHREAD_SIZE);
}
_pthread_introspection_hook_callout_thread_create(t);
}
-PTHREAD_NOINLINE
+OS_NOINLINE
static void
_pthread_introspection_hook_callout_thread_start(pthread_t t)
{
freesize = t->freesize - PTHREAD_SIZE;
freeaddr = t->freeaddr;
}
- _pthread_introspection_hook(PTHREAD_INTROSPECTION_THREAD_START, t,
+ _pthread_introspection_call_hook(PTHREAD_INTROSPECTION_THREAD_START, t,
freeaddr, freesize);
}
_pthread_introspection_hook_callout_thread_start(t);
}
-PTHREAD_NOINLINE
+OS_NOINLINE
static void
_pthread_introspection_hook_callout_thread_terminate(pthread_t t)
{
freesize = t->freesize - PTHREAD_SIZE;
freeaddr = t->freeaddr;
}
- _pthread_introspection_hook(PTHREAD_INTROSPECTION_THREAD_TERMINATE, t,
+ _pthread_introspection_call_hook(PTHREAD_INTROSPECTION_THREAD_TERMINATE, t,
freeaddr, freesize);
}
_pthread_introspection_hook_callout_thread_terminate(t);
}
-PTHREAD_NOINLINE
+OS_NOINLINE
static void
_pthread_introspection_hook_callout_thread_destroy(pthread_t t)
{
- _pthread_introspection_hook(PTHREAD_INTROSPECTION_THREAD_DESTROY, t, t,
+ _pthread_introspection_call_hook(PTHREAD_INTROSPECTION_THREAD_DESTROY, t, t,
PTHREAD_SIZE);
}
_pthread_introspection_hook_callout_thread_destroy(t);
}
-
-#if !VARIANT_DYLD
#pragma mark libplatform shims
+#if !VARIANT_DYLD
#include <platform/string.h>
* @APPLE_LICENSE_HEADER_END@
*/
-#include "offsets.h"
+#include "offsets_internal.h"
#if defined(__x86_64__)
#include <mach/mach_init.h>
#include <mach/mach_vm.h>
-#include <platform/compat.h>
+#if !VARIANT_DYLD
int
pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
{
size_t idx;
pthread_globals_t globals = _pthread_globals();
- _PTHREAD_LOCK(globals->pthread_atfork_lock);
+ _pthread_lock_lock(&globals->pthread_atfork_lock);
idx = globals->atfork_count++;
if (idx == 0) {
kern_return_t kr;
mach_vm_address_t storage = 0;
mach_vm_size_t size = PTHREAD_ATFORK_MAX * sizeof(struct pthread_atfork_entry);
- _PTHREAD_UNLOCK(globals->pthread_atfork_lock);
+ _pthread_lock_unlock(&globals->pthread_atfork_lock);
kr = mach_vm_map(mach_task_self(),
&storage,
size,
VM_PROT_DEFAULT,
VM_PROT_ALL,
VM_INHERIT_DEFAULT);
- _PTHREAD_LOCK(globals->pthread_atfork_lock);
+ _pthread_lock_lock(&globals->pthread_atfork_lock);
if (kr == KERN_SUCCESS) {
if (globals->atfork == globals->atfork_storage) {
globals->atfork = storage;
bzero(globals->atfork_storage, sizeof(globals->atfork_storage));
} else {
// Another thread did vm_map first.
- _PTHREAD_UNLOCK(globals->pthread_atfork_lock);
+ _pthread_lock_unlock(&globals->pthread_atfork_lock);
mach_vm_deallocate(mach_task_self(), storage, size);
- _PTHREAD_LOCK(globals->pthread_atfork_lock);
+ _pthread_lock_lock(&globals->pthread_atfork_lock);
}
} else {
res = ENOMEM;
e->parent = parent;
e->child = child;
}
- _PTHREAD_UNLOCK(globals->pthread_atfork_lock);
+ _pthread_lock_unlock(&globals->pthread_atfork_lock);
return res;
}
{
pthread_globals_t globals = _pthread_globals();
- _PTHREAD_LOCK(globals->pthread_atfork_lock);
+ _pthread_lock_lock(&globals->pthread_atfork_lock);
size_t idx;
for (idx = globals->atfork_count; idx > 0; --idx) {
struct pthread_atfork_entry *e = &globals->atfork[idx-1];
{
pthread_globals_t globals = _pthread_globals();
- _PTHREAD_LOCK(globals->psaved_self_global_lock);
+ _pthread_lock_lock(&globals->psaved_self_global_lock);
globals->psaved_self = pthread_self();
- _PTHREAD_LOCK(globals->psaved_self->lock);
+ _pthread_lock_lock(&globals->psaved_self->lock);
}
// Called after the fork(2) system call returns to the parent process.
{
pthread_globals_t globals = _pthread_globals();
- _PTHREAD_UNLOCK(globals->psaved_self->lock);
- _PTHREAD_UNLOCK(globals->psaved_self_global_lock);
+ _pthread_lock_unlock(&globals->psaved_self->lock);
+ _pthread_lock_unlock(&globals->psaved_self_global_lock);
}
// Iterate pthread_atfork parent handlers.
e->parent();
}
}
- _PTHREAD_UNLOCK(globals->pthread_atfork_lock);
+ _pthread_lock_unlock(&globals->pthread_atfork_lock);
}
// Called after the fork(2) system call returns to the new child process.
_pthread_atfork_child(void)
{
pthread_globals_t globals = _pthread_globals();
- _PTHREAD_LOCK_INIT(globals->psaved_self_global_lock);
+ _pthread_lock_init(&globals->psaved_self_global_lock);
__is_threaded = 0;
_pthread_main_thread_postfork_init(globals->psaved_self);
e->child();
}
}
- _PTHREAD_LOCK_INIT(globals->pthread_atfork_lock);
+ _pthread_lock_init(&globals->pthread_atfork_lock);
}
// Preserve legacy symbols for older iOS simulators
{
_pthread_atfork_child_handlers();
}
+#endif // !VARIANT_DYLD
#include <machine/vmparam.h>
#include <mach/vm_statistics.h>
-extern int _pthread_cond_wait(pthread_cond_t *cond,
- pthread_mutex_t *mutex,
- const struct timespec *abstime,
- int isRelative,
- int isconforming);
-extern int __sigwait(const sigset_t *set, int *sig);
-extern int __pthread_sigmask(int, const sigset_t *, sigset_t *);
-extern int __pthread_markcancel(mach_port_t);
-extern int __pthread_canceled(int);
-extern int __semwait_signal_nocancel(int, int, int, int, __int64_t, __int32_t);
-
-
-PTHREAD_NOEXPORT
-int _pthread_join(pthread_t thread, void **value_ptr, int conforming);
-
-static inline int
-_pthread_conformance(void)
-{
-#if __DARWIN_UNIX03
- if (__unix_conforming == 0)
- __unix_conforming = 1;
-#ifdef VARIANT_CANCELABLE
- return PTHREAD_CONFORM_UNIX03_CANCELABLE;
-#else /* !VARIANT_CANCELABLE */
- return PTHREAD_CONFORM_UNIX03_NOCANCEL;
-#endif
-#else /* __DARWIN_UNIX03 */
- return PTHREAD_CONFORM_DARWIN_LEGACY;
-#endif /* __DARWIN_UNIX03 */
-}
-
-#ifndef VARIANT_CANCELABLE
+#ifndef BUILDING_VARIANT /* [ */
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline int
_pthread_update_cancel_state(pthread_t thread, int mask, int state)
{
- int oldstate, newstate;
- os_atomic_rmw_loop2o(thread, cancel_state, oldstate, newstate, seq_cst, {
+ uint16_t oldstate, newstate;
+ os_atomic_rmw_loop(&thread->cancel_state, oldstate, newstate, relaxed, {
newstate = oldstate;
newstate &= ~mask;
newstate |= state;
return oldstate;
}
+/* When a thread exits set the cancellation state to DISABLE and DEFERRED */
+void
+_pthread_setcancelstate_exit(pthread_t thread, void *value_ptr)
+{
+ _pthread_update_cancel_state(thread,
+ _PTHREAD_CANCEL_STATE_MASK | _PTHREAD_CANCEL_TYPE_MASK,
+ PTHREAD_CANCEL_DISABLE | PTHREAD_CANCEL_DEFERRED |
+ _PTHREAD_CANCEL_EXITING);
+}
+
/*
* Cancel a thread
*/
int
pthread_cancel(pthread_t thread)
{
-#if __DARWIN_UNIX03
- if (__unix_conforming == 0)
- __unix_conforming = 1;
-#endif /* __DARWIN_UNIX03 */
-
if (!_pthread_is_valid(thread, NULL)) {
return(ESRCH);
}
if (thread->wqthread != 0) {
return(ENOTSUP);
}
-#if __DARWIN_UNIX03
- int state = os_atomic_or2o(thread, cancel_state, _PTHREAD_CANCEL_PENDING, relaxed);
+ int state = os_atomic_or(&thread->cancel_state, _PTHREAD_CANCEL_PENDING, relaxed);
if (state & PTHREAD_CANCEL_ENABLE) {
- mach_port_t kport = _pthread_kernel_thread(thread);
+ mach_port_t kport = _pthread_tsd_slot(thread, MACH_THREAD_SELF);
if (kport) __pthread_markcancel(kport);
}
-#else /* __DARWIN_UNIX03 */
- thread->cancel_state |= _PTHREAD_CANCEL_PENDING;
-#endif /* __DARWIN_UNIX03 */
return (0);
}
-
-void
-pthread_testcancel(void)
-{
- _pthread_testcancel(_pthread_conformance());
-}
-
-#ifndef BUILDING_VARIANT /* [ */
-
-PTHREAD_NOEXPORT_VARIANT
-void
-_pthread_exit_if_canceled(int error)
-{
- if (((error & 0xff) == EINTR) && __unix_conforming && (__pthread_canceled(0) == 0)) {
- pthread_t self = pthread_self();
-
- _pthread_validate_signature(self);
- self->cancel_error = error;
- self->canceled = true;
- pthread_exit(PTHREAD_CANCELED);
- }
-}
-
-
-static inline bool
-_pthread_is_canceled(pthread_t thread)
-{
- const int flags = (PTHREAD_CANCEL_ENABLE|_PTHREAD_CANCEL_PENDING);
- int state = os_atomic_load2o(thread, cancel_state, seq_cst);
- return (state & flags) == flags;
-}
-
-PTHREAD_NOEXPORT_VARIANT
-void
-_pthread_testcancel(int isconforming)
-{
- pthread_t self = pthread_self();
- if (_pthread_is_canceled(self)) {
- _pthread_validate_signature(self);
- // 4597450: begin
- self->canceled = (isconforming != PTHREAD_CONFORM_DARWIN_LEGACY);
- // 4597450: end
- pthread_exit(isconforming ? PTHREAD_CANCELED : NULL);
- }
-}
-
-PTHREAD_NOEXPORT
-void
-_pthread_markcancel_if_canceled(pthread_t thread, mach_port_t kport)
-{
- const int flags = (PTHREAD_CANCEL_ENABLE|_PTHREAD_CANCEL_PENDING);
- int state = os_atomic_load2o(thread, cancel_state, relaxed);
- if ((state & flags) == flags && __unix_conforming) {
- __pthread_markcancel(kport);
- }
-}
-
-/* When a thread exits set the cancellation state to DISABLE and DEFERRED */
-PTHREAD_NOEXPORT
-void
-_pthread_setcancelstate_exit(pthread_t thread, void *value_ptr)
-{
- _pthread_update_cancel_state(thread,
- _PTHREAD_CANCEL_STATE_MASK | _PTHREAD_CANCEL_TYPE_MASK,
- PTHREAD_CANCEL_DISABLE | PTHREAD_CANCEL_DEFERRED);
-}
-
-#endif /* !BUILDING_VARIANT ] */
-
/*
* Query/update the cancelability 'state' of a thread
*/
-PTHREAD_ALWAYS_INLINE
-static inline int
-_pthread_setcancelstate_internal(int state, int *oldstateptr, int conforming)
+PTHREAD_NOEXPORT_VARIANT
+int
+pthread_setcancelstate(int state, int *oldstateptr)
{
pthread_t self = pthread_self();
switch (state) {
case PTHREAD_CANCEL_ENABLE:
- if (conforming) {
- __pthread_canceled(1);
- }
+ __pthread_canceled(1);
break;
case PTHREAD_CANCEL_DISABLE:
- if (conforming) {
- __pthread_canceled(2);
- }
+ __pthread_canceled(2);
break;
default:
return EINVAL;
if (oldstateptr) {
*oldstateptr = oldstate & _PTHREAD_CANCEL_STATE_MASK;
}
- if (!conforming) {
- /* See if we need to 'die' now... */
- _pthread_testcancel(PTHREAD_CONFORM_DARWIN_LEGACY);
- }
return 0;
}
-PTHREAD_NOEXPORT_VARIANT
-int
-pthread_setcancelstate(int state, int *oldstate)
-{
-#if __DARWIN_UNIX03
- if (__unix_conforming == 0) {
- __unix_conforming = 1;
- }
- return (_pthread_setcancelstate_internal(state, oldstate, 1));
-#else /* __DARWIN_UNIX03 */
- return (_pthread_setcancelstate_internal(state, oldstate, 0));
-#endif /* __DARWIN_UNIX03 */
-}
-
/*
* Query/update the cancelability 'type' of a thread
*/
int
pthread_setcanceltype(int type, int *oldtype)
{
- pthread_t self;
+ pthread_t self = pthread_self();
-#if __DARWIN_UNIX03
- if (__unix_conforming == 0)
- __unix_conforming = 1;
-#endif /* __DARWIN_UNIX03 */
+ _pthread_validate_signature(self);
if ((type != PTHREAD_CANCEL_DEFERRED) &&
(type != PTHREAD_CANCEL_ASYNCHRONOUS))
return EINVAL;
- self = pthread_self();
- _pthread_validate_signature(self);
int oldstate = _pthread_update_cancel_state(self, _PTHREAD_CANCEL_TYPE_MASK, type);
if (oldtype) {
*oldtype = oldstate & _PTHREAD_CANCEL_TYPE_MASK;
}
-#if !__DARWIN_UNIX03
- /* See if we need to 'die' now... */
- _pthread_testcancel(PTHREAD_CONFORM_DARWIN_LEGACY);
-#endif /* __DARWIN_UNIX03 */
return (0);
}
-int
-pthread_sigmask(int how, const sigset_t * set, sigset_t * oset)
+OS_ALWAYS_INLINE
+static inline bool
+_pthread_is_canceled(pthread_t thread)
{
-#if __DARWIN_UNIX03
- int err = 0;
-
- if (__pthread_sigmask(how, set, oset) == -1) {
- err = errno;
- }
- return(err);
-#else /* __DARWIN_UNIX03 */
- return(__pthread_sigmask(how, set, oset));
-#endif /* __DARWIN_UNIX03 */
+ const int flags = (PTHREAD_CANCEL_ENABLE|_PTHREAD_CANCEL_PENDING);
+ int state = os_atomic_load(&thread->cancel_state, seq_cst);
+ return (state & flags) == flags;
}
-#ifndef BUILDING_VARIANT /* [ */
-
-typedef struct pthread_join_context_s {
- pthread_t waiter;
- void **value_ptr;
- mach_port_t kport;
- semaphore_t custom_stack_sema;
- bool detached;
-} pthread_join_context_s, *pthread_join_context_t;
-
+OS_ALWAYS_INLINE
static inline void *
_pthread_get_exit_value(pthread_t thread)
{
- if (__unix_conforming && _pthread_is_canceled(thread)) {
+ if (os_unlikely(_pthread_is_canceled(thread))) {
return PTHREAD_CANCELED;
}
return thread->tl_exit_value;
}
+void
+pthread_testcancel(void)
+{
+ pthread_t self = pthread_self();
+ if (os_unlikely(_pthread_is_canceled(self))) {
+ _pthread_validate_signature(self);
+ // 4597450: begin
+ self->canceled = true;
+ // 4597450: end
+ pthread_exit(PTHREAD_CANCELED);
+ }
+}
+
+void
+_pthread_markcancel_if_canceled(pthread_t thread, mach_port_t kport)
+{
+ if (os_unlikely(_pthread_is_canceled(thread))) {
+ __pthread_markcancel(kport);
+ }
+}
+
+void
+_pthread_exit_if_canceled(int error)
+{
+ if ((error & 0xff) == EINTR && __pthread_canceled(0) == 0) {
+ pthread_t self = pthread_self();
+
+ _pthread_validate_signature(self);
+ self->cancel_error = error;
+ self->canceled = true;
+ pthread_exit(PTHREAD_CANCELED);
+ }
+}
+
+int
+pthread_sigmask(int how, const sigset_t * set, sigset_t * oset)
+{
+ int err = 0;
+
+ if (__pthread_sigmask(how, set, oset) == -1) {
+ err = errno;
+ }
+ return(err);
+}
+
// called with _pthread_list_lock held
-PTHREAD_NOEXPORT
semaphore_t
_pthread_joiner_prepost_wake(pthread_t thread)
{
{
bool aborted = false;
- _PTHREAD_LOCK(_pthread_list_lock);
+ _pthread_lock_lock(&_pthread_list_lock);
if (!ctx->detached && thread->tl_exit_gate != MACH_PORT_DEAD) {
/*
* _pthread_joiner_prepost_wake() didn't happen
thread->tl_exit_gate = MACH_PORT_NULL;
aborted = true;
}
- _PTHREAD_UNLOCK(_pthread_list_lock);
+ _pthread_lock_unlock(&_pthread_list_lock);
return aborted;
}
static int
-_pthread_joiner_wait(pthread_t thread, pthread_join_context_t ctx, int conforming)
+_pthread_joiner_wait(pthread_t thread, pthread_join_context_t ctx,
+ pthread_conformance_t conforming)
{
uint32_t *exit_gate = &thread->tl_exit_gate;
int ulock_op = UL_UNFAIR_LOCK | ULF_NO_ERRNO;
* over the cancelation which will be acted upon at the next
* cancelation point.
*/
- if (conforming == PTHREAD_CONFORM_UNIX03_CANCELABLE &&
- _pthread_is_canceled(ctx->waiter)) {
+ if (os_unlikely(conforming == PTHREAD_CONFORM_UNIX03_CANCELABLE &&
+ _pthread_is_canceled(ctx->waiter))) {
if (_pthread_joiner_abort_wait(thread, ctx)) {
ctx->waiter->canceled = true;
pthread_exit(PTHREAD_CANCELED);
bool cleanup = false;
- _PTHREAD_LOCK(_pthread_list_lock);
+ _pthread_lock_lock(&_pthread_list_lock);
// If pthread_detach() was called, we can't safely dereference the thread,
// else, decide who gets to deallocate the thread (see _pthread_terminate).
if (!ctx->detached) {
thread->tl_join_ctx = NULL;
cleanup = thread->tl_joiner_cleans_up;
}
- _PTHREAD_UNLOCK(_pthread_list_lock);
+ _pthread_lock_unlock(&_pthread_list_lock);
if (cleanup) {
_pthread_deallocate(thread, false);
return 0;
}
-PTHREAD_NOEXPORT PTHREAD_NOINLINE
+OS_NOINLINE
int
-_pthread_join(pthread_t thread, void **value_ptr, int conforming)
+_pthread_join(pthread_t thread, void **value_ptr, pthread_conformance_t conforming)
{
pthread_t self = pthread_self();
pthread_join_context_s ctx = {
if (!_pthread_validate_thread_and_list_lock(thread)) {
return ESRCH;
}
+
_pthread_validate_signature(self);
if (!thread->tl_joinable || (thread->tl_join_ctx != NULL)) {
thread->tl_joinable = false;
if (value_ptr) *value_ptr = _pthread_get_exit_value(thread);
} else {
- ctx.kport = _pthread_kernel_thread(thread);
+ ctx.kport = _pthread_tsd_slot(thread, MACH_THREAD_SELF);
thread->tl_exit_gate = ctx.kport;
thread->tl_join_ctx = &ctx;
if (thread->tl_has_custom_stack) {
ctx.custom_stack_sema = (semaphore_t)os_get_cached_semaphore();
}
}
- _PTHREAD_UNLOCK(_pthread_list_lock);
+ _pthread_lock_unlock(&_pthread_list_lock);
if (res == 0) {
if (ctx.kport == MACH_PORT_NULL) {
}
#endif /* !BUILDING_VARIANT ] */
-#endif /* VARIANT_CANCELABLE */
-/*
- * Wait for a thread to terminate and obtain its exit value.
- */
+static inline pthread_conformance_t
+_pthread_conformance(void)
+{
+#ifdef VARIANT_CANCELABLE
+ return PTHREAD_CONFORM_UNIX03_CANCELABLE;
+#else /* !VARIANT_CANCELABLE */
+ return PTHREAD_CONFORM_UNIX03_NOCANCEL;
+#endif
+}
+
+static inline void
+_pthread_testcancel_if_cancelable_variant(void)
+{
+#ifdef VARIANT_CANCELABLE
+ pthread_testcancel();
+#endif
+}
+
int
pthread_join(pthread_t thread, void **value_ptr)
{
- int conforming = _pthread_conformance();
- if (conforming == PTHREAD_CONFORM_UNIX03_CANCELABLE) {
- _pthread_testcancel(conforming);
- }
- return _pthread_join(thread, value_ptr, conforming);
+ _pthread_testcancel_if_cancelable_variant();
+ return _pthread_join(thread, value_ptr, _pthread_conformance());
}
int
int
sigwait(const sigset_t * set, int * sig)
{
-#if __DARWIN_UNIX03
- int err = 0, conformance = _pthread_conformance();
+ int err = 0;
- if (__unix_conforming == 0)
- __unix_conforming = 1;
-
- if (conformance == PTHREAD_CONFORM_UNIX03_CANCELABLE) {
- _pthread_testcancel(conformance);
- }
+ _pthread_testcancel_if_cancelable_variant();
if (__sigwait(set, sig) == -1) {
err = errno;
- if (conformance == PTHREAD_CONFORM_UNIX03_CANCELABLE) {
- _pthread_testcancel(conformance);
- }
+ _pthread_testcancel_if_cancelable_variant();
/*
* EINTR that isn't a result of pthread_cancel()
}
}
return(err);
-#else /* __DARWIN_UNIX03 */
- if (__sigwait(set, sig) == -1) {
- /*
- * EINTR that isn't a result of pthread_cancel()
- * is translated to 0.
- */
- if (errno != EINTR) {
- return -1;
- }
- }
-
- return 0;
-#endif /* __DARWIN_UNIX03 */
}
#define PLOCKSTAT_MUTEX_RELEASE(x, y)
#endif /* PLOCKSTAT */
-extern int __gettimeofday(struct timeval *, struct timezone *);
-
-PTHREAD_NOEXPORT
-int _pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex,
- const struct timespec *abstime, int isRelative, int isconforming);
-
-PTHREAD_ALWAYS_INLINE
+typedef union {
+ uint64_t val;
+ struct {
+ uint32_t seq;
+ uint16_t waiters;
+ uint16_t signal;
+ };
+} pthread_ulock_cond_state_u;
+
+#define _PTHREAD_COND_WAITERS_INC \
+ (1ull << (offsetof(pthread_ulock_cond_state_u, waiters) * CHAR_BIT))
+
+OS_ALWAYS_INLINE
static inline void
-COND_GETSEQ_ADDR(_pthread_cond *cond,
+COND_GETSEQ_ADDR(pthread_cond_t *cond,
volatile uint64_t **c_lsseqaddr,
volatile uint32_t **c_lseqcnt,
volatile uint32_t **c_useqcnt,
*c_lsseqaddr = (volatile uint64_t *)*c_lseqcnt;
}
+OS_ALWAYS_INLINE
+static inline pthread_ulock_cond_state_u *
+_pthread_ulock_cond_state(pthread_cond_t *cond)
+{
+ return (pthread_ulock_cond_state_u *)&cond->c_seq[cond->misalign];
+}
+
#ifndef BUILDING_VARIANT /* [ */
-static void _pthread_cond_cleanup(void *arg);
-static void _pthread_cond_updateval(_pthread_cond *cond, _pthread_mutex *mutex,
+static void _pthread_psynch_cond_cleanup(void *arg);
+static void _pthread_cond_updateval(pthread_cond_t *cond, pthread_mutex_t *mutex,
int error, uint32_t updateval);
+static int
+_pthread_ulock_cond_wait_complete(pthread_ulock_cond_state_u *state,
+ pthread_mutex_t *mutex, int rc);
+static void
+_pthread_ulock_cond_cleanup(void *arg);
+
int
pthread_condattr_init(pthread_condattr_t *attr)
{
int res = EINVAL;
if (attr->sig == _PTHREAD_COND_ATTR_SIG) {
-#if __DARWIN_UNIX03
- if (pshared == PTHREAD_PROCESS_PRIVATE || pshared == PTHREAD_PROCESS_SHARED)
-#else /* __DARWIN_UNIX03 */
- if (pshared == PTHREAD_PROCESS_PRIVATE)
-#endif /* __DARWIN_UNIX03 */
- {
+ if (pshared == PTHREAD_PROCESS_PRIVATE || pshared == PTHREAD_PROCESS_SHARED) {
attr->pshared = pshared;
res = 0;
}
pthread_cond_timedwait_relative_np(pthread_cond_t *cond, pthread_mutex_t *mutex,
const struct timespec *abstime)
{
- return _pthread_cond_wait(cond, mutex, abstime, 1, 0);
+ return _pthread_cond_wait(cond, mutex, abstime, 1,
+ PTHREAD_CONFORM_UNIX03_NOCANCEL);
}
#endif /* !BUILDING_VARIANT ] */
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline int
-_pthread_cond_init(_pthread_cond *cond, const pthread_condattr_t *attr, int conforming)
+_pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr,
+ uint32_t sig)
{
volatile uint64_t *c_lsseqaddr;
volatile uint32_t *c_lseqcnt, *c_useqcnt, *c_sseqcnt;
cond->c_seq[2] = 0;
cond->unused = 0;
+ // TODO: PTHREAD_STRICT candidate
cond->misalign = (((uintptr_t)&cond->c_seq[0]) & 0x7) != 0;
COND_GETSEQ_ADDR(cond, &c_lsseqaddr, &c_lseqcnt, &c_useqcnt, &c_sseqcnt);
*c_sseqcnt = PTH_RWS_CV_CBIT; // set Sword to 0c
- if (conforming) {
- if (attr) {
- cond->pshared = attr->pshared;
- } else {
- cond->pshared = _PTHREAD_DEFAULT_PSHARED;
- }
+ if (attr) {
+ cond->pshared = attr->pshared;
} else {
cond->pshared = _PTHREAD_DEFAULT_PSHARED;
}
- long sig = _PTHREAD_COND_SIG;
-
// Ensure all contents are properly set before setting signature.
#if defined(__LP64__)
// For binary compatibility reasons we cannot require natural alignment of
// the 64bit 'sig' long value in the struct. rdar://problem/21610439
- uint32_t *sig32_ptr = (uint32_t*)&cond->sig;
- uint32_t *sig32_val = (uint32_t*)&sig;
- *(sig32_ptr + 1) = *(sig32_val + 1);
- os_atomic_store(sig32_ptr, *sig32_val, release);
-#else
- os_atomic_store2o(cond, sig, sig, release);
+ cond->sig._pad = 0;
#endif
+ os_atomic_store(&cond->sig.val, sig, release);
return 0;
}
#ifndef BUILDING_VARIANT /* [ */
-PTHREAD_NOINLINE
+OS_ALWAYS_INLINE
static int
-_pthread_cond_check_init_slow(_pthread_cond *cond, bool *inited)
+_pthread_cond_check_signature(pthread_cond_t *cond, uint32_t sig_current,
+ uint32_t *sig_inout)
{
- int res = EINVAL;
- if (cond->sig == _PTHREAD_COND_SIG_init) {
- _PTHREAD_LOCK(cond->lock);
- if (cond->sig == _PTHREAD_COND_SIG_init) {
- res = _pthread_cond_init(cond, NULL, 0);
- if (inited) {
- *inited = true;
- }
- } else if (cond->sig == _PTHREAD_COND_SIG) {
- res = 0;
+ int res = 0;
+ switch (sig_current) {
+ case _PTHREAD_COND_SIG_init:
+ __builtin_unreachable();
+ break;
+ case _PTHREAD_COND_SIG_pristine:
+ if (*sig_inout != _PTHREAD_COND_SIG_pristine) {
+ os_atomic_store(&cond->sig.val, *sig_inout, relaxed);
}
- _PTHREAD_UNLOCK(cond->lock);
- } else if (cond->sig == _PTHREAD_COND_SIG) {
- res = 0;
+ break;
+ case _PTHREAD_COND_SIG_psynch:
+ case _PTHREAD_COND_SIG_ulock:
+ if (*sig_inout == _PTHREAD_COND_SIG_pristine) {
+ *sig_inout = sig_current;
+ } else if (*sig_inout != sig_current) {
+ PTHREAD_INTERNAL_CRASH(0, "Mixed ulock and psych condvar use");
+ }
+ break;
+ default:
+ // TODO: PTHREAD_STRICT candidate
+ res = EINVAL;
+ break;
}
+
return res;
}
-PTHREAD_ALWAYS_INLINE
-static inline int
-_pthread_cond_check_init(_pthread_cond *cond, bool *inited)
+OS_NOINLINE
+static int
+_pthread_cond_check_init_slow(pthread_cond_t *cond, uint32_t *sig_inout)
{
- int res = 0;
- if (cond->sig != _PTHREAD_COND_SIG) {
- return _pthread_cond_check_init_slow(cond, inited);
+ int res;
+ _pthread_lock_lock(&cond->lock);
+
+ uint32_t sig_current = os_atomic_load(&cond->sig.val, relaxed);
+ if (sig_current == _PTHREAD_COND_SIG_init) {
+ res = _pthread_cond_init(cond, NULL, *sig_inout);
+ } else {
+ res = _pthread_cond_check_signature(cond, sig_current, sig_inout);
}
+
+ _pthread_lock_unlock(&cond->lock);
return res;
}
+/*
+ * These routines maintain the signature of the condition variable, which
+ * encodes a small state machine:
+ * - a statically initialized condvar begins with SIG_init
+ * - explicit initialization via _cond_init() and implicit initialization
+ * transition to SIG_pristine, as there have been no waiters so we don't know
+ * what kind of mutex we'll be used with
+ * - the first _cond_wait() transitions to one of SIG_psynch or SIG_ulock
+ * according to the mutex being waited on
+ *
+ * On entry, *sig_inout is the furthest state we can transition to given the
+ * calling context. On exit, it is the actual state we observed, after any
+ * possible advancement.
+ */
+OS_ALWAYS_INLINE
+static inline int
+_pthread_cond_check_init(pthread_cond_t *cond, uint32_t *sig_inout)
+{
+ uint32_t sig_current = os_atomic_load(&cond->sig.val, relaxed);
+ if (sig_current == _PTHREAD_COND_SIG_init) {
+ return _pthread_cond_check_init_slow(cond, sig_inout);
+ } else {
+ return _pthread_cond_check_signature(cond, sig_current, sig_inout);
+ }
+}
+
PTHREAD_NOEXPORT_VARIANT
int
-pthread_cond_destroy(pthread_cond_t *ocond)
+pthread_cond_destroy(pthread_cond_t *cond)
{
- _pthread_cond *cond = (_pthread_cond *)ocond;
int res = EINVAL;
- if (cond->sig == _PTHREAD_COND_SIG) {
- _PTHREAD_LOCK(cond->lock);
+ uint32_t sig = os_atomic_load(&cond->sig.val, relaxed);
+ switch (sig) {
+ case _PTHREAD_COND_SIG_psynch:
+ _pthread_lock_lock(&cond->lock);
uint64_t oldval64, newval64;
uint32_t lcntval, ucntval, scntval;
flags |= _PTHREAD_MTX_OPT_PSHARED;
}
- cond->sig = _PTHREAD_NO_SIG;
+ os_atomic_store(&cond->sig.val, _PTHREAD_NO_SIG, relaxed);
res = 0;
- _PTHREAD_UNLOCK(cond->lock);
+ _pthread_lock_unlock(&cond->lock);
if (needclearpre) {
(void)__psynch_cvclrprepost(cond, lcntval, ucntval, scntval, 0, lcntval, flags);
}
- } else if (cond->sig == _PTHREAD_COND_SIG_init) {
+ break;
+ case _PTHREAD_COND_SIG_init:
// Compatibility for misbehaving applications that attempt to
// destroy a statically initialized condition variable.
- cond->sig = _PTHREAD_NO_SIG;
+ //
+ // fall through
+ case _PTHREAD_COND_SIG_pristine:
+ case _PTHREAD_COND_SIG_ulock:
+ os_atomic_store(&cond->sig.val, _PTHREAD_NO_SIG, relaxed);
res = 0;
+ break;
+ default:
+ // TODO: PTHREAD_STRICT candidate
+ break;
}
return res;
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline int
-_pthread_cond_signal(pthread_cond_t *ocond, bool broadcast, mach_port_t thread)
+_pthread_psynch_cond_signal(pthread_cond_t *cond, bool broadcast,
+ mach_port_t thread)
{
- int res;
- _pthread_cond *cond = (_pthread_cond *)ocond;
-
uint32_t updateval;
uint32_t diffgen;
uint32_t ulval;
int retry_count = 0, uretry_count = 0;
int ucountreset = 0;
- bool inited = false;
- res = _pthread_cond_check_init(cond, &inited);
- if (res != 0 || inited == true) {
- return res;
- }
-
COND_GETSEQ_ADDR(cond, &c_lsseqaddr, &c_lseqcnt, &c_useqcnt, &c_sseqcnt);
bool retry;
if (broadcast) {
// pass old U val so kernel will know the diffgen
uint64_t cvudgen = ((uint64_t)ucntval << 32) | diffgen;
- updateval = __psynch_cvbroad(ocond, cvlsgen, cvudgen, flags, NULL, 0, 0);
+ updateval = __psynch_cvbroad(cond, cvlsgen, cvudgen, flags, NULL, 0, 0);
} else {
- updateval = __psynch_cvsignal(ocond, cvlsgen, ucntval, thread, NULL, 0, 0, flags);
+ updateval = __psynch_cvsignal(cond, cvlsgen, ucntval, thread, NULL, 0, 0, flags);
}
if (updateval != (uint32_t)-1 && updateval != 0) {
return 0;
}
+OS_ALWAYS_INLINE
+static inline int
+_pthread_ulock_cond_signal(pthread_cond_t *cond, bool broadcast,
+ mach_port_t thread)
+{
+ pthread_ulock_cond_state_u *state = _pthread_ulock_cond_state(cond);
+
+ pthread_ulock_cond_state_u oldstate, newstate;
+ // release to pair with acquire after wait
+ os_atomic_rmw_loop(&state->val, oldstate.val, newstate.val, release, {
+ if (!oldstate.waiters || oldstate.waiters == oldstate.signal) {
+ os_atomic_rmw_loop_give_up(return 0);
+ }
+
+ newstate = (pthread_ulock_cond_state_u){
+ .seq = oldstate.seq + 1,
+ .waiters = oldstate.waiters,
+ .signal = broadcast ? oldstate.waiters :
+ MIN(oldstate.signal + 1, oldstate.waiters),
+ };
+ });
+
+ PTHREAD_TRACE(ulcond_signal, cond, oldstate.val, newstate.val, broadcast);
+
+ // Priority hole: if we're pre-empted here, nobody else can signal the
+ // waiter we took responsibility for signaling by incrementing the signal
+ // count.
+
+ if (oldstate.signal < oldstate.waiters) {
+ uint32_t wake_op = UL_COMPARE_AND_WAIT | ULF_NO_ERRNO;
+ if (broadcast) {
+ wake_op |= ULF_WAKE_ALL;
+ } else if (thread) {
+ wake_op |= ULF_WAKE_THREAD;
+ }
+
+ for (;;) {
+ int rc = __ulock_wake(wake_op, &state->seq, thread);
+ if (rc < 0) {
+ switch (-rc) {
+ case EINTR:
+ continue;
+ case ENOENT:
+ break;
+ case EALREADY:
+ if (!thread) {
+ PTHREAD_INTERNAL_CRASH(0, "EALREADY from ulock_wake");
+ }
+ // Compatibility with psynch: promote to broadcast
+ return pthread_cond_broadcast(cond);
+ default:
+ PTHREAD_INTERNAL_CRASH(-rc, "ulock_wake failure");
+ }
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+OS_ALWAYS_INLINE
+static inline int
+_pthread_cond_signal(pthread_cond_t *cond, bool broadcast, mach_port_t thread)
+{
+ uint32_t sig = _PTHREAD_COND_SIG_pristine;
+ int res = _pthread_cond_check_init(cond, &sig);
+ if (res != 0 || sig == _PTHREAD_COND_SIG_pristine) {
+ return res;
+ }
+
+ switch (sig) {
+ case _PTHREAD_COND_SIG_psynch:
+ return _pthread_psynch_cond_signal(cond, broadcast, thread);
+ case _PTHREAD_COND_SIG_ulock:
+ return _pthread_ulock_cond_signal(cond, broadcast, thread);
+ default:
+ PTHREAD_INTERNAL_CRASH(sig, "impossible cond signature");
+ }
+}
+
/*
* Signal a condition variable, waking up all threads waiting for it.
*/
PTHREAD_NOEXPORT_VARIANT
int
-pthread_cond_broadcast(pthread_cond_t *ocond)
+pthread_cond_broadcast(pthread_cond_t *cond)
{
- return _pthread_cond_signal(ocond, true, MACH_PORT_NULL);
+ return _pthread_cond_signal(cond, true, MACH_PORT_NULL);
}
/*
*/
PTHREAD_NOEXPORT_VARIANT
int
-pthread_cond_signal_thread_np(pthread_cond_t *ocond, pthread_t thread)
+pthread_cond_signal_thread_np(pthread_cond_t *cond, pthread_t thread)
{
mach_port_t mp = MACH_PORT_NULL;
if (thread) {
mp = pthread_mach_thread_np((_Nonnull pthread_t)thread);
}
- return _pthread_cond_signal(ocond, false, mp);
+ return _pthread_cond_signal(cond, false, mp);
}
/*
*/
PTHREAD_NOEXPORT_VARIANT
int
-pthread_cond_signal(pthread_cond_t *ocond)
+pthread_cond_signal(pthread_cond_t *cond)
{
- return _pthread_cond_signal(ocond, false, MACH_PORT_NULL);
+ return _pthread_cond_signal(cond, false, MACH_PORT_NULL);
}
-/*
- * Manage a list of condition variables associated with a mutex
- */
-
-/*
- * Suspend waiting for a condition variable.
- * Note: we have to keep a list of condition variables which are using
- * this same mutex variable so we can detect invalid 'destroy' sequences.
- * If conformance is not cancelable, we skip the _pthread_testcancel(),
- * but keep the remaining conforming behavior..
- */
-PTHREAD_NOEXPORT PTHREAD_NOINLINE
-int
-_pthread_cond_wait(pthread_cond_t *ocond,
- pthread_mutex_t *omutex,
- const struct timespec *abstime,
- int isRelative,
- int conforming)
+static int
+_pthread_psynch_cond_wait(pthread_cond_t *cond,
+ pthread_mutex_t *mutex,
+ const struct timespec *then,
+ pthread_conformance_t conforming)
{
- int res;
- _pthread_cond *cond = (_pthread_cond *)ocond;
- _pthread_mutex *mutex = (_pthread_mutex *)omutex;
- struct timespec then = { 0, 0 };
uint32_t mtxgen, mtxugen, flags=0, updateval;
uint32_t lcntval, ucntval, scntval;
uint32_t nlval, ulval, savebits;
volatile uint32_t *c_lseqcnt, *c_useqcnt, *c_sseqcnt;
uint64_t oldval64, newval64, mugen, cvlsgen;
uint32_t *npmtx = NULL;
- int timeout_elapsed = 0;
- res = _pthread_cond_check_init(cond, NULL);
+ COND_GETSEQ_ADDR(cond, &c_lsseqaddr, &c_lseqcnt, &c_useqcnt, &c_sseqcnt);
+
+ do {
+ lcntval = *c_lseqcnt;
+ ucntval = *c_useqcnt;
+ scntval = *c_sseqcnt;
+
+ oldval64 = (((uint64_t)scntval) << 32);
+ oldval64 |= lcntval;
+
+ /* remove c and p bits on S word */
+ savebits = scntval & PTH_RWS_CV_BITSALL;
+ ulval = (scntval & PTHRW_COUNT_MASK);
+ nlval = lcntval + PTHRW_INC;
+ newval64 = (((uint64_t)ulval) << 32);
+ newval64 |= nlval;
+ } while (!os_atomic_cmpxchg(c_lsseqaddr, oldval64, newval64, seq_cst));
+
+ cond->busy = mutex;
+
+ int res = _pthread_mutex_droplock(mutex, &flags, &npmtx, &mtxgen, &mtxugen);
+
+ /* TBD: cases are for normal (non owner for recursive mutex; error checking)*/
if (res != 0) {
- return res;
+ return EINVAL;
}
+ if ((flags & _PTHREAD_MTX_OPT_NOTIFY) == 0) {
+ npmtx = NULL;
+ mugen = 0;
+ } else {
+ mugen = ((uint64_t)mtxugen << 32) | mtxgen;
+ }
+ flags &= ~_PTHREAD_MTX_OPT_MUTEX; /* reset the mutex bit as this is cvar */
- if (conforming) {
- if (!_pthread_mutex_check_signature(mutex) &&
- !_pthread_mutex_check_signature_init(mutex)) {
- return EINVAL;
+ cvlsgen = ((uint64_t)(ulval | savebits)<< 32) | nlval;
+
+ // SUSv3 requires pthread_cond_wait to be a cancellation point
+ if (conforming == PTHREAD_CONFORM_UNIX03_CANCELABLE) {
+ pthread_cleanup_push(_pthread_psynch_cond_cleanup, (void *)cond);
+ updateval = __psynch_cvwait(cond, cvlsgen, ucntval, (pthread_mutex_t *)npmtx, mugen, flags, (int64_t)(then->tv_sec), (int32_t)(then->tv_nsec));
+ pthread_testcancel();
+ pthread_cleanup_pop(0);
+ } else {
+ updateval = __psynch_cvwait(cond, cvlsgen, ucntval, (pthread_mutex_t *)npmtx, mugen, flags, (int64_t)(then->tv_sec), (int32_t)(then->tv_nsec));
+ }
+
+ if (updateval == (uint32_t)-1) {
+ int err = errno;
+ switch (err & 0xff) {
+ case ETIMEDOUT:
+ res = ETIMEDOUT;
+ break;
+ case EINTR:
+ // spurious wakeup (unless canceled)
+ res = 0;
+ break;
+ default:
+ res = EINVAL;
+ break;
}
- if (conforming == PTHREAD_CONFORM_UNIX03_CANCELABLE) {
- _pthread_testcancel(conforming);
+
+ // add unlock ref to show one less waiter
+ _pthread_cond_updateval(cond, mutex, err, 0);
+ } else if (updateval != 0) {
+ // Successful wait
+ // The return due to prepost and might have bit states
+ // update S and return for prepo if needed
+ _pthread_cond_updateval(cond, mutex, 0, updateval);
+ }
+
+ pthread_mutex_lock(mutex);
+
+ return res;
+}
+
+struct pthread_ulock_cond_cancel_ctx_s {
+ pthread_cond_t *cond;
+ pthread_mutex_t *mutex;
+};
+
+static int
+_pthread_ulock_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex,
+ const struct timespec *then, pthread_conformance_t conforming)
+{
+ bool cancelable = (conforming == PTHREAD_CONFORM_UNIX03_CANCELABLE);
+
+ uint64_t timeout_ns = 0;
+ if (then->tv_sec || then->tv_nsec) {
+ // psynch compatibility: cast and bitwise-truncate tv_nsec
+ uint64_t fraction_ns = ((uint32_t)then->tv_nsec) & 0x3fffffff;
+ if (os_mul_and_add_overflow(then->tv_sec, NSEC_PER_SEC, fraction_ns,
+ &timeout_ns)) {
+ // saturate (can't wait longer than 584 years...)
+ timeout_ns = UINT64_MAX;
+ }
+ }
+
+ pthread_ulock_cond_state_u *state = _pthread_ulock_cond_state(cond);
+
+ pthread_ulock_cond_state_u origstate = {
+ .val = os_atomic_add(&state->val, _PTHREAD_COND_WAITERS_INC, relaxed)
+ };
+
+ int rc = _pthread_mutex_ulock_unlock(mutex);
+ if (rc) {
+ return _pthread_ulock_cond_wait_complete(state, NULL, rc);
+ }
+
+ PTHREAD_TRACE(ulcond_wait, cond, origstate.val, timeout_ns, 0);
+
+ do {
+ const uint32_t wait_op = UL_COMPARE_AND_WAIT | ULF_NO_ERRNO;
+ if (cancelable) {
+ struct pthread_ulock_cond_cancel_ctx_s ctx = {
+ .cond = cond,
+ .mutex = mutex,
+ };
+ pthread_cleanup_push(_pthread_ulock_cond_cleanup, &ctx);
+ rc = __ulock_wait2(wait_op | ULF_WAIT_CANCEL_POINT, &state->seq,
+ origstate.seq, timeout_ns, 0);
+ pthread_testcancel();
+ pthread_cleanup_pop(0);
+ } else {
+ rc = __ulock_wait2(wait_op, &state->seq, origstate.seq, timeout_ns, 0);
+ }
+ if (rc < 0) {
+ switch (-rc) {
+ case EFAULT:
+ continue;
+ case EINTR:
+ // "These functions shall not return an error code of [EINTR]."
+ // => promote to spurious wake-up
+ rc = 0;
+ goto out;
+ case ETIMEDOUT:
+ rc = ETIMEDOUT;
+ goto out;
+ default:
+ PTHREAD_INTERNAL_CRASH(-rc, "ulock_wait failure");
+ }
+ } else {
+ // XXX for now don't care about other waiters
+ rc = 0;
}
+ } while (os_atomic_load(&state->seq, relaxed) == origstate.seq);
+
+out:
+ return _pthread_ulock_cond_wait_complete(state, mutex, rc);
+}
+
+static int
+_pthread_ulock_cond_wait_complete(pthread_ulock_cond_state_u *state,
+ pthread_mutex_t *mutex, int rc)
+{
+ if (mutex) {
+ // XXX Check this return value? Historically we haven't, but if rc == 0
+ // we could promote the return value to this one.
+ _pthread_mutex_ulock_lock(mutex, false);
+ }
+
+ pthread_ulock_cond_state_u oldstate, newstate;
+ // acquire to pair with release upon signal
+ os_atomic_rmw_loop(&state->val, oldstate.val, newstate.val, acquire, {
+ newstate = (pthread_ulock_cond_state_u){
+ .seq = oldstate.seq,
+ .waiters = oldstate.waiters - 1,
+ .signal = oldstate.signal ? oldstate.signal - 1 : 0,
+ };
+ });
+
+ return rc;
+}
+
+/*
+ * Suspend waiting for a condition variable.
+ * If conformance is not cancelable, we skip the pthread_testcancel(),
+ * but keep the remaining conforming behavior.
+ */
+PTHREAD_NOEXPORT OS_NOINLINE
+int
+_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex,
+ const struct timespec *abstime, int isRelative,
+ pthread_conformance_t conforming)
+{
+ int res;
+ struct timespec then = { 0, 0 };
+ bool timeout_elapsed = false;
+
+ if (!_pthread_mutex_check_signature(mutex) &&
+ !_pthread_mutex_check_signature_init(mutex)) {
+ return EINVAL;
+ }
+
+ bool ulock = _pthread_mutex_uses_ulock(mutex);
+ uint32_t sig = ulock ? _PTHREAD_COND_SIG_ulock : _PTHREAD_COND_SIG_psynch;
+ res = _pthread_cond_check_init(cond, &sig);
+ if (res != 0) {
+ return res;
+ }
+
+ if (conforming == PTHREAD_CONFORM_UNIX03_CANCELABLE) {
+ pthread_testcancel();
}
/* send relative time to kernel */
if (abstime) {
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= NSEC_PER_SEC) {
+ // TODO: PTHREAD_STRICT candidate
return EINVAL;
}
if ((abstime->tv_sec == now.tv_sec) ?
(abstime->tv_nsec <= now.tv_nsec) :
(abstime->tv_sec < now.tv_sec)) {
- timeout_elapsed = 1;
+ timeout_elapsed = true;
} else {
/* Compute relative time to sleep */
then.tv_nsec = abstime->tv_nsec - now.tv_nsec;
then.tv_sec = abstime->tv_sec;
then.tv_nsec = abstime->tv_nsec;
if ((then.tv_sec == 0) && (then.tv_nsec == 0)) {
- timeout_elapsed = 1;
+ timeout_elapsed = true;
}
}
}
- if (cond->busy != NULL && cond->busy != mutex) {
+ if (!ulock && cond->busy != NULL && cond->busy != mutex) {
+ // TODO: PTHREAD_STRICT candidate
return EINVAL;
}
* relock the mutex to allow other waiters to get in line and
* modify the condition state.
*/
- if (timeout_elapsed) {
- res = pthread_mutex_unlock(omutex);
+ if (timeout_elapsed) {
+ res = pthread_mutex_unlock(mutex);
if (res != 0) {
return res;
}
- res = pthread_mutex_lock(omutex);
+ res = pthread_mutex_lock(mutex);
if (res != 0) {
return res;
}
- return ETIMEDOUT;
- }
-
- COND_GETSEQ_ADDR(cond, &c_lsseqaddr, &c_lseqcnt, &c_useqcnt, &c_sseqcnt);
- do {
- lcntval = *c_lseqcnt;
- ucntval = *c_useqcnt;
- scntval = *c_sseqcnt;
-
- oldval64 = (((uint64_t)scntval) << 32);
- oldval64 |= lcntval;
-
- /* remove c and p bits on S word */
- savebits = scntval & PTH_RWS_CV_BITSALL;
- ulval = (scntval & PTHRW_COUNT_MASK);
- nlval = lcntval + PTHRW_INC;
- newval64 = (((uint64_t)ulval) << 32);
- newval64 |= nlval;
- } while (!os_atomic_cmpxchg(c_lsseqaddr, oldval64, newval64, seq_cst));
-
- cond->busy = mutex;
-
- res = _pthread_mutex_droplock(mutex, &flags, &npmtx, &mtxgen, &mtxugen);
-
- /* TBD: cases are for normal (non owner for recursive mutex; error checking)*/
- if (res != 0) {
- return EINVAL;
- }
- if ((flags & _PTHREAD_MTX_OPT_NOTIFY) == 0) {
- npmtx = NULL;
- mugen = 0;
- } else {
- mugen = ((uint64_t)mtxugen << 32) | mtxgen;
+ return ETIMEDOUT;
}
- flags &= ~_PTHREAD_MTX_OPT_MUTEX; /* reset the mutex bit as this is cvar */
- cvlsgen = ((uint64_t)(ulval | savebits)<< 32) | nlval;
-
- // SUSv3 requires pthread_cond_wait to be a cancellation point
- if (conforming) {
- pthread_cleanup_push(_pthread_cond_cleanup, (void *)cond);
- updateval = __psynch_cvwait(ocond, cvlsgen, ucntval, (pthread_mutex_t *)npmtx, mugen, flags, (int64_t)then.tv_sec, (int32_t)then.tv_nsec);
- _pthread_testcancel(conforming);
- pthread_cleanup_pop(0);
+ if (ulock) {
+ return _pthread_ulock_cond_wait(cond, mutex, &then, conforming);
} else {
- updateval = __psynch_cvwait(ocond, cvlsgen, ucntval, (pthread_mutex_t *)npmtx, mugen, flags, (int64_t)then.tv_sec, (int32_t)then.tv_nsec);
- }
-
- if (updateval == (uint32_t)-1) {
- int err = errno;
- switch (err & 0xff) {
- case ETIMEDOUT:
- res = ETIMEDOUT;
- break;
- case EINTR:
- // spurious wakeup (unless canceled)
- res = 0;
- break;
- default:
- res = EINVAL;
- break;
- }
-
- // add unlock ref to show one less waiter
- _pthread_cond_updateval(cond, mutex, err, 0);
- } else if (updateval != 0) {
- // Successful wait
- // The return due to prepost and might have bit states
- // update S and return for prepo if needed
- _pthread_cond_updateval(cond, mutex, 0, updateval);
+ return _pthread_psynch_cond_wait(cond, mutex, &then, conforming);
}
+}
- pthread_mutex_lock(omutex);
-
- return res;
+static void
+_pthread_ulock_cond_cleanup(void *arg)
+{
+ struct pthread_ulock_cond_cancel_ctx_s *ctx = arg;
+ pthread_ulock_cond_state_u *state = _pthread_ulock_cond_state(ctx->cond);
+
+ (void)_pthread_ulock_cond_wait_complete(state, ctx->mutex, 0);
+
+ // "A thread that has been unblocked because it has been canceled while
+ // blocked in a call to pthread_cond_timedwait() or pthread_cond_wait()
+ // shall not consume any condition signal that may be directed concurrently
+ // at the condition variable if there are other threads blocked on the
+ // condition variable."
+ //
+ // Since we have no way to know if we've eaten somebody else's signal, just
+ // signal again pessimistically.
+ pthread_cond_signal(ctx->cond);
}
static void
-_pthread_cond_cleanup(void *arg)
+_pthread_psynch_cond_cleanup(void *arg)
{
- _pthread_cond *cond = (_pthread_cond *)arg;
+ pthread_cond_t *cond = (pthread_cond_t *)arg;
pthread_t thread = pthread_self();
pthread_mutex_t *mutex;
}
// 4597450: end
- mutex = (pthread_mutex_t *)cond->busy;
+ mutex = cond->busy;
// add unlock ref to show one less waiter
- _pthread_cond_updateval(cond, (_pthread_mutex *)mutex,
- thread->cancel_error, 0);
+ _pthread_cond_updateval(cond, mutex, thread->cancel_error, 0);
/*
** Can't do anything if this fails -- we're on the way out
}
static void
-_pthread_cond_updateval(_pthread_cond *cond, _pthread_mutex *mutex,
+_pthread_cond_updateval(pthread_cond_t *cond, pthread_mutex_t *mutex,
int error, uint32_t updateval)
{
int needclearpre;
PTHREAD_NOEXPORT_VARIANT
int
-pthread_cond_init(pthread_cond_t *ocond, const pthread_condattr_t *attr)
+pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
{
- int conforming;
-
-#if __DARWIN_UNIX03
- conforming = 1;
-#else /* __DARWIN_UNIX03 */
- conforming = 0;
-#endif /* __DARWIN_UNIX03 */
-
- _pthread_cond *cond = (_pthread_cond *)ocond;
- _PTHREAD_LOCK_INIT(cond->lock);
- return _pthread_cond_init(cond, attr, conforming);
+ _pthread_lock_init(&cond->lock);
+ return _pthread_cond_init(cond, attr, _PTHREAD_COND_SIG_pristine);
}
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
+/*
+ * Copyright (c) 2019 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "internal.h"
-extern int __pthread_chdir(const char *path);
int
pthread_chdir_np(const char *path)
{
return __pthread_chdir(path);
}
-extern int __pthread_fchdir(int fd);
int
pthread_fchdir_np(int fd)
{
#include "resolver.h"
#include "internal.h"
-#include "dependency_private.h"
-#include <sys/ulock.h>
#define PREREQUISITE_FULFILLED (~0u)
-PTHREAD_NOEXPORT
-void _pthread_dependency_fulfill_slow(pthread_dependency_t *pr, uint32_t old);
-
-OS_ALWAYS_INLINE
-static inline mach_port_t
-_pthread_dependency_self(void)
-{
- void *v = _pthread_getspecific_direct(_PTHREAD_TSD_SLOT_MACH_THREAD_SELF);
- return (mach_port_t)(uintptr_t)v;
-}
-
+#if !VARIANT_DYLD
void
pthread_dependency_init_np(pthread_dependency_t *pr, pthread_t pth,
pthread_dependency_attr_t *attrs)
if (old == PREREQUISITE_FULFILLED) {
PTHREAD_CLIENT_CRASH(0, "Fufilling pthread_dependency_t twice");
}
- if (os_unlikely(old != _pthread_dependency_self())) {
+ if (os_unlikely(old != _pthread_mach_thread_self_direct())) {
PTHREAD_CLIENT_CRASH(old, "Fulfilled a dependency "
"not owned by current thread");
}
}
+PTHREAD_NOEXPORT_VARIANT
void
pthread_dependency_fulfill_np(pthread_dependency_t *pr, void *value)
{
if (old != 0) _pthread_dependency_fulfill_slow(pr, old);
}
+PTHREAD_NOEXPORT_VARIANT
void *
pthread_dependency_wait_np(pthread_dependency_t *pr)
{
PTHREAD_CLIENT_CRASH(cur, "Corrupted pthread_dependency_t");
}
+PTHREAD_NOEXPORT_VARIANT void*
+_pthread_atomic_xchg_ptr(void **p, void *v)
+{
+ return os_atomic_xchg(p, v, seq_cst);
+}
+
+PTHREAD_NOEXPORT_VARIANT uint32_t
+_pthread_atomic_xchg_uint32_relaxed(uint32_t *p, uint32_t v)
+{
+ return os_atomic_xchg(p, v, relaxed);
+}
+
+#endif // !VARIANT_DYLD
/* This function is never called and exists to provide never-fired dtrace
* probes so that user d scripts don't get errors.
*/
-PTHREAD_NOEXPORT PTHREAD_USED
-void
+OS_USED static void
+_plockstat_never_fired(void);
+static void
_plockstat_never_fired(void)
{
PLOCKSTAT_MUTEX_SPIN(NULL);
#define PTHREAD_MUTEX_INIT_UNUSED 1
-PTHREAD_NOEXPORT PTHREAD_WEAK
-int _pthread_mutex_lock_init_slow(_pthread_mutex *mutex, bool trylock);
-
-PTHREAD_NOEXPORT PTHREAD_WEAK // prevent inlining of return value into callers
-int _pthread_mutex_fairshare_lock_slow(_pthread_mutex *mutex, bool trylock);
-
-PTHREAD_NOEXPORT PTHREAD_WEAK // prevent inlining of return value into callers
-int _pthread_mutex_firstfit_lock_slow(_pthread_mutex *mutex, bool trylock);
-
-PTHREAD_NOEXPORT PTHREAD_WEAK // prevent inlining of return value into callers
-int _pthread_mutex_fairshare_unlock_slow(_pthread_mutex *mutex);
-
-PTHREAD_NOEXPORT PTHREAD_WEAK // prevent inlining of return value into callers
-int _pthread_mutex_firstfit_unlock_slow(_pthread_mutex *mutex);
-
-PTHREAD_NOEXPORT PTHREAD_WEAK // prevent inlining of return value into callers
-int _pthread_mutex_corruption_abort(_pthread_mutex *mutex);
-
-extern int __pthread_mutex_default_opt_policy PTHREAD_NOEXPORT;
+#if !VARIANT_DYLD
-
-int __pthread_mutex_default_opt_policy PTHREAD_NOEXPORT =
- _PTHREAD_MTX_OPT_POLICY_DEFAULT;
+int __pthread_mutex_default_opt_policy = _PTHREAD_MTX_OPT_POLICY_DEFAULT;
+bool __pthread_mutex_use_ulock = _PTHREAD_MTX_OPT_ULOCK_DEFAULT;
+bool __pthread_mutex_ulock_adaptive_spin = _PTHREAD_MTX_OPT_ADAPTIVE_DEFAULT;
static inline bool
_pthread_mutex_policy_validate(int policy)
}
}
-PTHREAD_NOEXPORT
void
_pthread_mutex_global_init(const char *envp[],
struct _pthread_registration_data *registration_data)
{
int opt = _PTHREAD_MTX_OPT_POLICY_DEFAULT;
if (registration_data->mutex_default_policy) {
- int policy = registration_data->mutex_default_policy;
+ int policy = registration_data->mutex_default_policy &
+ _PTHREAD_REG_DEFAULT_POLICY_MASK;
if (_pthread_mutex_policy_validate(policy)) {
opt = _pthread_mutex_policy_to_opt(policy);
}
if (opt != __pthread_mutex_default_opt_policy) {
__pthread_mutex_default_opt_policy = opt;
}
+
+ bool use_ulock = _PTHREAD_MTX_OPT_ULOCK_DEFAULT;
+ if (_os_xbs_chrooted) {
+ use_ulock = false;
+ } else {
+ envvar = _simple_getenv(envp, "PTHREAD_MUTEX_USE_ULOCK");
+ if (envvar) {
+ use_ulock = (envvar[0] == '1');
+ } else if (registration_data->mutex_default_policy) {
+ use_ulock = registration_data->mutex_default_policy &
+ _PTHREAD_REG_DEFAULT_USE_ULOCK;
+ }
+ }
+
+ if (use_ulock != __pthread_mutex_use_ulock) {
+ __pthread_mutex_use_ulock = use_ulock;
+ }
+
+ bool adaptive_spin = _PTHREAD_MTX_OPT_ADAPTIVE_DEFAULT;
+ envvar = _simple_getenv(envp, "PTHREAD_MUTEX_ADAPTIVE_SPIN");
+ if (envvar) {
+ adaptive_spin = (envvar[0] == '1');
+ } else if (registration_data->mutex_default_policy) {
+ adaptive_spin = registration_data->mutex_default_policy &
+ _PTHREAD_REG_DEFAULT_USE_ADAPTIVE_SPIN;
+ }
+
+ if (adaptive_spin != __pthread_mutex_ulock_adaptive_spin) {
+ __pthread_mutex_ulock_adaptive_spin = adaptive_spin;
+ }
}
+#endif // !VARIANT_DYLD
-PTHREAD_ALWAYS_INLINE
-static inline int _pthread_mutex_init(_pthread_mutex *mutex,
+OS_ALWAYS_INLINE
+static inline int _pthread_mutex_init(pthread_mutex_t *mutex,
const pthread_mutexattr_t *attr, uint32_t static_type);
typedef union mutex_seq {
#error MUTEX_GETSEQ_ADDR assumes little endian layout of 2 32-bit sequence words
#endif
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline void
-MUTEX_GETSEQ_ADDR(_pthread_mutex *mutex, mutex_seq **seqaddr)
+MUTEX_GETSEQ_ADDR(pthread_mutex_t *mutex, mutex_seq **seqaddr)
{
// 64-bit aligned address inside m_seq array (&m_seq[0] for aligned mutex)
// We don't require more than byte alignment on OS X. rdar://22278325
- *seqaddr = (void *)(((uintptr_t)mutex->m_seq + 0x7ul) & ~0x7ul);
+ *seqaddr = (void *)(((uintptr_t)mutex->psynch.m_seq + 0x7ul) & ~0x7ul);
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline void
-MUTEX_GETTID_ADDR(_pthread_mutex *mutex, uint64_t **tidaddr)
+MUTEX_GETTID_ADDR(pthread_mutex_t *mutex, uint64_t **tidaddr)
{
// 64-bit aligned address inside m_tid array (&m_tid[0] for aligned mutex)
// We don't require more than byte alignment on OS X. rdar://22278325
- *tidaddr = (void*)(((uintptr_t)mutex->m_tid + 0x7ul) & ~0x7ul);
+ *tidaddr = (void*)(((uintptr_t)mutex->psynch.m_tid + 0x7ul) & ~0x7ul);
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline void
mutex_seq_load(mutex_seq *seqaddr, mutex_seq *oldseqval)
{
#define mutex_seq_atomic_load(seqaddr, oldseqval, m) \
mutex_seq_atomic_load_##m(seqaddr, oldseqval)
-PTHREAD_ALWAYS_INLINE PTHREAD_USED
+OS_ALWAYS_INLINE OS_USED
static inline bool
mutex_seq_atomic_cmpxchgv_relaxed(mutex_seq *seqaddr, mutex_seq *oldseqval,
mutex_seq *newseqval)
newseqval->seq_LU, &oldseqval->seq_LU, relaxed);
}
-PTHREAD_ALWAYS_INLINE PTHREAD_USED
+OS_ALWAYS_INLINE OS_USED
static inline bool
mutex_seq_atomic_cmpxchgv_acquire(mutex_seq *seqaddr, mutex_seq *oldseqval,
mutex_seq *newseqval)
newseqval->seq_LU, &oldseqval->seq_LU, acquire);
}
-PTHREAD_ALWAYS_INLINE PTHREAD_USED
+OS_ALWAYS_INLINE OS_USED
static inline bool
mutex_seq_atomic_cmpxchgv_release(mutex_seq *seqaddr, mutex_seq *oldseqval,
mutex_seq *newseqval)
*/
PTHREAD_NOEXPORT_VARIANT
int
-pthread_mutex_init(pthread_mutex_t *omutex, const pthread_mutexattr_t *attr)
+pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
{
#if 0
/* conformance tests depend on not having this behavior */
if (_pthread_mutex_check_signature(mutex))
return EBUSY;
#endif
- _pthread_mutex *mutex = (_pthread_mutex *)omutex;
- _PTHREAD_LOCK_INIT(mutex->lock);
+ _pthread_lock_init(&mutex->lock);
return (_pthread_mutex_init(mutex, attr, 0x7));
}
-PTHREAD_NOEXPORT_VARIANT
+
int
pthread_mutex_getprioceiling(const pthread_mutex_t *omutex, int *prioceiling)
{
int res = EINVAL;
- _pthread_mutex *mutex = (_pthread_mutex *)omutex;
+ pthread_mutex_t *mutex = (pthread_mutex_t *)omutex;
if (_pthread_mutex_check_signature(mutex)) {
- _PTHREAD_LOCK(mutex->lock);
+ _pthread_lock_lock(&mutex->lock);
*prioceiling = mutex->prioceiling;
res = 0;
- _PTHREAD_UNLOCK(mutex->lock);
+ _pthread_lock_unlock(&mutex->lock);
}
return res;
}
-PTHREAD_NOEXPORT_VARIANT
int
-pthread_mutex_setprioceiling(pthread_mutex_t *omutex, int prioceiling,
+pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int prioceiling,
int *old_prioceiling)
{
int res = EINVAL;
- _pthread_mutex *mutex = (_pthread_mutex *)omutex;
if (_pthread_mutex_check_signature(mutex)) {
- _PTHREAD_LOCK(mutex->lock);
+ _pthread_lock_lock(&mutex->lock);
if (prioceiling >= -999 && prioceiling <= 999) {
*old_prioceiling = mutex->prioceiling;
mutex->prioceiling = (int16_t)prioceiling;
res = 0;
}
- _PTHREAD_UNLOCK(mutex->lock);
+ _pthread_lock_unlock(&mutex->lock);
}
return res;
}
-
int
pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr,
int *prioceiling)
int res = EINVAL;
if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG) {
switch (protocol) {
- case PTHREAD_PRIO_NONE:
- case PTHREAD_PRIO_INHERIT:
- case PTHREAD_PRIO_PROTECT:
- attr->protocol = protocol;
- res = 0;
- break;
+ case PTHREAD_PRIO_NONE:
+ case PTHREAD_PRIO_INHERIT:
+ case PTHREAD_PRIO_PROTECT:
+ attr->protocol = protocol;
+ res = 0;
+ break;
}
}
return res;
int res = EINVAL;
if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG) {
switch (type) {
- case PTHREAD_MUTEX_NORMAL:
- case PTHREAD_MUTEX_ERRORCHECK:
- case PTHREAD_MUTEX_RECURSIVE:
- //case PTHREAD_MUTEX_DEFAULT:
- attr->type = type;
- res = 0;
- break;
+ case PTHREAD_MUTEX_NORMAL:
+ case PTHREAD_MUTEX_ERRORCHECK:
+ case PTHREAD_MUTEX_RECURSIVE:
+ //case PTHREAD_MUTEX_DEFAULT:
+ attr->type = type;
+ res = 0;
+ break;
}
}
return res;
pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared)
{
int res = EINVAL;
-#if __DARWIN_UNIX03
- if (__unix_conforming == 0) {
- __unix_conforming = 1;
- }
-#endif /* __DARWIN_UNIX03 */
-
if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG) {
-#if __DARWIN_UNIX03
if (( pshared == PTHREAD_PROCESS_PRIVATE) ||
(pshared == PTHREAD_PROCESS_SHARED))
-#else /* __DARWIN_UNIX03 */
- if ( pshared == PTHREAD_PROCESS_PRIVATE)
-#endif /* __DARWIN_UNIX03 */
{
attr->pshared = pshared;
res = 0;
return res;
}
-PTHREAD_NOEXPORT PTHREAD_NOINLINE PTHREAD_NORETURN
+OS_NOINLINE
int
-_pthread_mutex_corruption_abort(_pthread_mutex *mutex)
+_pthread_mutex_corruption_abort(pthread_mutex_t *mutex)
{
PTHREAD_CLIENT_CRASH(0, "pthread_mutex corruption: mutex owner changed "
"in the middle of lock/unlock");
}
-PTHREAD_NOINLINE
+OS_NOINLINE
static int
-_pthread_mutex_check_init_slow(_pthread_mutex *mutex)
+_pthread_mutex_check_init_slow(pthread_mutex_t *mutex)
{
int res = EINVAL;
if (_pthread_mutex_check_signature_init(mutex)) {
- _PTHREAD_LOCK(mutex->lock);
+ _pthread_lock_lock(&mutex->lock);
if (_pthread_mutex_check_signature_init(mutex)) {
// initialize a statically initialized mutex to provide
// compatibility for misbehaving applications.
} else if (_pthread_mutex_check_signature(mutex)) {
res = 0;
}
- _PTHREAD_UNLOCK(mutex->lock);
+ _pthread_lock_unlock(&mutex->lock);
} else if (_pthread_mutex_check_signature(mutex)) {
res = 0;
}
return res;
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline int
-_pthread_mutex_check_init(_pthread_mutex *mutex)
+_pthread_mutex_check_init(pthread_mutex_t *mutex)
{
int res = 0;
if (!_pthread_mutex_check_signature(mutex)) {
return res;
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline bool
-_pthread_mutex_is_fairshare(_pthread_mutex *mutex)
+_pthread_mutex_is_fairshare(pthread_mutex_t *mutex)
{
return (mutex->mtxopts.options.policy == _PTHREAD_MTX_OPT_POLICY_FAIRSHARE);
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline bool
-_pthread_mutex_is_firstfit(_pthread_mutex *mutex)
+_pthread_mutex_is_firstfit(pthread_mutex_t *mutex)
{
return (mutex->mtxopts.options.policy == _PTHREAD_MTX_OPT_POLICY_FIRSTFIT);
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline bool
-_pthread_mutex_is_recursive(_pthread_mutex *mutex)
+_pthread_mutex_is_recursive(pthread_mutex_t *mutex)
{
return (mutex->mtxopts.options.type == PTHREAD_MUTEX_RECURSIVE);
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static int
-_pthread_mutex_lock_handle_options(_pthread_mutex *mutex, bool trylock,
+_pthread_mutex_lock_handle_options(pthread_mutex_t *mutex, bool trylock,
uint64_t *tidaddr)
{
if (mutex->mtxopts.options.type == PTHREAD_MUTEX_NORMAL) {
return 0;
}
- uint64_t selfid = _pthread_selfid_direct();
- if (os_atomic_load(tidaddr, relaxed) == selfid) {
+ uint64_t selfid = _pthread_threadid_self_np_direct();
+ if (os_atomic_load_wide(tidaddr, relaxed) == selfid) {
if (_pthread_mutex_is_recursive(mutex)) {
if (mutex->mtxopts.options.lock_count < USHRT_MAX) {
mutex->mtxopts.options.lock_count += 1;
return 0;
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static int
-_pthread_mutex_unlock_handle_options(_pthread_mutex *mutex, uint64_t *tidaddr)
+_pthread_mutex_unlock_handle_options(pthread_mutex_t *mutex, uint64_t *tidaddr)
{
if (mutex->mtxopts.options.type == PTHREAD_MUTEX_NORMAL) {
// NORMAL does not do EDEADLK checking
return 0;
}
- uint64_t selfid = _pthread_selfid_direct();
- if (os_atomic_load(tidaddr, relaxed) != selfid) {
+ uint64_t selfid = _pthread_threadid_self_np_direct();
+ if (os_atomic_load_wide(tidaddr, relaxed) != selfid) {
return -EPERM;
} else if (_pthread_mutex_is_recursive(mutex) &&
--mutex->mtxopts.options.lock_count) {
/*
* Drop the mutex unlock references from cond_wait or mutex_unlock.
*/
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline int
-_pthread_mutex_fairshare_unlock_updatebits(_pthread_mutex *mutex,
+_pthread_mutex_fairshare_unlock_updatebits(pthread_mutex_t *mutex,
uint32_t *flagsp, uint32_t **pmtxp, uint32_t *mgenp, uint32_t *ugenp)
{
uint32_t flags = mutex->mtxopts.value;
bool clearnotify, spurious;
do {
newseq = oldseq;
- oldtid = os_atomic_load(tidaddr, relaxed);
+ oldtid = os_atomic_load_wide(tidaddr, relaxed);
clearnotify = false;
spurious = false;
return 0;
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline int
-_pthread_mutex_fairshare_lock_updatebits(_pthread_mutex *mutex, uint64_t selfid)
+_pthread_mutex_fairshare_lock_updatebits(pthread_mutex_t *mutex, uint64_t selfid)
{
bool firstfit = _pthread_mutex_is_firstfit(mutex);
bool gotlock = true;
acquire));
if (gotlock) {
- os_atomic_store(tidaddr, selfid, relaxed);
+ os_atomic_store_wide(tidaddr, selfid, relaxed);
}
PTHREAD_TRACE(psynch_mutex_lock_updatebits, mutex, oldseq.lgenval,
return gotlock ? 0 : 1;
}
-PTHREAD_NOINLINE
+OS_NOINLINE
static int
-_pthread_mutex_fairshare_lock_wait(_pthread_mutex *mutex, mutex_seq newseq,
+_pthread_mutex_fairshare_lock_wait(pthread_mutex_t *mutex, mutex_seq newseq,
uint64_t oldtid)
{
uint64_t *tidaddr;
MUTEX_GETTID_ADDR(mutex, &tidaddr);
- uint64_t selfid = _pthread_selfid_direct();
+ uint64_t selfid = _pthread_threadid_self_np_direct();
PLOCKSTAT_MUTEX_BLOCK((pthread_mutex_t *)mutex);
do {
do {
updateval = __psynch_mutexwait(mutex, newseq.lgenval,
newseq.ugenval, oldtid, mutex->mtxopts.value);
- oldtid = os_atomic_load(tidaddr, relaxed);
+ oldtid = os_atomic_load_wide(tidaddr, relaxed);
} while (updateval == (uint32_t)-1);
// returns 0 on succesful update; in firstfit it may fail with 1
return 0;
}
-PTHREAD_NOEXPORT PTHREAD_NOINLINE
+OS_NOINLINE
int
-_pthread_mutex_fairshare_lock_slow(_pthread_mutex *omutex, bool trylock)
+_pthread_mutex_fairshare_lock_slow(pthread_mutex_t *mutex, bool trylock)
{
int res, recursive = 0;
- _pthread_mutex *mutex = (_pthread_mutex *)omutex;
mutex_seq *seqaddr;
MUTEX_GETSEQ_ADDR(mutex, &seqaddr);
uint64_t *tidaddr;
MUTEX_GETTID_ADDR(mutex, &tidaddr);
- uint64_t oldtid, selfid = _pthread_selfid_direct();
+ uint64_t oldtid, selfid = _pthread_threadid_self_np_direct();
res = _pthread_mutex_lock_handle_options(mutex, trylock, tidaddr);
if (res > 0) {
bool gotlock;
do {
newseq = oldseq;
- oldtid = os_atomic_load(tidaddr, relaxed);
+ oldtid = os_atomic_load_wide(tidaddr, relaxed);
gotlock = ((oldseq.lgenval & PTH_RWL_EBIT) == 0);
}
} while (!mutex_seq_atomic_cmpxchgv(seqaddr, &oldseq, &newseq, acquire));
- PTHREAD_TRACE(psynch_mutex_lock_updatebits, omutex, oldseq.lgenval,
+ PTHREAD_TRACE(psynch_mutex_lock_updatebits, mutex, oldseq.lgenval,
newseq.lgenval, 0);
if (gotlock) {
- os_atomic_store(tidaddr, selfid, relaxed);
+ os_atomic_store_wide(tidaddr, selfid, relaxed);
res = 0;
- PTHREAD_TRACE(psynch_mutex_ulock, omutex, newseq.lgenval,
+ PTHREAD_TRACE(psynch_mutex_ulock, mutex, newseq.lgenval,
newseq.ugenval, selfid);
} else if (trylock) {
res = EBUSY;
- PTHREAD_TRACE(psynch_mutex_utrylock_failed, omutex, newseq.lgenval,
+ PTHREAD_TRACE(psynch_mutex_utrylock_failed, mutex, newseq.lgenval,
newseq.ugenval, oldtid);
} else {
- PTHREAD_TRACE(psynch_mutex_ulock | DBG_FUNC_START, omutex,
+ PTHREAD_TRACE(psynch_mutex_ulock | DBG_FUNC_START, mutex,
newseq.lgenval, newseq.ugenval, oldtid);
res = _pthread_mutex_fairshare_lock_wait(mutex, newseq, oldtid);
- PTHREAD_TRACE(psynch_mutex_ulock | DBG_FUNC_END, omutex,
+ PTHREAD_TRACE(psynch_mutex_ulock | DBG_FUNC_END, mutex,
newseq.lgenval, newseq.ugenval, oldtid);
}
return res;
}
-PTHREAD_NOINLINE
+OS_NOINLINE
static inline int
-_pthread_mutex_fairshare_lock(_pthread_mutex *mutex, bool trylock)
+_pthread_mutex_fairshare_lock(pthread_mutex_t *mutex, bool trylock)
{
#if ENABLE_USERSPACE_TRACE
return _pthread_mutex_fairshare_lock_slow(mutex, trylock);
uint64_t *tidaddr;
MUTEX_GETTID_ADDR(mutex, &tidaddr);
- uint64_t selfid = _pthread_selfid_direct();
+ uint64_t selfid = _pthread_threadid_self_np_direct();
mutex_seq *seqaddr;
MUTEX_GETSEQ_ADDR(mutex, &seqaddr);
acquire)));
if (os_likely(gotlock)) {
- os_atomic_store(tidaddr, selfid, relaxed);
+ os_atomic_store_wide(tidaddr, selfid, relaxed);
return 0;
} else if (trylock) {
return EBUSY;
}
}
-PTHREAD_NOINLINE
+OS_NOINLINE
static int
-_pthread_mutex_fairshare_unlock_drop(_pthread_mutex *mutex, mutex_seq newseq,
+_pthread_mutex_fairshare_unlock_drop(pthread_mutex_t *mutex, mutex_seq newseq,
uint32_t flags)
{
int res;
MUTEX_GETTID_ADDR(mutex, &tidaddr);
PTHREAD_TRACE(psynch_mutex_uunlock | DBG_FUNC_START, mutex, newseq.lgenval,
- newseq.ugenval, os_atomic_load(tidaddr, relaxed));
+ newseq.ugenval, os_atomic_load_wide(tidaddr, relaxed));
updateval = __psynch_mutexdrop(mutex, newseq.lgenval, newseq.ugenval,
- os_atomic_load(tidaddr, relaxed), flags);
+ os_atomic_load_wide(tidaddr, relaxed), flags);
PTHREAD_TRACE(psynch_mutex_uunlock | DBG_FUNC_END, mutex, updateval, 0, 0);
return 0;
}
-PTHREAD_NOEXPORT PTHREAD_NOINLINE
+OS_NOINLINE
int
-_pthread_mutex_fairshare_unlock_slow(_pthread_mutex *mutex)
+_pthread_mutex_fairshare_unlock_slow(pthread_mutex_t *mutex)
{
int res;
mutex_seq newseq;
uint64_t *tidaddr;
MUTEX_GETTID_ADDR(mutex, &tidaddr);
PTHREAD_TRACE(psynch_mutex_uunlock, mutex, newseq.lgenval,
- newseq.ugenval, os_atomic_load(tidaddr, relaxed));
+ newseq.ugenval, os_atomic_load_wide(tidaddr, relaxed));
}
return 0;
}
-PTHREAD_NOINLINE
+OS_NOINLINE
static int
-_pthread_mutex_fairshare_unlock(_pthread_mutex *mutex)
+_pthread_mutex_fairshare_unlock(pthread_mutex_t *mutex)
{
#if ENABLE_USERSPACE_TRACE
return _pthread_mutex_fairshare_unlock_slow(mutex);
// is no stale ownership information. If the CAS of the seqaddr
// fails, we may loop, but it's still valid for the owner to be
// SWITCHING/0
- os_atomic_store(tidaddr, 0, relaxed);
+ os_atomic_store_wide(tidaddr, 0, relaxed);
do {
newseq = oldseq;
return 0;
}
+#pragma mark ulock
+
+OS_ALWAYS_INLINE
+static inline uint32_t
+_pthread_mutex_ulock_self_owner_value(void)
+{
+ mach_port_t self_port = _pthread_mach_thread_self_direct();
+ return self_port & _PTHREAD_MUTEX_ULOCK_OWNER_MASK;
+}
+
+OS_NOINLINE
+static int
+_pthread_mutex_ulock_lock_slow(pthread_mutex_t *mutex, uint32_t self_ownerval,
+ uint32_t state)
+{
+ bool success = false, kernel_waiters = false;
+
+ uint32_t wait_op = UL_UNFAIR_LOCK | ULF_NO_ERRNO;
+ if (__pthread_mutex_ulock_adaptive_spin) {
+ wait_op |= ULF_WAIT_ADAPTIVE_SPIN;
+ }
+
+ PLOCKSTAT_MUTEX_BLOCK((pthread_mutex_t *)mutex);
+ do {
+ bool owner_dead = false;
+
+ do {
+ uint32_t current_ownerval = state & _PTHREAD_MUTEX_ULOCK_OWNER_MASK;
+ if (os_unlikely(owner_dead)) {
+ // TODO: PTHREAD_STRICT candidate
+ //
+ // For a non-recursive mutex, this indicates that it's really
+ // being used as a semaphore: even though we're the current
+ // owner, in reality we're expecting another thread to 'unlock'
+ // this mutex on our behalf later.
+ //
+ // __ulock_wait(2) doesn't permit you to wait for yourself, so
+ // we need to first swap our ownership for the anonymous owner
+ current_ownerval =
+ MACH_PORT_DEAD & _PTHREAD_MUTEX_ULOCK_OWNER_MASK;
+ owner_dead = false;
+ }
+ uint32_t new_state =
+ current_ownerval | _PTHREAD_MUTEX_ULOCK_WAITERS_BIT;
+ success = os_atomic_cmpxchgv(&mutex->ulock.uval, state, new_state,
+ &state, relaxed);
+ if (!success) {
+ continue;
+ }
+
+ int rc = __ulock_wait(wait_op, &mutex->ulock, new_state, 0);
+
+ PTHREAD_TRACE(ulmutex_lock_wait, mutex, new_state, rc, 0);
+
+ if (os_unlikely(rc < 0)) {
+ switch (-rc) {
+ case EINTR:
+ case EFAULT:
+ break;
+ case EOWNERDEAD:
+ owner_dead = true;
+ continue;
+ default:
+ PTHREAD_INTERNAL_CRASH(rc, "ulock_wait failure");
+ }
+ } else if (rc > 0) {
+ kernel_waiters = true;
+ }
+
+ state = os_atomic_load(&mutex->ulock.uval, relaxed);
+ } while (state != _PTHREAD_MUTEX_ULOCK_UNLOCKED_VALUE);
+
+ uint32_t locked_state = self_ownerval;
+ if (kernel_waiters) {
+ locked_state |= _PTHREAD_MUTEX_ULOCK_WAITERS_BIT;
+ }
+
+ success = os_atomic_cmpxchgv(&mutex->ulock.uval, state, locked_state,
+ &state, acquire);
+ } while (!success);
+ PLOCKSTAT_MUTEX_BLOCKED((pthread_mutex_t *)mutex, BLOCK_SUCCESS_PLOCKSTAT);
+
+ return 0;
+}
+
+PTHREAD_NOEXPORT_VARIANT
+int
+_pthread_mutex_ulock_lock(pthread_mutex_t *mutex, bool trylock)
+{
+ uint32_t unlocked = _PTHREAD_MUTEX_ULOCK_UNLOCKED_VALUE;
+ uint32_t locked = _pthread_mutex_ulock_self_owner_value();
+ uint32_t state;
+
+ bool success = os_atomic_cmpxchgv(&mutex->ulock.uval, unlocked, locked,
+ &state, acquire);
+
+ if (trylock) {
+ PTHREAD_TRACE(ulmutex_trylock, mutex, locked, state, success);
+ } else {
+ PTHREAD_TRACE(ulmutex_lock, mutex, locked, state, success);
+ }
+
+ int rc = 0;
+ if (!success) {
+ if (trylock) {
+ rc = EBUSY;
+ } else {
+ rc = _pthread_mutex_ulock_lock_slow(mutex, locked, state);
+ }
+ }
+
+ if (rc) {
+ PLOCKSTAT_MUTEX_ERROR((pthread_mutex_t *)mutex, rc);
+ } else {
+ PLOCKSTAT_MUTEX_ACQUIRE((pthread_mutex_t *)mutex, /* recursive */ 0, 0);
+ }
+
+ return rc;
+}
+
+OS_NOINLINE
+static int
+_pthread_mutex_ulock_unlock_slow(pthread_mutex_t *mutex, uint32_t self_ownerval,
+ uint32_t orig_state)
+{
+ if (os_unlikely(orig_state == _PTHREAD_MUTEX_ULOCK_UNLOCKED_VALUE)) {
+ // XXX This is illegal, but psynch permitted it...
+ // TODO: PTHREAD_STRICT candidate
+ return 0;
+ }
+
+ uint32_t wake_flags = 0;
+
+ uint32_t orig_ownerval = orig_state & _PTHREAD_MUTEX_ULOCK_OWNER_MASK;
+ bool orig_waiters = orig_state & _PTHREAD_MUTEX_ULOCK_WAITERS_BIT;
+ if (os_unlikely(orig_ownerval != self_ownerval)) {
+ // XXX This is illegal, but psynch permitted it...
+ // TODO: PTHREAD_STRICT candidate
+ if (!orig_waiters) {
+ return 0;
+ }
+
+ wake_flags |= ULF_WAKE_ALLOW_NON_OWNER;
+ } else if (os_unlikely(!orig_waiters)) {
+ PTHREAD_INTERNAL_CRASH(0, "unlock_slow without orig_waiters");
+ }
+
+ for (;;) {
+ int rc = __ulock_wake(UL_UNFAIR_LOCK | ULF_NO_ERRNO | wake_flags,
+ &mutex->ulock, 0);
+
+ PTHREAD_TRACE(ulmutex_unlock_wake, mutex, rc, 0, 0);
+
+ if (os_unlikely(rc < 0)) {
+ switch (-rc) {
+ case EINTR:
+ continue;
+ case ENOENT:
+ break;
+ default:
+ PTHREAD_INTERNAL_CRASH(-rc, "ulock_wake failure");
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+PTHREAD_NOEXPORT_VARIANT
+int
+_pthread_mutex_ulock_unlock(pthread_mutex_t *mutex)
+{
+ uint32_t locked_uncontended = _pthread_mutex_ulock_self_owner_value();
+ uint32_t unlocked = _PTHREAD_MUTEX_ULOCK_UNLOCKED_VALUE;
+ uint32_t state = os_atomic_xchg(&mutex->ulock.uval, unlocked, release);
+
+ PTHREAD_TRACE(ulmutex_unlock, mutex, locked_uncontended, state, 0);
+
+ int rc = 0;
+ if (state != locked_uncontended) {
+ rc = _pthread_mutex_ulock_unlock_slow(mutex, locked_uncontended,
+ state);
+ }
+
+ if (rc) {
+ PLOCKSTAT_MUTEX_ERROR((pthread_mutex_t *)mutex, rc);
+ } else {
+ PLOCKSTAT_MUTEX_RELEASE((pthread_mutex_t *)mutex, /* recursive */ 0);
+ }
+
+ return rc;
+}
+
#pragma mark firstfit
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline int
-_pthread_mutex_firstfit_unlock_updatebits(_pthread_mutex *mutex,
+_pthread_mutex_firstfit_unlock_updatebits(pthread_mutex_t *mutex,
uint32_t *flagsp, uint32_t **mutexp, uint32_t *lvalp, uint32_t *uvalp)
{
uint32_t flags = mutex->mtxopts.value & ~_PTHREAD_MTX_OPT_NOTIFY;
do {
newseq = oldseq;
- oldtid = os_atomic_load(tidaddr, relaxed);
+ oldtid = os_atomic_load_wide(tidaddr, relaxed);
// More than one kernel waiter means we need to do a wake.
kernel_wake = diff_genseq(oldseq.lgenval, oldseq.ugenval) > 0;
newseq.lgenval &= ~PTH_RWL_EBIT;
return 0;
}
-PTHREAD_NOEXPORT PTHREAD_NOINLINE
+OS_NOINLINE
static int
-_pthread_mutex_firstfit_wake(_pthread_mutex *mutex, mutex_seq newseq,
+_pthread_mutex_firstfit_wake(pthread_mutex_t *mutex, mutex_seq newseq,
uint32_t flags)
{
PTHREAD_TRACE(psynch_ffmutex_wake, mutex, newseq.lgenval, newseq.ugenval,
return 0;
}
-PTHREAD_NOEXPORT PTHREAD_NOINLINE
+OS_NOINLINE
int
-_pthread_mutex_firstfit_unlock_slow(_pthread_mutex *mutex)
+_pthread_mutex_firstfit_unlock_slow(pthread_mutex_t *mutex)
{
mutex_seq newseq;
uint32_t flags;
return 0;
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static bool
-_pthread_mutex_firstfit_lock_updatebits(_pthread_mutex *mutex, uint64_t selfid,
+_pthread_mutex_firstfit_lock_updatebits(pthread_mutex_t *mutex, uint64_t selfid,
mutex_seq *newseqp)
{
bool gotlock;
} while (!mutex_seq_atomic_cmpxchgv(seqaddr, &oldseq, &newseq, acquire));
if (gotlock) {
- os_atomic_store(tidaddr, selfid, relaxed);
+ os_atomic_store_wide(tidaddr, selfid, relaxed);
}
PTHREAD_TRACE(psynch_ffmutex_lock_updatebits | DBG_FUNC_END, mutex,
return gotlock;
}
-PTHREAD_NOINLINE
+OS_NOINLINE
static int
-_pthread_mutex_firstfit_lock_wait(_pthread_mutex *mutex, mutex_seq newseq,
+_pthread_mutex_firstfit_lock_wait(pthread_mutex_t *mutex, mutex_seq newseq,
uint64_t oldtid)
{
uint64_t *tidaddr;
MUTEX_GETTID_ADDR(mutex, &tidaddr);
- uint64_t selfid = _pthread_selfid_direct();
+ uint64_t selfid = _pthread_threadid_self_np_direct();
PLOCKSTAT_MUTEX_BLOCK((pthread_mutex_t *)mutex);
do {
oldtid, mutex->mtxopts.value);
PTHREAD_TRACE(psynch_ffmutex_wait | DBG_FUNC_END, mutex,
uval, 0, 0);
- oldtid = os_atomic_load(tidaddr, relaxed);
+ oldtid = os_atomic_load_wide(tidaddr, relaxed);
} while (uval == (uint32_t)-1);
} while (!_pthread_mutex_firstfit_lock_updatebits(mutex, selfid, &newseq));
PLOCKSTAT_MUTEX_BLOCKED((pthread_mutex_t *)mutex, BLOCK_SUCCESS_PLOCKSTAT);
return 0;
}
-PTHREAD_NOEXPORT PTHREAD_NOINLINE
+OS_NOINLINE
int
-_pthread_mutex_firstfit_lock_slow(_pthread_mutex *mutex, bool trylock)
+_pthread_mutex_firstfit_lock_slow(pthread_mutex_t *mutex, bool trylock)
{
int res, recursive = 0;
uint64_t *tidaddr;
MUTEX_GETTID_ADDR(mutex, &tidaddr);
- uint64_t oldtid, selfid = _pthread_selfid_direct();
+ uint64_t oldtid, selfid = _pthread_threadid_self_np_direct();
res = _pthread_mutex_lock_handle_options(mutex, trylock, tidaddr);
if (res > 0) {
bool gotlock;
do {
newseq = oldseq;
- oldtid = os_atomic_load(tidaddr, relaxed);
+ oldtid = os_atomic_load_wide(tidaddr, relaxed);
gotlock = is_rwl_ebit_clear(oldseq.lgenval);
if (trylock && !gotlock) {
newseq.lgenval, newseq.ugenval, 0);
if (gotlock) {
- os_atomic_store(tidaddr, selfid, relaxed);
+ os_atomic_store_wide(tidaddr, selfid, relaxed);
res = 0;
PTHREAD_TRACE(psynch_mutex_ulock, mutex, newseq.lgenval,
newseq.ugenval, selfid);
#pragma mark fast path
-PTHREAD_NOEXPORT PTHREAD_NOINLINE
+OS_NOINLINE
int
-_pthread_mutex_droplock(_pthread_mutex *mutex, uint32_t *flagsp,
+_pthread_mutex_droplock(pthread_mutex_t *mutex, uint32_t *flagsp,
uint32_t **pmtxp, uint32_t *mgenp, uint32_t *ugenp)
{
if (_pthread_mutex_is_fairshare(mutex)) {
mgenp, ugenp);
}
-PTHREAD_NOEXPORT PTHREAD_NOINLINE
+OS_NOINLINE
int
-_pthread_mutex_lock_init_slow(_pthread_mutex *mutex, bool trylock)
+_pthread_mutex_lock_init_slow(pthread_mutex_t *mutex, bool trylock)
{
int res;
if (os_unlikely(_pthread_mutex_is_fairshare(mutex))) {
return _pthread_mutex_fairshare_lock_slow(mutex, trylock);
+ } else if (os_unlikely(_pthread_mutex_uses_ulock(mutex))) {
+ return _pthread_mutex_ulock_lock(mutex, trylock);
}
return _pthread_mutex_firstfit_lock_slow(mutex, trylock);
}
-PTHREAD_NOEXPORT PTHREAD_NOINLINE
+OS_NOINLINE
static int
-_pthread_mutex_unlock_init_slow(_pthread_mutex *mutex)
+_pthread_mutex_unlock_init_slow(pthread_mutex_t *mutex)
{
int res;
if (os_unlikely(_pthread_mutex_is_fairshare(mutex))) {
return _pthread_mutex_fairshare_unlock_slow(mutex);
+ } else if (os_unlikely(_pthread_mutex_uses_ulock(mutex))) {
+ return _pthread_mutex_ulock_unlock(mutex);
}
return _pthread_mutex_firstfit_unlock_slow(mutex);
}
PTHREAD_NOEXPORT_VARIANT
int
-pthread_mutex_unlock(pthread_mutex_t *omutex)
+pthread_mutex_unlock(pthread_mutex_t *mutex)
{
- _pthread_mutex *mutex = (_pthread_mutex *)omutex;
if (os_unlikely(!_pthread_mutex_check_signature_fast(mutex))) {
return _pthread_mutex_unlock_init_slow(mutex);
}
return _pthread_mutex_fairshare_unlock(mutex);
}
+ if (os_unlikely(_pthread_mutex_uses_ulock(mutex))) {
+ return _pthread_mutex_ulock_unlock(mutex);
+ }
+
#if ENABLE_USERSPACE_TRACE
return _pthread_mutex_firstfit_unlock_slow(mutex);
#elif PLOCKSTAT
// is no stale ownership information. If the CAS of the seqaddr
// fails, we may loop, but it's still valid for the owner to be
// SWITCHING/0
- os_atomic_store(tidaddr, 0, relaxed);
+ os_atomic_store_wide(tidaddr, 0, relaxed);
do {
newseq = oldseq;
return 0;
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline int
-_pthread_mutex_firstfit_lock(pthread_mutex_t *omutex, bool trylock)
+_pthread_mutex_firstfit_lock(pthread_mutex_t *mutex, bool trylock)
{
- _pthread_mutex *mutex = (_pthread_mutex *)omutex;
- if (os_unlikely(!_pthread_mutex_check_signature_fast(mutex))) {
- return _pthread_mutex_lock_init_slow(mutex, trylock);
- }
-
- if (os_unlikely(_pthread_mutex_is_fairshare(mutex))) {
- return _pthread_mutex_fairshare_lock(mutex, trylock);
- }
-
-#if ENABLE_USERSPACE_TRACE
- return _pthread_mutex_firstfit_lock_slow(mutex, trylock);
-#elif PLOCKSTAT
- if (PLOCKSTAT_MUTEX_ACQUIRE_ENABLED() || PLOCKSTAT_MUTEX_ERROR_ENABLED()) {
- return _pthread_mutex_firstfit_lock_slow(mutex, trylock);
- }
-#endif
-
/*
* This is the first-fit fast path. The fairshare fast-ish path is in
- * _pthread_mutex_firstfit_lock()
+ * _pthread_mutex_fairshare_lock()
*/
uint64_t *tidaddr;
MUTEX_GETTID_ADDR(mutex, &tidaddr);
- uint64_t selfid = _pthread_selfid_direct();
+ uint64_t selfid = _pthread_threadid_self_np_direct();
mutex_seq *seqaddr;
MUTEX_GETSEQ_ADDR(mutex, &seqaddr);
acquire)));
if (os_likely(gotlock)) {
- os_atomic_store(tidaddr, selfid, relaxed);
+ os_atomic_store_wide(tidaddr, selfid, relaxed);
return 0;
} else if (trylock) {
return EBUSY;
}
}
+OS_ALWAYS_INLINE
+static inline int
+_pthread_mutex_lock(pthread_mutex_t *mutex, bool trylock)
+{
+ if (os_unlikely(!_pthread_mutex_check_signature_fast(mutex))) {
+ return _pthread_mutex_lock_init_slow(mutex, trylock);
+ }
+
+ if (os_unlikely(_pthread_mutex_is_fairshare(mutex))) {
+ return _pthread_mutex_fairshare_lock(mutex, trylock);
+ }
+
+ if (os_unlikely(_pthread_mutex_uses_ulock(mutex))) {
+ return _pthread_mutex_ulock_lock(mutex, trylock);
+ }
+
+#if ENABLE_USERSPACE_TRACE
+ return _pthread_mutex_firstfit_lock_slow(mutex, trylock);
+#elif PLOCKSTAT
+ if (PLOCKSTAT_MUTEX_ACQUIRE_ENABLED() || PLOCKSTAT_MUTEX_ERROR_ENABLED()) {
+ return _pthread_mutex_firstfit_lock_slow(mutex, trylock);
+ }
+#endif
+
+ return _pthread_mutex_firstfit_lock(mutex, trylock);
+}
+
PTHREAD_NOEXPORT_VARIANT
int
pthread_mutex_lock(pthread_mutex_t *mutex)
{
- return _pthread_mutex_firstfit_lock(mutex, false);
+ return _pthread_mutex_lock(mutex, false);
}
PTHREAD_NOEXPORT_VARIANT
int
pthread_mutex_trylock(pthread_mutex_t *mutex)
{
- return _pthread_mutex_firstfit_lock(mutex, true);
+ return _pthread_mutex_lock(mutex, true);
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline int
-_pthread_mutex_init(_pthread_mutex *mutex, const pthread_mutexattr_t *attr,
+_pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr,
uint32_t static_type)
{
mutex->mtxopts.value = 0;
mutex->mtxopts.options.pshared = attr->pshared;
} else {
switch (static_type) {
- case 1:
- mutex->mtxopts.options.type = PTHREAD_MUTEX_ERRORCHECK;
- break;
- case 2:
- mutex->mtxopts.options.type = PTHREAD_MUTEX_RECURSIVE;
- break;
- case 3:
- /* firstfit fall thru */
- case 7:
- mutex->mtxopts.options.type = PTHREAD_MUTEX_DEFAULT;
- break;
- default:
- return EINVAL;
+ case 1:
+ mutex->mtxopts.options.type = PTHREAD_MUTEX_ERRORCHECK;
+ break;
+ case 2:
+ mutex->mtxopts.options.type = PTHREAD_MUTEX_RECURSIVE;
+ break;
+ case 3:
+ /* firstfit fall thru */
+ case 7:
+ mutex->mtxopts.options.type = PTHREAD_MUTEX_DEFAULT;
+ break;
+ default:
+ return EINVAL;
}
mutex->prioceiling = _PTHREAD_DEFAULT_PRIOCEILING;
}
mutex->mtxopts.options.pshared = _PTHREAD_DEFAULT_PSHARED;
}
- mutex->priority = 0;
-
- mutex_seq *seqaddr;
- MUTEX_GETSEQ_ADDR(mutex, &seqaddr);
- uint64_t *tidaddr;
- MUTEX_GETTID_ADDR(mutex, &tidaddr);
+ mutex->priority = 0;
-#if PTHREAD_MUTEX_INIT_UNUSED
- if ((uint32_t*)tidaddr != mutex->m_tid) {
- mutex->mtxopts.options.misalign = 1;
- __builtin_memset(mutex->m_tid, 0xff, sizeof(mutex->m_tid));
- }
- __builtin_memset(mutex->m_mis, 0xff, sizeof(mutex->m_mis));
-#endif // PTHREAD_MUTEX_INIT_UNUSED
- *tidaddr = 0;
- *seqaddr = (mutex_seq){ };
long sig = _PTHREAD_MUTEX_SIG;
if (mutex->mtxopts.options.type == PTHREAD_MUTEX_NORMAL &&
sig = _PTHREAD_MUTEX_SIG_fast;
}
+ // Criteria for ulock eligility:
+ // - not ERRORCHECK or RECURSIVE
+ // - not FAIRSHARE
+ // - not PROCESS_SHARED
+ // - checkfix for rdar://21813573 not active
+ //
+ // All of these should be addressed eventually.
+ if (mutex->mtxopts.options.type == PTHREAD_MUTEX_NORMAL &&
+ mutex->mtxopts.options.policy == _PTHREAD_MTX_OPT_POLICY_FIRSTFIT &&
+ mutex->mtxopts.options.pshared == PTHREAD_PROCESS_PRIVATE &&
+ sig == _PTHREAD_MUTEX_SIG_fast) {
+ mutex->mtxopts.options.ulock = __pthread_mutex_use_ulock;
+ } else {
+ mutex->mtxopts.options.ulock = false;
+ }
+
+ if (mutex->mtxopts.options.ulock) {
+#if PTHREAD_MUTEX_INIT_UNUSED
+ __builtin_memset(&mutex->psynch, 0xff, sizeof(mutex->psynch));
+#endif // PTHREAD_MUTEX_INIT_UNUSED
+
+ mutex->ulock = _PTHREAD_MUTEX_ULOCK_UNLOCKED;
+ } else {
+ mutex_seq *seqaddr;
+ MUTEX_GETSEQ_ADDR(mutex, &seqaddr);
+
+ uint64_t *tidaddr;
+ MUTEX_GETTID_ADDR(mutex, &tidaddr);
+
+#if PTHREAD_MUTEX_INIT_UNUSED
+ if ((uint32_t*)tidaddr != mutex->psynch.m_tid) {
+ // TODO: PTHREAD_STRICT candidate
+ mutex->mtxopts.options.misalign = 1;
+ __builtin_memset(mutex->psynch.m_tid, 0xff,
+ sizeof(mutex->psynch.m_tid));
+ }
+ __builtin_memset(mutex->psynch.m_mis, 0xff, sizeof(mutex->psynch.m_mis));
+#endif // PTHREAD_MUTEX_INIT_UNUSED
+ *tidaddr = 0;
+ *seqaddr = (mutex_seq){ };
+ }
+
#if PTHREAD_MUTEX_INIT_UNUSED
// For detecting copied mutexes and smashes during debugging
uint32_t sig32 = (uint32_t)sig;
*(sig32_ptr + 1) = *(sig32_val + 1);
os_atomic_store(sig32_ptr, *sig32_val, release);
#else
- os_atomic_store2o(mutex, sig, sig, release);
+ os_atomic_store(&mutex->sig, sig, release);
#endif
return 0;
PTHREAD_NOEXPORT_VARIANT
int
-pthread_mutex_destroy(pthread_mutex_t *omutex)
+pthread_mutex_destroy(pthread_mutex_t *mutex)
{
- _pthread_mutex *mutex = (_pthread_mutex *)omutex;
-
int res = EINVAL;
- _PTHREAD_LOCK(mutex->lock);
+ _pthread_lock_lock(&mutex->lock);
if (_pthread_mutex_check_signature(mutex)) {
- mutex_seq *seqaddr;
- MUTEX_GETSEQ_ADDR(mutex, &seqaddr);
-
- mutex_seq seq;
- mutex_seq_load(seqaddr, &seq);
-
- uint64_t *tidaddr;
- MUTEX_GETTID_ADDR(mutex, &tidaddr);
+ // TODO: PTHREAD_STRICT candidate
+ res = EBUSY;
- if ((os_atomic_load(tidaddr, relaxed) == 0) &&
- (seq.lgenval & PTHRW_COUNT_MASK) ==
- (seq.ugenval & PTHRW_COUNT_MASK)) {
- mutex->sig = _PTHREAD_NO_SIG;
+ if (_pthread_mutex_uses_ulock(mutex) &&
+ mutex->ulock.uval == _PTHREAD_MUTEX_ULOCK_UNLOCKED_VALUE) {
res = 0;
} else {
- res = EBUSY;
+ mutex_seq *seqaddr;
+ MUTEX_GETSEQ_ADDR(mutex, &seqaddr);
+
+ mutex_seq seq;
+ mutex_seq_load(seqaddr, &seq);
+
+ uint64_t *tidaddr;
+ MUTEX_GETTID_ADDR(mutex, &tidaddr);
+
+ if ((os_atomic_load_wide(tidaddr, relaxed) == 0) &&
+ (seq.lgenval & PTHRW_COUNT_MASK) ==
+ (seq.ugenval & PTHRW_COUNT_MASK)) {
+ res = 0;
+ }
}
} else if (_pthread_mutex_check_signature_init(mutex)) {
- mutex->sig = _PTHREAD_NO_SIG;
res = 0;
}
- _PTHREAD_UNLOCK(mutex->lock);
+
+ if (res == 0) {
+ mutex->sig = _PTHREAD_NO_SIG;
+ }
+
+ _pthread_lock_unlock(&mutex->lock);
return res;
}
int
pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
{
-#if __DARWIN_UNIX03
- if (__unix_conforming == 0) {
- __unix_conforming = 1;
- }
if (attr->sig != _PTHREAD_MUTEX_ATTR_SIG) {
return EINVAL;
}
-#endif /* __DARWIN_UNIX03 */
attr->sig = _PTHREAD_NO_SIG;
return 0;
#include "resolver.h"
#include "internal.h"
-#if DEBUG
-#include <platform/compat.h> // for bzero
-#endif
#ifdef PLOCKSTAT
#include "plockstat.h"
// maximum number of times a read lock may be obtained
#define MAX_READ_LOCKS (INT_MAX - 1)
-union rwlock_seq; // forward declaration
-enum rwlock_seqfields; // forward declaration
-
-PTHREAD_NOEXPORT PTHREAD_WEAK // prevent inlining of return value into callers
-int _pthread_rwlock_lock_slow(pthread_rwlock_t *orwlock, bool readlock,
- bool trylock);
-
-PTHREAD_NOEXPORT PTHREAD_WEAK // prevent inlining of return value into callers
-int _pthread_rwlock_unlock_slow(pthread_rwlock_t *orwlock,
- enum rwlock_seqfields updated_seqfields);
-
#if defined(__LP64__)
#define RWLOCK_USE_INT128 1
if (_pthread_debuglog >= 0) { \
_simple_dprintf(_pthread_debuglog, "rw_" #op " %p tck %7llu thr %llx " \
"L %x -> %x S %x -> %x U %x -> %x updt %x\n", rwlock, \
- mach_absolute_time() - _pthread_debugstart, _pthread_selfid_direct(), \
+ mach_absolute_time() - _pthread_debugstart, _pthread_threadid_self_np_direct(), \
(f) & RWLOCK_SEQ_LS ? (oldseq).lcntval : 0, \
(f) & RWLOCK_SEQ_LS ? (newseq).lcntval : 0, \
(f) & RWLOCK_SEQ_LS ? (oldseq).rw_seq : 0, \
#error RWLOCK_GETSEQ_ADDR assumes little endian layout of sequence words
#endif
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline void
-RWLOCK_GETSEQ_ADDR(_pthread_rwlock *rwlock, rwlock_seq **seqaddr)
+RWLOCK_GETSEQ_ADDR(pthread_rwlock_t *rwlock, rwlock_seq **seqaddr)
{
// 128-bit aligned address inside rw_seq & rw_mis arrays
*seqaddr = (void*)(((uintptr_t)rwlock->rw_seq + 0xful) & ~0xful);
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline void
-RWLOCK_GETTID_ADDR(_pthread_rwlock *rwlock, uint64_t **tidaddr)
+RWLOCK_GETTID_ADDR(pthread_rwlock_t *rwlock, uint64_t **tidaddr)
{
// 64-bit aligned address inside rw_tid array (&rw_tid[0] for aligned lock)
*tidaddr = (void*)(((uintptr_t)rwlock->rw_tid + 0x7ul) & ~0x7ul);
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline void
rwlock_seq_load(rwlock_seq *seqaddr, rwlock_seq *oldseqval,
const rwlock_seqfields seqfields)
}
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline void
rwlock_seq_atomic_load_relaxed(rwlock_seq *seqaddr, rwlock_seq *oldseqval,
const rwlock_seqfields seqfields)
// Workaround clang armv81 codegen bug for 128bit os_atomic_load
// rdar://problem/31213932
oldseqval->seq_LSU = seqaddr->seq_LSU;
- while (!os_atomic_cmpxchgvw(&seqaddr->atomic_seq_LSU,
+ while (!os_atomic_cmpxchgv(&seqaddr->atomic_seq_LSU,
oldseqval->seq_LSU, oldseqval->seq_LSU, &oldseqval->seq_LSU,
relaxed));
#else
- oldseqval->seq_LSU = os_atomic_load(&seqaddr->atomic_seq_LSU, relaxed);
+ oldseqval->seq_LSU = os_atomic_load_wide(&seqaddr->atomic_seq_LSU, relaxed);
#endif
#else
- oldseqval->seq_LS = os_atomic_load(&seqaddr->atomic_seq_LS, relaxed);
+ oldseqval->seq_LS = os_atomic_load_wide(&seqaddr->atomic_seq_LS, relaxed);
oldseqval->seq_U = os_atomic_load(&seqaddr->atomic_seq_U, relaxed);
#endif
break;
case RWLOCK_SEQ_LS:
- oldseqval->seq_LS = os_atomic_load(&seqaddr->atomic_seq_LS, relaxed);
+ oldseqval->seq_LS = os_atomic_load_wide(&seqaddr->atomic_seq_LS, relaxed);
break;
#if DEBUG // unused
case RWLOCK_SEQ_U:
#define rwlock_seq_atomic_load(seqaddr, oldseqval, seqfields, m) \
rwlock_seq_atomic_load_##m(seqaddr, oldseqval, seqfields)
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline rwlock_seqfields
rwlock_seq_atomic_cmpxchgv_relaxed(rwlock_seq *seqaddr, rwlock_seq *oldseqval,
rwlock_seq *newseqval, const rwlock_seqfields seqfields)
return updated_seqfields;
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline rwlock_seqfields
rwlock_seq_atomic_cmpxchgv_acquire(rwlock_seq *seqaddr, rwlock_seq *oldseqval,
rwlock_seq *newseqval, const rwlock_seqfields seqfields)
return updated_seqfields;
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline rwlock_seqfields
rwlock_seq_atomic_cmpxchgv_release(rwlock_seq *seqaddr, rwlock_seq *oldseqval,
rwlock_seq *newseqval, const rwlock_seqfields seqfields)
if (!r) oldseqval->seq_U = newseqval->seq_U;
updated_seqfields = r ? RWLOCK_SEQ_LSU : RWLOCK_SEQ_U;
} else {
- oldseqval->seq_LS = os_atomic_load(&seqaddr->atomic_seq_LS,relaxed);
+ oldseqval->seq_LS = os_atomic_load_wide(&seqaddr->atomic_seq_LS,
+ relaxed);
}
#endif
break;
{
int res = EINVAL;
if (attr->sig == _PTHREAD_RWLOCK_ATTR_SIG) {
-#if __DARWIN_UNIX03
if (( pshared == PTHREAD_PROCESS_PRIVATE) ||
(pshared == PTHREAD_PROCESS_SHARED))
-#else /* __DARWIN_UNIX03 */
- if ( pshared == PTHREAD_PROCESS_PRIVATE)
-#endif /* __DARWIN_UNIX03 */
{
attr->pshared = pshared ;
res = 0;
#endif /* !BUILDING_VARIANT ] */
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline int
-_pthread_rwlock_init(_pthread_rwlock *rwlock, const pthread_rwlockattr_t *attr)
+_pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr)
{
uint64_t *tidaddr;
RWLOCK_GETTID_ADDR(rwlock, &tidaddr);
*(sig32_ptr + 1) = *(sig32_val + 1);
os_atomic_store(sig32_ptr, *sig32_val, release);
#else
- os_atomic_store2o(rwlock, sig, sig, release);
+ os_atomic_store(&rwlock->sig, sig, release);
#endif
return 0;
return(rval);
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline void
-_pthread_rwlock_updateval(_pthread_rwlock *rwlock, uint32_t updateval)
+_pthread_rwlock_updateval(pthread_rwlock_t *rwlock, uint32_t updateval)
{
bool isoverlap = (updateval & PTH_RWL_MBIT) != 0;
RWLOCK_DEBUG_SEQ(update, rwlock, oldseq, newseq, updateval, RWLOCK_SEQ_LS);
}
-#if __DARWIN_UNIX03
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline int
-_pthread_rwlock_check_busy(_pthread_rwlock *rwlock)
+_pthread_rwlock_check_busy(pthread_rwlock_t *rwlock)
{
int res = 0;
return res;
}
-#endif /* __DARWIN_UNIX03 */
PTHREAD_NOEXPORT_VARIANT
int
-pthread_rwlock_destroy(pthread_rwlock_t *orwlock)
+pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
{
int res = 0;
- _pthread_rwlock *rwlock = (_pthread_rwlock *)orwlock;
- _PTHREAD_LOCK(rwlock->lock);
+ _pthread_lock_lock(&rwlock->lock);
if (_pthread_rwlock_check_signature(rwlock)) {
-#if __DARWIN_UNIX03
res = _pthread_rwlock_check_busy(rwlock);
-#endif /* __DARWIN_UNIX03 */
} else if (!_pthread_rwlock_check_signature_init(rwlock)) {
res = EINVAL;
}
if (res == 0) {
rwlock->sig = _PTHREAD_NO_SIG;
}
- _PTHREAD_UNLOCK(rwlock->lock);
+ _pthread_lock_unlock(&rwlock->lock);
return res;
}
PTHREAD_NOEXPORT_VARIANT
int
-pthread_rwlock_init(pthread_rwlock_t *orwlock, const pthread_rwlockattr_t *attr)
+pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr)
{
int res = 0;
- _pthread_rwlock *rwlock = (_pthread_rwlock *)orwlock;
-#if __DARWIN_UNIX03
if (attr && attr->sig != _PTHREAD_RWLOCK_ATTR_SIG) {
res = EINVAL;
}
if (res == 0 && _pthread_rwlock_check_signature(rwlock)) {
res = _pthread_rwlock_check_busy(rwlock);
}
-#endif
if (res == 0) {
- _PTHREAD_LOCK_INIT(rwlock->lock);
+ _pthread_lock_init(&rwlock->lock);
res = _pthread_rwlock_init(rwlock, attr);
}
return res;
}
-PTHREAD_NOINLINE
+OS_NOINLINE
static int
-_pthread_rwlock_check_init_slow(pthread_rwlock_t *orwlock)
+_pthread_rwlock_check_init_slow(pthread_rwlock_t *rwlock)
{
int res = EINVAL;
- _pthread_rwlock *rwlock = (_pthread_rwlock *)orwlock;
if (_pthread_rwlock_check_signature_init(rwlock)) {
- _PTHREAD_LOCK(rwlock->lock);
+ _pthread_lock_lock(&rwlock->lock);
if (_pthread_rwlock_check_signature_init(rwlock)) {
res = _pthread_rwlock_init(rwlock, NULL);
} else if (_pthread_rwlock_check_signature(rwlock)){
res = 0;
}
- _PTHREAD_UNLOCK(rwlock->lock);
+ _pthread_lock_unlock(&rwlock->lock);
} else if (_pthread_rwlock_check_signature(rwlock)){
res = 0;
}
if (res != 0) {
- PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, res);
+ PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, res);
}
return res;
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline int
-_pthread_rwlock_check_init(pthread_rwlock_t *orwlock)
+_pthread_rwlock_check_init(pthread_rwlock_t *rwlock)
{
int res = 0;
- _pthread_rwlock *rwlock = (_pthread_rwlock *)orwlock;
if (!_pthread_rwlock_check_signature(rwlock)) {
- return _pthread_rwlock_check_init_slow(orwlock);
+ return _pthread_rwlock_check_init_slow(rwlock);
}
return res;
}
-PTHREAD_NOINLINE
+OS_NOINLINE
static int
-_pthread_rwlock_lock_wait(pthread_rwlock_t *orwlock, bool readlock,
+_pthread_rwlock_lock_wait(pthread_rwlock_t *rwlock, bool readlock,
rwlock_seq newseq)
{
int res;
- _pthread_rwlock *rwlock = (_pthread_rwlock *)orwlock;
#ifdef PLOCKSTAT
int plockstat = readlock ? READ_LOCK_PLOCKSTAT : WRITE_LOCK_PLOCKSTAT;
uint32_t updateval;
- PLOCKSTAT_RW_BLOCK(orwlock, plockstat);
+ PLOCKSTAT_RW_BLOCK(rwlock, plockstat);
do {
if (readlock) {
- updateval = __psynch_rw_rdlock(orwlock, newseq.lcntval,
+ updateval = __psynch_rw_rdlock(rwlock, newseq.lcntval,
newseq.ucntval, newseq.rw_seq, rwlock->rw_flags);
} else {
- updateval = __psynch_rw_wrlock(orwlock, newseq.lcntval,
+ updateval = __psynch_rw_wrlock(rwlock, newseq.lcntval,
newseq.ucntval, newseq.rw_seq, rwlock->rw_flags);
}
if (updateval == (uint32_t)-1) {
if (res == 0) {
_pthread_rwlock_updateval(rwlock, updateval);
- PLOCKSTAT_RW_BLOCKED(orwlock, plockstat, BLOCK_SUCCESS_PLOCKSTAT);
+ PLOCKSTAT_RW_BLOCKED(rwlock, plockstat, BLOCK_SUCCESS_PLOCKSTAT);
} else {
- PLOCKSTAT_RW_BLOCKED(orwlock, plockstat, BLOCK_FAIL_PLOCKSTAT);
+ PLOCKSTAT_RW_BLOCKED(rwlock, plockstat, BLOCK_FAIL_PLOCKSTAT);
PTHREAD_INTERNAL_CRASH(res, "kernel rwlock returned unknown error");
}
return res;
}
-PTHREAD_NOEXPORT PTHREAD_NOINLINE
+OS_NOINLINE
int
-_pthread_rwlock_lock_slow(pthread_rwlock_t *orwlock, bool readlock,
+_pthread_rwlock_lock_slow(pthread_rwlock_t *rwlock, bool readlock,
bool trylock)
{
int res;
- _pthread_rwlock *rwlock = (_pthread_rwlock *)orwlock;
#ifdef PLOCKSTAT
int plockstat = readlock ? READ_LOCK_PLOCKSTAT : WRITE_LOCK_PLOCKSTAT;
#endif
- res = _pthread_rwlock_check_init(orwlock);
+ res = _pthread_rwlock_check_init(rwlock);
if (res != 0) return res;
rwlock_seq *seqaddr;
rwlock_seq oldseq, newseq;
rwlock_seq_atomic_load(seqaddr, &oldseq, RWLOCK_SEQ_LSU, relaxed);
-#if __DARWIN_UNIX03
uint64_t *tidaddr;
RWLOCK_GETTID_ADDR(rwlock, &tidaddr);
- uint64_t selfid = _pthread_selfid_direct();
+ uint64_t selfid = _pthread_threadid_self_np_direct();
if (is_rwl_ebit_set(oldseq.lcntval)) {
- if (os_atomic_load(tidaddr, relaxed) == selfid) return EDEADLK;
+ if (os_atomic_load_wide(tidaddr, relaxed) == selfid) return EDEADLK;
}
-#endif /* __DARWIN_UNIX03 */
int retry_count;
bool gotlock;
RWLOCK_SEQ_LS, acquire));
if (gotlock) {
-#if __DARWIN_UNIX03
- if (!readlock) os_atomic_store(tidaddr, selfid, relaxed);
-#endif /* __DARWIN_UNIX03 */
+ if (!readlock) os_atomic_store_wide(tidaddr, selfid, relaxed);
res = 0;
} else if (trylock) {
res = EBUSY;
} else {
- res = _pthread_rwlock_lock_wait(orwlock, readlock, newseq);
+ res = _pthread_rwlock_lock_wait(rwlock, readlock, newseq);
}
out:
#ifdef PLOCKSTAT
if (res == 0) {
- PLOCKSTAT_RW_ACQUIRE(orwlock, plockstat);
+ PLOCKSTAT_RW_ACQUIRE(rwlock, plockstat);
} else {
- PLOCKSTAT_RW_ERROR(orwlock, plockstat, res);
+ PLOCKSTAT_RW_ERROR(rwlock, plockstat, res);
}
#endif
return res;
}
-PTHREAD_ALWAYS_INLINE
+OS_ALWAYS_INLINE
static inline int
-_pthread_rwlock_lock(pthread_rwlock_t *orwlock, bool readlock, bool trylock)
+_pthread_rwlock_lock(pthread_rwlock_t *rwlock, bool readlock, bool trylock)
{
- _pthread_rwlock *rwlock = (_pthread_rwlock *)orwlock;
#if PLOCKSTAT
if (PLOCKSTAT_RW_ACQUIRE_ENABLED() || PLOCKSTAT_RW_ERROR_ENABLED()) {
- return _pthread_rwlock_lock_slow(orwlock, readlock, trylock);
+ return _pthread_rwlock_lock_slow(rwlock, readlock, trylock);
}
#endif
if (os_unlikely(!_pthread_rwlock_check_signature(rwlock))) {
- return _pthread_rwlock_lock_slow(orwlock, readlock, trylock);
+ return _pthread_rwlock_lock_slow(rwlock, readlock, trylock);
}
rwlock_seq *seqaddr;
// slowpath below (which has rwlock_seq_atomic_load)
rwlock_seq_load(seqaddr, &oldseq, RWLOCK_SEQ_LSU);
-#if __DARWIN_UNIX03
if (os_unlikely(is_rwl_ebit_set(oldseq.lcntval))) {
- return _pthread_rwlock_lock_slow(orwlock, readlock, trylock);
+ return _pthread_rwlock_lock_slow(rwlock, readlock, trylock);
}
-#endif /* __DARWIN_UNIX03 */
bool gotlock;
do {
if (readlock) {
if (os_unlikely(diff_genseq(oldseq.lcntval, oldseq.ucntval) >=
PTHRW_MAX_READERS)) {
- return _pthread_rwlock_lock_slow(orwlock, readlock,trylock);
+ return _pthread_rwlock_lock_slow(rwlock, readlock, trylock);
}
// Need to update L (remove U bit) and S word
newseq.lcntval &= ~PTH_RWL_UBIT;
newseq.lcntval += PTHRW_INC;
newseq.rw_seq += PTHRW_INC;
} else {
- return _pthread_rwlock_lock_slow(orwlock, readlock, trylock);
+ return _pthread_rwlock_lock_slow(rwlock, readlock, trylock);
}
} while (os_unlikely(!rwlock_seq_atomic_cmpxchgv(seqaddr, &oldseq, &newseq,
RWLOCK_SEQ_LS, acquire)));
if (os_likely(gotlock)) {
-#if __DARWIN_UNIX03
if (!readlock) {
uint64_t *tidaddr;
RWLOCK_GETTID_ADDR(rwlock, &tidaddr);
- uint64_t selfid = _pthread_selfid_direct();
- os_atomic_store(tidaddr, selfid, relaxed);
+ uint64_t selfid = _pthread_threadid_self_np_direct();
+ os_atomic_store_wide(tidaddr, selfid, relaxed);
}
-#endif /* __DARWIN_UNIX03 */
return 0;
} else if (trylock) {
return EBUSY;
PTHREAD_NOEXPORT_VARIANT
int
-pthread_rwlock_rdlock(pthread_rwlock_t *orwlock)
+pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
{
// read lock, no try
- return _pthread_rwlock_lock(orwlock, true, false);
+ return _pthread_rwlock_lock(rwlock, true, false);
}
PTHREAD_NOEXPORT_VARIANT
int
-pthread_rwlock_tryrdlock(pthread_rwlock_t *orwlock)
+pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
{
// read lock, try lock
- return _pthread_rwlock_lock(orwlock, true, true);
+ return _pthread_rwlock_lock(rwlock, true, true);
}
PTHREAD_NOEXPORT_VARIANT
int
-pthread_rwlock_wrlock(pthread_rwlock_t *orwlock)
+pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
{
// write lock, no try
- return _pthread_rwlock_lock(orwlock, false, false);
+ return _pthread_rwlock_lock(rwlock, false, false);
}
PTHREAD_NOEXPORT_VARIANT
int
-pthread_rwlock_trywrlock(pthread_rwlock_t *orwlock)
+pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
{
// write lock, try lock
- return _pthread_rwlock_lock(orwlock, false, true);
+ return _pthread_rwlock_lock(rwlock, false, true);
}
-PTHREAD_NOINLINE
+OS_NOINLINE
static int
-_pthread_rwlock_unlock_drop(pthread_rwlock_t *orwlock, rwlock_seq oldseq,
+_pthread_rwlock_unlock_drop(pthread_rwlock_t *rwlock, rwlock_seq oldseq,
rwlock_seq newseq)
{
int res;
- _pthread_rwlock *rwlock = (_pthread_rwlock *)orwlock;
RWLOCK_DEBUG_SEQ(unlock, rwlock, oldseq, newseq, !droplock, RWLOCK_SEQ_LSU);
uint32_t updateval;
do {
- updateval = __psynch_rw_unlock(orwlock, oldseq.lcntval,
+ updateval = __psynch_rw_unlock(rwlock, oldseq.lcntval,
newseq.ucntval, newseq.rw_seq, rwlock->rw_flags);
if (updateval == (uint32_t)-1) {
res = errno;
return res;
}
-PTHREAD_NOEXPORT PTHREAD_NOINLINE
+OS_NOINLINE
int
-_pthread_rwlock_unlock_slow(pthread_rwlock_t *orwlock,
+_pthread_rwlock_unlock_slow(pthread_rwlock_t *rwlock,
rwlock_seqfields updated_seqfields)
{
int res;
- _pthread_rwlock *rwlock = (_pthread_rwlock *)orwlock;
rwlock_seqfields seqfields = RWLOCK_SEQ_LSU;
#ifdef PLOCKSTAT
int wrlock = 0;
#endif
- res = _pthread_rwlock_check_init(orwlock);
+ res = _pthread_rwlock_check_init(rwlock);
if (res != 0) return res;
rwlock_seq *seqaddr;
#ifdef PLOCKSTAT
wrlock = 1;
#endif
-#if __DARWIN_UNIX03
uint64_t *tidaddr;
RWLOCK_GETTID_ADDR(rwlock, &tidaddr);
- os_atomic_store(tidaddr, 0, relaxed);
-#endif /* __DARWIN_UNIX03 */
+ os_atomic_store_wide(tidaddr, 0, relaxed);
}
bool droplock;
seqaddr, &oldseq, &newseq, seqfields, release)));
if (droplock) {
- res = _pthread_rwlock_unlock_drop(orwlock, oldseq, newseq);
+ res = _pthread_rwlock_unlock_drop(rwlock, oldseq, newseq);
}
- PLOCKSTAT_RW_RELEASE(orwlock, wrlock);
+ PLOCKSTAT_RW_RELEASE(rwlock, wrlock);
return res;
}
PTHREAD_NOEXPORT_VARIANT
int
-pthread_rwlock_unlock(pthread_rwlock_t *orwlock)
+pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
{
- _pthread_rwlock *rwlock = (_pthread_rwlock *)orwlock;
rwlock_seqfields seqfields = RWLOCK_SEQ_LSU;
rwlock_seqfields updated_seqfields = RWLOCK_SEQ_NONE;
#if PLOCKSTAT
if (PLOCKSTAT_RW_RELEASE_ENABLED() || PLOCKSTAT_RW_ERROR_ENABLED()) {
- return _pthread_rwlock_unlock_slow(orwlock, updated_seqfields);
+ return _pthread_rwlock_unlock_slow(rwlock, updated_seqfields);
}
#endif
if (os_unlikely(!_pthread_rwlock_check_signature(rwlock))) {
- return _pthread_rwlock_unlock_slow(orwlock, updated_seqfields);
+ return _pthread_rwlock_unlock_slow(rwlock, updated_seqfields);
}
rwlock_seq *seqaddr;
}
if (is_rwl_ebit_set(oldseq.lcntval)) {
-#if __DARWIN_UNIX03
uint64_t *tidaddr;
RWLOCK_GETTID_ADDR(rwlock, &tidaddr);
- os_atomic_store(tidaddr, 0, relaxed);
-#endif /* __DARWIN_UNIX03 */
+ os_atomic_store_wide(tidaddr, 0, relaxed);
}
do {
if (updated_seqfields) {
- return _pthread_rwlock_unlock_slow(orwlock, updated_seqfields);
+ return _pthread_rwlock_unlock_slow(rwlock, updated_seqfields);
}
newseq = oldseq;
// no L/S update if lock is not exclusive or no writer pending
// kernel transition only needed if U == S
} else {
- return _pthread_rwlock_unlock_slow(orwlock, updated_seqfields);
+ return _pthread_rwlock_unlock_slow(rwlock, updated_seqfields);
}
}
} while (os_unlikely(seqfields != (updated_seqfields =
*/
#include "internal.h"
-#include <TargetConditionals.h>
#ifndef PTHREAD_KEY_LEGACY_SUPPORT
#if TARGET_OS_DRIVERKIT
int res = EAGAIN; // Returns EAGAIN if key cannot be allocated.
pthread_key_t k;
- _PTHREAD_LOCK(__pthread_tsd_lock);
+ _pthread_lock_lock(&__pthread_tsd_lock);
for (k = __pthread_tsd_start; k < __pthread_tsd_end; k++) {
if (_pthread_key_set_destructor(k, destructor)) {
*key = k;
break;
}
}
- _PTHREAD_UNLOCK(__pthread_tsd_lock);
+ _pthread_lock_unlock(&__pthread_tsd_lock);
return res;
}
{
int res = EINVAL; // Returns EINVAL if key is not allocated.
- _PTHREAD_LOCK(__pthread_tsd_lock);
+ _pthread_lock_lock(&__pthread_tsd_lock);
if (key >= __pthread_tsd_start && key < __pthread_tsd_end) {
if (_pthread_key_unset_destructor(key)) {
- struct _pthread *p;
- _PTHREAD_LOCK(_pthread_list_lock);
+ pthread_t p;
+ _pthread_lock_lock(&_pthread_list_lock);
TAILQ_FOREACH(p, &__pthread_head, tl_plist) {
// No lock for word-sized write.
p->tsd[key] = 0;
}
- _PTHREAD_UNLOCK(_pthread_list_lock);
+ _pthread_lock_unlock(&_pthread_list_lock);
res = 0;
}
}
- _PTHREAD_UNLOCK(__pthread_tsd_lock);
+ _pthread_lock_unlock(&__pthread_tsd_lock);
return res;
}
-#endif // !VARIANT_DYLD
-int
-pthread_setspecific(pthread_key_t key, const void *value)
+static inline int
+_pthread_setspecific(pthread_t thread, pthread_key_t key, const void *value)
{
int res = EINVAL;
-#if !VARIANT_DYLD
if (key >= __pthread_tsd_first && key < __pthread_tsd_end) {
bool created = _pthread_key_get_destructor(key, NULL);
if (key < __pthread_tsd_start || created) {
- struct _pthread *self = pthread_self();
- self->tsd[key] = (void *)value;
+ thread->tsd[key] = (void *)value;
res = 0;
if (key < __pthread_tsd_start) {
// XXX: is this really necessary?
_pthread_key_set_destructor(key, NULL);
}
- if (key > self->max_tsd_key) {
- self->max_tsd_key = (uint16_t)key;
+ if (key > thread->max_tsd_key) {
+ thread->max_tsd_key = (uint16_t)key;
}
}
}
-#endif // !VARIANT_DYLD
return res;
}
+#endif // !VARIANT_DYLD
+
+int
+pthread_setspecific(pthread_key_t key, const void *value)
+{
+#if VARIANT_DYLD
+ return ENOTSUP;
+#else
+ return _pthread_setspecific(pthread_self(), key, value);
+#endif // !VARIANT_DYLD
+}
int
_pthread_setspecific_static(pthread_key_t key, void *value)
}
#if !VARIANT_DYLD
+int
+pthread_introspection_setspecific_np(pthread_t thread,
+ pthread_key_t key, const void *value)
+{
+ pthread_t self = _pthread_self();
+ if (os_unlikely(self->introspection != PTHREAD_INTROSPECTION_THREAD_CREATE)) {
+ PTHREAD_CLIENT_CRASH(0, "Calling pthread_introspection_setspecific_np "
+ "outside of a CREATE introspection hook");
+ }
+ return _pthread_setspecific(thread, key, value);
+
+}
+
+void *
+pthread_introspection_getspecific_np(pthread_t thread, pthread_key_t key)
+{
+ pthread_t self = _pthread_self();
+ if (os_unlikely(self->introspection != PTHREAD_INTROSPECTION_THREAD_DESTROY)) {
+ PTHREAD_CLIENT_CRASH(0, "Calling pthread_introspection_getspecific_np "
+ "outside of a DESTROY introspection hook");
+ }
+ return thread->tsd[key];
+}
+
static void
_pthread_tsd_cleanup_key(pthread_t self, pthread_key_t key)
{
}
}
}
-#endif // !VARIANT_DYLD
-#if !VARIANT_DYLD
static void
_pthread_tsd_cleanup_new(pthread_t self)
{
// Iterate from dynamic-key start to dynamic-key end, if the key has both
// a desctructor and a value then _pthread_tsd_cleanup_key would cause
// us to re-trigger the destructor.
- Dl_info i;
pthread_key_t k;
for (k = __pthread_tsd_start; k < __pthread_tsd_end; k++) {
if (value && destructor) {
_simple_asl_log(ASL_LEVEL_ERR, "pthread_tsd",
"warning: dynamic tsd keys dirty after static key cleanup loop.");
-
+#if 0
+ // enable this for debugging
+ Dl_info i;
if (dladdr(destructor, &i) == 0) {
_simple_asl_log(ASL_LEVEL_ERR, "pthread_tsd", i.dli_fname);
_simple_asl_log(ASL_LEVEL_ERR, "pthread_tsd", i.dli_saddr);
}
+#endif
}
}
}
{
int res = EINVAL; // Returns EINVAL if key is out of range.
if (key >= __pthread_tsd_first && key < __pthread_tsd_start) {
- _PTHREAD_LOCK(__pthread_tsd_lock);
+ _pthread_lock_lock(&__pthread_tsd_lock);
_pthread_key_set_destructor(key, destructor);
if (key > __pthread_tsd_max) {
__pthread_tsd_max = key;
}
- _PTHREAD_UNLOCK(__pthread_tsd_lock);
+ _pthread_lock_unlock(&__pthread_tsd_lock);
res = 0;
}
return res;
_pthread_validate_signature(self);
return self;
}
+
+// rdar://57406917
+pthread_t
+_pthread_self(void)
+{
+ return pthread_self();
+}
#include "internal.h"
-#include <_simple.h>
#include <mach/mach_vm.h>
#include <unistd.h>
#include <spawn.h>
#include <spawn_private.h>
+#include <pthread/spawn.h>
#include <sys/spawn_internal.h>
#include <sys/ulock.h>
-// TODO: remove me when internal.h can include *_private.h itself
-#include "workqueue_private.h"
-#include "qos_private.h"
-
#define PTHREAD_OVERRIDE_SIGNATURE (0x6f766572)
#define PTHREAD_OVERRIDE_SIG_DEAD (0x7265766f)
+#if !defined(VARIANT_STATIC)
+// internally redirected upcalls in case qos overrides are used
+// before __pthread_init has run
+PTHREAD_NOEXPORT void *
+malloc(size_t sz)
+{
+ if (os_likely(_pthread_malloc)) {
+ return _pthread_malloc(sz);
+ } else {
+ return NULL;
+ }
+}
+
+PTHREAD_NOEXPORT void
+free(void *p)
+{
+ if (os_likely(_pthread_free)) {
+ _pthread_free(p);
+ }
+}
+#endif // VARIANT_STATIC
+
struct pthread_override_s
{
uint32_t sig;
int
pthread_get_qos_class_np(pthread_t thread, qos_class_t *qc, int *relpri)
{
- pthread_priority_t pp = thread->tsd[_PTHREAD_TSD_SLOT_PTHREAD_QOS_CLASS];
+ pthread_priority_t pp = _pthread_tsd_slot(thread, PTHREAD_QOS_CLASS);
_pthread_priority_split(pp, qc, relpri);
return 0;
}
posix_spawnattr_set_qos_class_np(posix_spawnattr_t * __restrict __attr, qos_class_t __qos_class)
{
switch (__qos_class) {
- case QOS_CLASS_UTILITY:
- return posix_spawnattr_set_qos_clamp_np(__attr, POSIX_SPAWN_PROC_CLAMP_UTILITY);
- case QOS_CLASS_BACKGROUND:
- return posix_spawnattr_set_qos_clamp_np(__attr, POSIX_SPAWN_PROC_CLAMP_BACKGROUND);
- case QOS_CLASS_MAINTENANCE:
- return posix_spawnattr_set_qos_clamp_np(__attr, POSIX_SPAWN_PROC_CLAMP_MAINTENANCE);
- default:
- return EINVAL;
+ case QOS_CLASS_UTILITY:
+ return posix_spawnattr_set_qos_clamp_np(__attr, POSIX_SPAWN_PROC_CLAMP_UTILITY);
+ case QOS_CLASS_BACKGROUND:
+ return posix_spawnattr_set_qos_clamp_np(__attr, POSIX_SPAWN_PROC_CLAMP_BACKGROUND);
+ case QOS_CLASS_MAINTENANCE:
+ return posix_spawnattr_set_qos_clamp_np(__attr, POSIX_SPAWN_PROC_CLAMP_MAINTENANCE);
+ default:
+ return EINVAL;
}
}
}
switch (clamp) {
- case POSIX_SPAWN_PROC_CLAMP_UTILITY:
- *__qos_class = QOS_CLASS_UTILITY;
- break;
- case POSIX_SPAWN_PROC_CLAMP_BACKGROUND:
- *__qos_class = QOS_CLASS_BACKGROUND;
- break;
- case POSIX_SPAWN_PROC_CLAMP_MAINTENANCE:
- *__qos_class = QOS_CLASS_MAINTENANCE;
- break;
- default:
- *__qos_class = QOS_CLASS_UNSPECIFIED;
- break;
+ case POSIX_SPAWN_PROC_CLAMP_UTILITY:
+ *__qos_class = QOS_CLASS_UTILITY;
+ break;
+ case POSIX_SPAWN_PROC_CLAMP_BACKGROUND:
+ *__qos_class = QOS_CLASS_BACKGROUND;
+ break;
+ case POSIX_SPAWN_PROC_CLAMP_MAINTENANCE:
+ *__qos_class = QOS_CLASS_MAINTENANCE;
+ break;
+ default:
+ *__qos_class = QOS_CLASS_UNSPECIFIED;
+ break;
}
return 0;
--- /dev/null
+/*
+ * Copyright (c) 2003-2019 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#ifndef __LIBPTHREAD_TYPES_INTERNAL_H__
+#define __LIBPTHREAD_TYPES_INTERNAL_H__
+
+/*!
+ * @file types_internal.h
+ *
+ * @brief
+ * This file exposes all the internal pthread types used by the library.
+ *
+ * @discussion
+ * This header must be included first, as it masks the opaque definitions
+ * exposed to libpthread clients in the SDK.
+ */
+
+#define _PTHREAD_ONCE_T
+typedef struct pthread_once_s pthread_once_t;
+
+#define _PTHREAD_MUTEX_T
+#define _PTHREAD_MUTEXATTR_T
+typedef struct pthread_mutex_s pthread_mutex_t;
+typedef struct pthread_mutexattr_s pthread_mutexattr_t;
+
+#define _PTHREAD_COND_T
+#define _PTHREAD_CONDATTR_T
+typedef struct pthread_cond_s pthread_cond_t;
+typedef struct pthread_condattr_s pthread_condattr_t;
+
+#define _PTHREAD_RWLOCK_T
+#define _PTHREAD_RWLOCKATTR_T
+typedef struct pthread_rwlock_s pthread_rwlock_t;
+typedef struct pthread_rwlockattr_s pthread_rwlockattr_t;
+
+#define _PTHREAD_T
+#define _PTHREAD_ATTR_T
+typedef struct pthread_s *pthread_t;
+typedef struct pthread_attr_s pthread_attr_t;
+
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/queue.h>
+#include <sys/param.h>
+
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+
+#include <os/base_private.h>
+#include <os/once_private.h>
+#include <os/lock.h>
+
+#include "pthread/posix_sched.h"
+#include "pthread/workqueue_private.h"
+#include "sys/_pthread/_pthread_types.h"
+
+#pragma mark - constants
+
+#define _PTHREAD_NO_SIG 0x00000000
+#define _PTHREAD_MUTEX_ATTR_SIG 0x4D545841 /* 'MTXA' */
+#define _PTHREAD_MUTEX_SIG 0x4D555458 /* 'MUTX' */
+#define _PTHREAD_MUTEX_SIG_fast 0x4D55545A /* 'MUTZ' */
+#define _PTHREAD_MUTEX_SIG_MASK 0xfffffffd
+#define _PTHREAD_MUTEX_SIG_CMP 0x4D555458 /* _PTHREAD_MUTEX_SIG & _PTHREAD_MUTEX_SIG_MASK */
+#define _PTHREAD_MUTEX_SIG_init 0x32AAABA7 /* [almost] ~'MUTX' */
+#define _PTHREAD_ERRORCHECK_MUTEX_SIG_init 0x32AAABA1
+#define _PTHREAD_RECURSIVE_MUTEX_SIG_init 0x32AAABA2
+#define _PTHREAD_FIRSTFIT_MUTEX_SIG_init 0x32AAABA3
+#define _PTHREAD_MUTEX_SIG_init_MASK 0xfffffff0
+#define _PTHREAD_MUTEX_SIG_init_CMP 0x32AAABA0
+#define _PTHREAD_COND_ATTR_SIG 0x434E4441 /* 'CNDA' */
+#define _PTHREAD_COND_SIG_init 0x3CB0B1BB /* [almost] ~'COND' */
+#define _PTHREAD_COND_SIG_pristine 0x434F4E44 /* 'COND' */
+#define _PTHREAD_COND_SIG_psynch 0x434F4E45 /* 'COND' + 0b01: 'CONE' */
+#define _PTHREAD_COND_SIG_ulock 0x434F4E46 /* 'COND' + 0b10: 'CONF' */
+#define _PTHREAD_ATTR_SIG 0x54484441 /* 'THDA' */
+#define _PTHREAD_ONCE_SIG 0x4F4E4345 /* 'ONCE' */
+#define _PTHREAD_ONCE_SIG_init 0x30B1BCBA /* [almost] ~'ONCE' */
+#define _PTHREAD_SIG 0x54485244 /* 'THRD' */
+#define _PTHREAD_RWLOCK_ATTR_SIG 0x52574C41 /* 'RWLA' */
+#define _PTHREAD_RWLOCK_SIG 0x52574C4B /* 'RWLK' */
+#define _PTHREAD_RWLOCK_SIG_init 0x2DA8B3B4 /* [almost] ~'RWLK' */
+
+__enum_closed_decl(pthread_conformance_t, unsigned, {
+ PTHREAD_CONFORM_UNIX03_NOCANCEL = 1,
+ PTHREAD_CONFORM_UNIX03_CANCELABLE = 2,
+});
+
+/* Pull the pthread_t into the same page as the top of the stack so we dirty one less page.
+ * <rdar://problem/19941744> The pthread_s struct at the top of the stack shouldn't be page-aligned
+ */
+#if defined(__arm64__)
+#define PTHREAD_T_OFFSET (12*1024)
+#else
+#define PTHREAD_T_OFFSET 0
+#endif
+
+#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
+#define _EXTERNAL_POSIX_THREAD_KEYS_MAX 256
+#define _INTERNAL_POSIX_THREAD_KEYS_MAX 256
+#define _INTERNAL_POSIX_THREAD_KEYS_END 512
+#else
+#define _EXTERNAL_POSIX_THREAD_KEYS_MAX 512
+#define _INTERNAL_POSIX_THREAD_KEYS_MAX 256
+#define _INTERNAL_POSIX_THREAD_KEYS_END 768
+#endif
+
+#define PTHREAD_ATFORK_INLINE_MAX 10
+
+#define MAXTHREADNAMESIZE 64
+
+#define _PTHREAD_DEFAULT_INHERITSCHED PTHREAD_INHERIT_SCHED
+#define _PTHREAD_DEFAULT_PROTOCOL PTHREAD_PRIO_NONE
+#define _PTHREAD_DEFAULT_PRIOCEILING 0
+#define _PTHREAD_DEFAULT_POLICY SCHED_OTHER
+#define _PTHREAD_DEFAULT_STACKSIZE 0x80000 /* 512K */
+#define _PTHREAD_DEFAULT_PSHARED PTHREAD_PROCESS_PRIVATE
+
+#define _PTHREAD_CANCEL_STATE_MASK 0x01
+#define _PTHREAD_CANCEL_TYPE_MASK 0x02
+#define _PTHREAD_CANCEL_PENDING 0x10 /* pthread_cancel() has been called for this thread */
+#define _PTHREAD_CANCEL_EXITING 0x20
+
+#define pthread_assert_type_size(type) \
+ static_assert(sizeof(struct type##_s) == sizeof(struct _opaque_##type##_t), "")
+#define pthread_assert_type_alias(type, f1, f2) \
+ static_assert(offsetof(struct type##_s, f1) == offsetof(struct _opaque_##type##_t, f2), "")
+
+typedef os_unfair_lock _pthread_lock;
+struct _pthread_registration_data;
+
+
+#pragma mark - pthread_once_t
+
+struct pthread_once_s {
+ long sig;
+ os_once_t once;
+};
+
+pthread_assert_type_size(pthread_once);
+pthread_assert_type_alias(pthread_once, sig, __sig);
+
+#pragma mark - pthread_mutex_t, pthread_mutexattr_t
+
+#define _PTHREAD_MUTEX_POLICY_LAST (PTHREAD_MUTEX_POLICY_FIRSTFIT_NP + 1)
+#define _PTHREAD_MTX_OPT_POLICY_FAIRSHARE 1
+#define _PTHREAD_MTX_OPT_POLICY_FIRSTFIT 2
+#define _PTHREAD_MTX_OPT_POLICY_DEFAULT _PTHREAD_MTX_OPT_POLICY_FIRSTFIT
+// The following pthread_mutex_options_s defintions exist in synch_internal.h
+// such that the kernel extension can test for flags. They must be kept in
+// sync with the bit values in the struct above.
+// _PTHREAD_MTX_OPT_PSHARED 0x010
+// _PTHREAD_MTX_OPT_NOTIFY 0x1000
+// _PTHREAD_MTX_OPT_MUTEX 0x2000
+
+#define _PTHREAD_MTX_OPT_ULOCK_DEFAULT false
+#define _PTHREAD_MTX_OPT_ADAPTIVE_DEFAULT false
+
+// The fixed mask is used to mask out portions of the mutex options that
+// change on a regular basis (notify, lock_count).
+#define _PTHREAD_MTX_OPT_FIXED_MASK 0x27ff
+
+struct pthread_mutex_options_s {
+ uint32_t
+ protocol:2,
+ type:2,
+ pshared:2,
+ policy:3,
+ hold:2,
+ misalign:1,
+ notify:1,
+ mutex:1,
+ ulock:1,
+ unused:1,
+ lock_count:16;
+};
+
+#define _PTHREAD_MUTEX_ULOCK_OWNER_MASK 0xfffffffcu
+#define _PTHREAD_MUTEX_ULOCK_WAITERS_BIT 0x00000001u
+#define _PTHREAD_MUTEX_ULOCK_UNLOCKED_VALUE 0x0u
+#define _PTHREAD_MUTEX_ULOCK_UNLOCKED \
+ ((struct _pthread_mutex_ulock_s){0})
+
+typedef struct _pthread_mutex_ulock_s {
+ uint32_t uval;
+} *_pthread_mutex_ulock_t;
+
+struct pthread_mutex_s {
+ long sig;
+ _pthread_lock lock;
+ union {
+ uint32_t value;
+ struct pthread_mutex_options_s options;
+ } mtxopts;
+ int16_t prioceiling;
+ int16_t priority;
+#if defined(__LP64__)
+ uint32_t _pad;
+#endif
+ union {
+ struct {
+ uint32_t m_tid[2]; // thread id of thread that has mutex locked
+ uint32_t m_seq[2]; // mutex sequence id
+ uint32_t m_mis[2]; // for misaligned locks m_tid/m_seq will span into here
+ } psynch;
+ struct _pthread_mutex_ulock_s ulock;
+ };
+#if defined(__LP64__)
+ uint32_t _reserved[4];
+#else
+ uint32_t _reserved[1];
+#endif
+};
+
+pthread_assert_type_size(pthread_mutex);
+pthread_assert_type_alias(pthread_mutex, sig, __sig);
+
+struct pthread_mutexattr_s {
+ long sig;
+ int prioceiling;
+ uint32_t
+ protocol:2,
+ type:2,
+ pshared:2,
+ opt:3,
+ unused:23;
+};
+
+pthread_assert_type_size(pthread_mutexattr);
+pthread_assert_type_alias(pthread_mutexattr, sig, __sig);
+
+#pragma mark - pthread_rwlock_t, pthread_rwlockattr_t
+
+struct pthread_rwlock_s {
+ long sig;
+ _pthread_lock lock;
+ uint32_t
+ unused:29,
+ misalign:1,
+ pshared:2;
+ uint32_t rw_flags;
+#if defined(__LP64__)
+ uint32_t _pad;
+#endif
+ uint32_t rw_tid[2]; // thread id of thread that has exclusive (write) lock
+ uint32_t rw_seq[4]; // rw sequence id (at 128-bit aligned boundary)
+ uint32_t rw_mis[4]; // for misaligned locks rw_seq will span into here
+#if defined(__LP64__)
+ uint32_t _reserved[34];
+#else
+ uint32_t _reserved[18];
+#endif
+};
+
+pthread_assert_type_size(pthread_rwlock);
+pthread_assert_type_alias(pthread_rwlock, sig, __sig);
+
+struct pthread_rwlockattr_s {
+ long sig;
+ int pshared;
+#if defined(__LP64__)
+ uint32_t _reserved[3];
+#else
+ uint32_t _reserved[2];
+#endif
+};
+
+pthread_assert_type_size(pthread_rwlockattr);
+pthread_assert_type_alias(pthread_rwlockattr, sig, __sig);
+
+#pragma mark - pthread_cond_t, pthread_condattr_t
+
+struct pthread_cond_s {
+ struct {
+ uint32_t val;
+#if defined(__LP64__)
+ uint32_t _pad;
+#endif
+ } sig;
+ _pthread_lock lock;
+ uint32_t
+ unused:29,
+ misalign:1,
+ pshared:2;
+ pthread_mutex_t *busy;
+ uint32_t c_seq[3];
+#if defined(__LP64__)
+ uint32_t _reserved[3];
+#endif
+};
+
+pthread_assert_type_size(pthread_cond);
+pthread_assert_type_alias(pthread_cond, sig, __sig);
+
+struct pthread_condattr_s {
+ long sig;
+ uint32_t
+ pshared:2,
+ unsupported:30;
+};
+
+pthread_assert_type_size(pthread_condattr);
+pthread_assert_type_alias(pthread_condattr, sig, __sig);
+
+#pragma mark - pthread_t, pthread_attr_t
+
+typedef struct pthread_join_context_s {
+ pthread_t waiter;
+ void **value_ptr;
+ mach_port_t kport;
+ semaphore_t custom_stack_sema;
+ bool detached;
+} pthread_join_context_s, *pthread_join_context_t;
+
+#define MAXTHREADNAMESIZE 64
+
+struct pthread_s {
+ long sig;
+ struct __darwin_pthread_handler_rec *__cleanup_stack;
+
+ //
+ // Fields protected by _pthread_list_lock
+ //
+
+ TAILQ_ENTRY(pthread_s) tl_plist; // global thread list [aligned]
+ struct pthread_join_context_s *tl_join_ctx;
+ void *tl_exit_value;
+ uint8_t tl_policy;
+ // pthread knows that tl_joinable bit comes immediately after tl_policy
+ uint8_t
+ tl_joinable:1,
+ tl_joiner_cleans_up:1,
+ tl_has_custom_stack:1,
+ __tl_pad:5;
+ uint16_t introspection;
+ // MACH_PORT_NULL if no joiner
+ // tsd[_PTHREAD_TSD_SLOT_MACH_THREAD_SELF] when has a joiner
+ // MACH_PORT_DEAD if the thread exited
+ uint32_t tl_exit_gate;
+ struct sched_param tl_param;
+ void *__unused_padding;
+
+ //
+ // Fields protected by pthread_t::lock
+ //
+
+ _pthread_lock lock;
+ uint16_t max_tsd_key;
+ uint16_t
+ inherit:8,
+ kernalloc:1,
+ schedset:1,
+ wqthread:1,
+ wqkillset:1,
+ __flags_pad:4;
+
+ char pthread_name[MAXTHREADNAMESIZE]; // includes NUL [aligned]
+
+ void *(*fun)(void *); // thread start routine
+ void *arg; // thread start routine argument
+ int wq_nevents; // wqthreads (workloop / kevent)
+ bool wq_outsideqos;
+ uint8_t canceled; // 4597450 set if conformant cancelation happened
+ uint16_t cancel_state; // whether the thread can be canceled [atomic]
+ errno_t cancel_error;
+ errno_t err_no; // thread-local errno
+
+ void *stackaddr; // base of the stack (page aligned)
+ void *stackbottom; // stackaddr - stacksize
+ void *freeaddr; // stack/thread allocation base address
+ size_t freesize; // stack/thread allocation size
+ size_t guardsize; // guard page size in bytes
+
+ // tsd-base relative accessed elements
+ __attribute__((aligned(8)))
+ uint64_t thread_id; // 64-bit unique thread id
+
+ /* Thread Specific Data slots
+ *
+ * The offset of this field from the start of the structure is difficult to
+ * change on OS X because of a thorny bitcompat issue: mono has hard coded
+ * the value into their source. Newer versions of mono will fall back to
+ * scanning to determine it at runtime, but there's lots of software built
+ * with older mono that won't. We will have to break them someday...
+ */
+ __attribute__ ((aligned (16)))
+ void *tsd[_EXTERNAL_POSIX_THREAD_KEYS_MAX + _INTERNAL_POSIX_THREAD_KEYS_MAX];
+};
+
+TAILQ_HEAD(__pthread_list, pthread_s);
+
+#if 0 // pthread_t is never stack-allocated, so it doesn't matter
+pthread_assert_type_size(pthread);
+#endif
+pthread_assert_type_alias(pthread, sig, __sig);
+pthread_assert_type_alias(pthread, __cleanup_stack, __cleanup_stack);
+#if __LP64__
+static_assert(offsetof(struct pthread_s, tsd) == 224, "TSD LP64 offset");
+#else
+static_assert(offsetof(struct pthread_s, tsd) == 176, "TSD ILP32 offset");
+#endif
+
+#define _PTHREAD_ATTR_REFILLMS_MAX ((2<<24) - 1)
+
+struct pthread_attr_s {
+ long sig;
+ size_t guardsize; // size in bytes of stack overflow guard area
+ void *stackaddr; // stack base; vm_page_size aligned
+ size_t stacksize; // stack size; multiple of vm_page_size and >= PTHREAD_STACK_MIN
+ union {
+ struct sched_param param; // [aligned]
+ unsigned long qosclass; // pthread_priority_t
+ };
+ uint32_t
+ detached:8,
+ inherit:8,
+ policy:8,
+ schedset:1,
+ qosset:1,
+ policyset:1,
+ cpupercentset:1,
+ defaultguardpage:1,
+ unused:3;
+ uint32_t
+ cpupercent:8,
+ refillms:24;
+#if defined(__LP64__)
+ uint32_t _reserved[4];
+#else
+ uint32_t _reserved[2];
+#endif
+};
+
+pthread_assert_type_size(pthread_attr);
+pthread_assert_type_alias(pthread_attr, sig, __sig);
+
+#pragma mark - atfork / qos
+
+struct pthread_atfork_entry {
+ void (*prepare)(void);
+ void (*parent)(void);
+ void (*child)(void);
+};
+
+#define PTHREAD_ATFORK_INLINE_MAX 10
+#if defined(__arm__)
+// Hack. We don't want to depend on libcompiler_rt. armv7 implements integer
+// division by calling into compiler_rt. vm_page_size isn't a constant and
+// pthread_atfork_entry is 12 bytes so the compiler can't strength-reduce the
+// division, so it generates a call into compiler_rt.
+// So let's just use PAGE_MAX_SIZE on armv7, which is a constant. At worst
+// this wastes a maybe dozen K if we are actaully running on a smaller page
+// size than the max.
+// At the time of this writing we don't have any supported iOS armv7 hardware
+// that has different vm_page_size and PAGE_MAX_SIZE.
+#define PTHREAD_ATFORK_MAX (PAGE_MAX_SIZE/sizeof(struct pthread_atfork_entry))
+#else // defined(__arm__)
+#define PTHREAD_ATFORK_MAX (vm_page_size/sizeof(struct pthread_atfork_entry))
+#endif // defined(__arm__)
+
+struct pthread_globals_s {
+ // atfork.c
+ pthread_t psaved_self;
+ _pthread_lock psaved_self_global_lock;
+ _pthread_lock pthread_atfork_lock;
+
+ size_t atfork_count;
+ struct pthread_atfork_entry atfork_storage[PTHREAD_ATFORK_INLINE_MAX];
+ struct pthread_atfork_entry *atfork;
+ uint16_t qmp_logical[THREAD_QOS_LAST];
+ uint16_t qmp_physical[THREAD_QOS_LAST];
+
+};
+typedef struct pthread_globals_s *pthread_globals_t;
+
+#endif // __LIBPTHREAD_TYPES_INTERNAL_H__
+++ /dev/null
-/*
- * Copyright (c) 2012 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include <TargetConditionals.h>
-#if defined(__i386__)
-
-#define BUILDING_VARIANT 1
-
-#undef __DARWIN_UNIX03
-#define __DARWIN_UNIX03 0
-
-#include "../pthread_cancelable.c"
-
-#endif
+++ /dev/null
-/*
- * Copyright (c) 2012 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include <TargetConditionals.h>
-#if defined(__i386__)
-
-#define BUILDING_VARIANT 1
-
-#undef __DARWIN_UNIX03
-#define __DARWIN_UNIX03 0
-
-#include "../pthread_cond.c"
-
-#endif
+++ /dev/null
-/*
- * Copyright (c) 2012 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include <TargetConditionals.h>
-#if defined(__i386__)
-
-#define BUILDING_VARIANT 1
-
-#undef __DARWIN_UNIX03
-#define __DARWIN_UNIX03 0
-
-#include "../pthread_mutex.c"
-
-#endif
+++ /dev/null
-/*
- * Copyright (c) 2012 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include <TargetConditionals.h>
-#if defined(__i386__)
-
-#define BUILDING_VARIANT 1
-
-#undef __DARWIN_UNIX03
-#define __DARWIN_UNIX03 0
-
-#define _pthread_rwlock_lock_slow _pthread_rwlock_lock_legacy_slow
-#define _pthread_rwlock_unlock_slow _pthread_rwlock_unlock_legacy_slow
-
-#include "../pthread_rwlock.c"
-
-#endif
+++ /dev/null
-/*
- * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-#ifndef _PTHREAD_ATTR_T
-#define _PTHREAD_ATTR_T
-#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_attr_t */
-typedef __darwin_pthread_attr_t pthread_attr_t;
-#endif /* _PTHREAD_ATTR_T */
+++ /dev/null
-/*
- * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-#ifndef _PTHREAD_COND_T
-#define _PTHREAD_COND_T
-#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_cond_t */
-typedef __darwin_pthread_cond_t pthread_cond_t;
-#endif /* _PTHREAD_COND_T */
+++ /dev/null
-/*
- * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-#ifndef _PTHREAD_CONDATTR_T
-#define _PTHREAD_CONDATTR_T
-#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_condattr_t */
-typedef __darwin_pthread_condattr_t pthread_condattr_t;
-#endif /* _PTHREAD_CONDATTR_T */
+++ /dev/null
-/*
- * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-#ifndef _PTHREAD_KEY_T
-#define _PTHREAD_KEY_T
-#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_key_t */
-typedef __darwin_pthread_key_t pthread_key_t;
-#endif /* _PTHREAD_KEY_T */
+++ /dev/null
-/*
- * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-#ifndef _PTHREAD_MUTEX_T
-#define _PTHREAD_MUTEX_T
-#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_mutex_t */
-typedef __darwin_pthread_mutex_t pthread_mutex_t;
-#endif /*_PTHREAD_MUTEX_T */
+++ /dev/null
-/*
- * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-#ifndef _PTHREAD_MUTEXATTR_T
-#define _PTHREAD_MUTEXATTR_T
-#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_mutexattr_t */
-typedef __darwin_pthread_mutexattr_t pthread_mutexattr_t;
-#endif /* _PTHREAD_MUTEXATTR_T */
+++ /dev/null
-/*
- * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-#ifndef _PTHREAD_ONCE_T
-#define _PTHREAD_ONCE_T
-#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_once_t */
-typedef __darwin_pthread_once_t pthread_once_t;
-#endif /* _PTHREAD_ONCE_T */
+++ /dev/null
-/*
- * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-#ifndef _PTHREAD_RWLOCK_T
-#define _PTHREAD_RWLOCK_T
-#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_rwlock_t */
-typedef __darwin_pthread_rwlock_t pthread_rwlock_t;
-#endif /* _PTHREAD_RWLOCK_T */
+++ /dev/null
-/*
- * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-#ifndef _PTHREAD_RWLOCKATTR_T
-#define _PTHREAD_RWLOCKATTR_T
-#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_rwlockattr_t */
-typedef __darwin_pthread_rwlockattr_t pthread_rwlockattr_t;
-#endif /* _PTHREAD_RWLOCKATTR_T */
+++ /dev/null
-/*
- * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-#ifndef _PTHREAD_T
-#define _PTHREAD_T
-#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_t */
-typedef __darwin_pthread_t pthread_t;
-#endif /* _PTHREAD_T */
+++ /dev/null
-/*
- * Copyright (c) 2003-2013 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-
-#ifndef _SYS__PTHREAD_TYPES_H_
-#define _SYS__PTHREAD_TYPES_H_
-
-#include <sys/cdefs.h>
-
-// pthread opaque structures
-#if defined(__LP64__)
-#define __PTHREAD_SIZE__ 8176
-#define __PTHREAD_ATTR_SIZE__ 56
-#define __PTHREAD_MUTEXATTR_SIZE__ 8
-#define __PTHREAD_MUTEX_SIZE__ 56
-#define __PTHREAD_CONDATTR_SIZE__ 8
-#define __PTHREAD_COND_SIZE__ 40
-#define __PTHREAD_ONCE_SIZE__ 8
-#define __PTHREAD_RWLOCK_SIZE__ 192
-#define __PTHREAD_RWLOCKATTR_SIZE__ 16
-#else // !__LP64__
-#define __PTHREAD_SIZE__ 4088
-#define __PTHREAD_ATTR_SIZE__ 36
-#define __PTHREAD_MUTEXATTR_SIZE__ 8
-#define __PTHREAD_MUTEX_SIZE__ 40
-#define __PTHREAD_CONDATTR_SIZE__ 4
-#define __PTHREAD_COND_SIZE__ 24
-#define __PTHREAD_ONCE_SIZE__ 4
-#define __PTHREAD_RWLOCK_SIZE__ 124
-#define __PTHREAD_RWLOCKATTR_SIZE__ 12
-#endif // !__LP64__
-
-struct __darwin_pthread_handler_rec {
- void (*__routine)(void *); // Routine to call
- void *__arg; // Argument to pass
- struct __darwin_pthread_handler_rec *__next;
-};
-
-struct _opaque_pthread_attr_t {
- long __sig;
- char __opaque[__PTHREAD_ATTR_SIZE__];
-};
-
-struct _opaque_pthread_cond_t {
- long __sig;
- char __opaque[__PTHREAD_COND_SIZE__];
-};
-
-struct _opaque_pthread_condattr_t {
- long __sig;
- char __opaque[__PTHREAD_CONDATTR_SIZE__];
-};
-
-struct _opaque_pthread_mutex_t {
- long __sig;
- char __opaque[__PTHREAD_MUTEX_SIZE__];
-};
-
-struct _opaque_pthread_mutexattr_t {
- long __sig;
- char __opaque[__PTHREAD_MUTEXATTR_SIZE__];
-};
-
-struct _opaque_pthread_once_t {
- long __sig;
- char __opaque[__PTHREAD_ONCE_SIZE__];
-};
-
-struct _opaque_pthread_rwlock_t {
- long __sig;
- char __opaque[__PTHREAD_RWLOCK_SIZE__];
-};
-
-struct _opaque_pthread_rwlockattr_t {
- long __sig;
- char __opaque[__PTHREAD_RWLOCKATTR_SIZE__];
-};
-
-struct _opaque_pthread_t {
- long __sig;
- struct __darwin_pthread_handler_rec *__cleanup_stack;
- char __opaque[__PTHREAD_SIZE__];
-};
-
-typedef struct _opaque_pthread_attr_t __darwin_pthread_attr_t;
-typedef struct _opaque_pthread_cond_t __darwin_pthread_cond_t;
-typedef struct _opaque_pthread_condattr_t __darwin_pthread_condattr_t;
-typedef unsigned long __darwin_pthread_key_t;
-typedef struct _opaque_pthread_mutex_t __darwin_pthread_mutex_t;
-typedef struct _opaque_pthread_mutexattr_t __darwin_pthread_mutexattr_t;
-typedef struct _opaque_pthread_once_t __darwin_pthread_once_t;
-typedef struct _opaque_pthread_rwlock_t __darwin_pthread_rwlock_t;
-typedef struct _opaque_pthread_rwlockattr_t __darwin_pthread_rwlockattr_t;
-typedef struct _opaque_pthread_t *__darwin_pthread_t;
-
-#endif // _SYS__PTHREAD_TYPES_H_
+++ /dev/null
-/*
- * Copyright (c) 2013-2014 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef _SYS_QOS_H
-#define _SYS_QOS_H
-
-#include <sys/cdefs.h>
-#include <Availability.h>
-
-/*!
- * @typedef qos_class_t
- *
- * @abstract
- * An abstract thread quality of service (QOS) classification.
- *
- * @discussion
- * Thread quality of service (QOS) classes are ordered abstract representations
- * of the nature of work that is expected to be performed by a pthread, dispatch
- * queue, or NSOperation. Each class specifies a maximum thread scheduling
- * priority for that band (which may be used in combination with a relative
- * priority offset within the band), as well as quality of service
- * characteristics for timer latency, CPU throughput, I/O throughput, network
- * socket traffic management behavior and more.
- *
- * A best effort is made to allocate available system resources to every QOS
- * class. Quality of service degredation only occurs during system resource
- * contention, proportionally to the QOS class. That said, QOS classes
- * representing user-initiated work attempt to achieve peak throughput while
- * QOS classes for other work attempt to achieve peak energy and thermal
- * efficiency, even in the absence of contention. Finally, the use of QOS
- * classes does not allow threads to supersede any limits that may be applied
- * to the overall process.
- */
-
-/*!
- * @constant QOS_CLASS_USER_INTERACTIVE
- * @abstract A QOS class which indicates work performed by this thread
- * is interactive with the user.
- * @discussion Such work is requested to run at high priority relative to other
- * work on the system. Specifying this QOS class is a request to run with
- * nearly all available system CPU and I/O bandwidth even under contention.
- * This is not an energy-efficient QOS class to use for large tasks. The use of
- * this QOS class should be limited to critical interaction with the user such
- * as handling events on the main event loop, view drawing, animation, etc.
- *
- * @constant QOS_CLASS_USER_INITIATED
- * @abstract A QOS class which indicates work performed by this thread
- * was initiated by the user and that the user is likely waiting for the
- * results.
- * @discussion Such work is requested to run at a priority below critical user-
- * interactive work, but relatively higher than other work on the system. This
- * is not an energy-efficient QOS class to use for large tasks. Its use
- * should be limited to operations of short enough duration that the user is
- * unlikely to switch tasks while waiting for the results. Typical
- * user-initiated work will have progress indicated by the display of
- * placeholder content or modal user interface.
- *
- * @constant QOS_CLASS_DEFAULT
- * @abstract A default QOS class used by the system in cases where more specific
- * QOS class information is not available.
- * @discussion Such work is requested to run at a priority below critical user-
- * interactive and user-initiated work, but relatively higher than utility and
- * background tasks. Threads created by pthread_create() without an attribute
- * specifying a QOS class will default to QOS_CLASS_DEFAULT. This QOS class
- * value is not intended to be used as a work classification, it should only be
- * set when propagating or restoring QOS class values provided by the system.
- *
- * @constant QOS_CLASS_UTILITY
- * @abstract A QOS class which indicates work performed by this thread
- * may or may not be initiated by the user and that the user is unlikely to be
- * immediately waiting for the results.
- * @discussion Such work is requested to run at a priority below critical user-
- * interactive and user-initiated work, but relatively higher than low-level
- * system maintenance tasks. The use of this QOS class indicates the work
- * should be run in an energy and thermally-efficient manner. The progress of
- * utility work may or may not be indicated to the user, but the effect of such
- * work is user-visible.
- *
- * @constant QOS_CLASS_BACKGROUND
- * @abstract A QOS class which indicates work performed by this thread was not
- * initiated by the user and that the user may be unaware of the results.
- * @discussion Such work is requested to run at a priority below other work.
- * The use of this QOS class indicates the work should be run in the most energy
- * and thermally-efficient manner.
- *
- * @constant QOS_CLASS_UNSPECIFIED
- * @abstract A QOS class value which indicates the absence or removal of QOS
- * class information.
- * @discussion As an API return value, may indicate that threads or pthread
- * attributes were configured with legacy API incompatible or in conflict with
- * the QOS class system.
- */
-
-#define __QOS_ENUM(name, type, ...) enum { __VA_ARGS__ }; typedef type name##_t
-#define __QOS_CLASS_AVAILABLE(...)
-
-#if defined(__cplusplus) || defined(__OBJC__) || __LP64__
-#if defined(__has_feature) && defined(__has_extension)
-#if __has_feature(objc_fixed_enum) || __has_extension(cxx_strong_enums)
-#undef __QOS_ENUM
-#define __QOS_ENUM(name, type, ...) typedef enum : type { __VA_ARGS__ } name##_t
-#endif
-#endif
-#if __has_feature(enumerator_attributes)
-#undef __QOS_CLASS_AVAILABLE
-#define __QOS_CLASS_AVAILABLE __API_AVAILABLE
-#endif
-#endif
-
-__QOS_ENUM(qos_class, unsigned int,
- QOS_CLASS_USER_INTERACTIVE
- __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x21,
- QOS_CLASS_USER_INITIATED
- __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x19,
- QOS_CLASS_DEFAULT
- __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x15,
- QOS_CLASS_UTILITY
- __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x11,
- QOS_CLASS_BACKGROUND
- __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x09,
- QOS_CLASS_UNSPECIFIED
- __QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x00,
-);
-
-#undef __QOS_ENUM
-
-/*!
- * @constant QOS_MIN_RELATIVE_PRIORITY
- * @abstract The minimum relative priority that may be specified within a
- * QOS class. These priorities are relative only within a given QOS class
- * and meaningful only for the current process.
- */
-#define QOS_MIN_RELATIVE_PRIORITY (-15)
-
-/* Userspace (only) definitions */
-
-#ifndef KERNEL
-
-__BEGIN_DECLS
-
-/*!
- * @function qos_class_self
- *
- * @abstract
- * Returns the requested QOS class of the current thread.
- *
- * @return
- * One of the QOS class values in qos_class_t.
- */
-__API_AVAILABLE(macos(10.10), ios(8.0))
-qos_class_t
-qos_class_self(void);
-
-/*!
- * @function qos_class_main
- *
- * @abstract
- * Returns the initial requested QOS class of the main thread.
- *
- * @discussion
- * The QOS class that the main thread of a process is created with depends on
- * the type of process (e.g. application or daemon) and on how it has been
- * launched.
- *
- * This function returns that initial requested QOS class value chosen by the
- * system to enable propagation of that classification to matching work not
- * executing on the main thread.
- *
- * @return
- * One of the QOS class values in qos_class_t.
- */
-__API_AVAILABLE(macos(10.10), ios(8.0))
-qos_class_t
-qos_class_main(void);
-
-__END_DECLS
-
-#endif // KERNEL
-
-#endif // _SYS_QOS_H
+++ /dev/null
-/*
- * Copyright (c) 2014 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef _QOS_SYS_PRIVATE_H
-#define _QOS_SYS_PRIVATE_H
-
-/*!
- * @constant QOS_CLASS_MAINTENANCE
- * @abstract A QOS class which indicates work performed by this thread was not
- * initiated by the user and that the user may be unaware of the results.
- * @discussion Such work is requested to run at a priority far below other work
- * including significant I/O throttling. The use of this QOS class indicates
- * the work should be run in the most energy and thermally-efficient manner
- * possible, and may be deferred for a long time in order to preserve
- * system responsiveness for the user.
- * This is SPI for use by Spotlight and Time Machine only.
- */
-#define QOS_CLASS_MAINTENANCE ((qos_class_t)0x05)
-
-#endif //_QOS_SYS_PRIVATE_H
TARGETS += wq_limits
TARGETS += add_timer_termination
TARGETS += perf_contended_mutex_rwlock
+TARGETS += pthread_jit_write_protection
+pthread_jit_write_protection: CODE_SIGN_ENTITLEMENTS=pthread_jit_write_protection-entitlements.plist
# this should be CUSTOM_TARGETS, see "Compatibility defines" in Makefile.targets
OTHER_TARGETS := stackoverflow_crash
OTHER_CFLAGS := -DDARWINTEST -Weverything \
-Wno-vla -Wno-bad-function-cast -Wno-missing-noreturn \
-Wno-missing-field-initializers -Wno-format-pedantic \
- -Wno-gnu-folding-constant -Wno-used-but-marked-unused
+ -Wno-gnu-folding-constant -Wno-used-but-marked-unused \
+ -Wno-padded
OTHER_LDFLAGS := -ldarwintest_utils
#TARGETS += main_stack_legacy // Disabled by default due to linker warnings
install-stackoverflow_crash: stackoverflow_crash
mkdir -p $(INSTALLDIR)/assets
@cp $(SYMROOT)/assets/stackoverflow_crash $(INSTALLDIR)/assets
+
T_ASSERT_POSIX_ZERO(pthread_join(p[i], NULL), NULL);
}
}
+
+#pragma mark invalid concurrent mutex use
+
+// XXX ulock-based condvars don't detect concurrent waiting for now
+#if 0
+
+static pthread_cond_t concurrent_cond = PTHREAD_COND_INITIALIZER;
+
+static void *
+invalid_wait_thread(void *arg)
+{
+ pthread_mutex_t *mutex = arg;
+
+ int rc = pthread_mutex_lock(mutex);
+ T_ASSERT_POSIX_ZERO(rc, "lock mutex");
+
+ while (true) {
+ rc = pthread_cond_wait(&concurrent_cond, mutex);
+ if (rc == EINVAL) {
+ T_PASS("Detected EINVAL");
+ T_END;
+ } else {
+ T_ASSERT_POSIX_ZERO(rc, "cond_wait");
+ }
+ }
+}
+
+T_DECL(cond_invalid_concurrent_mutex, "Detect concurrent waits with different mutexes as invalid")
+{
+ int rc;
+ pthread_t threads[2];
+ pthread_mutex_t mutexes[2] = {
+ PTHREAD_MUTEX_INITIALIZER,
+ PTHREAD_MUTEX_INITIALIZER,
+ };
+
+ for (int i = 0; i < 2; i++) {
+ rc = pthread_create(&threads[i], NULL, invalid_wait_thread,
+ &mutexes[i]);
+ T_ASSERT_POSIX_ZERO(rc, "pthread_create");
+ }
+
+ // will not return
+ pthread_join(threads[0], NULL);
+}
+
+#endif
+
+#pragma mark mutex ping pong test
+
+struct cond_mutex_ping_pong_ctx_s {
+ pthread_mutex_t mutex;
+ int arrived;
+ int group;
+};
+
+static struct {
+ pthread_mutex_t sync_mutex;
+ pthread_cond_t sync_cond;
+ int group;
+ pthread_cond_t shared_cond;
+} ping_pong = {
+ .sync_mutex = PTHREAD_MUTEX_INITIALIZER,
+ .sync_cond = PTHREAD_COND_INITIALIZER,
+ .group = 0,
+ .shared_cond = PTHREAD_COND_INITIALIZER,
+};
+
+#define PING_PONG_NGROUPS 2
+#define PING_PONG_GROUP_NTHREADS 3
+#define PING_PONG_ITERATIONS 5000
+
+static void *
+ping_pong_thread(void *arg)
+{
+ int rc;
+ struct cond_mutex_ping_pong_ctx_s *ctx = arg;
+
+ for (int i = 1; i < PING_PONG_ITERATIONS; i++) {
+ if (i % 5000 == 0) {
+ T_LOG("Iteration %d", i);
+ }
+
+ // wait for our turn to synchronize on the shared_cond barrier
+ rc = pthread_mutex_lock(&ping_pong.sync_mutex);
+ T_QUIET; T_ASSERT_POSIX_ZERO(rc, "lock sync_mutex");
+
+ while (ping_pong.group != ctx->group) {
+ rc = pthread_cond_wait(&ping_pong.sync_cond, &ping_pong.sync_mutex);
+ T_QUIET; T_ASSERT_POSIX_ZERO(rc, "sync cond_wait");
+ }
+
+ rc = pthread_mutex_unlock(&ping_pong.sync_mutex);
+ T_QUIET; T_ASSERT_POSIX_ZERO(rc, "unlock sync_mutex");
+
+ rc = pthread_mutex_lock(&ctx->mutex);
+ T_QUIET; T_ASSERT_POSIX_ZERO(rc, "lock mutex");
+
+ ctx->arrived++;
+
+ if (ctx->arrived == i * PING_PONG_GROUP_NTHREADS) {
+ // end our turn with shared_cond
+ rc = pthread_cond_broadcast(&ping_pong.shared_cond);
+ T_QUIET; T_ASSERT_POSIX_ZERO(rc, "shared cond_broadcast");
+
+ // let the next group begin
+ rc = pthread_mutex_lock(&ping_pong.sync_mutex);
+ T_QUIET; T_ASSERT_POSIX_ZERO(rc, "lock sync_mutex");
+
+ ping_pong.group = (ping_pong.group + 1) % PING_PONG_NGROUPS;
+
+ rc = pthread_mutex_unlock(&ping_pong.sync_mutex);
+ T_QUIET; T_ASSERT_POSIX_ZERO(rc, "unlock sync_mutex");
+
+ // for fun, do this broadcast outside the mutex
+ rc = pthread_cond_broadcast(&ping_pong.sync_cond);
+ T_QUIET; T_ASSERT_POSIX_ZERO(rc, "sync cond_broadcast");
+
+ } else {
+ while (ctx->arrived < i * PING_PONG_GROUP_NTHREADS) {
+ rc = pthread_cond_wait(&ping_pong.shared_cond, &ctx->mutex);
+ T_QUIET; T_ASSERT_POSIX_ZERO(rc, "shared cond_wait");
+
+ // TODO: assert that you now hold the correct group mutex
+ }
+ }
+
+ rc = pthread_mutex_unlock(&ctx->mutex);
+ T_QUIET; T_ASSERT_POSIX_ZERO(rc, "unlock mutex");
+ }
+
+ return NULL;
+}
+
+T_DECL(cond_mutex_ping_pong, "Wait on the same condition variable with different mutexes",
+ T_META_ENVVAR("PTHREAD_MUTEX_USE_ULOCK=1"))
+{
+ int rc;
+ pthread_t threads[PING_PONG_NGROUPS][PING_PONG_GROUP_NTHREADS];
+ struct cond_mutex_ping_pong_ctx_s ctxs[PING_PONG_NGROUPS];
+
+ for (int i = 0; i < PING_PONG_NGROUPS; i++) {
+ struct cond_mutex_ping_pong_ctx_s *ctx = &ctxs[i];
+ *ctx = (struct cond_mutex_ping_pong_ctx_s){
+ .mutex = PTHREAD_MUTEX_INITIALIZER,
+ .group = i,
+ };
+
+ for (int j = 0; j < PING_PONG_GROUP_NTHREADS; j++) {
+ rc = pthread_create(&threads[i][j], NULL, ping_pong_thread, ctx);
+ T_ASSERT_POSIX_ZERO(rc, "pthread_create");
+ }
+ }
+
+ for (int i = 0; i < PING_PONG_NGROUPS; i++) {
+ for (int j = 0; j < PING_PONG_GROUP_NTHREADS; j++) {
+ rc = pthread_join(threads[i][j], NULL);
+ T_ASSERT_POSIX_ZERO(rc, "pthread_join");
+ }
+ }
+}
+
+#pragma mark signal_thread_np tests
+
+static struct signal_thread_ctx_s {
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ bool signaled;
+} signal_thread_ctx = {
+ .mutex = PTHREAD_MUTEX_INITIALIZER,
+ .cond = PTHREAD_COND_INITIALIZER,
+};
+
+static void *
+chosen_waiter(void *arg __unused)
+{
+ struct signal_thread_ctx_s *ctx = &signal_thread_ctx;
+
+ int rc = pthread_mutex_lock(&ctx->mutex);
+ T_ASSERT_POSIX_ZERO(rc, "chosen waiter lock");
+
+ while (!ctx->signaled) {
+ rc = pthread_cond_wait(&ctx->cond, &ctx->mutex);
+ T_ASSERT_POSIX_ZERO(rc, "chosen waiter cond_wait");
+ }
+
+ T_PASS("chosen waiter woke");
+ T_END;
+}
+
+static void *
+other_waiter_thread(void *arg __unused)
+{
+ struct signal_thread_ctx_s *ctx = &signal_thread_ctx;
+
+ int rc = pthread_mutex_lock(&ctx->mutex);
+ T_ASSERT_POSIX_ZERO(rc, "other waiter lock");
+
+ while (true) {
+ rc = pthread_cond_wait(&ctx->cond, &ctx->mutex);
+ T_ASSERT_POSIX_ZERO(rc, "other waiter cond_wait");
+ }
+
+ T_ASSERT_FAIL("Not reached");
+ return NULL;
+}
+
+T_DECL(cond_signal_thread_np_waiting, "signal a specific thread that's waiting")
+{
+ int rc;
+ struct signal_thread_ctx_s *ctx = &signal_thread_ctx;
+
+ pthread_attr_t other_attr;
+ rc = pthread_attr_init(&other_attr);
+ T_QUIET; T_ASSERT_POSIX_ZERO(rc, "pthread_attr_init");
+
+ rc = pthread_attr_set_qos_class_np(&other_attr,
+ QOS_CLASS_USER_INTERACTIVE, 0);
+ T_ASSERT_POSIX_ZERO(rc, "pthread_attr_set_qos_class_np");
+
+ pthread_t other;
+ rc = pthread_create(&other, &other_attr, other_waiter_thread, NULL);
+ T_ASSERT_POSIX_ZERO(rc, "create other thread");
+
+ pthread_t chosen;
+ rc = pthread_create(&chosen, NULL, chosen_waiter, NULL);
+ T_ASSERT_POSIX_ZERO(rc, "create chosen thread");
+
+ T_LOG("Waiting for threads to wait");
+ sleep(5);
+
+ rc = pthread_mutex_lock(&ctx->mutex);
+ T_ASSERT_POSIX_ZERO(rc, "lock mutex");
+
+ ctx->signaled = true;
+
+ rc = pthread_mutex_unlock(&ctx->mutex);
+ T_ASSERT_POSIX_ZERO(rc, "unlock mutex");
+
+ rc = pthread_cond_signal_thread_np(&ctx->cond, chosen);
+ T_ASSERT_POSIX_ZERO(rc, "cond_signal_thread_np");
+
+ pthread_join(chosen, NULL);
+}
+
+static void *
+absent_chosen_waiter(void *arg __unused)
+{
+ T_LOG("chosen thread doing nothing forever");
+ while (true) {
+ sleep(100);
+ }
+
+ T_ASSERT_FAIL("Not reached");
+ return NULL;
+}
+
+static void *
+not_absent_waiter(void *arg __unused)
+{
+ struct signal_thread_ctx_s *ctx = &signal_thread_ctx;
+
+ int rc = pthread_mutex_lock(&ctx->mutex);
+ T_ASSERT_POSIX_ZERO(rc, "other waiter lock");
+
+ while (!ctx->signaled) {
+ rc = pthread_cond_wait(&ctx->cond, &ctx->mutex);
+ T_ASSERT_POSIX_ZERO(rc, "other waiter cond_wait");
+ }
+
+ T_PASS("other waiter woke");
+ T_END;
+}
+
+T_DECL(cond_signal_thread_np_not_waiting, "signal a specific thread that isn't waiting")
+{
+ int rc;
+ struct signal_thread_ctx_s *ctx = &signal_thread_ctx;
+
+ pthread_t other;
+ rc = pthread_create(&other, NULL, not_absent_waiter, NULL);
+ T_ASSERT_POSIX_ZERO(rc, "create other thread");
+
+ pthread_t chosen;
+ rc = pthread_create(&chosen, NULL, absent_chosen_waiter, NULL);
+ T_ASSERT_POSIX_ZERO(rc, "create chosen thread");
+
+ T_LOG("Waiting for threads to wait");
+ sleep(5);
+
+ rc = pthread_mutex_lock(&ctx->mutex);
+ T_ASSERT_POSIX_ZERO(rc, "lock mutex");
+
+ ctx->signaled = true;
+
+ rc = pthread_mutex_unlock(&ctx->mutex);
+ T_ASSERT_POSIX_ZERO(rc, "unlock mutex");
+
+ rc = pthread_cond_signal_thread_np(&ctx->cond, chosen);
+ T_ASSERT_POSIX_ZERO(rc, "cond_signal_thread_np");
+
+ pthread_join(other, NULL);
+}
+
+#pragma mark cancel signal race test
+
+static struct cancel_signal_race_context_s {
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+} cancel_signal_race_context = {
+ .mutex = PTHREAD_MUTEX_INITIALIZER,
+ .cond = PTHREAD_COND_INITIALIZER,
+};
+
+static void
+cancelee_cleanup_handler(void *arg __unused)
+{
+ T_LOG("cancelee cleanup handler");
+
+ struct cancel_signal_race_context_s *ctx = &cancel_signal_race_context;
+ int rc = pthread_mutex_unlock(&ctx->mutex);
+ T_ASSERT_POSIX_ZERO(rc, "cleanup mutex unlock");
+}
+
+static void *
+cancelee_thread(void *arg __unused)
+{
+ struct cancel_signal_race_context_s *ctx = &cancel_signal_race_context;
+
+ int rc = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+ T_QUIET; T_ASSERT_POSIX_ZERO(rc, "disabled cancelation of cancelee thread");
+
+ rc = pthread_mutex_lock(&ctx->mutex);
+ T_ASSERT_POSIX_ZERO(rc, "cancelee lock");
+
+ rc = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+ if (rc) {
+ // manual T_QUIET since we can't safely call into libdarwintest with
+ // cancelation enabled
+ T_ASSERT_POSIX_ZERO(rc, "cancelation re-enabled");
+ }
+
+ pthread_cleanup_push(cancelee_cleanup_handler, NULL);
+
+ rc = pthread_cond_wait(&ctx->cond, &ctx->mutex);
+
+ pthread_cleanup_pop(0);
+
+ int rc2 = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+ T_QUIET; T_ASSERT_POSIX_ZERO(rc2, "re-disabled cancelation of cancelee thread");
+
+ // If we make it here we didn't manage to exercise the race, but that's
+ // legal.
+ T_ASSERT_POSIX_ZERO(rc, "cancelee woke from cond_wait");
+
+ rc = pthread_mutex_unlock(&ctx->mutex);
+ T_ASSERT_POSIX_ZERO(rc, "cancelee unlocked");
+
+ return NULL;
+}
+
+static struct {
+ int dummy;
+} other_thread_timed_out;
+
+static void *
+other_racing_thread(void *arg __unused)
+{
+ struct cancel_signal_race_context_s *ctx = &cancel_signal_race_context;
+
+ int rc = pthread_mutex_lock(&ctx->mutex);
+ T_ASSERT_POSIX_ZERO(rc, "other lock");
+
+ struct timespec ts = {
+ .tv_sec = 10,
+ };
+
+ rc = pthread_cond_timedwait_relative_np(&ctx->cond, &ctx->mutex, &ts);
+
+ int rc2 = pthread_mutex_unlock(&ctx->mutex);
+ T_ASSERT_POSIX_ZERO(rc2, "other thread unlocked");
+
+ if (rc == ETIMEDOUT) {
+ T_LOG("other thread timed out");
+ return &other_thread_timed_out;
+ } else {
+ // XXX if we change the algorithm in a way that can lead to spurious
+ // wakeups then this logic might become invalid, but at this point it's
+ // not possible
+ T_ASSERT_POSIX_ZERO(rc, "other thread woke from wait");
+ return NULL;
+ }
+}
+
+T_DECL(cond_cancel_signal_race, "Validate waiter cancelation does not eat wakes",
+ T_META_ENVVAR("PTHREAD_MUTEX_USE_ULOCK=1"))
+{
+ int rc;
+ struct cancel_signal_race_context_s *ctx = &cancel_signal_race_context;
+
+ pthread_attr_t cancelee_attr;
+ rc = pthread_attr_init(&cancelee_attr);
+ T_QUIET; T_ASSERT_POSIX_ZERO(rc, "pthread_attr_init");
+
+ rc = pthread_attr_set_qos_class_np(&cancelee_attr,
+ QOS_CLASS_USER_INTERACTIVE, 0);
+ T_ASSERT_POSIX_ZERO(rc, "pthread_attr_set_qos_class_np");
+
+ pthread_t cancelee;
+ rc = pthread_create(&cancelee, &cancelee_attr, cancelee_thread, NULL);
+ T_ASSERT_POSIX_SUCCESS(rc, "create cancelee");
+
+ pthread_attr_t other_attr;
+ rc = pthread_attr_init(&other_attr);
+ T_QUIET; T_ASSERT_POSIX_ZERO(rc, "pthread_attr_init");
+
+ rc = pthread_attr_set_qos_class_np(&other_attr,
+ QOS_CLASS_USER_INITIATED, 0);
+ T_ASSERT_POSIX_ZERO(rc, "pthread_attr_set_qos_class_np");
+
+ pthread_t other;
+ rc = pthread_create(&other, &other_attr, other_racing_thread, NULL);
+ T_ASSERT_POSIX_SUCCESS(rc, "create other thread");
+
+ // Give them time to wait
+ // TODO: find some reliable way of waiting until they're really blocked?
+ sleep(2);
+
+ rc = pthread_cond_signal(&ctx->cond);
+
+ // Now quickly cancel, hopefully before they make it to userspace
+ (void)pthread_cancel(cancelee);
+
+ T_ASSERT_POSIX_ZERO(rc, "signal cancelee");
+
+ void *cancelee_retval, *other_retval;
+
+ rc = pthread_join(cancelee, &cancelee_retval);
+ T_ASSERT_POSIX_ZERO(rc, "join cancelee");
+
+ rc = pthread_join(other, &other_retval);
+ T_ASSERT_POSIX_ZERO(rc, "join other");
+
+ if (cancelee_retval == PTHREAD_CANCELED) {
+ T_LOG("cancelee was canceled");
+ T_ASSERT_EQ(other_retval, NULL, "other thread must have woken");
+ } else {
+ T_LOG("cancelee was not canceled quickly enough");
+ T_ASSERT_EQ(cancelee_retval, NULL, "cancelee returned success");
+ T_ASSERT_EQ(other_retval, &other_thread_timed_out, "other thread timed out");
+ }
+}
}
T_DECL(mutex_default_policy,
- "Tests that the default mutex policy is fairshare")
+ "Tests that the default mutex policy is firstfit")
{
check_process_default_mutex_policy(_PTHREAD_MUTEX_POLICY_FIRSTFIT);
}
T_DECL(mutex_default_policy_sysctl,
"Tests that setting the policy sysctl changes the default policy")
{
- int firstfit_default = _PTHREAD_MUTEX_POLICY_FIRSTFIT;
+ int fairshare_default = _PTHREAD_MUTEX_POLICY_FAIRSHARE;
T_EXPECT_POSIX_ZERO(
- sysctlbyname("kern.pthread_mutex_default_policy", NULL, NULL, &firstfit_default, sizeof(firstfit_default)),
- "Changed the default policy sysctl to firstfit");
+ sysctlbyname("kern.pthread_mutex_default_policy", NULL, NULL, &fairshare_default, sizeof(fairshare_default)),
+ "Changed the default policy sysctl to fairshare");
dt_helper_t helper = dt_child_helper("mutex_default_policy_sysctl_helper");
dt_run_helpers(&helper, 1, 5);
T_HELPER_DECL(mutex_default_policy_sysctl_helper, "sysctl helper")
{
- check_process_default_mutex_policy(_PTHREAD_MUTEX_POLICY_FIRSTFIT);
+ check_process_default_mutex_policy(_PTHREAD_MUTEX_POLICY_FAIRSHARE);
- int default_default = _PTHREAD_MUTEX_POLICY_FAIRSHARE;
+ int default_default = _PTHREAD_MUTEX_POLICY_FIRSTFIT;
T_EXPECT_POSIX_ZERO(
sysctlbyname("kern.pthread_mutex_default_policy", NULL, NULL, &default_default, sizeof(default_default)),
- "Restored the default policy to fairshare");
+ "Restored the default policy to firstfit");
T_END;
}
T_DECL(mutex_default_policy_envvar,
"Tests that setting the policy environment variable changes the default policy",
- T_META_ENVVAR("PTHREAD_MUTEX_DEFAULT_POLICY=3"))
+ T_META_ENVVAR("PTHREAD_MUTEX_DEFAULT_POLICY=1"))
{
- check_process_default_mutex_policy(_PTHREAD_MUTEX_POLICY_FIRSTFIT);
+ check_process_default_mutex_policy(_PTHREAD_MUTEX_POLICY_FAIRSHARE);
+}
+
+static void *
+mutex_as_semaphore_signaller(void *arg)
+{
+ pthread_mutex_t *mtx = arg;
+ int rc = pthread_mutex_unlock(mtx);
+ T_ASSERT_POSIX_ZERO(rc, "unlock");
+
+ return NULL;
+}
+
+T_DECL(mutex_as_semaphore_lock_owned, "Recursively lock a normal mutex to use as a semaphore")
+{
+ pthread_t signaller;
+ pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
+ int rc = pthread_mutex_lock(&mtx);
+ T_ASSERT_POSIX_ZERO(rc, "lock");
+
+ rc = pthread_create(&signaller, NULL, mutex_as_semaphore_signaller, &mtx);
+ T_ASSERT_POSIX_ZERO(rc, "create");
+
+ rc = pthread_mutex_lock(&mtx);
+ T_ASSERT_POSIX_ZERO(rc, "recursive lock");
+
+ rc = pthread_join(signaller, NULL);
+ T_ASSERT_POSIX_ZERO(rc, "join");
+
+ T_END;
}
T_DECL(pthread_attr_setstacksize, "pthread_attr_setstacksize")
{
+ T_LOG("vm_page_size: %lld vm_kernel_page_size: %lld round_page(MIN): %lld", vm_page_size, vm_kernel_page_size, round_page(PTHREAD_STACK_MIN));
size_t stacksizes[] = {PTHREAD_STACK_MIN, 1024ULL * 16, 1024ULL * 32, 1024ULL * 1024};
for (int i = 0; (size_t)i < sizeof(stacksizes)/sizeof(stacksizes[0]); i++){
pthread_t t = NULL;
#include "darwintest_defaults.h"
-#include "../src/pthread_cwd.c"
-
// /tmp is a symlink, so use full path for strict compare
#define WORKDIR "/private/var/tmp/ptwork"
#define WORKDIR1 WORKDIR "/one"
#include <stdio.h>
#include <pthread.h>
+#include <pthread/private.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
}
T_PASS("Success!");
}
+
+static void
+key_dtor(void *value)
+{
+ T_ASSERT_EQ(1, pthread_self_is_exiting_np(), "exiting");
+}
+
+T_DECL(pthread_self_is_exiting_np, "pthread_self_is_exiting_np")
+{
+ pthread_key_t key;
+
+ T_ASSERT_POSIX_ZERO(pthread_key_create(&key, key_dtor), NULL);
+ pthread_setspecific(key, (void *)-1);
+ T_ASSERT_EQ(0, pthread_self_is_exiting_np(), "not exiting");
+ pthread_exit(NULL);
+}
#include "darwintest_defaults.h"
static pthread_introspection_hook_t prev_pthread_introspection_hook;
+static pthread_key_t key;
+static atomic_int keys_set;
+static atomic_int keys_cleared;
+static const char value_for_key[] = "used as a TSD value";
+
+static void
+key_destructor(void *ctx)
+{
+ T_EXPECT_EQ(ctx, (void *)value_for_key, "check value");
+ keys_cleared++;
+}
#define THREAD_COUNT 3
{
static atomic_int create_count;
static atomic_int terminate_count;
+ static atomic_int destroy_count;
uint64_t tid;
pthread_threadid_np(NULL, &tid);
- if (event == PTHREAD_INTROSPECTION_THREAD_CREATE) {
+ switch (event) {
+ case PTHREAD_INTROSPECTION_THREAD_CREATE:
+ atomic_fetch_add(&keys_set, 1);
+ pthread_introspection_setspecific_np(thread, key, value_for_key);
T_LOG("event = PTHREAD_INTROSPECTION_THREAD_CREATE, thread = %p:%lld, addr = %p, size = 0x%zx", thread, tid, addr, size);
create_count++;
- } else if (event == PTHREAD_INTROSPECTION_THREAD_TERMINATE) {
+ break;
+ case PTHREAD_INTROSPECTION_THREAD_TERMINATE:
T_LOG("event = PTHREAD_INTROSPECTION_THREAD_TERMINATE, thread = %p:%lld, addr = %p, size = 0x%zx", thread, tid, addr, size);
terminate_count++;
T_ASSERT_GE(create_count, THREAD_COUNT, NULL);
T_PASS("Got termination events");
+ break;
+ case PTHREAD_INTROSPECTION_THREAD_DESTROY:
+ T_LOG("event = PTHREAD_INTROSPECTION_THREAD_DESTROY, thread = %p:%lld, addr = %p, size = 0x%zx", thread, tid, addr, size);
+ destroy_count++;
+ T_ASSERT_NULL(pthread_introspection_getspecific_np(thread, key), "should have cleared");
+ T_ASSERT_NE(keys_cleared, 0, "should have cleared a key");
+ T_PASS("Got destruction events");
T_END;
}
}
T_DECL(pthread_introspection, "PR-25679871",
- T_META_TIMEOUT(30), T_META_ALL_VALID_ARCHS(YES))
+ T_META_TIMEOUT(30), T_META_ALL_VALID_ARCHS(YES))
{
prev_pthread_introspection_hook = pthread_introspection_hook_install(&my_pthread_introspection_hook);
+ pthread_key_create(&key, key_destructor);
// minus one that comes after this block
for (int i = 0; i < THREAD_COUNT - 1; i++) {
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>dynamic-codesigning</key>
+ <true/>
+</dict>
+</plist>
+
--- /dev/null
+#include <darwintest.h>
+#include <darwintest_perf.h>
+
+#include <sys/mman.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <libkern/OSCacheControl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+
+#include <mach/vm_param.h>
+#include <pthread.h>
+
+#if __has_include(<ptrauth.h>)
+#include <ptrauth.h>
+#endif
+
+T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true));
+
+/* Enumerations */
+typedef enum _access_type {
+ ACCESS_WRITE,
+ ACCESS_EXECUTE,
+} access_type_t;
+
+typedef enum _fault_strategy {
+ FAULT_STRAT_NONE,
+ FAULT_STRAT_RX,
+ FAULT_STRAT_RW
+} fault_strategy_t;
+
+/* Structures */
+typedef struct {
+ uint64_t fault_count;
+ fault_strategy_t fault_strategy;
+ bool fault_expected;
+} fault_state_t;
+
+/* Globals */
+static void * rwx_addr = NULL;
+static pthread_key_t jit_test_fault_state_key;
+
+/*
+ * Return instruction encodings; a default value is given so that this test can
+ * be built for an architecture that may not support the tested feature.
+ */
+#ifdef __arm__
+static uint32_t ret_encoding = 0xe12fff1e;
+#elif defined(__arm64__)
+static uint32_t ret_encoding = 0xd65f03c0;
+#elif defined(__x86_64__)
+static uint32_t ret_encoding = 0x909090c3;;
+#else
+#error "Unsupported architecture"
+#endif
+
+/* Allocate a fault_state_t, and associate it with the current thread. */
+static fault_state_t *
+fault_state_create(void)
+{
+ fault_state_t * fault_state = malloc(sizeof(fault_state_t));
+
+ if (fault_state) {
+ fault_state->fault_count = 0;
+ fault_state->fault_strategy = FAULT_STRAT_NONE;
+ fault_state->fault_expected = false;
+
+ if (pthread_setspecific(jit_test_fault_state_key, fault_state)) {
+ free(fault_state);
+ fault_state = NULL;
+ }
+ }
+
+ return fault_state;
+}
+
+/* Disassociate the given fault state from the current thread, and destroy it. */
+static void
+fault_state_destroy(void * fault_state)
+{
+ if (fault_state == NULL) {
+ T_ASSERT_FAIL("Attempted to fault_state_destroy NULL");
+ }
+
+ free(fault_state);
+}
+
+/*
+ * A signal handler that attempts to resolve anticipated faults through use of
+ * the pthread_jit_write_protect functions.
+ */
+static void
+access_failed_handler(int signum)
+{
+ fault_state_t * fault_state;
+
+ /* This handler should ONLY handle SIGBUS. */
+ if (signum != SIGBUS) {
+ T_ASSERT_FAIL("Unexpected signal sent to handler");
+ }
+
+ if (!(fault_state = pthread_getspecific(jit_test_fault_state_key))) {
+ T_ASSERT_FAIL("Failed to retrieve fault state");
+ }
+
+ if (!(fault_state->fault_expected)) {
+ T_ASSERT_FAIL("Unexpected fault taken");
+ }
+
+ /* We should not see a second fault. */
+ fault_state->fault_expected = false;
+
+ switch (fault_state->fault_strategy) {
+ case FAULT_STRAT_NONE:
+ T_ASSERT_FAIL("No fault strategy");
+
+ /* Just in case we try to do something different. */
+ break;
+ case FAULT_STRAT_RX:
+ pthread_jit_write_protect_np(TRUE);
+ break;
+ case FAULT_STRAT_RW:
+ pthread_jit_write_protect_np(FALSE);
+ break;
+ }
+
+ fault_state->fault_count++;
+}
+
+/*
+ * Attempt the specified access; if the access faults, this will return true;
+ * otherwise, it will return false.
+ */
+static bool
+does_access_fault(access_type_t access_type, void * addr)
+{
+ uint64_t old_fault_count;
+ uint64_t new_fault_count;
+
+ fault_state_t * fault_state;
+
+ struct sigaction old_action; /* Save area for any existing action. */
+ struct sigaction new_action; /* The action we wish to install for SIGBUS. */
+
+ bool retval = false;
+
+ void (*func)(void);
+
+ new_action.sa_handler = access_failed_handler; /* A handler for write failures. */
+ new_action.sa_mask = 0; /* Don't modify the mask. */
+ new_action.sa_flags = 0; /* Flags? Who needs those? */
+
+ if (addr == NULL) {
+ T_ASSERT_FAIL("Access attempted against NULL");
+ }
+
+ if (!(fault_state = pthread_getspecific(jit_test_fault_state_key))) {
+ T_ASSERT_FAIL("Failed to retrieve fault state");
+ }
+
+ old_fault_count = fault_state->fault_count;
+
+ /* Install a handler so that we can catch SIGBUS. */
+ sigaction(SIGBUS, &new_action, &old_action);
+
+ /* Perform the requested operation. */
+ switch (access_type) {
+ case ACCESS_WRITE:
+ fault_state->fault_strategy = FAULT_STRAT_RW;
+ fault_state->fault_expected = true;
+
+ __sync_synchronize();
+
+ /* Attempt to scrawl a return instruction to the given address. */
+ *((volatile uint32_t *)addr) = ret_encoding;
+
+ __sync_synchronize();
+
+ fault_state->fault_expected = false;
+ fault_state->fault_strategy = FAULT_STRAT_NONE;
+
+ /* Invalidate the instruction cache line that we modified. */
+ sys_cache_control(kCacheFunctionPrepareForExecution, addr, sizeof(ret_encoding));
+
+ break;
+ case ACCESS_EXECUTE:
+ /* This is a request to branch to the given address. */
+#if __has_feature(ptrauth_calls)
+ func = ptrauth_sign_unauthenticated((void *)addr, ptrauth_key_function_pointer, 0);
+#else
+ func = (void (*)(void))addr;
+#endif
+
+
+ fault_state->fault_strategy = FAULT_STRAT_RX;
+ fault_state->fault_expected = true;
+
+ __sync_synchronize();
+
+ /* Branch. */
+ func();
+
+ __sync_synchronize();
+
+ fault_state->fault_expected = false;
+ fault_state->fault_strategy = FAULT_STRAT_NONE;
+
+ break;
+ }
+
+ /* Restore the old SIGBUS handler. */
+ sigaction(SIGBUS, &old_action, NULL);
+
+ new_fault_count = fault_state->fault_count;
+
+ if (new_fault_count > old_fault_count) {
+ /* Indicate that we took a fault. */
+ retval = true;
+ }
+
+ return retval;
+}
+
+static void *
+expect_write_fail_thread(__unused void * arg)
+{
+ fault_state_create();
+
+ if (does_access_fault(ACCESS_WRITE, rwx_addr)) {
+ pthread_exit((void *)0);
+ } else {
+ pthread_exit((void *)1);
+ }
+}
+
+T_DECL(pthread_jit_write_protect,
+ "Verify that the pthread_jit_write_protect interfaces work correctly")
+{
+ void * addr = NULL;
+ size_t alloc_size = PAGE_SIZE;
+ fault_state_t * fault_state = NULL;
+ int err = 0;
+ bool key_created = false;
+ void * join_value = NULL;
+ pthread_t pthread;
+ bool expect_fault = pthread_jit_write_protect_supported_np();
+
+ T_SETUPBEGIN;
+
+ /* Set up the necessary state for the test. */
+ err = pthread_key_create(&jit_test_fault_state_key, fault_state_destroy);
+
+ T_ASSERT_POSIX_ZERO(err, 0, "Create pthread key");
+
+ key_created = true;
+
+ fault_state = fault_state_create();
+
+ T_ASSERT_NOTNULL(fault_state, "Create fault state");
+
+ /*
+ * Create a JIT enabled mapping that we can use to test restriction of
+ * RWX mappings.
+ */
+ rwx_addr = mmap(addr, alloc_size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE | MAP_JIT, -1, 0);
+
+ T_ASSERT_NE_PTR(rwx_addr, MAP_FAILED, "Map range as MAP_JIT");
+
+ T_SETUPEND;
+
+ /*
+ * Validate that we fault when we should, and that we do not fault when
+ * we should not fault.
+ */
+ pthread_jit_write_protect_np(FALSE);
+
+ T_EXPECT_EQ(does_access_fault(ACCESS_WRITE, rwx_addr), 0, "Write with RWX->RW");
+
+ pthread_jit_write_protect_np(TRUE);
+
+ T_EXPECT_EQ(does_access_fault(ACCESS_EXECUTE, rwx_addr), 0, "Execute with RWX->RX");
+
+ pthread_jit_write_protect_np(TRUE);
+
+ T_EXPECT_EQ(does_access_fault(ACCESS_WRITE, rwx_addr), expect_fault, "Write with RWX->RX");
+
+ pthread_jit_write_protect_np(FALSE);
+
+ T_EXPECT_EQ(does_access_fault(ACCESS_EXECUTE, rwx_addr), expect_fault, "Execute with RWX->RW");
+
+ pthread_jit_write_protect_np(FALSE);
+
+ if (expect_fault) {
+ /*
+ * Create another thread for testing multithreading; mark this as setup
+ * as this test is not targeted towards the pthread create/join APIs.
+ */
+ T_SETUPBEGIN;
+
+ T_ASSERT_POSIX_ZERO(pthread_create(&pthread, NULL, expect_write_fail_thread, NULL), "pthread_create expect_write_fail_thread");
+
+ T_ASSERT_POSIX_ZERO(pthread_join(pthread, &join_value), "pthread_join expect_write_fail_thread");
+
+ T_SETUPEND;
+
+ /*
+ * Validate that the other thread was unable to write to the JIT region
+ * without independently using the pthread_jit_write_protect code.
+ */
+ T_ASSERT_NULL((join_value), "Write on other thread with RWX->RX, "
+ "RWX->RW on parent thread");
+ }
+
+ /* We're done with the test; tear down our extra state. */
+ /*
+ * This would be better dealt with using T_ATEND, but this would require
+ * making many variables global. This can be changed in the future.
+ * For now, mark this as SETUP (even though this is really teardown).
+ */
+ T_SETUPBEGIN;
+
+ T_ASSERT_POSIX_SUCCESS(munmap(rwx_addr, alloc_size), "Unmap MAP_JIT mapping");
+
+ if (fault_state) {
+ T_ASSERT_POSIX_ZERO(pthread_setspecific(jit_test_fault_state_key, NULL), "Remove fault_state");
+
+ fault_state_destroy(fault_state);
+ }
+
+ if (key_created) {
+ T_ASSERT_POSIX_ZERO(pthread_key_delete(jit_test_fault_state_key), "Delete fault state key");
+ }
+
+ T_SETUPEND;
+}
+
+T_DECL(thread_self_restrict_rwx_perf,
+ "Test the performance of the thread_self_restrict_rwx interfaces",
+ T_META_TAG_PERF, T_META_CHECK_LEAKS(false))
+{
+ dt_stat_time_t dt_stat_time;
+
+ dt_stat_time = dt_stat_time_create("rx->rw->rx time");
+
+ T_STAT_MEASURE_LOOP(dt_stat_time) {
+ pthread_jit_write_protect_np(FALSE);
+ pthread_jit_write_protect_np(TRUE);
+ }
+
+ dt_stat_finalize(dt_stat_time);
+}
#include <pthread.h>
#include <stdio.h>
+#include <sys/sysctl.h>
#include "darwintest_defaults.h"
T_ASSERT_POSIX_ZERO(pthread_key_delete(key), NULL);
}
+
+static uint32_t
+get_ncpu(void)
+{
+ static uint32_t activecpu;
+ if (!activecpu) {
+ uint32_t n;
+ size_t s = sizeof(activecpu);
+ sysctlbyname("hw.activecpu", &n, &s, NULL, 0);
+ activecpu = n;
+ }
+ return activecpu;
+}
+
+T_DECL(cpuid, "cpu id", T_META_ALL_VALID_ARCHS(YES))
+{
+ pthread_t child;
+
+ size_t cpu_id;
+ if (pthread_cpu_number_np(&cpu_id)) {
+ T_FAIL("Should not fail to get CPU id");
+ }
+
+ T_ASSERT_LE(cpu_id, get_ncpu(), "Got a valid CPU id");
+}
#include <dispatch/dispatch.h>
-#include "../private/workqueue_private.h"
-#include "../private/qos_private.h"
+#include "../private/pthread/workqueue_private.h"
+#include "../private/pthread/qos_private.h"
#include "wq_kevent.h"
#include <dispatch/dispatch.h>
-#include "../private/workqueue_private.h"
-#include "../private/qos_private.h"
+#include "../private/pthread/workqueue_private.h"
+#include "../private/pthread/qos_private.h"
#include "wq_kevent.h"
#include <dispatch/dispatch.h>
-#include "../private/workqueue_private.h"
-#include "../private/qos_private.h"
+#include "../private/pthread/workqueue_private.h"
+#include "../private/pthread/qos_private.h"
#include "wq_kevent.h"
pthread_setname_np.3 \
pthread_setspecific.3 \
pthread_threadid_np.3 \
- pthread_yield_np.3"
+ pthread_yield_np.3 \
+ pthread_jit_write_protect_np.3"
+
cp $BASE_PAGES "$DSTROOT"/usr/share/man/man3
ln -fh pthread_getschedparam.3 pthread_setschedparam.3
ln -fh pthread_rwlock_rdlock.3 pthread_rwlock_tryrdlock.3
ln -fh pthread_rwlock_wrlock.3 pthread_rwlock_trywrlock.3
+ln -fh pthread_jit_write_protect_np.3 pthread_jit_write_protect_supported_np.3
for M in \
pthread_attr_destroy.3 \
if [ "$ACTION" = build ]; then exit 0; fi
-DSTROOT="${DSTROOT}/${SDK_INSTALL_HEADERS_ROOT}"
+install_headers()
+{
+ mkdir -p "${DSTROOT}/${SDK_INSTALL_HEADERS_ROOT}$2"
+ cp -r "${SRCROOT}/$1" "${DSTROOT}/${SDK_INSTALL_HEADERS_ROOT}$2"
-DESTDIR="$DSTROOT/usr/include/sys"
-mkdir -p "$DESTDIR"
-for X in \
- qos.h \
- ; do
- cp "sys/$X" "$DESTDIR"
-done
-
-DESTDIR="$DSTROOT/usr/local/include/sys"
-mkdir -p "$DESTDIR"
-for X in \
- qos_private.h \
- ; do
- cp "sys/$X" "$DESTDIR"
-done
-
-DESTDIR="$DSTROOT/usr/include/sys/_pthread"
-mkdir -p "$DESTDIR"
-for X in \
- _pthread_attr_t.h \
- _pthread_cond_t.h \
- _pthread_condattr_t.h \
- _pthread_key_t.h \
- _pthread_mutex_t.h \
- _pthread_mutexattr_t.h \
- _pthread_once_t.h \
- _pthread_rwlock_t.h \
- _pthread_rwlockattr_t.h \
- _pthread_t.h \
- _pthread_types.h \
- ; do
- cp "sys/_pthread/$X" "$DESTDIR"
-done
+ find "${DSTROOT}/${SDK_INSTALL_HEADERS_ROOT}$2" -type f -name *.h -print0 | \
+ xargs -0I % unifdef -t ${COPY_HEADERS_UNIFDEF_FLAGS} -o "%" "%"
+ find "${DSTROOT}/${SDK_INSTALL_HEADERS_ROOT}$2" -type f -name *.modulemap -print0 | \
+ xargs -0I % unifdef -t ${COPY_HEADERS_UNIFDEF_FLAGS} -o "%" "%"
+}
+install_headers "include/sys" "/usr/include"
+install_headers "private/sys" "/usr/local/include"
INFOPLIST_FILE = kern/pthread-Info.plist
ALWAYS_SEARCH_USER_PATHS = NO
-SRCROOT_SEARCH_PATHS = $(SRCROOT) $(SRCROOT)/pthread $(SRCROOT)/private
+SRCROOT_SEARCH_PATHS = $(SRCROOT)/private $(SRCROOT)/include $(SRCROOT)
HEADER_SEARCH_PATHS = $(SDKROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders $(SDKROOT)/System/Library/Frameworks/Kernel.framework/Headers $(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders $(SDKROOT)/System/Library/Frameworks/System.framework/Headers $(SRCROOT_SEARCH_PATHS)
GCC_C_LANGUAGE_STANDARD = gnu11
CLANG_CXX_LANGUAGE_STANDARD = gnu++0x
--- /dev/null
+# aliases file for pthread old-symbol aliases
+# <symbol> <alias>
+
+_pthread_cancel$UNIX2003 _pthread_cancel
+_pthread_cond_init$UNIX2003 _pthread_cond_init
+_pthread_cond_timedwait$UNIX2003 _pthread_cond_timedwait
+_pthread_cond_wait$UNIX2003 _pthread_cond_wait
+_pthread_join$UNIX2003 _pthread_join
+_pthread_mutexattr_destroy$UNIX2003 _pthread_mutexattr_destroy
+_pthread_rwlock_destroy$UNIX2003 _pthread_rwlock_destroy
+_pthread_rwlock_init$UNIX2003 _pthread_rwlock_init
+_pthread_rwlock_rdlock$UNIX2003 _pthread_rwlock_rdlock
+_pthread_rwlock_tryrdlock$UNIX2003 _pthread_rwlock_tryrdlock
+_pthread_rwlock_trywrlock$UNIX2003 _pthread_rwlock_trywrlock
+_pthread_rwlock_unlock$UNIX2003 _pthread_rwlock_unlock
+_pthread_rwlock_wrlock$UNIX2003 _pthread_rwlock_wrlock
+_pthread_setcancelstate$UNIX2003 _pthread_setcancelstate
+_pthread_setcanceltype$UNIX2003 _pthread_setcanceltype
+_pthread_sigmask$UNIX2003 _pthread_sigmask
+_pthread_testcancel$UNIX2003 _pthread_testcancel
+_sigwait$UNIX2003 _sigwait
--- /dev/null
+// TAPI
+SUPPORTS_TEXT_BASED_API = YES
+SUPPORTS_TEXT_BASED_API[sdk=iphonesimulator*] = NO
+TAPI_VERIFY_MODE = Pedantic
+
+TAPI_PREPROCESSOR = -DPTHREAD_LAYOUT_SPI=1 -Dposix_spawnattr_t="void *"
+TAPI_ADD_PUBLIC_HEADERS = -extra-public-header $(DSTROOT)$(SDK_INSTALL_HEADERS_ROOT)/usr/include/pthread/sched.h -extra-public-header $(DSTROOT)$(SDK_INSTALL_HEADERS_ROOT)/usr/include/sys/qos.h
+TAPI_ADD_PRIVATE_HEADERS = -extra-private-header $(PROJECT_DIR)/src/exports_internal.h
+TAPI_EXCL_PRIVATE_HEADERS = -exclude-private-header $(DSTROOT)$(SDK_INSTALL_HEADERS_ROOT)/usr/local/include/pthread/qos.h -exclude-private-header $(DSTROOT)$(SDK_INSTALL_HEADERS_ROOT)/usr/local/include/pthread/spinlock_private.h
+TAPI_ADD_ALIASES = -alias_list $(PROJECT_DIR)/xcodescripts/pthread.aliases
+OTHER_TAPI_FLAGS = -umbrella System $(TAPI_ADD_PUBLIC_HEADERS) $(TAPI_ADD_PRIVATE_HEADERS) $(TAPI_EXCL_PRIVATE_HEADERS) $(TAPI_ADD_ALIASES) $(TAPI_PREPROCESSOR)
# aliases file for pthread old-symbol aliases
# <symbol> <alias>
+
+_pthread_is_threaded_np __pthread_is_threaded
+_sched_yield _cthread_yield
+_sched_yield _pthread_yield_np
___pthread_supported_features
___pthread_tsd_lock
___pthread_tsd_max
-___unix_conforming
__main_qos
__pthread_count
__pthread_list_lock
PUBLIC_HEADERS_FOLDER_PATH = $(SDK_INSTALL_HEADERS_ROOT)/usr/include/pthread
PRIVATE_HEADERS_FOLDER_PATH = $(SDK_INSTALL_HEADERS_ROOT)/usr/local/include/pthread
-SRCROOT_SEARCH_PATHS = $(SRCROOT) $(SRCROOT)/private $(SRCROOT)/os $(SRCROOT)/src/resolver
+COPY_HEADERS_RUN_UNIFDEF = YES
+COPY_HEADERS_UNIFDEF_FLAGS = -U__PTHREAD_BUILDING_PTHREAD__
+
+SRCROOT_SEARCH_PATHS = $(SRCROOT)/src/resolver $(SRCROOT)/private $(SRCROOT)/include $(SRCROOT)
SYSTEM_FRAMEWORK_HEADERS = $(SDKROOT)/$(SDK_INSTALL_HEADERS_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders
HEADER_SEARCH_PATHS = $($(PRODUCT_NAME)_SEARCH_PATHS) $(SRCROOT_SEARCH_PATHS) $(inherited)
SYSTEM_HEADER_SEARCH_PATHS = $(SYSTEM_FRAMEWORK_HEADERS) $(SDKROOT)/$(SDK_INSTALL_HEADERS_ROOT)/usr/local/include $(SDKROOT)/$(SDK_INSTALL_HEADERS_ROOT)/usr/include
GCC_WARN_64_TO_32_BIT_CONVERSION = YES
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES
GCC_WARN_ABOUT_MISSING_NEWLINE = YES
-//GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES
+GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES
GCC_WARN_ABOUT_RETURN_TYPE = YES
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES
GCC_WARN_SIGN_COMPARE = YES
CLANG_WARN_UNREACHABLE_CODE = YES
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
-DISABLED_WARNING_CFLAGS = -Wno-int-conversion -Wno-missing-prototypes -Wno-sign-compare -Wno-sign-conversion -Wno-unused-parameter
-WARNING_CFLAGS = -Wall -Wextra -Warray-bounds-pointer-arithmetic -Wcomma -Wconditional-uninitialized -Wcovered-switch-default -Wdate-time -Wdeprecated -Wdouble-promotion -Wduplicate-enum -Wfloat-equal -Widiomatic-parentheses -Wignored-qualifiers -Wimplicit-fallthrough -Wmissing-noreturn -Wnullable-to-nonnull-conversion -Wover-aligned -Wpointer-arith -Wstatic-in-inline -Wtautological-compare -Wunguarded-availability -Wunused $(NO_WARNING_CFLAGS) $(DISABLED_WARNING_CFLAGS)
-NO_WARNING_CFLAGS = -Wno-pedantic -Wno-bad-function-cast -Wno-c++98-compat-pedantic -Wno-cast-align -Wno-cast-qual -Wno-disabled-macro-expansion -Wno-documentation-unknown-command -Wno-format-nonliteral -Wno-missing-variable-declarations -Wno-packed -Wno-padded -Wno-reserved-id-macro -Wno-switch-enum -Wno-undef -Wno-unreachable-code-aggressive -Wno-unused-macros -Wno-used-but-marked-unused
+DISABLED_WARNING_CFLAGS = -Wno-int-conversion -Wno-sign-compare -Wno-sign-conversion -Wno-unused-parameter
+WARNING_CFLAGS = -Wall -Wextra -Wmost -Warray-bounds-pointer-arithmetic -Wcomma -Wconditional-uninitialized -Wcovered-switch-default -Wdate-time -Wdeprecated -Wdouble-promotion -Wduplicate-enum -Wfloat-equal -Widiomatic-parentheses -Wignored-qualifiers -Wimplicit-fallthrough -Wmissing-noreturn -Wnullable-to-nonnull-conversion -Wover-aligned -Wpointer-arith -Wstatic-in-inline -Wtautological-compare -Wunguarded-availability -Wunused -Watomic-implicit-seq-cst $(NO_WARNING_CFLAGS) $(DISABLED_WARNING_CFLAGS)
+NO_WARNING_CFLAGS = -Wno-pedantic -Wno-bad-function-cast -Wno-c++98-compat-pedantic -Wno-cast-align -Wno-cast-qual -Wno-disabled-macro-expansion -Wno-documentation-unknown-command -Wno-format-nonliteral -Wno-packed -Wno-padded -Wno-reserved-id-macro -Wno-switch-enum -Wno-undef -Wno-unreachable-code-aggressive -Wno-unused-macros -Wno-used-but-marked-unused
-BASE_PREPROCESSOR_MACROS = __LIBC__ __DARWIN_UNIX03=1 __DARWIN_64_BIT_INO_T=1 __DARWIN_NON_CANCELABLE=1 __DARWIN_VERS_1050=1 _FORTIFY_SOURCE=0 __PTHREAD_BUILDING_PTHREAD__=1 $(SIM_PREPROCESSOR_MACROS) __PTHREAD_EXPOSE_INTERNALS__
+BASE_PREPROCESSOR_MACROS = __LIBC__ __POSIX_LIB__ __DARWIN_UNIX03=1 __DARWIN_64_BIT_INO_T=1 __DARWIN_NON_CANCELABLE=1 __DARWIN_VERS_1050=1 _FORTIFY_SOURCE=0 __PTHREAD_BUILDING_PTHREAD__=1 $(SIM_PREPROCESSOR_MACROS) __PTHREAD_EXPOSE_INTERNALS__ OS_ATOMIC_CONFIG_MEMORY_ORDER_DEPENDENCY=1
GCC_PREPROCESSOR_DEFINITIONS = $(BASE_PREPROCESSOR_MACROS) $(PLATFORM_PREPROCESSOR_DEFINITIONS)
// TODO: Remove -fstack-protector on _debug when it is moved to libplatform
DYLIB_CURRENT_VERSION = $(RC_ProjectSourceVersion)
DYLIB_COMPATIBILITY_VERSION = 1
DIRTY_LDFLAGS = -Wl,-dirty_data_list,$(SRCROOT)/xcodescripts/pthread.dirty
-DIRTY_LDFLAGS[sdk=macos*] =
-DYLIB_LDFLAGS = -Wl,-alias_list,$(SRCROOT)/xcodescripts/pthread.aliases -Wl,-umbrella,System -L$(SDK_INSTALL_ROOT)/usr/lib/system -lsystem_kernel -lsystem_platform -ldyld -lcompiler_rt
-OTHER_LDFLAGS = $(DYLIB_LDFLAGS) $(DIRTY_LDFLAGS) $(CR_LDFLAGS) $(PLATFORM_LDFLAGS) $(SIMULATOR_LDFLAGS)
+
+LEGACY_ALIAS_LDFLAGS =
+LEGACY_ALIAS_LDFLAGS[sdk=macos*][arch=i386*] = -Wl,-alias_list,$(SRCROOT)/xcodescripts/pthread-i386.aliases
+ALIAS_LDFLAGS = -Wl,-alias_list,$(SRCROOT)/xcodescripts/pthread.aliases $(LEGACY_ALIAS_LDFLAGS)
+
+// rdar://problem/46882983&54282933
+// On macOS, to support the i386 watchOS Simulator, we will continue building
+// libpthread with an i386 slice for the foreseeable future, even though the
+// rest of the OS has dropped i386. (This also applies to libplatform and
+// libsyscall). Normally, dylibs with any dependency on another dylib need
+// to link libdyld for lazy stub binding. libdyld has many dependencies, so
+// that would create a dependency cycle that leads to the whole libSystem
+// umbrella keeping an i386 slice. Instead, ld64 has changed so that the
+// i386 simulator_support slice of libpthread doesn't use lazy binding and so
+// doesn't need -ldyld.
+// So, to break the dependency cycle, macOS libpthread will not link libdyld.
+// All other platforms (including DriverKit on macOS) will continue to link
+// libdyld.
+MACOS_NO_LIBDYLD_LDFLAGS = -ldyld
+MACOS_NO_LIBDYLD_LDFLAGS[sdk=macos*] =
+
+DYLIB_LDFLAGS = -Wl,-umbrella,System -L$(SDK_INSTALL_ROOT)/usr/lib/system -lsystem_kernel -lsystem_platform $(MACOS_NO_LIBDYLD_LDFLAGS) // Don't add compiler_rt or libdyld
+OTHER_LDFLAGS = $(ALIAS_LDFLAGS) $(DYLIB_LDFLAGS) $(DIRTY_LDFLAGS) $(CR_LDFLAGS) $(PLATFORM_LDFLAGS) $(SIMULATOR_LDFLAGS)
SIMULATOR_LDFLAGS =
SIMULATOR_LDFLAGS[sdk=macosx*] = -Wl,-simulator_support
--- /dev/null
+#include "pthread.xcconfig"
+#include "pthread-tapi.xcconfig"
#include "pthread.xcconfig"
+#include "pthread-tapi.xcconfig"
PRODUCT_NAME = pthread
GCC_PREPROCESSOR_DEFINITIONS = $(BASE_PREPROCESSOR_MACROS) VARIANT_STATIC=1
OTHER_LDFLAGS =
+INSTALLHDRS_SCRIPT_PHASE = NO