]> git.saurik.com Git - apple/libpthread.git/blob - src/internal.h
9f2e127f37789a1e3c1e48ca3529bed25802476c
[apple/libpthread.git] / src / internal.h
1 /*
2 * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /*
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 *
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
59 struct _pthread_attr_t; /* forward reference */
60 typedef struct _pthread_attr_t pthread_attr_t;
61
62 #include <_simple.h>
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>
70 #include <mach/mach.h>
71 #include <mach/mach_error.h>
72 #include <sys/queue.h>
73
74 #define __OS_EXPOSE_INTERNALS__ 1
75 #include <os/internal/internal_shared.h>
76 #include <os/once_private.h>
77
78 #if TARGET_IPHONE_SIMULATOR
79 #error Unsupported target
80 #endif
81
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
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
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
118 #define OS_UNFAIR_LOCK_INLINE 1
119 #include <os/lock_private.h>
120 typedef 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
128 // List of all pthreads in the process.
129 TAILQ_HEAD(__pthread_list, _pthread);
130 extern struct __pthread_list __pthread_head;
131
132 // Lock protects access to above list.
133 extern _pthread_lock _pthread_list_lock;
134
135 extern int __is_threaded;
136
137 #if PTHREAD_DEBUG_LOG
138 #include <mach/mach_time.h>
139 extern int _pthread_debuglog;
140 extern uint64_t _pthread_debugstart;
141 #endif
142
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
158 typedef 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;
173
174 _pthread_lock lock; // protect access to everything below
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
184 #if defined(__LP64__)
185 uint32_t pad0;
186 #endif
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
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]
207
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
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];
229 } *pthread_t;
230
231
232 struct _pthread_attr_t {
233 long sig;
234 _pthread_lock lock;
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
266 typedef 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
276 struct _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
289 typedef struct {
290 long sig;
291 _pthread_lock lock;
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
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
304 #if defined(__LP64__)
305 uint32_t _reserved[4];
306 #else
307 uint32_t _reserved[1];
308 #endif
309 } _pthread_mutex;
310
311
312 #define _PTHREAD_CONDATTR_T
313 typedef struct {
314 long sig;
315 uint32_t pshared:2,
316 unsupported:30;
317 } pthread_condattr_t;
318
319
320 typedef struct {
321 long sig;
322 _pthread_lock lock;
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
335 typedef struct {
336 long sig;
337 os_once_t once;
338 } pthread_once_t;
339
340
341 #define _PTHREAD_RWLOCKATTR_T
342 typedef 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
353 typedef struct {
354 long sig;
355 _pthread_lock lock;
356 uint32_t unused:29,
357 misalign:1,
358 pshared:2;
359 uint32_t rw_flags;
360 #if defined(__LP64__)
361 uint32_t _pad;
362 #endif
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
366 #if defined(__LP64__)
367 uint32_t _reserved[34];
368 #else
369 uint32_t _reserved[18];
370 #endif
371 } _pthread_rwlock;
372
373 #include "pthread.h"
374 #include "pthread_spis.h"
375
376 _Static_assert(sizeof(_pthread_mutex) == sizeof(pthread_mutex_t),
377 "Incorrect _pthread_mutex structure size");
378
379 _Static_assert(sizeof(_pthread_rwlock) == sizeof(pthread_rwlock_t),
380 "Incorrect _pthread_rwlock structure size");
381
382 // Internal references to pthread_self() use TSD slot 0 directly.
383 inline 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
390 PTHREAD_ALWAYS_INLINE
391 inline static uint64_t __attribute__((__pure__))
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' */
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 */
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
413 #define _PTHREAD_FIRSTFIT_MUTEX_SIG_init 0x32AAABA3
414 #define _PTHREAD_MUTEX_SIG_init_MASK 0xfffffff0
415 #define _PTHREAD_MUTEX_SIG_init_CMP 0x32AAABA0
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 */
448 #define _PTHREAD_CANCEL_INITIALIZED 0x20 /* the thread in the list is properly initialized */
449
450 extern boolean_t swtch_pri(int);
451
452 #include "kern/kern_internal.h"
453
454 /* Prototypes. */
455
456 /* Internal globals. */
457 PTHREAD_NOEXPORT extern int __pthread_supported_features;
458
459 /* Functions defined in machine-dependent files. */
460 PTHREAD_NOEXPORT void _pthread_setup(pthread_t th, void (*f)(pthread_t), void *sp, int suspended, int needresume);
461
462 PTHREAD_NOEXPORT void _pthread_tsd_cleanup(pthread_t self);
463
464 PTHREAD_NOEXPORT int _pthread_mutex_droplock(_pthread_mutex *mutex, uint32_t * flagp, uint32_t ** pmtxp, uint32_t * mgenp, uint32_t * ugenp);
465
466 /* internally redirected upcalls. */
467 PTHREAD_NOEXPORT void* malloc(size_t);
468 PTHREAD_NOEXPORT void free(void*);
469
470 /* syscall interfaces */
471 extern uint32_t __psynch_mutexwait(pthread_mutex_t * mutex, uint32_t mgen, uint32_t ugen, uint64_t tid, uint32_t flags);
472 extern uint32_t __psynch_mutexdrop(pthread_mutex_t * mutex, uint32_t mgen, uint32_t ugen, uint64_t tid, uint32_t flags);
473
474 extern uint32_t __psynch_cvbroad(pthread_cond_t * cv, uint64_t cvlsgen, uint64_t cvudgen, uint32_t flags, pthread_mutex_t * mutex, uint64_t mugen, uint64_t tid);
475 extern uint32_t __psynch_cvsignal(pthread_cond_t * cv, uint64_t cvlsgen, uint32_t cvugen, int thread_port, pthread_mutex_t * mutex, uint64_t mugen, uint64_t tid, uint32_t flags);
476 extern uint32_t __psynch_cvwait(pthread_cond_t * cv, uint64_t cvlsgen, uint32_t cvugen, pthread_mutex_t * mutex, uint64_t mugen, uint32_t flags, int64_t sec, uint32_t nsec);
477 extern uint32_t __psynch_cvclrprepost(void * cv, uint32_t cvgen, uint32_t cvugen, uint32_t cvsgen, uint32_t prepocnt, uint32_t preposeq, uint32_t flags);
478 extern uint32_t __psynch_rw_longrdlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
479 extern uint32_t __psynch_rw_yieldwrlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
480 extern int __psynch_rw_downgrade(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
481 extern uint32_t __psynch_rw_upgrade(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
482 extern uint32_t __psynch_rw_rdlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
483 extern uint32_t __psynch_rw_wrlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
484 extern uint32_t __psynch_rw_unlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
485 extern uint32_t __psynch_rw_unlock2(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
486 extern uint32_t __bsdthread_ctl(uintptr_t cmd, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3);
487
488 PTHREAD_EXTERN
489 int
490 __proc_info(int callnum, int pid, int flavor, uint64_t arg, void * buffer, int buffersize);
491
492 PTHREAD_NOEXPORT int _pthread_join_cleanup(pthread_t thread, void ** value_ptr, int conforming);
493
494 PTHREAD_NORETURN PTHREAD_NOEXPORT
495 void
496 __pthread_abort(void);
497
498 PTHREAD_NORETURN PTHREAD_NOEXPORT
499 void
500 __pthread_abort_reason(const char *fmt, ...) __printflike(1,2);
501
502 PTHREAD_NOEXPORT
503 void
504 _pthread_set_main_qos(pthread_priority_t qos);
505
506 PTHREAD_NOEXPORT
507 void
508 _pthread_key_global_init(const char *envp[]);
509
510 PTHREAD_NOEXPORT
511 void
512 _pthread_mutex_global_init(const char *envp[], struct _pthread_registration_data *registration_data);
513
514 PTHREAD_EXPORT
515 void
516 _pthread_start(pthread_t self, mach_port_t kport, void *(*fun)(void *), void * funarg, size_t stacksize, unsigned int flags);
517
518 PTHREAD_EXPORT
519 void
520 _pthread_wqthread(pthread_t self, mach_port_t kport, void *stackaddr, void *keventlist, int flags, int nkevents);
521
522 PTHREAD_NOEXPORT
523 void
524 _pthread_main_thread_init(pthread_t p);
525
526 PTHREAD_NOEXPORT
527 void
528 _pthread_bsdthread_init(struct _pthread_registration_data *data);
529
530 PTHREAD_NOEXPORT_VARIANT
531 void
532 _pthread_clear_qos_tsd(mach_port_t thread_port);
533
534 PTHREAD_NOEXPORT_VARIANT
535 void
536 _pthread_testcancel(pthread_t thread, int isconforming);
537
538 PTHREAD_EXPORT
539 void
540 _pthread_exit_if_canceled(int error);
541
542 PTHREAD_NOEXPORT
543 void
544 _pthread_markcancel_if_canceled(pthread_t thread, mach_port_t kport);
545
546 PTHREAD_NOEXPORT
547 void
548 _pthread_setcancelstate_exit(pthread_t self, void *value_ptr, int conforming);
549
550 PTHREAD_NOEXPORT
551 void *
552 _pthread_get_exit_value(pthread_t t, int conforming);
553
554 PTHREAD_ALWAYS_INLINE
555 static inline mach_port_t
556 _pthread_kernel_thread(pthread_t t)
557 {
558 return t->tsd[_PTHREAD_TSD_SLOT_MACH_THREAD_SELF];
559 }
560
561 PTHREAD_ALWAYS_INLINE
562 static inline void
563 _pthread_set_kernel_thread(pthread_t t, mach_port_t p)
564 {
565 t->tsd[_PTHREAD_TSD_SLOT_MACH_THREAD_SELF] = p;
566 }
567
568 #define PTHREAD_ABORT(f,...) __pthread_abort_reason( \
569 "%s:%s:%u: " f, __FILE__, __func__, __LINE__, ## __VA_ARGS__)
570
571 #define PTHREAD_ASSERT(b) \
572 do { if (!(b)) PTHREAD_ABORT("failed assertion `%s'", #b); } while (0)
573
574 #include <os/semaphore_private.h>
575 #include <os/alloc_once_private.h>
576
577 struct pthread_atfork_entry {
578 void (*prepare)(void);
579 void (*parent)(void);
580 void (*child)(void);
581 };
582
583 #define PTHREAD_ATFORK_INLINE_MAX 10
584 #define PTHREAD_ATFORK_MAX (vm_page_size/sizeof(struct pthread_atfork_entry))
585
586 struct pthread_globals_s {
587 // atfork.c
588 pthread_t psaved_self;
589 _pthread_lock psaved_self_global_lock;
590 _pthread_lock pthread_atfork_lock;
591
592 size_t atfork_count;
593 struct pthread_atfork_entry atfork_storage[PTHREAD_ATFORK_INLINE_MAX];
594 struct pthread_atfork_entry *atfork;
595 uint16_t qmp_logical[THREAD_QOS_LAST];
596 uint16_t qmp_physical[THREAD_QOS_LAST];
597
598 };
599 typedef struct pthread_globals_s *pthread_globals_t;
600
601 __attribute__((__pure__))
602 static inline pthread_globals_t
603 _pthread_globals(void)
604 {
605 return os_alloc_once(OS_ALLOC_ONCE_KEY_LIBSYSTEM_PTHREAD,
606 sizeof(struct pthread_globals_s),
607 NULL);
608 }
609
610 #pragma mark _pthread_mutex_check_signature
611
612 PTHREAD_ALWAYS_INLINE
613 static inline bool
614 _pthread_mutex_check_signature_fast(_pthread_mutex *mutex)
615 {
616 return (mutex->sig == _PTHREAD_MUTEX_SIG_fast);
617 }
618
619 PTHREAD_ALWAYS_INLINE
620 static inline bool
621 _pthread_mutex_check_signature(_pthread_mutex *mutex)
622 {
623 return ((mutex->sig & _PTHREAD_MUTEX_SIG_MASK) == _PTHREAD_MUTEX_SIG_CMP);
624 }
625
626 PTHREAD_ALWAYS_INLINE
627 static inline bool
628 _pthread_mutex_check_signature_init(_pthread_mutex *mutex)
629 {
630 return ((mutex->sig & _PTHREAD_MUTEX_SIG_init_MASK) ==
631 _PTHREAD_MUTEX_SIG_init_CMP);
632 }
633
634 #pragma mark _pthread_rwlock_check_signature
635
636 PTHREAD_ALWAYS_INLINE
637 static inline bool
638 _pthread_rwlock_check_signature(_pthread_rwlock *rwlock)
639 {
640 return (rwlock->sig == _PTHREAD_RWLOCK_SIG);
641 }
642
643 PTHREAD_ALWAYS_INLINE
644 static inline bool
645 _pthread_rwlock_check_signature_init(_pthread_rwlock *rwlock)
646 {
647 return (rwlock->sig == _PTHREAD_RWLOCK_SIG_init);
648 }
649
650 /* ALWAYS called with list lock and return with list lock */
651 PTHREAD_ALWAYS_INLINE
652 static inline bool
653 _pthread_is_valid_locked(pthread_t thread)
654 {
655 pthread_t p;
656 loop:
657 TAILQ_FOREACH(p, &__pthread_head, plist) {
658 if (p == thread) {
659 int state = os_atomic_load(&p->cancel_state, relaxed);
660 if (state & _PTHREAD_CANCEL_INITIALIZED) {
661 return true;
662 }
663 _PTHREAD_UNLOCK(_pthread_list_lock);
664 thread_switch(_pthread_kernel_thread(p),
665 SWITCH_OPTION_OSLOCK_DEPRESS, 1);
666 _PTHREAD_LOCK(_pthread_list_lock);
667 goto loop;
668 }
669 }
670
671 return false;
672 }
673
674 #define PTHREAD_IS_VALID_LOCK_THREAD 0x1
675
676 PTHREAD_ALWAYS_INLINE
677 static inline bool
678 _pthread_is_valid(pthread_t thread, int flags, mach_port_t *portp)
679 {
680 mach_port_t kport = MACH_PORT_NULL;
681 bool valid;
682
683 if (thread == NULL) {
684 return false;
685 }
686
687 if (thread == pthread_self()) {
688 valid = true;
689 kport = _pthread_kernel_thread(thread);
690 if (flags & PTHREAD_IS_VALID_LOCK_THREAD) {
691 _PTHREAD_LOCK(thread->lock);
692 }
693 } else {
694 _PTHREAD_LOCK(_pthread_list_lock);
695 if (_pthread_is_valid_locked(thread)) {
696 kport = _pthread_kernel_thread(thread);
697 valid = true;
698 if (flags & PTHREAD_IS_VALID_LOCK_THREAD) {
699 _PTHREAD_LOCK(thread->lock);
700 }
701 } else {
702 valid = false;
703 }
704 _PTHREAD_UNLOCK(_pthread_list_lock);
705 }
706
707 if (portp != NULL) {
708 *portp = kport;
709 }
710 return valid;
711 }
712
713 PTHREAD_ALWAYS_INLINE
714 static inline void*
715 _pthread_atomic_xchg_ptr_inline(void **p, void *v)
716 {
717 return os_atomic_xchg(p, v, seq_cst);
718 }
719
720 PTHREAD_ALWAYS_INLINE
721 static inline uint32_t
722 _pthread_atomic_xchg_uint32_relaxed_inline(uint32_t *p,uint32_t v)
723 {
724 return os_atomic_xchg(p, v, relaxed);
725 }
726
727 #define _pthread_atomic_xchg_ptr(p, v) \
728 _pthread_atomic_xchg_ptr_inline(p, v)
729 #define _pthread_atomic_xchg_uint32_relaxed(p, v) \
730 _pthread_atomic_xchg_uint32_relaxed_inline(p, v)
731
732 #endif /* _POSIX_PTHREAD_INTERNALS_H */