#ifndef __LIBPTHREAD_TYPES_INTERNAL_H__
#define __LIBPTHREAD_TYPES_INTERNAL_H__
#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
#define _PTHREAD_MUTEX_SIG 0x4D555458
#define _PTHREAD_MUTEX_SIG_fast 0x4D55545A
#define _PTHREAD_MUTEX_SIG_MASK 0xfffffffd
#define _PTHREAD_MUTEX_SIG_CMP 0x4D555458
#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_MUTEX_SIG_init_MASK 0xfffffff0
#define _PTHREAD_MUTEX_SIG_init_CMP 0x32AAABA0
#define _PTHREAD_COND_ATTR_SIG 0x434E4441
#define _PTHREAD_COND_SIG_init 0x3CB0B1BB
#define _PTHREAD_COND_SIG_pristine 0x434F4E44
#define _PTHREAD_COND_SIG_psynch 0x434F4E45
#define _PTHREAD_COND_SIG_ulock 0x434F4E46
#define _PTHREAD_ATTR_SIG 0x54484441
#define _PTHREAD_ONCE_SIG 0x4F4E4345
#define _PTHREAD_ONCE_SIG_init 0x30B1BCBA
#define _PTHREAD_SIG 0x54485244
#define _PTHREAD_RWLOCK_ATTR_SIG 0x52574C41
#define _PTHREAD_RWLOCK_SIG 0x52574C4B
#define _PTHREAD_RWLOCK_SIG_init 0x2DA8B3B4
__enum_closed_decl(pthread_conformance_t, unsigned, {
PTHREAD_CONFORM_UNIX03_NOCANCEL = 1,
PTHREAD_CONFORM_UNIX03_CANCELABLE = 2,
});
#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
#define _PTHREAD_DEFAULT_PSHARED PTHREAD_PROCESS_PRIVATE
#define _PTHREAD_CANCEL_STATE_MASK 0x01
#define _PTHREAD_CANCEL_TYPE_MASK 0x02
#define _PTHREAD_CANCEL_PENDING 0x10
#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
#define _PTHREAD_MTX_OPT_ULOCK_DEFAULT false
#define _PTHREAD_MTX_OPT_ADAPTIVE_DEFAULT false
#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]; uint32_t m_seq[2]; uint32_t m_mis[2]; } 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]; uint32_t rw_seq[4]; uint32_t rw_mis[4]; #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;
TAILQ_ENTRY(pthread_s) tl_plist; struct pthread_join_context_s *tl_join_ctx;
void *tl_exit_value;
uint8_t tl_policy;
uint8_t
tl_joinable:1,
tl_joiner_cleans_up:1,
tl_has_custom_stack:1,
__tl_pad:5;
uint16_t introspection;
uint32_t tl_exit_gate;
struct sched_param tl_param;
void *__unused_padding;
_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];
void *(*fun)(void *); void *arg; int wq_nevents; bool wq_outsideqos;
uint8_t canceled; uint16_t cancel_state; errno_t cancel_error;
errno_t err_no;
void *stackaddr; void *stackbottom; void *freeaddr; size_t freesize; size_t guardsize;
__attribute__((aligned(8)))
uint64_t thread_id;
__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; void *stackaddr; size_t stacksize; union {
struct sched_param param; unsigned long qosclass; };
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__)
#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 {
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__