Add Back dthread Folder

This commit is contained in:
Thomas A 2022-01-13 20:14:23 -08:00
parent ee2b311299
commit de165b2874
21 changed files with 5707 additions and 0 deletions

4
dthread/README.md Normal file
View File

@ -0,0 +1,4 @@
# dthread
This directory is home to Darling's port of Apple's pthread kext. The original source is from libpthread-416.60.2
The goal here is to have Apple's pthread code work with our LKM with as few modifications as possible.

View File

@ -0,0 +1 @@
../../kern_internal.h

View File

@ -0,0 +1 @@
../../kern_trace.h

View File

@ -0,0 +1 @@
../../synch_internal.h

View File

@ -0,0 +1 @@
../../workqueue_internal.h

View File

@ -0,0 +1,225 @@
/*
* 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
#ifdef __DARLING__
// i'm pretty sure Apple should be defining this too
#define __QOS_AVAILABLE_10_15_1
#endif
#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

View File

@ -0,0 +1,304 @@
/*
* 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

View File

@ -0,0 +1,32 @@
/*
* 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 */

View File

@ -0,0 +1,32 @@
/*
* 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 */

View File

@ -0,0 +1,120 @@
/*
* 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_

200
dthread/include/sys/qos.h Normal file
View File

@ -0,0 +1,200 @@
/*
* 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

View File

@ -0,0 +1,40 @@
/*
* 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

65
dthread/kern_init.c Normal file
View File

@ -0,0 +1,65 @@
//
// pthread.c
// pthread
//
// Created by Matt Wright on 9/13/12.
// Copyright (c) 2012 Matt Wright. All rights reserved.
//
#include <kern/thread.h>
#include <kern/debug.h>
#include "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);
pthread_callbacks_t pthread_kern;
const struct pthread_functions_s pthread_internal_functions = {
.pthread_init = _pthread_init,
.pth_proc_hashinit = _pth_proc_hashinit,
.pth_proc_hashdelete = _pth_proc_hashdelete,
.bsdthread_create = _bsdthread_create,
.bsdthread_register = _bsdthread_register,
.bsdthread_terminate = _bsdthread_terminate,
.thread_selfid = _thread_selfid,
.psynch_mutexwait = _psynch_mutexwait,
.psynch_mutexdrop = _psynch_mutexdrop,
.psynch_cvbroad = _psynch_cvbroad,
.psynch_cvsignal = _psynch_cvsignal,
.psynch_cvwait = _psynch_cvwait,
.psynch_cvclrprepost = _psynch_cvclrprepost,
.psynch_rw_longrdlock = _psynch_rw_longrdlock,
.psynch_rw_rdlock = _psynch_rw_rdlock,
.psynch_rw_unlock = _psynch_rw_unlock,
.psynch_rw_wrlock = _psynch_rw_wrlock,
.psynch_rw_yieldwrlock = _psynch_rw_yieldwrlock,
.pthread_find_owner = _pthread_find_owner,
.pthread_get_thread_kwq = _pthread_get_thread_kwq,
.workq_create_threadstack = workq_create_threadstack,
.workq_destroy_threadstack = workq_destroy_threadstack,
.workq_setup_thread = workq_setup_thread,
.workq_handle_stack_events = workq_handle_stack_events,
.workq_markfree_threadstack = workq_markfree_threadstack,
};
kern_return_t pthread_start(__unused kmod_info_t * ki, __unused void *d)
{
pthread_kext_register((pthread_functions_t)&pthread_internal_functions, &pthread_kern);
return KERN_SUCCESS;
}
kern_return_t pthread_stop(__unused kmod_info_t *ki, __unused void *d)
{
return KERN_FAILURE;
}
struct uthread*
current_uthread(void)
{
thread_t th = current_thread();
return pthread_kern->get_bsdthread_info(th);
}

227
dthread/kern_internal.h Normal file
View File

@ -0,0 +1,227 @@
/*
* Copyright (c) 2000-2003 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@
*/
// header name modified for Darling
#ifndef _DTHREAD_KERN_INTERNAL_H
#define _DTHREAD_KERN_INTERNAL_H
#include <pthread/bsdthread_private.h>
#include <pthread/priority_private.h>
#include <pthread/workqueue_syscalls.h>
#ifdef KERNEL
struct ksyn_waitq_element;
#include <stdatomic.h>
#include <kern/thread_call.h>
#include <kern/kcdata.h>
#ifdef __DARLING__
#include <kern/thread.h>
#else
#include <sys/pthread_shims.h>
#endif
#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"
/* 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
* from this call either zero or -1, allowing us to return a positive number for feature bits.
*/
#define PTHREAD_FEATURE_DISPATCHFUNC 0x01 /* same as WQOPS_QUEUE_NEWSPISUPP, checks for dispatch function support */
#define PTHREAD_FEATURE_FINEPRIO 0x02 /* are fine grained prioirities available */
#define PTHREAD_FEATURE_BSDTHREADCTL 0x04 /* is the bsdthread_ctl syscall available */
#define PTHREAD_FEATURE_SETSELF 0x08 /* is the BSDTHREAD_CTL_SET_SELF command of bsdthread_ctl available */
#define PTHREAD_FEATURE_QOS_MAINTENANCE 0x10 /* is QOS_CLASS_MAINTENANCE available */
#define PTHREAD_FEATURE_RESERVED 0x20 /* burnt, shipped in OSX 10.11 & iOS 9 with partial kevent delivery support */
#define PTHREAD_FEATURE_KEVENT 0x40 /* supports direct kevent delivery */
#define PTHREAD_FEATURE_WORKLOOP 0x80 /* supports workloops */
#define PTHREAD_FEATURE_QOS_DEFAULT 0x40000000 /* the kernel supports QOS_CLASS_DEFAULT */
/* userspace <-> kernel registration struct, for passing data to/from the kext during main thread init. */
struct _pthread_registration_data {
/*
* version == sizeof(struct _pthread_registration_data)
*
* The structure can only grow, so we use its size as the version.
* Userspace initializes this to the size of its structure and the kext
* will copy out the version that was actually consumed.
*
* n.b. you must make sure the size of this structure isn't LP64-dependent
*/
uint64_t version;
uint64_t dispatch_queue_offset; /* copy-in */
uint64_t /* pthread_priority_t */ main_qos; /* copy-out */
uint32_t tsd_offset; /* copy-in */
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 */
uint32_t mutex_default_policy; /* copy-out */
} __attribute__ ((packed));
/*
* "error" flags returned by fail condvar syscalls
*/
#define ECVCLEARED 0x100
#define ECVPREPOST 0x200
#ifdef KERNEL
/* The set of features, from the feature bits above, that we support. */
#define PTHREAD_FEATURE_SUPPORTED ( \
PTHREAD_FEATURE_DISPATCHFUNC | \
PTHREAD_FEATURE_FINEPRIO | \
PTHREAD_FEATURE_BSDTHREADCTL | \
PTHREAD_FEATURE_SETSELF | \
PTHREAD_FEATURE_QOS_MAINTENANCE | \
PTHREAD_FEATURE_QOS_DEFAULT | \
PTHREAD_FEATURE_KEVENT | \
PTHREAD_FEATURE_WORKLOOP )
#ifdef __DARLING__
// since we had to move the `pthread_shims.h` include down, we need to declare this differently
struct pthread_callbacks_s;
extern const struct pthread_callbacks_s* pthread_kern;
#else
extern pthread_callbacks_t pthread_kern;
#endif
struct ksyn_waitq_element {
TAILQ_ENTRY(ksyn_waitq_element) kwe_list; /* link to other list members */
void * kwe_kwqqueue; /* queue blocked on */
thread_t kwe_thread;
uint16_t kwe_state; /* state */
uint16_t kwe_flags;
uint32_t kwe_lockseq; /* the sequence of the entry */
uint32_t kwe_count; /* upper bound on number of matches still pending */
uint32_t kwe_psynchretval; /* thread retval */
void *kwe_uth; /* uthread */
};
typedef struct ksyn_waitq_element * ksyn_waitq_element_t;
#define PTH_DEFAULT_STACKSIZE 512*1024
#define MAX_PTHREAD_SIZE 64*1024
/* exported from the kernel but not present in any headers. */
extern thread_t port_name_to_thread(mach_port_name_t port_name);
/* function declarations for pthread_kext.c */
void pthread_init(void);
void psynch_zoneinit(void);
void _pth_proc_hashinit(proc_t p);
void _pth_proc_hashdelete(proc_t p);
void pth_global_hashinit(void);
void psynch_wq_cleanup(void*, void*);
void _pthread_init(void);
int _fill_procworkqueue(proc_t p, struct proc_workqueueinfo * pwqinfo);
uint32_t _get_pwq_state_kdp(proc_t p);
void _workqueue_exit(struct proc *p);
void _workqueue_mark_exiting(struct proc *p);
void _workqueue_thread_yielded(void);
sched_call_t _workqueue_get_sched_callback(void);
int _bsdthread_create(struct proc *p, user_addr_t user_func, user_addr_t user_funcarg, user_addr_t user_stack, user_addr_t user_pthread, uint32_t flags, user_addr_t *retval);
int _bsdthread_register(struct proc *p, user_addr_t threadstart, user_addr_t wqthread, int pthsize, user_addr_t dummy_value, user_addr_t targetconc_ptr, uint64_t dispatchqueue_offset, int32_t *retval);
int _bsdthread_terminate(struct proc *p, user_addr_t stackaddr, size_t size, uint32_t kthport, uint32_t sem, int32_t *retval);
int _bsdthread_ctl_set_qos(struct proc *p, user_addr_t cmd, mach_port_name_t kport, user_addr_t tsd_priority_addr, user_addr_t arg3, int *retval);
int _bsdthread_ctl_set_self(struct proc *p, user_addr_t cmd, pthread_priority_t priority, mach_port_name_t voucher, _pthread_set_flags_t flags, int *retval);
int _bsdthread_ctl_qos_override_start(struct proc *p, user_addr_t cmd, mach_port_name_t kport, pthread_priority_t priority, user_addr_t resource, int *retval);
int _bsdthread_ctl_qos_override_end(struct proc *p, user_addr_t cmd, mach_port_name_t kport, user_addr_t resource, user_addr_t arg3, int *retval);
int _bsdthread_ctl_qos_override_dispatch(struct proc __unused *p, user_addr_t __unused cmd, mach_port_name_t kport, pthread_priority_t priority, user_addr_t arg3, int __unused *retval);
int _bsdthread_ctl_qos_override_reset(struct proc __unused *p, user_addr_t __unused cmd, user_addr_t arg1, user_addr_t arg2, user_addr_t arg3, int __unused *retval);
int _bsdthread_ctl_qos_dispatch_asynchronous_override_add(struct proc __unused *p, user_addr_t __unused cmd, mach_port_name_t kport, pthread_priority_t priority, user_addr_t resource, int __unused *retval);
int _bsdthread_ctl_qos_dispatch_asynchronous_override_reset(struct proc __unused *p, user_addr_t __unused cmd, int reset_all, user_addr_t resource, user_addr_t arg3, int __unused *retval);
int _bsdthread_ctl(struct proc *p, user_addr_t cmd, user_addr_t arg1, user_addr_t arg2, user_addr_t arg3, int *retval);
int _thread_selfid(__unused struct proc *p, uint64_t *retval);
int _workq_kernreturn(struct proc *p, int options, user_addr_t item, int arg2, int arg3, int32_t *retval);
int _workq_open(struct proc *p, int32_t *retval);
int _psynch_mutexwait(proc_t p, user_addr_t mutex, uint32_t mgen, uint32_t ugen, uint64_t tid, uint32_t flags, uint32_t * retval);
int _psynch_mutexdrop(proc_t p, user_addr_t mutex, uint32_t mgen, uint32_t ugen, uint64_t tid, uint32_t flags, uint32_t * retval);
int _psynch_cvbroad(proc_t p, user_addr_t cv, uint64_t cvlsgen, uint64_t cvudgen, uint32_t flags, user_addr_t mutex, uint64_t mugen, uint64_t tid, uint32_t *retval);
int _psynch_cvsignal(proc_t p, user_addr_t cv, uint64_t cvlsgen, uint32_t cvugen, int thread_port, user_addr_t mutex, uint64_t mugen, uint64_t tid, uint32_t flags, uint32_t * retval);
int _psynch_cvwait(proc_t p, user_addr_t cv, uint64_t cvlsgen, uint32_t cvugen, user_addr_t mutex, uint64_t mugen, uint32_t flags, int64_t sec, uint32_t nsec, uint32_t * retval);
int _psynch_cvclrprepost(proc_t p, user_addr_t cv, uint32_t cvgen, uint32_t cvugen, uint32_t cvsgen, uint32_t prepocnt, uint32_t preposeq, uint32_t flags, int *retval);
int _psynch_rw_longrdlock(proc_t p, user_addr_t rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags, uint32_t * retval);
int _psynch_rw_rdlock(proc_t p, user_addr_t rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags, uint32_t *retval);
int _psynch_rw_unlock(proc_t p, user_addr_t rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags, uint32_t *retval);
int _psynch_rw_wrlock(proc_t p, user_addr_t rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags, uint32_t *retval);
int _psynch_rw_yieldwrlock(proc_t p, user_addr_t rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags, uint32_t *retval);
void _pthread_find_owner(thread_t thread, struct stackshot_thread_waitinfo *waitinfo);
void * _pthread_get_thread_kwq(thread_t thread);
extern lck_grp_attr_t *pthread_lck_grp_attr;
extern lck_grp_t *pthread_lck_grp;
extern lck_attr_t *pthread_lck_attr;
extern lck_mtx_t *pthread_list_mlock;
extern thread_call_t psynch_thcall;
struct uthread* current_uthread(void);
int
workq_create_threadstack(proc_t p, vm_map_t vmap, mach_vm_offset_t *out_addr);
int
workq_destroy_threadstack(proc_t p, vm_map_t vmap, mach_vm_offset_t stackaddr);
void
workq_setup_thread(proc_t p, thread_t th, vm_map_t map, user_addr_t stackaddr,
mach_port_name_t kport, int th_qos, int setup_flags, int upcall_flags);
int
workq_handle_stack_events(proc_t p, thread_t th, vm_map_t map,
user_addr_t stackaddr, mach_port_name_t kport,
user_addr_t events, int nevents, int upcall_flags);
void
workq_markfree_threadstack(proc_t p, thread_t th, vm_map_t vmap,
user_addr_t stackaddr);
#ifdef __DARLING__
// move it down here because it needs `struct ksyn_waitq_element` to be defined
#include <sys/pthread_shims.h>
#endif
#endif // KERNEL
#endif // _DTHREAD_KERN_INTERNAL_H

1020
dthread/kern_support.c Normal file

File diff suppressed because it is too large Load Diff

2835
dthread/kern_synch.c Normal file

File diff suppressed because it is too large Load Diff

164
dthread/kern_trace.h Normal file
View File

@ -0,0 +1,164 @@
/*
* Copyright (c) 2000-2003 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 _KERN_TRACE_H_
#define _KERN_TRACE_H_
/* pthread kext, or userspace, kdebug trace points. Defined here and output to
* /usr/share/misc/pthread.codes during build.
*/
// userspace trace points force slow-paths, so must be compiled in
#define ENABLE_USERSPACE_TRACE 0
// pthread tracing subclasses
# define _TRACE_SUB_DEFAULT 0
# define _TRACE_SUB_WORKQUEUE 1
// WQ_TRACE_REQUESTS_SUBCLASS is 2, in xnu
# define _TRACE_SUB_MUTEX 3
# define _TRACE_SUB_CONDVAR 4
#ifndef _PTHREAD_BUILDING_CODES_
#include <sys/kdebug.h>
#ifndef DBG_PTHREAD
#define DBG_PTHREAD DBG_WORKQUEUE
#endif
#if KERNEL
#include <vm/vm_kern.h>
extern uint32_t pthread_debug_tracing;
static __unused void*
VM_UNSLIDE(void* ptr)
{
vm_offset_t unslid_ptr;
vm_kernel_unslide_or_perm_external(ptr, &unslid_ptr);
return (void*)unslid_ptr;
}
# 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
# include <sys/kdebug.h>
# define PTHREAD_TRACE(x, a, b, c, d) kdebug_trace(TRACE_##x, a, b, c, d)
#else // ENABLE_USERSPACE_TRACE
# define PTHREAD_TRACE(x, a, b, c, d) do { } while(0)
#endif // ENABLE_USERSPACE_TRACE
#endif // KERNEL
# define TRACE_CODE(name, subclass, code) \
static const int TRACE_##name = KDBG_CODE(DBG_PTHREAD, subclass, code)
#else // _PTHREAD_BUILDING_CODES_
/* When not included as a header, this file is pre-processed into perl source to generate
* the pthread.codes file during build.
*/
# define DBG_PTHREAD 9
# define STR(x) #x
# define TRACE_CODE(name, subclass, code) \
printf("0x%x\t%s\n", ((DBG_PTHREAD << 24) | ((subclass & 0xff) << 16) | ((code & 0x3fff) << 2)), STR(name))
#endif // _PTHREAD_BUILDING_CODES_
/* These defines translate into TRACE_<name> when used in source code, and are
* pre-processed out to a codes file by the build system.
*/
// "default" trace points
TRACE_CODE(pthread_thread_create, _TRACE_SUB_DEFAULT, 0x10);
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_mutex_uunlock, _TRACE_SUB_MUTEX, 0x2);
TRACE_CODE(psynch_ksyn_incorrect_owner, _TRACE_SUB_MUTEX, 0x3);
TRACE_CODE(psynch_mutex_lock_updatebits, _TRACE_SUB_MUTEX, 0x4);
TRACE_CODE(psynch_mutex_unlock_updatebits, _TRACE_SUB_MUTEX, 0x5);
TRACE_CODE(psynch_mutex_clearprepost, _TRACE_SUB_MUTEX, 0x6);
TRACE_CODE(psynch_mutex_kwqallocate, _TRACE_SUB_MUTEX, 0x7);
TRACE_CODE(psynch_mutex_kwqdeallocate, _TRACE_SUB_MUTEX, 0x8);
TRACE_CODE(psynch_mutex_kwqprepost, _TRACE_SUB_MUTEX, 0x9);
TRACE_CODE(psynch_mutex_markprepost, _TRACE_SUB_MUTEX, 0x10);
TRACE_CODE(psynch_mutex_kwqcollision, _TRACE_SUB_MUTEX, 0x11);
TRACE_CODE(psynch_ffmutex_lock_updatebits, _TRACE_SUB_MUTEX, 0x12);
TRACE_CODE(psynch_ffmutex_unlock_updatebits, _TRACE_SUB_MUTEX, 0x13);
TRACE_CODE(psynch_ffmutex_wake, _TRACE_SUB_MUTEX, 0x14);
TRACE_CODE(psynch_mutex_kwqsignal, _TRACE_SUB_MUTEX, 0x15);
TRACE_CODE(psynch_ffmutex_wait, _TRACE_SUB_MUTEX, 0x16);
TRACE_CODE(psynch_mutex_kwqwait, _TRACE_SUB_MUTEX, 0x17);
TRACE_CODE(psynch_cvar_kwait, _TRACE_SUB_CONDVAR, 0x0);
TRACE_CODE(psynch_cvar_clrprepost, _TRACE_SUB_CONDVAR, 0x1);
TRACE_CODE(psynch_cvar_freeitems, _TRACE_SUB_CONDVAR, 0x2);
TRACE_CODE(psynch_cvar_signal, _TRACE_SUB_CONDVAR, 0x3);
TRACE_CODE(psynch_cvar_broadcast, _TRACE_SUB_CONDVAR, 0x5);
TRACE_CODE(psynch_cvar_zeroed, _TRACE_SUB_CONDVAR, 0x6);
TRACE_CODE(psynch_cvar_updateval, _TRACE_SUB_CONDVAR, 0x7);
#endif // _KERN_TRACE_H_

201
dthread/pthread_kext.c Normal file
View File

@ -0,0 +1,201 @@
/**
* a brief rationale on why we need this
* ---
*
* so, sometime around the release of macOS 10.9 (with xnu-2422.1.72),
* Apple decided to stuff pthread support in-kernel into a kext (pthread.kext)
*
* we already have most of the functions implemented in `psync_support.c`, this file just takes care of the rest
* and the necessary plumbing for XNU's `pthread_shims.c` so that we can use XNU's own interface as much as possible
*
* ignore the following; i've actually decided against building `pthread_workqueue.c`
* (turns out its usage in `turnstile.c` only matters when workqueues are already being used for something else)
*
* > up until recently, we didn't really build any parts of XNU that needed it
* >
* > however, the new turnstile subsystem requires functions that are implemented in `pthread_workqueue.c`,
* > and it's relatively simple to build that file by adding support for the functions it calls out to
* > (and easy enough that it's better than stubbing them)
*
* so like i said, that reason is no longer valid. i decided to leave this in anyways because i had already completely
* added it in and it works so ¯\_()_/¯
*/
#include <duct/duct.h>
#include <duct/duct_pre_xnu.h>
#include <kern/kern_types.h>
#include <sys/proc.h>
#include "kern_internal.h"
#include <duct/duct_post_xnu.h>
#include "pthread_kext.h"
/**
*
* `pthread_shims.c` plumbing
*
*/
static const struct pthread_functions_s _darling_pthread_functions = {
.pthread_init = _pthread_init,
.pth_proc_hashinit = _pth_proc_hashinit,
.pth_proc_hashdelete = _pth_proc_hashdelete,
.bsdthread_create = _bsdthread_create,
.bsdthread_register = _bsdthread_register,
.bsdthread_terminate = _bsdthread_terminate,
.thread_selfid = _thread_selfid,
.psynch_mutexwait = _psynch_mutexwait,
.psynch_mutexdrop = _psynch_mutexdrop,
.psynch_cvbroad = _psynch_cvbroad,
.psynch_cvsignal = _psynch_cvsignal,
.psynch_cvwait = _psynch_cvwait,
.psynch_cvclrprepost = _psynch_cvclrprepost,
.psynch_rw_longrdlock = _psynch_rw_longrdlock,
.psynch_rw_rdlock = _psynch_rw_rdlock,
.psynch_rw_unlock = _psynch_rw_unlock,
.psynch_rw_wrlock = _psynch_rw_wrlock,
.psynch_rw_yieldwrlock = _psynch_rw_yieldwrlock,
.pthread_find_owner = _pthread_find_owner,
.pthread_get_thread_kwq = _pthread_get_thread_kwq,
.workq_create_threadstack = workq_create_threadstack,
.workq_destroy_threadstack = workq_destroy_threadstack,
.workq_setup_thread = workq_setup_thread,
.workq_handle_stack_events = workq_handle_stack_events,
.workq_markfree_threadstack = workq_markfree_threadstack,
};
// called by our kernel module during initialization
//
// this is different from `darling_pthread_init`, because this function is the one that sets up
// the pthread kext plumbing, while the `pthread_init` is only called by some BSD code after the kext has already been set up
void darling_pthread_kext_init(void) {
// we don't really need the callbacks, since we're not actually a kext and we have full access to the whole kernel,
// but it's easier to provide the callbacks than it is to modify every instance of `pthread_kern->whatever(...)`.
// plus, `pthread_shims.c` won't take "no" for an answer (it'll panic if we give it `NULL`).
// we have this a local variable though, because since we *aren't* a kext, we have `pthread_kern` already defined in `pthread_shims.c`
pthread_callbacks_t callbacks = NULL;
pthread_kext_register(&_darling_pthread_functions, &callbacks);
};
// called by our kernel module when it's going to be unloaded
void darling_pthread_kext_exit(void) {};
// temporarily copied over from kern_support.c (until we start building that file)
// <copied from="libpthread://416.60.2/kern/kern_support.c" modified="true">
#ifdef __DARLING__
uint32_t pthread_debug_tracing = 0;
#else
uint32_t pthread_debug_tracing = 1;
#endif
#ifdef __DARLING__
static lck_grp_attr_t the_real_pthread_lck_grp_attr;
static lck_grp_t the_real_pthread_lck_grp;
static lck_attr_t the_real_pthread_lck_attr;
static lck_mtx_t the_real_pthread_list_mlock;
lck_grp_attr_t* pthread_lck_grp_attr = &the_real_pthread_lck_grp_attr;
lck_grp_t* pthread_lck_grp = &the_real_pthread_lck_grp;
lck_attr_t* pthread_lck_attr = &the_real_pthread_lck_attr;
#else
lck_grp_attr_t *pthread_lck_grp_attr;
lck_grp_t *pthread_lck_grp;
lck_attr_t *pthread_lck_attr;
#endif
void
_pthread_init(void)
{
#ifdef __DARLING__
lck_grp_attr_setdefault(pthread_lck_grp_attr);
lck_grp_init(pthread_lck_grp, "pthread", pthread_lck_grp_attr);
lck_attr_setdefault(pthread_lck_attr);
pthread_list_mlock = &the_real_pthread_list_mlock;
lck_mtx_init(pthread_list_mlock, pthread_lck_grp, pthread_lck_attr);
#else
pthread_lck_grp_attr = lck_grp_attr_alloc_init();
pthread_lck_grp = lck_grp_alloc_init("pthread", pthread_lck_grp_attr);
/*
* allocate the lock attribute for pthread synchronizers
*/
pthread_lck_attr = lck_attr_alloc_init();
pthread_list_mlock = lck_mtx_alloc_init(pthread_lck_grp, pthread_lck_attr);
#endif
pth_global_hashinit();
psynch_thcall = thread_call_allocate(psynch_wq_cleanup, NULL);
psynch_zoneinit();
#ifndef __DARLING__
int policy_bootarg;
if (PE_parse_boot_argn("pthread_mutex_default_policy", &policy_bootarg, sizeof(policy_bootarg))) {
pthread_mutex_default_policy = policy_bootarg;
}
sysctl_register_oid(&sysctl__kern_pthread_mutex_default_policy);
#endif
}
// </copied>
/**
* stubbed functions
*/
/**
* nobody really needs this next set of functions right now,
* so we can just stub them for now
*/
int _bsdthread_create(proc_t p, user_addr_t user_func, user_addr_t user_funcarg, user_addr_t user_stack, user_addr_t user_pthread, uint32_t flags, user_addr_t* retval) {
return ENOTSUP;
};
int _bsdthread_register(proc_t p, user_addr_t threadstart, user_addr_t wqthread, int pthsize, user_addr_t dummy_value, user_addr_t targetconc_ptr, uint64_t dispatchqueue_offset, int32_t* retval) {
return ENOTSUP;
};
int _bsdthread_terminate(proc_t p, user_addr_t stackaddr, size_t size, uint32_t kthport, uint32_t sem, int32_t* retval) {
return ENOTSUP;
};
int _thread_selfid(proc_t p, uint64_t* retval) {
return ENOTSUP;
};
int _bsdthread_register2(proc_t p, user_addr_t threadstart, user_addr_t wqthread, uint32_t flags, user_addr_t stack_addr_hint, user_addr_t targetconc_ptr, uint32_t dispatchqueue_offset, uint32_t tsd_offset, int32_t* retval) {
return ENOTSUP;
};
/**
* now these are actually needed by `pthread_workqueue.c`
*/
int workq_handle_stack_events(proc_t p, thread_t th, vm_map_t map, user_addr_t stackaddr, mach_port_name_t kport, user_addr_t events, int nevents, int upcall_flags) {
return ENOTSUP;
};
int workq_create_threadstack(proc_t p, vm_map_t vmap, mach_vm_offset_t* out_addr) {
return ENOTSUP;
};
int workq_destroy_threadstack(proc_t p, vm_map_t vmap, mach_vm_offset_t stackaddr) {
return ENOTSUP;
};
void workq_setup_thread(proc_t p, thread_t th, vm_map_t map, user_addr_t stackaddr, mach_port_name_t kport, int th_qos, int setup_flags, int upcall_flags) {
};
void workq_markfree_threadstack(proc_t p, thread_t th, vm_map_t map, user_addr_t stackaddr) {
};

7
dthread/pthread_kext.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef _DARLING_LKM_PTHREAD_KEXT_H_
#define _DARLING_LKM_PTHREAD_KEXT_H_
void darling_pthread_kext_init(void);
void darling_pthread_kext_exit(void);
#endif // _DARLING_LKM_PTHREAD_KEXT_H_

173
dthread/synch_internal.h Normal file
View File

@ -0,0 +1,173 @@
/*
* Copyright (c) 2000-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@
*/
#ifndef __SYNCH_INTERNAL_H__
#define __SYNCH_INTERNAL_H__
// kwe_state
enum {
KWE_THREAD_INWAIT = 1,
KWE_THREAD_PREPOST,
KWE_THREAD_BROADCAST,
};
#define _PTHREAD_MTX_OPT_PSHARED 0x010
#define _PTHREAD_MTX_OPT_NOTIFY 0x1000 /* notify to drop mutex handling in cvwait */
#define _PTHREAD_MTX_OPT_MUTEX 0x2000 /* this is a mutex type */
#define PTHRW_COUNT_SHIFT 8
#define PTHRW_INC (1 << PTHRW_COUNT_SHIFT)
#define PTHRW_BIT_MASK ((1 << PTHRW_COUNT_SHIFT) - 1)
#define PTHRW_COUNT_MASK ((uint32_t)~PTHRW_BIT_MASK)
#define PTHRW_MAX_READERS PTHRW_COUNT_MASK
// L word
#define PTH_RWL_KBIT 0x01 // cannot acquire in user mode
#define PTH_RWL_EBIT 0x02 // exclusive lock in progress
#define PTH_RWL_WBIT 0x04 // write waiters pending in kernel
#define PTH_RWL_PBIT 0x04 // prepost (cv) pending in kernel
#define PTH_RWL_MTX_WAIT 0x20 // in cvar in mutex wait
#define PTH_RWL_UBIT 0x40 // lock is unlocked (no readers or writers)
#define PTH_RWL_MBIT 0x40 // overlapping grants from kernel (only in updateval)
#define PTH_RWL_IBIT 0x80 // lock reset, held until first successful unlock
#define PTHRW_RWL_INIT PTH_RWL_IBIT // reset on the lock bits (U)
#define PTHRW_RWLOCK_INIT (PTH_RWL_IBIT | PTH_RWL_UBIT) // reset on the lock bits (U)
// S word
#define PTH_RWS_SBIT 0x01 // kernel transition seq not set yet
#define PTH_RWS_IBIT 0x02 // Sequence is not set on return from kernel
#define PTH_RWS_CV_CBIT PTH_RWS_SBIT // kernel has cleared all info w.r.s.t CV
#define PTH_RWS_CV_PBIT PTH_RWS_IBIT // kernel has prepost/fake structs only,no waiters
#define PTH_RWS_CV_BITSALL (PTH_RWS_CV_CBIT | PTH_RWS_CV_PBIT)
#define PTH_RWS_CV_MBIT PTH_RWL_MBIT // to indicate prepost return from kernel
#define PTH_RWS_CV_RESET_PBIT ((uint32_t)~PTH_RWS_CV_PBIT)
#define PTH_RWS_WSVBIT 0x04 // save W bit
#define PTHRW_RWS_SAVEMASK (PTH_RWS_WSVBIT) // save bits mask
#define PTHRW_RWS_INIT PTH_RWS_SBIT // reset on the lock bits (U)
// rw_flags
#define PTHRW_KERN_PROCESS_SHARED 0x10
#define PTHRW_KERN_PROCESS_PRIVATE 0x20
#define PTHREAD_MTX_TID_SWITCHING (uint64_t)-1
// L word tests
#define is_rwl_ebit_set(x) (((x) & PTH_RWL_EBIT) != 0)
#define is_rwl_wbit_set(x) (((x) & PTH_RWL_WBIT) != 0)
#define is_rwl_ebit_clear(x) (((x) & PTH_RWL_EBIT) == 0)
#define is_rwl_readoverlap(x) (((x) & PTH_RWL_MBIT) != 0)
// S word tests
#define is_rws_sbit_set(x) (((x) & PTH_RWS_SBIT) != 0)
#define is_rws_unlockinit_set(x) (((x) & PTH_RWS_IBIT) != 0)
#define is_rws_savemask_set(x) (((x) & PTHRW_RWS_SAVEMASK) != 0)
#define is_rws_pbit_set(x) (((x) & PTH_RWS_CV_PBIT) != 0)
// kwe_flags
#define KWE_FLAG_LOCKPREPOST 0x1 // cvwait caused a lock prepost
static inline int
is_seqlower(uint32_t x, uint32_t y)
{
x &= PTHRW_COUNT_MASK;
y &= PTHRW_COUNT_MASK;
if (x < y) {
return ((y - x) < (PTHRW_MAX_READERS / 2));
} else {
return ((x - y) > (PTHRW_MAX_READERS / 2));
}
}
static inline int
is_seqlower_eq(uint32_t x, uint32_t y)
{
if ((x & PTHRW_COUNT_MASK) == (y & PTHRW_COUNT_MASK)) {
return 1;
} else {
return is_seqlower(x, y);
}
}
static inline int
is_seqhigher(uint32_t x, uint32_t y)
{
x &= PTHRW_COUNT_MASK;
y &= PTHRW_COUNT_MASK;
if (x > y) {
return ((x - y) < (PTHRW_MAX_READERS / 2));
} else {
return ((y - x) > (PTHRW_MAX_READERS / 2));
}
}
static inline int
is_seqhigher_eq(uint32_t x, uint32_t y)
{
if ((x & PTHRW_COUNT_MASK) == (y & PTHRW_COUNT_MASK)) {
return 1;
} else {
return is_seqhigher(x,y);
}
}
static inline int
diff_genseq(uint32_t x, uint32_t y)
{
x &= PTHRW_COUNT_MASK;
y &= PTHRW_COUNT_MASK;
if (x == y) {
return 0;
} else if (x > y) {
return x - y;
} else {
return ((PTHRW_MAX_READERS - y) + x + PTHRW_INC);
}
}
static inline int
find_diff(uint32_t upto, uint32_t lowest)
{
uint32_t diff;
if (upto == lowest)
return(0);
#if 0
diff = diff_genseq(upto, lowest);
#else
if (is_seqlower(upto, lowest) != 0)
diff = diff_genseq(lowest, upto);
else
diff = diff_genseq(upto, lowest);
#endif
diff = (diff >> PTHRW_COUNT_SHIFT);
return(diff);
}
#endif /* __SYNCH_INTERNAL_H__ */

View File

@ -0,0 +1,54 @@
/*
* 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 DTHREAD_WORKQUEUE_INTERNAL_H // header name changed for Darling
#define DTHREAD_WORKQUEUE_INTERNAL_H
#ifdef __DARLING__
#include <pthread/workqueue_internal.h>
#endif
/* 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 // DTHREAD_WORKQUEUE_INTERNAL_H