2 * Copyright (c) 2003-2019 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #ifndef __LIBPTHREAD_TYPES_INTERNAL_H__
30 #define __LIBPTHREAD_TYPES_INTERNAL_H__
33 * @file types_internal.h
36 * This file exposes all the internal pthread types used by the library.
39 * This header must be included first, as it masks the opaque definitions
40 * exposed to libpthread clients in the SDK.
43 #define _PTHREAD_ONCE_T
44 typedef struct pthread_once_s pthread_once_t
;
46 #define _PTHREAD_MUTEX_T
47 #define _PTHREAD_MUTEXATTR_T
48 typedef struct pthread_mutex_s pthread_mutex_t
;
49 typedef struct pthread_mutexattr_s pthread_mutexattr_t
;
51 #define _PTHREAD_COND_T
52 #define _PTHREAD_CONDATTR_T
53 typedef struct pthread_cond_s pthread_cond_t
;
54 typedef struct pthread_condattr_s pthread_condattr_t
;
56 #define _PTHREAD_RWLOCK_T
57 #define _PTHREAD_RWLOCKATTR_T
58 typedef struct pthread_rwlock_s pthread_rwlock_t
;
59 typedef struct pthread_rwlockattr_s pthread_rwlockattr_t
;
62 #define _PTHREAD_ATTR_T
63 typedef struct pthread_s
*pthread_t
;
64 typedef struct pthread_attr_s pthread_attr_t
;
74 #include <sys/queue.h>
75 #include <sys/param.h>
77 #include <mach/mach.h>
78 #include <mach/mach_error.h>
80 #include <os/base_private.h>
81 #include <os/once_private.h>
84 #include "pthread/posix_sched.h"
85 #include "pthread/workqueue_private.h"
86 #include "sys/_pthread/_pthread_types.h"
88 #pragma mark - constants
90 #define _PTHREAD_NO_SIG 0x00000000
91 #define _PTHREAD_MUTEX_ATTR_SIG 0x4D545841 /* 'MTXA' */
92 #define _PTHREAD_MUTEX_SIG 0x4D555458 /* 'MUTX' */
93 #define _PTHREAD_MUTEX_SIG_fast 0x4D55545A /* 'MUTZ' */
94 #define _PTHREAD_MUTEX_SIG_MASK 0xfffffffd
95 #define _PTHREAD_MUTEX_SIG_CMP 0x4D555458 /* _PTHREAD_MUTEX_SIG & _PTHREAD_MUTEX_SIG_MASK */
96 #define _PTHREAD_MUTEX_SIG_init 0x32AAABA7 /* [almost] ~'MUTX' */
97 #define _PTHREAD_ERRORCHECK_MUTEX_SIG_init 0x32AAABA1
98 #define _PTHREAD_RECURSIVE_MUTEX_SIG_init 0x32AAABA2
99 #define _PTHREAD_FIRSTFIT_MUTEX_SIG_init 0x32AAABA3
100 #define _PTHREAD_MUTEX_SIG_init_MASK 0xfffffff0
101 #define _PTHREAD_MUTEX_SIG_init_CMP 0x32AAABA0
102 #define _PTHREAD_COND_ATTR_SIG 0x434E4441 /* 'CNDA' */
103 #define _PTHREAD_COND_SIG_init 0x3CB0B1BB /* [almost] ~'COND' */
104 #define _PTHREAD_COND_SIG_pristine 0x434F4E44 /* 'COND' */
105 #define _PTHREAD_COND_SIG_psynch 0x434F4E45 /* 'COND' + 0b01: 'CONE' */
106 #define _PTHREAD_COND_SIG_ulock 0x434F4E46 /* 'COND' + 0b10: 'CONF' */
107 #define _PTHREAD_ATTR_SIG 0x54484441 /* 'THDA' */
108 #define _PTHREAD_ONCE_SIG 0x4F4E4345 /* 'ONCE' */
109 #define _PTHREAD_ONCE_SIG_init 0x30B1BCBA /* [almost] ~'ONCE' */
110 #define _PTHREAD_SIG 0x54485244 /* 'THRD' */
111 #define _PTHREAD_RWLOCK_ATTR_SIG 0x52574C41 /* 'RWLA' */
112 #define _PTHREAD_RWLOCK_SIG 0x52574C4B /* 'RWLK' */
113 #define _PTHREAD_RWLOCK_SIG_init 0x2DA8B3B4 /* [almost] ~'RWLK' */
115 __enum_closed_decl(pthread_conformance_t
, unsigned, {
116 PTHREAD_CONFORM_UNIX03_NOCANCEL
= 1,
117 PTHREAD_CONFORM_UNIX03_CANCELABLE
= 2,
120 /* Pull the pthread_t into the same page as the top of the stack so we dirty one less page.
121 * <rdar://problem/19941744> The pthread_s struct at the top of the stack shouldn't be page-aligned
123 #if defined(__arm64__)
124 #define PTHREAD_T_OFFSET (12*1024)
126 #define PTHREAD_T_OFFSET 0
129 #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
130 #define _EXTERNAL_POSIX_THREAD_KEYS_MAX 256
131 #define _INTERNAL_POSIX_THREAD_KEYS_MAX 256
132 #define _INTERNAL_POSIX_THREAD_KEYS_END 512
134 #define _EXTERNAL_POSIX_THREAD_KEYS_MAX 512
135 #define _INTERNAL_POSIX_THREAD_KEYS_MAX 256
136 #define _INTERNAL_POSIX_THREAD_KEYS_END 768
139 #define PTHREAD_ATFORK_INLINE_MAX 10
141 #define MAXTHREADNAMESIZE 64
143 #define _PTHREAD_DEFAULT_INHERITSCHED PTHREAD_INHERIT_SCHED
144 #define _PTHREAD_DEFAULT_PROTOCOL PTHREAD_PRIO_NONE
145 #define _PTHREAD_DEFAULT_PRIOCEILING 0
146 #define _PTHREAD_DEFAULT_POLICY SCHED_OTHER
147 #define _PTHREAD_DEFAULT_STACKSIZE 0x80000 /* 512K */
148 #define _PTHREAD_DEFAULT_PSHARED PTHREAD_PROCESS_PRIVATE
150 #define _PTHREAD_CANCEL_STATE_MASK 0x01
151 #define _PTHREAD_CANCEL_TYPE_MASK 0x02
152 #define _PTHREAD_CANCEL_PENDING 0x10 /* pthread_cancel() has been called for this thread */
153 #define _PTHREAD_CANCEL_EXITING 0x20
155 #define pthread_assert_type_size(type) \
156 static_assert(sizeof(struct type##_s) == sizeof(struct _opaque_##type##_t), "")
157 #define pthread_assert_type_alias(type, f1, f2) \
158 static_assert(offsetof(struct type##_s, f1) == offsetof(struct _opaque_##type##_t, f2), "")
160 typedef os_unfair_lock _pthread_lock
;
161 struct _pthread_registration_data
;
164 #pragma mark - pthread_once_t
166 struct pthread_once_s
{
171 pthread_assert_type_size(pthread_once
);
172 pthread_assert_type_alias(pthread_once
, sig
, __sig
);
174 #pragma mark - pthread_mutex_t, pthread_mutexattr_t
176 #define _PTHREAD_MUTEX_POLICY_LAST (PTHREAD_MUTEX_POLICY_FIRSTFIT_NP + 1)
177 #define _PTHREAD_MTX_OPT_POLICY_FAIRSHARE 1
178 #define _PTHREAD_MTX_OPT_POLICY_FIRSTFIT 2
179 #define _PTHREAD_MTX_OPT_POLICY_DEFAULT _PTHREAD_MTX_OPT_POLICY_FIRSTFIT
180 // The following pthread_mutex_options_s defintions exist in synch_internal.h
181 // such that the kernel extension can test for flags. They must be kept in
182 // sync with the bit values in the struct above.
183 // _PTHREAD_MTX_OPT_PSHARED 0x010
184 // _PTHREAD_MTX_OPT_NOTIFY 0x1000
185 // _PTHREAD_MTX_OPT_MUTEX 0x2000
187 #define _PTHREAD_MTX_OPT_ULOCK_DEFAULT false
188 #define _PTHREAD_MTX_OPT_ADAPTIVE_DEFAULT false
190 // The fixed mask is used to mask out portions of the mutex options that
191 // change on a regular basis (notify, lock_count).
192 #define _PTHREAD_MTX_OPT_FIXED_MASK 0x27ff
194 struct pthread_mutex_options_s
{
209 #define _PTHREAD_MUTEX_ULOCK_OWNER_MASK 0xfffffffcu
210 #define _PTHREAD_MUTEX_ULOCK_WAITERS_BIT 0x00000001u
211 #define _PTHREAD_MUTEX_ULOCK_UNLOCKED_VALUE 0x0u
212 #define _PTHREAD_MUTEX_ULOCK_UNLOCKED \
213 ((struct _pthread_mutex_ulock_s){0})
215 typedef struct _pthread_mutex_ulock_s
{
217 } *_pthread_mutex_ulock_t
;
219 struct pthread_mutex_s
{
224 struct pthread_mutex_options_s options
;
228 #if defined(__LP64__)
233 uint32_t m_tid
[2]; // thread id of thread that has mutex locked
234 uint32_t m_seq
[2]; // mutex sequence id
235 uint32_t m_mis
[2]; // for misaligned locks m_tid/m_seq will span into here
237 struct _pthread_mutex_ulock_s ulock
;
239 #if defined(__LP64__)
240 uint32_t _reserved
[4];
242 uint32_t _reserved
[1];
246 pthread_assert_type_size(pthread_mutex
);
247 pthread_assert_type_alias(pthread_mutex
, sig
, __sig
);
249 struct pthread_mutexattr_s
{
260 pthread_assert_type_size(pthread_mutexattr
);
261 pthread_assert_type_alias(pthread_mutexattr
, sig
, __sig
);
263 #pragma mark - pthread_rwlock_t, pthread_rwlockattr_t
265 struct pthread_rwlock_s
{
273 #if defined(__LP64__)
276 uint32_t rw_tid
[2]; // thread id of thread that has exclusive (write) lock
277 uint32_t rw_seq
[4]; // rw sequence id (at 128-bit aligned boundary)
278 uint32_t rw_mis
[4]; // for misaligned locks rw_seq will span into here
279 #if defined(__LP64__)
280 uint32_t _reserved
[34];
282 uint32_t _reserved
[18];
286 pthread_assert_type_size(pthread_rwlock
);
287 pthread_assert_type_alias(pthread_rwlock
, sig
, __sig
);
289 struct pthread_rwlockattr_s
{
292 #if defined(__LP64__)
293 uint32_t _reserved
[3];
295 uint32_t _reserved
[2];
299 pthread_assert_type_size(pthread_rwlockattr
);
300 pthread_assert_type_alias(pthread_rwlockattr
, sig
, __sig
);
302 #pragma mark - pthread_cond_t, pthread_condattr_t
304 struct pthread_cond_s
{
307 #if defined(__LP64__)
316 pthread_mutex_t
*busy
;
318 #if defined(__LP64__)
319 uint32_t _reserved
[3];
323 pthread_assert_type_size(pthread_cond
);
324 pthread_assert_type_alias(pthread_cond
, sig
, __sig
);
326 struct pthread_condattr_s
{
333 pthread_assert_type_size(pthread_condattr
);
334 pthread_assert_type_alias(pthread_condattr
, sig
, __sig
);
336 #pragma mark - pthread_t, pthread_attr_t
338 typedef struct pthread_join_context_s
{
342 semaphore_t custom_stack_sema
;
344 } pthread_join_context_s
, *pthread_join_context_t
;
346 #define MAXTHREADNAMESIZE 64
350 struct __darwin_pthread_handler_rec
*__cleanup_stack
;
353 // Fields protected by _pthread_list_lock
356 TAILQ_ENTRY(pthread_s
) tl_plist
; // global thread list [aligned]
357 struct pthread_join_context_s
*tl_join_ctx
;
360 // pthread knows that tl_joinable bit comes immediately after tl_policy
363 tl_joiner_cleans_up
:1,
364 tl_has_custom_stack
:1,
366 uint16_t introspection
;
367 // MACH_PORT_NULL if no joiner
368 // tsd[_PTHREAD_TSD_SLOT_MACH_THREAD_SELF] when has a joiner
369 // MACH_PORT_DEAD if the thread exited
370 uint32_t tl_exit_gate
;
371 struct sched_param tl_param
;
372 void *__unused_padding
;
375 // Fields protected by pthread_t::lock
379 uint16_t max_tsd_key
;
388 char pthread_name
[MAXTHREADNAMESIZE
]; // includes NUL [aligned]
390 void *(*fun
)(void *); // thread start routine
391 void *arg
; // thread start routine argument
392 int wq_nevents
; // wqthreads (workloop / kevent)
394 uint8_t canceled
; // 4597450 set if conformant cancelation happened
395 uint16_t cancel_state
; // whether the thread can be canceled [atomic]
396 errno_t cancel_error
;
397 errno_t err_no
; // thread-local errno
399 void *stackaddr
; // base of the stack (page aligned)
400 void *stackbottom
; // stackaddr - stacksize
401 void *freeaddr
; // stack/thread allocation base address
402 size_t freesize
; // stack/thread allocation size
403 size_t guardsize
; // guard page size in bytes
405 // tsd-base relative accessed elements
406 __attribute__((aligned(8)))
407 uint64_t thread_id
; // 64-bit unique thread id
409 /* Thread Specific Data slots
411 * The offset of this field from the start of the structure is difficult to
412 * change on OS X because of a thorny bitcompat issue: mono has hard coded
413 * the value into their source. Newer versions of mono will fall back to
414 * scanning to determine it at runtime, but there's lots of software built
415 * with older mono that won't. We will have to break them someday...
417 __attribute__ ((aligned (16)))
418 void *tsd
[_EXTERNAL_POSIX_THREAD_KEYS_MAX
+ _INTERNAL_POSIX_THREAD_KEYS_MAX
];
421 TAILQ_HEAD(__pthread_list
, pthread_s
);
423 #if 0 // pthread_t is never stack-allocated, so it doesn't matter
424 pthread_assert_type_size(pthread
);
426 pthread_assert_type_alias(pthread
, sig
, __sig
);
427 pthread_assert_type_alias(pthread
, __cleanup_stack
, __cleanup_stack
);
429 static_assert(offsetof(struct pthread_s
, tsd
) == 224, "TSD LP64 offset");
431 static_assert(offsetof(struct pthread_s
, tsd
) == 176, "TSD ILP32 offset");
434 #define _PTHREAD_ATTR_REFILLMS_MAX ((2<<24) - 1)
436 struct pthread_attr_s
{
438 size_t guardsize
; // size in bytes of stack overflow guard area
439 void *stackaddr
; // stack base; vm_page_size aligned
440 size_t stacksize
; // stack size; multiple of vm_page_size and >= PTHREAD_STACK_MIN
442 struct sched_param param
; // [aligned]
443 unsigned long qosclass
; // pthread_priority_t
458 #if defined(__LP64__)
459 uint32_t _reserved
[4];
461 uint32_t _reserved
[2];
465 pthread_assert_type_size(pthread_attr
);
466 pthread_assert_type_alias(pthread_attr
, sig
, __sig
);
468 #pragma mark - atfork / qos
470 struct pthread_atfork_entry
{
471 void (*prepare
)(void);
472 void (*parent
)(void);
476 #define PTHREAD_ATFORK_INLINE_MAX 10
478 // Hack. We don't want to depend on libcompiler_rt. armv7 implements integer
479 // division by calling into compiler_rt. vm_page_size isn't a constant and
480 // pthread_atfork_entry is 12 bytes so the compiler can't strength-reduce the
481 // division, so it generates a call into compiler_rt.
482 // So let's just use PAGE_MAX_SIZE on armv7, which is a constant. At worst
483 // this wastes a maybe dozen K if we are actaully running on a smaller page
484 // size than the max.
485 // At the time of this writing we don't have any supported iOS armv7 hardware
486 // that has different vm_page_size and PAGE_MAX_SIZE.
487 #define PTHREAD_ATFORK_MAX (PAGE_MAX_SIZE/sizeof(struct pthread_atfork_entry))
488 #else // defined(__arm__)
489 #define PTHREAD_ATFORK_MAX (vm_page_size/sizeof(struct pthread_atfork_entry))
490 #endif // defined(__arm__)
492 struct pthread_globals_s
{
494 pthread_t psaved_self
;
495 _pthread_lock psaved_self_global_lock
;
496 _pthread_lock pthread_atfork_lock
;
499 struct pthread_atfork_entry atfork_storage
[PTHREAD_ATFORK_INLINE_MAX
];
500 struct pthread_atfork_entry
*atfork
;
501 uint16_t qmp_logical
[THREAD_QOS_LAST
];
502 uint16_t qmp_physical
[THREAD_QOS_LAST
];
505 typedef struct pthread_globals_s
*pthread_globals_t
;
507 #endif // __LIBPTHREAD_TYPES_INTERNAL_H__