]> git.saurik.com Git - apple/libpthread.git/blame - src/internal.h
libpthread-301.30.1.tar.gz
[apple/libpthread.git] / src / internal.h
CommitLineData
f1a1da6c
A
1/*
2 * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
a0619f9c 5 *
f1a1da6c
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
a0619f9c 12 *
f1a1da6c
A
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
a0619f9c 20 *
f1a1da6c
A
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/*
a0619f9c
A
24 * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
25 * All Rights Reserved
26 *
27 * Permission to use, copy, modify, and distribute this software and
28 * its documentation for any purpose and without fee is hereby granted,
29 * provided that the above copyright notice appears in all copies and
30 * that both the copyright notice and this permission notice appear in
31 * supporting documentation.
32 *
33 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
34 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
35 * FOR A PARTICULAR PURPOSE.
36 *
37 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
38 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
39 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
40 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
41 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
42 *
f1a1da6c
A
43 */
44/*
45 * MkLinux
46 */
47
48/*
49 * POSIX Threads - IEEE 1003.1c
50 */
51
52#ifndef _POSIX_PTHREAD_INTERNALS_H
53#define _POSIX_PTHREAD_INTERNALS_H
54
55#define _PTHREAD_BUILDING_PTHREAD_
56
57// suppress pthread_attr_t typedef in sys/signal.h
58#define _PTHREAD_ATTR_T
59struct _pthread_attr_t; /* forward reference */
60typedef struct _pthread_attr_t pthread_attr_t;
61
964d3577 62#include <_simple.h>
f1a1da6c
A
63#include <assert.h>
64#include <stddef.h>
65#include <stdint.h>
66#include <stdlib.h>
67#include <limits.h>
68#include <errno.h>
69#include <TargetConditionals.h>
f1a1da6c
A
70#include <mach/mach.h>
71#include <mach/mach_error.h>
f1a1da6c
A
72#include <sys/queue.h>
73
2546420a
A
74#define __OS_EXPOSE_INTERNALS__ 1
75#include <os/internal/internal_shared.h>
76#include <os/once_private.h>
77
a0619f9c
A
78#if TARGET_IPHONE_SIMULATOR
79#error Unsupported target
80#endif
81
2546420a
A
82#define PTHREAD_INTERNAL_CRASH(c, x) do { \
83 _os_set_crash_log_cause_and_message((c), \
84 "BUG IN LIBPTHREAD: " x); \
85 __builtin_trap(); \
86 } while (0)
87
88#define PTHREAD_CLIENT_CRASH(c, x) do { \
89 _os_set_crash_log_cause_and_message((c), \
90 "BUG IN CLIENT OF LIBPTHREAD: " x); \
91 __builtin_trap(); \
92 } while (0)
93
f1a1da6c
A
94#ifndef __POSIX_LIB__
95#define __POSIX_LIB__
96#endif
97
98#ifndef PTHREAD_LAYOUT_SPI
99#define PTHREAD_LAYOUT_SPI 1
100#endif
101
102#include "posix_sched.h"
103#include "tsd_private.h"
104#include "spinlock_private.h"
105
a0619f9c
A
106#define PTHREAD_EXPORT extern __attribute__((visibility("default")))
107#define PTHREAD_EXTERN extern
108#define PTHREAD_NOEXPORT __attribute__((visibility("hidden")))
109#define PTHREAD_NOEXPORT_VARIANT
110#define PTHREAD_NORETURN __attribute__((__noreturn__))
111#define PTHREAD_ALWAYS_INLINE __attribute__((always_inline))
112#define PTHREAD_NOINLINE __attribute__((noinline))
113#define PTHREAD_WEAK __attribute__((weak))
114#define PTHREAD_USED __attribute__((used))
115#define PTHREAD_NOT_TAIL_CALLED __attribute__((__not_tail_called__))
116
117
2546420a
A
118#define OS_UNFAIR_LOCK_INLINE 1
119#include <os/lock_private.h>
120typedef os_unfair_lock _pthread_lock;
121#define _PTHREAD_LOCK_INITIALIZER OS_UNFAIR_LOCK_INIT
122#define _PTHREAD_LOCK_INIT(lock) ((lock) = (_pthread_lock)_PTHREAD_LOCK_INITIALIZER)
123#define _PTHREAD_LOCK(lock) os_unfair_lock_lock_with_options_inline(&(lock), OS_UNFAIR_LOCK_DATA_SYNCHRONIZATION)
124#define _PTHREAD_LOCK_FROM_MACH_THREAD(lock) os_unfair_lock_lock_inline_no_tsd_4libpthread(&(lock))
125#define _PTHREAD_UNLOCK(lock) os_unfair_lock_unlock_inline(&(lock))
126#define _PTHREAD_UNLOCK_FROM_MACH_THREAD(lock) os_unfair_lock_unlock_inline_no_tsd_4libpthread(&(lock))
127
f1a1da6c
A
128// List of all pthreads in the process.
129TAILQ_HEAD(__pthread_list, _pthread);
130extern struct __pthread_list __pthread_head;
131
132// Lock protects access to above list.
2546420a 133extern _pthread_lock _pthread_list_lock;
f1a1da6c
A
134
135extern int __is_threaded;
136
a0619f9c
A
137#if PTHREAD_DEBUG_LOG
138#include <mach/mach_time.h>
139extern int _pthread_debuglog;
140extern uint64_t _pthread_debugstart;
141#endif
142
f1a1da6c
A
143/*
144 * Compiled-in limits
145 */
146#if TARGET_OS_EMBEDDED
147#define _EXTERNAL_POSIX_THREAD_KEYS_MAX 256
148#define _INTERNAL_POSIX_THREAD_KEYS_MAX 256
149#define _INTERNAL_POSIX_THREAD_KEYS_END 512
150#else
151#define _EXTERNAL_POSIX_THREAD_KEYS_MAX 512
152#define _INTERNAL_POSIX_THREAD_KEYS_MAX 256
153#define _INTERNAL_POSIX_THREAD_KEYS_END 768
154#endif
155
156#define MAXTHREADNAMESIZE 64
157#define _PTHREAD_T
158typedef struct _pthread {
159 //
160 // ABI - These fields are externally known as struct _opaque_pthread_t.
161 //
162 long sig; // _PTHREAD_SIG
163 struct __darwin_pthread_handler_rec *__cleanup_stack;
164
165 //
166 // SPI - These fields are private.
167 //
168 // these fields are globally protected by _pthread_list_lock:
169 uint32_t childrun:1,
170 parentcheck:1,
171 childexit:1,
172 pad3:29;
a0619f9c 173
2546420a 174 _pthread_lock lock; // protect access to everything below
f1a1da6c
A
175 uint32_t detached:8,
176 inherit:8,
177 policy:8,
178 kernalloc:1,
179 schedset:1,
180 wqthread:1,
181 wqkillset:1,
182 pad:4;
183
2546420a 184#if defined(__LP64__)
f1a1da6c
A
185 uint32_t pad0;
186#endif
f1a1da6c
A
187
188 void *(*fun)(void*); // thread start routine
189 void *arg; // thread start routine argument
190 void *exit_value; // thread exit value storage
191
192 semaphore_t joiner_notify; // pthread_join notification
193
194 int max_tsd_key;
195 int cancel_state; // whether the thread can be cancelled
196 int cancel_error;
197
f1a1da6c
A
198 int err_no; // thread-local errno
199
200 struct _pthread *joiner;
201
202 struct sched_param param; // [aligned]
203
204 TAILQ_ENTRY(_pthread) plist; // global thread list [aligned]
205
206 char pthread_name[MAXTHREADNAMESIZE]; // includes NUL [aligned]
2546420a 207
f1a1da6c
A
208 void *stackaddr; // base of the stack (page aligned)
209 size_t stacksize; // size of stack (page multiple and >= PTHREAD_STACK_MIN)
210
211 void* freeaddr; // stack/thread allocation base address
212 size_t freesize; // stack/thread allocation size
213 size_t guardsize; // guard page size in bytes
214
2546420a
A
215 // tsd-base relative accessed elements
216 __attribute__((aligned(8)))
217 uint64_t thread_id; // 64-bit unique thread id
218
219 /* Thread Specific Data slots
220 *
221 * The offset of this field from the start of the structure is difficult to
222 * change on OS X because of a thorny bitcompat issue: mono has hard coded
223 * the value into their source. Newer versions of mono will fall back to
224 * scanning to determine it at runtime, but there's lots of software built
225 * with older mono that won't. We will have to break them someday...
226 */
227 __attribute__ ((aligned (16)))
228 void *tsd[_EXTERNAL_POSIX_THREAD_KEYS_MAX + _INTERNAL_POSIX_THREAD_KEYS_MAX];
f1a1da6c
A
229} *pthread_t;
230
231
232struct _pthread_attr_t {
233 long sig;
2546420a 234 _pthread_lock lock;
f1a1da6c
A
235 uint32_t detached:8,
236 inherit:8,
237 policy:8,
238 fastpath:1,
239 schedset:1,
240 qosset:1,
241 unused:5;
242 struct sched_param param; // [aligned]
243 void *stackaddr; // stack base; vm_page_size aligned
244 size_t stacksize; // stack size; multiple of vm_page_size and >= PTHREAD_STACK_MIN
245 size_t guardsize; // size in bytes of stack overflow guard area
246 unsigned long qosclass;
247#if defined(__LP64__)
248 uint32_t _reserved[2];
249#else
250 uint32_t _reserved[1];
251#endif
252};
253
254/*
255 * Mutex attributes
256 */
257#define _PTHREAD_MUTEX_POLICY_NONE 0
258#define _PTHREAD_MUTEX_POLICY_FAIRSHARE 1
259#define _PTHREAD_MUTEX_POLICY_FIRSTFIT 2
260#define _PTHREAD_MUTEX_POLICY_REALTIME 3
261#define _PTHREAD_MUTEX_POLICY_ADAPTIVE 4
262#define _PTHREAD_MUTEX_POLICY_PRIPROTECT 5
263#define _PTHREAD_MUTEX_POLICY_PRIINHERIT 6
264
265#define _PTHREAD_MUTEXATTR_T
266typedef struct {
267 long sig;
268 int prioceiling;
269 uint32_t protocol:2,
270 type:2,
271 pshared:2,
272 policy:3,
273 unused:23;
274} pthread_mutexattr_t;
275
276struct _pthread_mutex_options {
277 uint32_t protocol:2,
278 type:2,
279 pshared:2,
280 policy:3,
281 hold:2,
282 misalign:1,
283 notify:1,
284 mutex:1,
285 unused:2,
286 lock_count:16;
287};
288
289typedef struct {
290 long sig;
2546420a 291 _pthread_lock lock;
f1a1da6c
A
292 union {
293 uint32_t value;
294 struct _pthread_mutex_options options;
295 } mtxopts;
296 int16_t prioceiling;
297 int16_t priority;
298#if defined(__LP64__)
299 uint32_t _pad;
300#endif
3a6437e6
A
301 uint32_t m_tid[2]; // thread id of thread that has mutex locked
302 uint32_t m_seq[2]; // mutex sequence id
303 uint32_t m_mis[2]; // for misaligned locks m_tid/m_seq will span into here
f1a1da6c 304#if defined(__LP64__)
3a6437e6
A
305 uint32_t _reserved[4];
306#else
307 uint32_t _reserved[1];
f1a1da6c 308#endif
f1a1da6c
A
309} _pthread_mutex;
310
311
312#define _PTHREAD_CONDATTR_T
313typedef struct {
314 long sig;
315 uint32_t pshared:2,
316 unsupported:30;
317} pthread_condattr_t;
318
319
320typedef struct {
321 long sig;
2546420a 322 _pthread_lock lock;
f1a1da6c
A
323 uint32_t unused:29,
324 misalign:1,
325 pshared:2;
326 _pthread_mutex *busy;
327 uint32_t c_seq[3];
328#if defined(__LP64__)
329 uint32_t _reserved[3];
330#endif
331} _pthread_cond;
332
333
334#define _PTHREAD_ONCE_T
335typedef struct {
336 long sig;
337 os_once_t once;
338} pthread_once_t;
339
340
341#define _PTHREAD_RWLOCKATTR_T
342typedef struct {
343 long sig;
344 int pshared;
345#if defined(__LP64__)
346 uint32_t _reserved[3];
347#else
348 uint32_t _reserved[2];
349#endif
350} pthread_rwlockattr_t;
351
352
353typedef struct {
354 long sig;
2546420a 355 _pthread_lock lock;
f1a1da6c 356 uint32_t unused:29,
a0619f9c
A
357 misalign:1,
358 pshared:2;
f1a1da6c
A
359 uint32_t rw_flags;
360#if defined(__LP64__)
361 uint32_t _pad;
362#endif
a0619f9c
A
363 uint32_t rw_tid[2]; // thread id of thread that has exclusive (write) lock
364 uint32_t rw_seq[4]; // rw sequence id (at 128-bit aligned boundary)
365 uint32_t rw_mis[4]; // for misaligned locks rw_seq will span into here
f1a1da6c 366#if defined(__LP64__)
a0619f9c 367 uint32_t _reserved[34];
f1a1da6c 368#else
a0619f9c 369 uint32_t _reserved[18];
f1a1da6c
A
370#endif
371} _pthread_rwlock;
372
3a6437e6 373#include "pthread.h"
f1a1da6c
A
374#include "pthread_spis.h"
375
3a6437e6
A
376_Static_assert(sizeof(_pthread_mutex) == sizeof(pthread_mutex_t),
377 "Incorrect _pthread_mutex structure size");
378
a0619f9c
A
379_Static_assert(sizeof(_pthread_rwlock) == sizeof(pthread_rwlock_t),
380 "Incorrect _pthread_rwlock structure size");
381
f1a1da6c
A
382// Internal references to pthread_self() use TSD slot 0 directly.
383inline static pthread_t __attribute__((__pure__))
384_pthread_self_direct(void)
385{
386 return _pthread_getspecific_direct(_PTHREAD_TSD_SLOT_PTHREAD_SELF);
387}
388#define pthread_self() _pthread_self_direct()
389
a0619f9c
A
390PTHREAD_ALWAYS_INLINE
391inline static uint64_t __attribute__((__pure__))
f1a1da6c
A
392_pthread_selfid_direct(void)
393{
394 return (_pthread_self_direct())->thread_id;
395}
396
397#define _PTHREAD_DEFAULT_INHERITSCHED PTHREAD_INHERIT_SCHED
398#define _PTHREAD_DEFAULT_PROTOCOL PTHREAD_PRIO_NONE
399#define _PTHREAD_DEFAULT_PRIOCEILING 0
400#define _PTHREAD_DEFAULT_POLICY SCHED_OTHER
401#define _PTHREAD_DEFAULT_STACKSIZE 0x80000 /* 512K */
402#define _PTHREAD_DEFAULT_PSHARED PTHREAD_PROCESS_PRIVATE
403
404#define _PTHREAD_NO_SIG 0x00000000
405#define _PTHREAD_MUTEX_ATTR_SIG 0x4D545841 /* 'MTXA' */
406#define _PTHREAD_MUTEX_SIG 0x4D555458 /* 'MUTX' */
964d3577
A
407#define _PTHREAD_MUTEX_SIG_fast 0x4D55545A /* 'MUTZ' */
408#define _PTHREAD_MUTEX_SIG_MASK 0xfffffffd
409#define _PTHREAD_MUTEX_SIG_CMP 0x4D555458 /* _PTHREAD_MUTEX_SIG & _PTHREAD_MUTEX_SIG_MASK */
f1a1da6c
A
410#define _PTHREAD_MUTEX_SIG_init 0x32AAABA7 /* [almost] ~'MUTX' */
411#define _PTHREAD_ERRORCHECK_MUTEX_SIG_init 0x32AAABA1
412#define _PTHREAD_RECURSIVE_MUTEX_SIG_init 0x32AAABA2
964d3577 413#define _PTHREAD_FIRSTFIT_MUTEX_SIG_init 0x32AAABA3
f1a1da6c 414#define _PTHREAD_MUTEX_SIG_init_MASK 0xfffffff0
964d3577 415#define _PTHREAD_MUTEX_SIG_init_CMP 0x32AAABA0
f1a1da6c
A
416#define _PTHREAD_COND_ATTR_SIG 0x434E4441 /* 'CNDA' */
417#define _PTHREAD_COND_SIG 0x434F4E44 /* 'COND' */
418#define _PTHREAD_COND_SIG_init 0x3CB0B1BB /* [almost] ~'COND' */
419#define _PTHREAD_ATTR_SIG 0x54484441 /* 'THDA' */
420#define _PTHREAD_ONCE_SIG 0x4F4E4345 /* 'ONCE' */
421#define _PTHREAD_ONCE_SIG_init 0x30B1BCBA /* [almost] ~'ONCE' */
422#define _PTHREAD_SIG 0x54485244 /* 'THRD' */
423#define _PTHREAD_RWLOCK_ATTR_SIG 0x52574C41 /* 'RWLA' */
424#define _PTHREAD_RWLOCK_SIG 0x52574C4B /* 'RWLK' */
425#define _PTHREAD_RWLOCK_SIG_init 0x2DA8B3B4 /* [almost] ~'RWLK' */
426
427
428#define _PTHREAD_KERN_COND_SIG 0x12345678 /* */
429#define _PTHREAD_KERN_MUTEX_SIG 0x34567812 /* */
430#define _PTHREAD_KERN_RWLOCK_SIG 0x56781234 /* */
431
432#define _PTHREAD_CREATE_PARENT 4
433#define _PTHREAD_EXITED 8
434// 4597450: begin
435#define _PTHREAD_WASCANCEL 0x10
436// 4597450: end
437
438#if defined(DEBUG)
439#define _PTHREAD_MUTEX_OWNER_SELF pthread_self()
440#else
441#define _PTHREAD_MUTEX_OWNER_SELF (pthread_t)0x12141968
442#endif
443#define _PTHREAD_MUTEX_OWNER_SWITCHING (pthread_t)(~0)
444
445#define _PTHREAD_CANCEL_STATE_MASK 0x01
446#define _PTHREAD_CANCEL_TYPE_MASK 0x02
447#define _PTHREAD_CANCEL_PENDING 0x10 /* pthread_cancel() has been called for this thread */
a0619f9c 448#define _PTHREAD_CANCEL_INITIALIZED 0x20 /* the thread in the list is properly initialized */
f1a1da6c
A
449
450extern boolean_t swtch_pri(int);
451
f1a1da6c
A
452#include "kern/kern_internal.h"
453
454/* Prototypes. */
455
456/* Internal globals. */
457PTHREAD_NOEXPORT extern int __pthread_supported_features;
458
459/* Functions defined in machine-dependent files. */
460PTHREAD_NOEXPORT void _pthread_setup(pthread_t th, void (*f)(pthread_t), void *sp, int suspended, int needresume);
461
462PTHREAD_NOEXPORT void _pthread_tsd_cleanup(pthread_t self);
463
a0619f9c 464PTHREAD_NOEXPORT int _pthread_mutex_droplock(_pthread_mutex *mutex, uint32_t * flagp, uint32_t ** pmtxp, uint32_t * mgenp, uint32_t * ugenp);
f1a1da6c
A
465
466/* internally redirected upcalls. */
467PTHREAD_NOEXPORT void* malloc(size_t);
468PTHREAD_NOEXPORT void free(void*);
469
470/* syscall interfaces */
471extern uint32_t __psynch_mutexwait(pthread_mutex_t * mutex, uint32_t mgen, uint32_t ugen, uint64_t tid, uint32_t flags);
472extern uint32_t __psynch_mutexdrop(pthread_mutex_t * mutex, uint32_t mgen, uint32_t ugen, uint64_t tid, uint32_t flags);
473
474extern uint32_t __psynch_cvbroad(pthread_cond_t * cv, uint64_t cvlsgen, uint64_t cvudgen, uint32_t flags, pthread_mutex_t * mutex, uint64_t mugen, uint64_t tid);
475extern uint32_t __psynch_cvsignal(pthread_cond_t * cv, uint64_t cvlsgen, uint32_t cvugen, int thread_port, pthread_mutex_t * mutex, uint64_t mugen, uint64_t tid, uint32_t flags);
476extern uint32_t __psynch_cvwait(pthread_cond_t * cv, uint64_t cvlsgen, uint32_t cvugen, pthread_mutex_t * mutex, uint64_t mugen, uint32_t flags, int64_t sec, uint32_t nsec);
477extern uint32_t __psynch_cvclrprepost(void * cv, uint32_t cvgen, uint32_t cvugen, uint32_t cvsgen, uint32_t prepocnt, uint32_t preposeq, uint32_t flags);
478extern uint32_t __psynch_rw_longrdlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
479extern uint32_t __psynch_rw_yieldwrlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
480extern int __psynch_rw_downgrade(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
481extern uint32_t __psynch_rw_upgrade(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
482extern uint32_t __psynch_rw_rdlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
483extern uint32_t __psynch_rw_wrlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
484extern uint32_t __psynch_rw_unlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
485extern uint32_t __psynch_rw_unlock2(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
486extern uint32_t __bsdthread_ctl(uintptr_t cmd, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3);
487
488PTHREAD_EXTERN
489int
490__proc_info(int callnum, int pid, int flavor, uint64_t arg, void * buffer, int buffersize);
491
f1a1da6c
A
492PTHREAD_NOEXPORT int _pthread_join_cleanup(pthread_t thread, void ** value_ptr, int conforming);
493
494PTHREAD_NORETURN PTHREAD_NOEXPORT
495void
496__pthread_abort(void);
497
498PTHREAD_NORETURN PTHREAD_NOEXPORT
499void
a0619f9c 500__pthread_abort_reason(const char *fmt, ...) __printflike(1,2);
f1a1da6c
A
501
502PTHREAD_NOEXPORT
503void
504_pthread_set_main_qos(pthread_priority_t qos);
505
964d3577
A
506PTHREAD_NOEXPORT
507void
508_pthread_key_global_init(const char *envp[]);
509
f1a1da6c
A
510PTHREAD_EXPORT
511void
512_pthread_start(pthread_t self, mach_port_t kport, void *(*fun)(void *), void * funarg, size_t stacksize, unsigned int flags);
513
514PTHREAD_EXPORT
515void
964d3577 516_pthread_wqthread(pthread_t self, mach_port_t kport, void *stackaddr, void *keventlist, int flags, int nkevents);
f1a1da6c
A
517
518PTHREAD_NOEXPORT
519void
a0619f9c 520_pthread_main_thread_init(pthread_t p);
f1a1da6c 521
a0619f9c
A
522PTHREAD_NOEXPORT
523void
524_pthread_bsdthread_init(void);
525
526PTHREAD_NOEXPORT_VARIANT
f1a1da6c
A
527void
528_pthread_clear_qos_tsd(mach_port_t thread_port);
529
a0619f9c 530PTHREAD_NOEXPORT_VARIANT
f1a1da6c
A
531void
532_pthread_testcancel(pthread_t thread, int isconforming);
533
534PTHREAD_EXPORT
535void
536_pthread_exit_if_canceled(int error);
537
a0619f9c
A
538PTHREAD_NOEXPORT
539void
540_pthread_markcancel_if_canceled(pthread_t thread, mach_port_t kport);
541
542PTHREAD_NOEXPORT
543void
544_pthread_setcancelstate_exit(pthread_t self, void *value_ptr, int conforming);
545
546PTHREAD_NOEXPORT
547void *
548_pthread_get_exit_value(pthread_t t, int conforming);
549
f1a1da6c
A
550PTHREAD_ALWAYS_INLINE
551static inline mach_port_t
552_pthread_kernel_thread(pthread_t t)
553{
554 return t->tsd[_PTHREAD_TSD_SLOT_MACH_THREAD_SELF];
555}
556
557PTHREAD_ALWAYS_INLINE
558static inline void
559_pthread_set_kernel_thread(pthread_t t, mach_port_t p)
560{
561 t->tsd[_PTHREAD_TSD_SLOT_MACH_THREAD_SELF] = p;
562}
563
a0619f9c
A
564#define PTHREAD_ABORT(f,...) __pthread_abort_reason( \
565 "%s:%s:%u: " f, __FILE__, __func__, __LINE__, ## __VA_ARGS__)
f1a1da6c 566
a0619f9c
A
567#define PTHREAD_ASSERT(b) \
568 do { if (!(b)) PTHREAD_ABORT("failed assertion `%s'", #b); } while (0)
f1a1da6c
A
569
570#include <os/semaphore_private.h>
571#include <os/alloc_once_private.h>
572
573struct pthread_atfork_entry {
574 void (*prepare)(void);
575 void (*parent)(void);
576 void (*child)(void);
577};
578
579#define PTHREAD_ATFORK_INLINE_MAX 10
580#define PTHREAD_ATFORK_MAX (vm_page_size/sizeof(struct pthread_atfork_entry))
581
582struct pthread_globals_s {
583 // atfork.c
584 pthread_t psaved_self;
2546420a
A
585 _pthread_lock psaved_self_global_lock;
586 _pthread_lock pthread_atfork_lock;
f1a1da6c
A
587
588 size_t atfork_count;
589 struct pthread_atfork_entry atfork_storage[PTHREAD_ATFORK_INLINE_MAX];
590 struct pthread_atfork_entry *atfork;
a0619f9c
A
591 uint16_t qmp_logical[THREAD_QOS_LAST];
592 uint16_t qmp_physical[THREAD_QOS_LAST];
593
f1a1da6c
A
594};
595typedef struct pthread_globals_s *pthread_globals_t;
596
597__attribute__((__pure__))
598static inline pthread_globals_t
599_pthread_globals(void)
600{
601 return os_alloc_once(OS_ALLOC_ONCE_KEY_LIBSYSTEM_PTHREAD,
602 sizeof(struct pthread_globals_s),
603 NULL);
604}
605
964d3577
A
606#pragma mark _pthread_mutex_check_signature
607
608PTHREAD_ALWAYS_INLINE
609static inline bool
610_pthread_mutex_check_signature_fast(_pthread_mutex *mutex)
611{
a0619f9c 612 return (mutex->sig == _PTHREAD_MUTEX_SIG_fast);
964d3577
A
613}
614
615PTHREAD_ALWAYS_INLINE
616static inline bool
617_pthread_mutex_check_signature(_pthread_mutex *mutex)
618{
a0619f9c 619 return ((mutex->sig & _PTHREAD_MUTEX_SIG_MASK) == _PTHREAD_MUTEX_SIG_CMP);
964d3577
A
620}
621
622PTHREAD_ALWAYS_INLINE
623static inline bool
624_pthread_mutex_check_signature_init(_pthread_mutex *mutex)
625{
a0619f9c
A
626 return ((mutex->sig & _PTHREAD_MUTEX_SIG_init_MASK) ==
627 _PTHREAD_MUTEX_SIG_init_CMP);
628}
629
630#pragma mark _pthread_rwlock_check_signature
631
632PTHREAD_ALWAYS_INLINE
633static inline bool
634_pthread_rwlock_check_signature(_pthread_rwlock *rwlock)
635{
636 return (rwlock->sig == _PTHREAD_RWLOCK_SIG);
637}
638
639PTHREAD_ALWAYS_INLINE
640static inline bool
641_pthread_rwlock_check_signature_init(_pthread_rwlock *rwlock)
642{
643 return (rwlock->sig == _PTHREAD_RWLOCK_SIG_init);
644}
645
646/* ALWAYS called with list lock and return with list lock */
647PTHREAD_ALWAYS_INLINE
648static inline bool
649_pthread_is_valid_locked(pthread_t thread)
650{
651 pthread_t p;
652loop:
653 TAILQ_FOREACH(p, &__pthread_head, plist) {
654 if (p == thread) {
655 int state = os_atomic_load(&p->cancel_state, relaxed);
656 if (state & _PTHREAD_CANCEL_INITIALIZED) {
657 return true;
658 }
659 _PTHREAD_UNLOCK(_pthread_list_lock);
660 thread_switch(_pthread_kernel_thread(p),
661 SWITCH_OPTION_OSLOCK_DEPRESS, 1);
662 _PTHREAD_LOCK(_pthread_list_lock);
663 goto loop;
664 }
665 }
666
667 return false;
668}
669
670#define PTHREAD_IS_VALID_LOCK_THREAD 0x1
671
672PTHREAD_ALWAYS_INLINE
673static inline bool
674_pthread_is_valid(pthread_t thread, int flags, mach_port_t *portp)
675{
676 mach_port_t kport = MACH_PORT_NULL;
677 bool valid;
678
679 if (thread == NULL) {
680 return false;
681 }
682
683 if (thread == pthread_self()) {
684 valid = true;
685 kport = _pthread_kernel_thread(thread);
686 if (flags & PTHREAD_IS_VALID_LOCK_THREAD) {
687 _PTHREAD_LOCK(thread->lock);
688 }
689 } else {
690 _PTHREAD_LOCK(_pthread_list_lock);
691 if (_pthread_is_valid_locked(thread)) {
692 kport = _pthread_kernel_thread(thread);
693 valid = true;
694 if (flags & PTHREAD_IS_VALID_LOCK_THREAD) {
695 _PTHREAD_LOCK(thread->lock);
696 }
697 } else {
698 valid = false;
699 }
700 _PTHREAD_UNLOCK(_pthread_list_lock);
701 }
702
703 if (portp != NULL) {
704 *portp = kport;
705 }
706 return valid;
707}
708
709PTHREAD_ALWAYS_INLINE
710static inline void*
711_pthread_atomic_xchg_ptr_inline(void **p, void *v)
712{
713 return os_atomic_xchg(p, v, seq_cst);
714}
715
716PTHREAD_ALWAYS_INLINE
717static inline uint32_t
718_pthread_atomic_xchg_uint32_relaxed_inline(uint32_t *p,uint32_t v)
719{
720 return os_atomic_xchg(p, v, relaxed);
964d3577
A
721}
722
a0619f9c
A
723#define _pthread_atomic_xchg_ptr(p, v) \
724 _pthread_atomic_xchg_ptr_inline(p, v)
725#define _pthread_atomic_xchg_uint32_relaxed(p, v) \
726 _pthread_atomic_xchg_uint32_relaxed_inline(p, v)
727
f1a1da6c 728#endif /* _POSIX_PTHREAD_INTERNALS_H */