1112918Sjeff/* 2153496Sdavidxu * Copyright (C) 2005 Daniel M. Eischen <deischen@freebsd.org> 3153496Sdavidxu * Copyright (c) 2005 David Xu <davidxu@freebsd.org> 4112918Sjeff * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>. 5153496Sdavidxu * 6112918Sjeff * All rights reserved. 7112918Sjeff * 8112918Sjeff * Redistribution and use in source and binary forms, with or without 9112918Sjeff * modification, are permitted provided that the following conditions 10112918Sjeff * are met: 11112918Sjeff * 1. Redistributions of source code must retain the above copyright 12153496Sdavidxu * notice unmodified, this list of conditions, and the following 13153496Sdavidxu * disclaimer. 14112918Sjeff * 2. Redistributions in binary form must reproduce the above copyright 15112918Sjeff * notice, this list of conditions and the following disclaimer in the 16112918Sjeff * documentation and/or other materials provided with the distribution. 17112918Sjeff * 18153496Sdavidxu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19153496Sdavidxu * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20153496Sdavidxu * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21153496Sdavidxu * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22153496Sdavidxu * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23153496Sdavidxu * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24153496Sdavidxu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25153496Sdavidxu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26153496Sdavidxu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27153496Sdavidxu * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28112918Sjeff * 29112918Sjeff * $FreeBSD$ 30112918Sjeff */ 31112918Sjeff 32112918Sjeff#ifndef _THR_PRIVATE_H 33112918Sjeff#define _THR_PRIVATE_H 34112918Sjeff 35112918Sjeff/* 36112918Sjeff * Include files. 37112918Sjeff */ 38112918Sjeff#include <sys/types.h> 39144518Sdavidxu#include <sys/time.h> 40112918Sjeff#include <sys/cdefs.h> 41112918Sjeff#include <sys/queue.h> 42176783Sdavidxu#include <sys/param.h> 43176783Sdavidxu#include <sys/cpuset.h> 44144518Sdavidxu#include <machine/atomic.h> 45144518Sdavidxu#include <errno.h> 46144518Sdavidxu#include <limits.h> 47112918Sjeff#include <signal.h> 48144518Sdavidxu#include <stddef.h> 49112918Sjeff#include <stdio.h> 50144518Sdavidxu#include <unistd.h> 51112918Sjeff#include <ucontext.h> 52144518Sdavidxu#include <sys/thr.h> 53144518Sdavidxu#include <pthread.h> 54144518Sdavidxu 55201546Sdavidxu#define SYM_FB10(sym) __CONCAT(sym, _fb10) 56201546Sdavidxu#define SYM_FBP10(sym) __CONCAT(sym, _fbp10) 57201546Sdavidxu#define WEAK_REF(sym, alias) __weak_reference(sym, alias) 58201546Sdavidxu#define SYM_COMPAT(sym, impl, ver) __sym_compat(sym, impl, ver) 59201546Sdavidxu#define SYM_DEFAULT(sym, impl, ver) __sym_default(sym, impl, ver) 60201546Sdavidxu 61201546Sdavidxu#define FB10_COMPAT(func, sym) \ 62201546Sdavidxu WEAK_REF(func, SYM_FB10(sym)); \ 63201546Sdavidxu SYM_COMPAT(sym, SYM_FB10(sym), FBSD_1.0) 64201546Sdavidxu 65201546Sdavidxu#define FB10_COMPAT_PRIVATE(func, sym) \ 66201546Sdavidxu WEAK_REF(func, SYM_FBP10(sym)); \ 67201546Sdavidxu SYM_DEFAULT(sym, SYM_FBP10(sym), FBSDprivate_1.0) 68201546Sdavidxu 69144518Sdavidxu#include "pthread_md.h" 70144518Sdavidxu#include "thr_umtx.h" 71144921Sdavidxu#include "thread_db.h" 72144518Sdavidxu 73212630Sdavidxu#ifdef _PTHREAD_FORCED_UNWIND 74213297Sdavidxu#define _BSD_SOURCE 75213297Sdavidxu#include <unwind.h> 76212630Sdavidxu#endif 77212630Sdavidxu 78153593Sdavidxutypedef TAILQ_HEAD(pthreadlist, pthread) pthreadlist; 79153593Sdavidxutypedef TAILQ_HEAD(atfork_head, pthread_atfork) atfork_head; 80161681SdavidxuTAILQ_HEAD(mutex_queue, pthread_mutex); 81112918Sjeff 82144518Sdavidxu/* Signal to do cancellation */ 83234424Sgnn#define SIGCANCEL SIGTHR 84112918Sjeff 85112918Sjeff/* 86112918Sjeff * Kernel fatal error handler macro. 87112918Sjeff */ 88144518Sdavidxu#define PANIC(string) _thread_exit(__FILE__,__LINE__,string) 89112918Sjeff 90144518Sdavidxu/* Output debug messages like this: */ 91144518Sdavidxu#define stdout_debug(args...) _thread_printf(STDOUT_FILENO, ##args) 92171763Sdavidxu#define stderr_debug(args...) _thread_printf(STDERR_FILENO, ##args) 93144518Sdavidxu 94144518Sdavidxu#ifdef _PTHREADS_INVARIANTS 95144518Sdavidxu#define THR_ASSERT(cond, msg) do { \ 96144518Sdavidxu if (__predict_false(!(cond))) \ 97123351Smtm PANIC(msg); \ 98123351Smtm} while (0) 99144518Sdavidxu#else 100144518Sdavidxu#define THR_ASSERT(cond, msg) 101144518Sdavidxu#endif 102123351Smtm 103154160Sdavidxu#ifdef PIC 104154160Sdavidxu# define STATIC_LIB_REQUIRE(name) 105154160Sdavidxu#else 106154160Sdavidxu# define STATIC_LIB_REQUIRE(name) __asm (".globl " #name) 107154160Sdavidxu#endif 108154160Sdavidxu 109144518Sdavidxu#define TIMESPEC_ADD(dst, src, val) \ 110144518Sdavidxu do { \ 111144518Sdavidxu (dst)->tv_sec = (src)->tv_sec + (val)->tv_sec; \ 112144518Sdavidxu (dst)->tv_nsec = (src)->tv_nsec + (val)->tv_nsec; \ 113147534Sdavidxu if ((dst)->tv_nsec >= 1000000000) { \ 114144518Sdavidxu (dst)->tv_sec++; \ 115144518Sdavidxu (dst)->tv_nsec -= 1000000000; \ 116144518Sdavidxu } \ 117117048Smtm } while (0) 118117048Smtm 119144518Sdavidxu#define TIMESPEC_SUB(dst, src, val) \ 120144518Sdavidxu do { \ 121144518Sdavidxu (dst)->tv_sec = (src)->tv_sec - (val)->tv_sec; \ 122144518Sdavidxu (dst)->tv_nsec = (src)->tv_nsec - (val)->tv_nsec; \ 123144518Sdavidxu if ((dst)->tv_nsec < 0) { \ 124144518Sdavidxu (dst)->tv_sec--; \ 125144518Sdavidxu (dst)->tv_nsec += 1000000000; \ 126144518Sdavidxu } \ 127117276Smtm } while (0) 128117048Smtm 129213241Sdavidxu/* XXX These values should be same as those defined in pthread.h */ 130213241Sdavidxu#define THR_MUTEX_INITIALIZER ((struct pthread_mutex *)NULL) 131213241Sdavidxu#define THR_ADAPTIVE_MUTEX_INITIALIZER ((struct pthread_mutex *)1) 132213241Sdavidxu#define THR_MUTEX_DESTROYED ((struct pthread_mutex *)2) 133213241Sdavidxu#define THR_COND_INITIALIZER ((struct pthread_cond *)NULL) 134213241Sdavidxu#define THR_COND_DESTROYED ((struct pthread_cond *)1) 135213241Sdavidxu#define THR_RWLOCK_INITIALIZER ((struct pthread_rwlock *)NULL) 136213241Sdavidxu#define THR_RWLOCK_DESTROYED ((struct pthread_rwlock *)1) 137213241Sdavidxu 138216641Sdavidxu#define PMUTEX_FLAG_TYPE_MASK 0x0ff 139216641Sdavidxu#define PMUTEX_FLAG_PRIVATE 0x100 140216641Sdavidxu#define PMUTEX_FLAG_DEFERED 0x200 141216641Sdavidxu#define PMUTEX_TYPE(mtxflags) ((mtxflags) & PMUTEX_FLAG_TYPE_MASK) 142216641Sdavidxu 143216641Sdavidxu#define MAX_DEFER_WAITERS 50 144216641Sdavidxu 145144518Sdavidxustruct pthread_mutex { 146144518Sdavidxu /* 147144518Sdavidxu * Lock for accesses to this structure. 148144518Sdavidxu */ 149161681Sdavidxu struct umutex m_lock; 150216641Sdavidxu int m_flags; 151144518Sdavidxu struct pthread *m_owner; 152144518Sdavidxu int m_count; 153174585Sdavidxu int m_spinloops; 154174585Sdavidxu int m_yieldloops; 155144518Sdavidxu /* 156161681Sdavidxu * Link for all mutexes a thread currently owns. 157144518Sdavidxu */ 158144518Sdavidxu TAILQ_ENTRY(pthread_mutex) m_qe; 159144518Sdavidxu}; 160112918Sjeff 161112918Sjeffstruct pthread_mutex_attr { 162112918Sjeff enum pthread_mutextype m_type; 163112918Sjeff int m_protocol; 164112918Sjeff int m_ceiling; 165112918Sjeff}; 166112918Sjeff 167112918Sjeff#define PTHREAD_MUTEXATTR_STATIC_INITIALIZER \ 168112918Sjeff { PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, 0, MUTEX_FLAGS_PRIVATE } 169112918Sjeff 170144518Sdavidxustruct pthread_cond { 171216641Sdavidxu __uint32_t __has_user_waiters; 172216641Sdavidxu __uint32_t __has_kern_waiters; 173216641Sdavidxu __uint32_t __flags; 174216641Sdavidxu __uint32_t __clock_id; 175112958Sjeff}; 176112958Sjeff 177144518Sdavidxustruct pthread_cond_attr { 178144518Sdavidxu int c_pshared; 179144518Sdavidxu int c_clockid; 180112918Sjeff}; 181112918Sjeff 182144518Sdavidxustruct pthread_barrier { 183164903Sdavidxu struct umutex b_lock; 184164903Sdavidxu struct ucond b_cv; 185233022Sdavidxu int64_t b_cycle; 186233022Sdavidxu int b_count; 187233022Sdavidxu int b_waiters; 188233022Sdavidxu int b_refcount; 189233022Sdavidxu int b_destroying; 190124837Smtm}; 191124837Smtm 192144518Sdavidxustruct pthread_barrierattr { 193144518Sdavidxu int pshared; 194112918Sjeff}; 195112918Sjeff 196144518Sdavidxustruct pthread_spinlock { 197162061Sdavidxu struct umutex s_lock; 198112918Sjeff}; 199112918Sjeff 200112918Sjeff/* 201112918Sjeff * Flags for condition variables. 202112918Sjeff */ 203144518Sdavidxu#define COND_FLAGS_PRIVATE 0x01 204144518Sdavidxu#define COND_FLAGS_INITED 0x02 205144518Sdavidxu#define COND_FLAGS_BUSY 0x04 206112918Sjeff 207112918Sjeff/* 208112918Sjeff * Cleanup definitions. 209112918Sjeff */ 210112918Sjeffstruct pthread_cleanup { 211179662Sdavidxu struct pthread_cleanup *prev; 212179662Sdavidxu void (*routine)(void *); 213112918Sjeff void *routine_arg; 214179662Sdavidxu int onheap; 215112918Sjeff}; 216112918Sjeff 217144518Sdavidxu#define THR_CLEANUP_PUSH(td, func, arg) { \ 218144518Sdavidxu struct pthread_cleanup __cup; \ 219144518Sdavidxu \ 220144518Sdavidxu __cup.routine = func; \ 221144518Sdavidxu __cup.routine_arg = arg; \ 222179662Sdavidxu __cup.onheap = 0; \ 223179662Sdavidxu __cup.prev = (td)->cleanup; \ 224144518Sdavidxu (td)->cleanup = &__cup; 225144518Sdavidxu 226144518Sdavidxu#define THR_CLEANUP_POP(td, exec) \ 227179662Sdavidxu (td)->cleanup = __cup.prev; \ 228144518Sdavidxu if ((exec) != 0) \ 229144518Sdavidxu __cup.routine(__cup.routine_arg); \ 230144518Sdavidxu} 231144518Sdavidxu 232131181Smtmstruct pthread_atfork { 233131181Smtm TAILQ_ENTRY(pthread_atfork) qe; 234131181Smtm void (*prepare)(void); 235131181Smtm void (*parent)(void); 236131181Smtm void (*child)(void); 237131181Smtm}; 238131181Smtm 239112918Sjeffstruct pthread_attr { 240214334Sdavidxu#define pthread_attr_start_copy sched_policy 241112918Sjeff int sched_policy; 242112918Sjeff int sched_inherit; 243112918Sjeff int prio; 244112918Sjeff int suspend; 245144518Sdavidxu#define THR_STACK_USER 0x100 /* 0xFF reserved for <pthread.h> */ 246112918Sjeff int flags; 247112918Sjeff void *stackaddr_attr; 248112918Sjeff size_t stacksize_attr; 249112918Sjeff size_t guardsize_attr; 250214334Sdavidxu#define pthread_attr_end_copy cpuset 251176781Sdavidxu cpuset_t *cpuset; 252176781Sdavidxu size_t cpusetsize; 253112918Sjeff}; 254112918Sjeff 255216641Sdavidxustruct wake_addr { 256216641Sdavidxu struct wake_addr *link; 257216641Sdavidxu unsigned int value; 258216641Sdavidxu char pad[12]; 259216641Sdavidxu}; 260216641Sdavidxu 261216641Sdavidxustruct sleepqueue { 262216641Sdavidxu TAILQ_HEAD(, pthread) sq_blocked; 263216641Sdavidxu SLIST_HEAD(, sleepqueue) sq_freeq; 264216641Sdavidxu LIST_ENTRY(sleepqueue) sq_hash; 265216641Sdavidxu SLIST_ENTRY(sleepqueue) sq_flink; 266216641Sdavidxu void *sq_wchan; 267216641Sdavidxu int sq_type; 268216641Sdavidxu}; 269216641Sdavidxu 270112918Sjeff/* 271112918Sjeff * Thread creation state attributes. 272112918Sjeff */ 273144518Sdavidxu#define THR_CREATE_RUNNING 0 274144518Sdavidxu#define THR_CREATE_SUSPENDED 1 275112918Sjeff 276112918Sjeff/* 277112918Sjeff * Miscellaneous definitions. 278112918Sjeff */ 279144518Sdavidxu#define THR_STACK_DEFAULT (sizeof(void *) / 4 * 1024 * 1024) 280112918Sjeff 281112918Sjeff/* 282112918Sjeff * Maximum size of initial thread's stack. This perhaps deserves to be larger 283112918Sjeff * than the stacks of other threads, since many applications are likely to run 284112918Sjeff * almost entirely on this stack. 285112918Sjeff */ 286144518Sdavidxu#define THR_STACK_INITIAL (THR_STACK_DEFAULT * 2) 287112918Sjeff 288112918Sjeff/* 289158073Sdavidxu * Define priorities returned by kernel. 290112918Sjeff */ 291158073Sdavidxu#define THR_MIN_PRIORITY (_thr_priorities[SCHED_OTHER-1].pri_min) 292160287Sdavidxu#define THR_MAX_PRIORITY (_thr_priorities[SCHED_OTHER-1].pri_max) 293158073Sdavidxu#define THR_DEF_PRIORITY (_thr_priorities[SCHED_OTHER-1].pri_default) 294112918Sjeff 295158073Sdavidxu#define THR_MIN_RR_PRIORITY (_thr_priorities[SCHED_RR-1].pri_min) 296158073Sdavidxu#define THR_MAX_RR_PRIORITY (_thr_priorities[SCHED_RR-1].pri_max) 297158073Sdavidxu#define THR_DEF_RR_PRIORITY (_thr_priorities[SCHED_RR-1].pri_default) 298112918Sjeff 299158073Sdavidxu/* XXX The SCHED_FIFO should have same priority range as SCHED_RR */ 300158073Sdavidxu#define THR_MIN_FIFO_PRIORITY (_thr_priorities[SCHED_FIFO_1].pri_min) 301160287Sdavidxu#define THR_MAX_FIFO_PRIORITY (_thr_priorities[SCHED_FIFO-1].pri_max) 302158073Sdavidxu#define THR_DEF_FIFO_PRIORITY (_thr_priorities[SCHED_FIFO-1].pri_default) 303158073Sdavidxu 304158073Sdavidxustruct pthread_prio { 305158073Sdavidxu int pri_min; 306158073Sdavidxu int pri_max; 307158073Sdavidxu int pri_default; 308158073Sdavidxu}; 309158073Sdavidxu 310112918Sjeffstruct pthread_rwlockattr { 311112918Sjeff int pshared; 312112918Sjeff}; 313112918Sjeff 314112918Sjeffstruct pthread_rwlock { 315177850Sdavidxu struct urwlock lock; 316177770Sdavidxu struct pthread *owner; 317112918Sjeff}; 318112918Sjeff 319112918Sjeff/* 320112918Sjeff * Thread states. 321112918Sjeff */ 322112918Sjeffenum pthread_state { 323112918Sjeff PS_RUNNING, 324144518Sdavidxu PS_DEAD 325112918Sjeff}; 326112918Sjeff 327112918Sjeffstruct pthread_specific_elem { 328112918Sjeff const void *data; 329112918Sjeff int seqno; 330112918Sjeff}; 331112918Sjeff 332144518Sdavidxustruct pthread_key { 333144518Sdavidxu volatile int allocated; 334144518Sdavidxu int seqno; 335144518Sdavidxu void (*destructor)(void *); 336124718Smtm}; 337124718Smtm 338112918Sjeff/* 339161681Sdavidxu * lwpid_t is 32bit but kernel thr API exports tid as long type 340161681Sdavidxu * in very earily date. 341161681Sdavidxu */ 342161681Sdavidxu#define TID(thread) ((uint32_t) ((thread)->tid)) 343161681Sdavidxu 344161681Sdavidxu/* 345112918Sjeff * Thread structure. 346112918Sjeff */ 347112918Sjeffstruct pthread { 348231106Sdavidxu#define _pthread_startzero tid 349157194Sdavidxu /* Kernel thread id. */ 350157194Sdavidxu long tid; 351157194Sdavidxu#define TID_TERMINATED 1 352112918Sjeff 353112918Sjeff /* 354112918Sjeff * Lock for accesses to this thread structure. 355112918Sjeff */ 356162061Sdavidxu struct umutex lock; 357112918Sjeff 358144518Sdavidxu /* Internal condition variable cycle number. */ 359178647Sdavidxu uint32_t cycle; 360144518Sdavidxu 361144518Sdavidxu /* How many low level locks the thread held. */ 362144518Sdavidxu int locklevel; 363144518Sdavidxu 364154055Sdavidxu /* 365154055Sdavidxu * Set to non-zero when this thread has entered a critical 366154055Sdavidxu * region. We allow for recursive entries into critical regions. 367154055Sdavidxu */ 368154055Sdavidxu int critical_count; 369154055Sdavidxu 370144518Sdavidxu /* Signal blocked counter. */ 371144518Sdavidxu int sigblock; 372144518Sdavidxu 373144518Sdavidxu /* Queue entry for list of all threads. */ 374144518Sdavidxu TAILQ_ENTRY(pthread) tle; /* link for all threads in process */ 375144518Sdavidxu 376144518Sdavidxu /* Queue entry for GC lists. */ 377144518Sdavidxu TAILQ_ENTRY(pthread) gcle; 378144518Sdavidxu 379144518Sdavidxu /* Hash queue entry. */ 380144518Sdavidxu LIST_ENTRY(pthread) hle; 381144518Sdavidxu 382216641Sdavidxu /* Sleep queue entry */ 383216641Sdavidxu TAILQ_ENTRY(pthread) wle; 384216641Sdavidxu 385144518Sdavidxu /* Threads reference count. */ 386144518Sdavidxu int refcount; 387144518Sdavidxu 388112918Sjeff /* 389112918Sjeff * Thread start routine, argument, stack pointer and thread 390112918Sjeff * attributes. 391112918Sjeff */ 392112918Sjeff void *(*start_routine)(void *); 393112918Sjeff void *arg; 394112918Sjeff struct pthread_attr attr; 395112918Sjeff 396164583Sdavidxu#define SHOULD_CANCEL(thr) \ 397212841Sdavidxu ((thr)->cancel_pending && (thr)->cancel_enable && \ 398212841Sdavidxu (thr)->no_cancel == 0) 399112918Sjeff 400164583Sdavidxu /* Cancellation is enabled */ 401164583Sdavidxu int cancel_enable; 402112918Sjeff 403164583Sdavidxu /* Cancellation request is pending */ 404164583Sdavidxu int cancel_pending; 405164583Sdavidxu 406164583Sdavidxu /* Thread is at cancellation point */ 407164583Sdavidxu int cancel_point; 408164583Sdavidxu 409212841Sdavidxu /* Cancellation is temporarily disabled */ 410212841Sdavidxu int no_cancel; 411164877Sdavidxu 412164583Sdavidxu /* Asynchronouse cancellation is enabled */ 413164583Sdavidxu int cancel_async; 414164583Sdavidxu 415164583Sdavidxu /* Cancellation is in progress */ 416164583Sdavidxu int cancelling; 417164583Sdavidxu 418144518Sdavidxu /* Thread temporary signal mask. */ 419144518Sdavidxu sigset_t sigmask; 420112918Sjeff 421212076Sdavidxu /* Thread should unblock SIGCANCEL. */ 422176784Sdavidxu int unblock_sigcancel; 423176784Sdavidxu 424212076Sdavidxu /* In sigsuspend state */ 425212076Sdavidxu int in_sigsuspend; 426212076Sdavidxu 427212076Sdavidxu /* deferred signal info */ 428212076Sdavidxu siginfo_t deferred_siginfo; 429212076Sdavidxu 430212076Sdavidxu /* signal mask to restore. */ 431212076Sdavidxu sigset_t deferred_sigmask; 432212076Sdavidxu 433212076Sdavidxu /* the sigaction should be used for deferred signal. */ 434212076Sdavidxu struct sigaction deferred_sigact; 435212076Sdavidxu 436258766Skib /* deferred signal delivery is performed, do not reenter. */ 437258766Skib int deferred_run; 438258766Skib 439176817Sdavidxu /* Force new thread to exit. */ 440176817Sdavidxu int force_exit; 441176817Sdavidxu 442144518Sdavidxu /* Thread state: */ 443163307Sdavidxu enum pthread_state state; 444144518Sdavidxu 445112918Sjeff /* 446112918Sjeff * Error variable used instead of errno. The function __error() 447112918Sjeff * returns a pointer to this. 448112918Sjeff */ 449144518Sdavidxu int error; 450112918Sjeff 451112918Sjeff /* 452112918Sjeff * The joiner is the thread that is joining to this thread. The 453112918Sjeff * join status keeps track of a join operation to another thread. 454112918Sjeff */ 455112918Sjeff struct pthread *joiner; 456112918Sjeff 457144518Sdavidxu /* Miscellaneous flags; only set with scheduling lock held. */ 458144518Sdavidxu int flags; 459144518Sdavidxu#define THR_FLAGS_PRIVATE 0x0001 460144518Sdavidxu#define THR_FLAGS_NEED_SUSPEND 0x0002 /* thread should be suspended */ 461144518Sdavidxu#define THR_FLAGS_SUSPENDED 0x0004 /* thread is suspended */ 462212629Sdavidxu#define THR_FLAGS_DETACHED 0x0008 /* thread is detached */ 463144518Sdavidxu 464144518Sdavidxu /* Thread list flags; only set with thread list lock held. */ 465144518Sdavidxu int tlflags; 466144518Sdavidxu#define TLFLAGS_GC_SAFE 0x0001 /* thread safe for cleaning */ 467144518Sdavidxu#define TLFLAGS_IN_TDLIST 0x0002 /* thread in all thread list */ 468212629Sdavidxu#define TLFLAGS_IN_GCLIST 0x0004 /* thread in gc list */ 469144518Sdavidxu 470161681Sdavidxu /* Queue of currently owned NORMAL or PRIO_INHERIT type mutexes. */ 471161681Sdavidxu struct mutex_queue mutexq; 472112918Sjeff 473161681Sdavidxu /* Queue of all owned PRIO_PROTECT mutexes. */ 474161681Sdavidxu struct mutex_queue pp_mutexq; 475161681Sdavidxu 476112918Sjeff void *ret; 477112918Sjeff struct pthread_specific_elem *specific; 478112918Sjeff int specific_data_count; 479112918Sjeff 480144518Sdavidxu /* Number rwlocks rdlocks held. */ 481144518Sdavidxu int rdlock_count; 482144518Sdavidxu 483112918Sjeff /* 484144518Sdavidxu * Current locks bitmap for rtld. */ 485144518Sdavidxu int rtld_bits; 486112918Sjeff 487144518Sdavidxu /* Thread control block */ 488144518Sdavidxu struct tcb *tcb; 489144518Sdavidxu 490112918Sjeff /* Cleanup handlers Link List */ 491144518Sdavidxu struct pthread_cleanup *cleanup; 492144921Sdavidxu 493212630Sdavidxu#ifdef _PTHREAD_FORCED_UNWIND 494212630Sdavidxu struct _Unwind_Exception ex; 495212630Sdavidxu void *unwind_stackend; 496213161Sdavidxu int unwind_disabled; 497212630Sdavidxu#endif 498212630Sdavidxu 499157194Sdavidxu /* 500157194Sdavidxu * Magic value to help recognize a valid thread structure 501157194Sdavidxu * from an invalid one: 502157194Sdavidxu */ 503157194Sdavidxu#define THR_MAGIC ((u_int32_t) 0xd09ba115) 504157194Sdavidxu u_int32_t magic; 505157194Sdavidxu 506144921Sdavidxu /* Enable event reporting */ 507144921Sdavidxu int report_events; 508144921Sdavidxu 509144921Sdavidxu /* Event mask */ 510144921Sdavidxu int event_mask; 511144921Sdavidxu 512144921Sdavidxu /* Event */ 513144921Sdavidxu td_event_msg_t event_buf; 514216641Sdavidxu 515216641Sdavidxu /* Wait channel */ 516216641Sdavidxu void *wchan; 517216641Sdavidxu 518216641Sdavidxu /* Referenced mutex. */ 519216641Sdavidxu struct pthread_mutex *mutex_obj; 520216641Sdavidxu 521216641Sdavidxu /* Thread will sleep. */ 522216641Sdavidxu int will_sleep; 523216641Sdavidxu 524216641Sdavidxu /* Number of threads deferred. */ 525216641Sdavidxu int nwaiter_defer; 526216641Sdavidxu 527216641Sdavidxu /* Deferred threads from pthread_cond_signal. */ 528216641Sdavidxu unsigned int *defer_waiters[MAX_DEFER_WAITERS]; 529231106Sdavidxu#define _pthread_endzero wake_addr 530231106Sdavidxu 531231106Sdavidxu struct wake_addr *wake_addr; 532231106Sdavidxu#define WAKE_ADDR(td) ((td)->wake_addr) 533231106Sdavidxu 534231106Sdavidxu /* Sleep queue */ 535231106Sdavidxu struct sleepqueue *sleepqueue; 536231106Sdavidxu 537112918Sjeff}; 538112918Sjeff 539212536Sdavidxu#define THR_SHOULD_GC(thrd) \ 540212536Sdavidxu ((thrd)->refcount == 0 && (thrd)->state == PS_DEAD && \ 541212536Sdavidxu ((thrd)->flags & THR_FLAGS_DETACHED) != 0) 542212536Sdavidxu 543154055Sdavidxu#define THR_IN_CRITICAL(thrd) \ 544154055Sdavidxu (((thrd)->locklevel > 0) || \ 545154055Sdavidxu ((thrd)->critical_count > 0)) 546154055Sdavidxu 547157111Sdavidxu#define THR_CRITICAL_ENTER(thrd) \ 548157111Sdavidxu (thrd)->critical_count++ 549157111Sdavidxu 550157111Sdavidxu#define THR_CRITICAL_LEAVE(thrd) \ 551177871Sdavidxu do { \ 552177871Sdavidxu (thrd)->critical_count--; \ 553177871Sdavidxu _thr_ast(thrd); \ 554177871Sdavidxu } while (0) 555157111Sdavidxu 556162061Sdavidxu#define THR_UMUTEX_TRYLOCK(thrd, lck) \ 557162061Sdavidxu _thr_umutex_trylock((lck), TID(thrd)) 558144518Sdavidxu 559162061Sdavidxu#define THR_UMUTEX_LOCK(thrd, lck) \ 560162061Sdavidxu _thr_umutex_lock((lck), TID(thrd)) 561144518Sdavidxu 562162061Sdavidxu#define THR_UMUTEX_TIMEDLOCK(thrd, lck, timo) \ 563162061Sdavidxu _thr_umutex_timedlock((lck), TID(thrd), (timo)) 564144518Sdavidxu 565162061Sdavidxu#define THR_UMUTEX_UNLOCK(thrd, lck) \ 566162061Sdavidxu _thr_umutex_unlock((lck), TID(thrd)) 567144518Sdavidxu 568144518Sdavidxu#define THR_LOCK_ACQUIRE(thrd, lck) \ 569144518Sdavidxudo { \ 570144518Sdavidxu (thrd)->locklevel++; \ 571162061Sdavidxu _thr_umutex_lock(lck, TID(thrd)); \ 572144518Sdavidxu} while (0) 573144518Sdavidxu 574216641Sdavidxu#define THR_LOCK_ACQUIRE_SPIN(thrd, lck) \ 575216641Sdavidxudo { \ 576216641Sdavidxu (thrd)->locklevel++; \ 577216641Sdavidxu _thr_umutex_lock_spin(lck, TID(thrd)); \ 578216641Sdavidxu} while (0) 579216641Sdavidxu 580154129Sdavidxu#ifdef _PTHREADS_INVARIANTS 581154129Sdavidxu#define THR_ASSERT_LOCKLEVEL(thrd) \ 582144518Sdavidxudo { \ 583154129Sdavidxu if (__predict_false((thrd)->locklevel <= 0)) \ 584144518Sdavidxu _thr_assert_lock_level(); \ 585144518Sdavidxu} while (0) 586154129Sdavidxu#else 587154129Sdavidxu#define THR_ASSERT_LOCKLEVEL(thrd) 588154129Sdavidxu#endif 589144518Sdavidxu 590154129Sdavidxu#define THR_LOCK_RELEASE(thrd, lck) \ 591154129Sdavidxudo { \ 592154129Sdavidxu THR_ASSERT_LOCKLEVEL(thrd); \ 593162061Sdavidxu _thr_umutex_unlock((lck), TID(thrd)); \ 594154129Sdavidxu (thrd)->locklevel--; \ 595154129Sdavidxu _thr_ast(thrd); \ 596154129Sdavidxu} while (0) 597154129Sdavidxu 598144518Sdavidxu#define THR_LOCK(curthrd) THR_LOCK_ACQUIRE(curthrd, &(curthrd)->lock) 599144518Sdavidxu#define THR_UNLOCK(curthrd) THR_LOCK_RELEASE(curthrd, &(curthrd)->lock) 600144518Sdavidxu#define THR_THREAD_LOCK(curthrd, thr) THR_LOCK_ACQUIRE(curthrd, &(thr)->lock) 601144518Sdavidxu#define THR_THREAD_UNLOCK(curthrd, thr) THR_LOCK_RELEASE(curthrd, &(thr)->lock) 602144518Sdavidxu 603212536Sdavidxu#define THREAD_LIST_RDLOCK(curthrd) \ 604144518Sdavidxudo { \ 605212536Sdavidxu (curthrd)->locklevel++; \ 606212536Sdavidxu _thr_rwl_rdlock(&_thr_list_lock); \ 607144518Sdavidxu} while (0) 608144518Sdavidxu 609212536Sdavidxu#define THREAD_LIST_WRLOCK(curthrd) \ 610212536Sdavidxudo { \ 611212536Sdavidxu (curthrd)->locklevel++; \ 612212536Sdavidxu _thr_rwl_wrlock(&_thr_list_lock); \ 613212536Sdavidxu} while (0) 614212536Sdavidxu 615144518Sdavidxu#define THREAD_LIST_UNLOCK(curthrd) \ 616144518Sdavidxudo { \ 617212536Sdavidxu _thr_rwl_unlock(&_thr_list_lock); \ 618212536Sdavidxu (curthrd)->locklevel--; \ 619212536Sdavidxu _thr_ast(curthrd); \ 620144518Sdavidxu} while (0) 621144518Sdavidxu 622112918Sjeff/* 623144518Sdavidxu * Macros to insert/remove threads to the all thread list and 624144518Sdavidxu * the gc list. 625112918Sjeff */ 626144518Sdavidxu#define THR_LIST_ADD(thrd) do { \ 627144518Sdavidxu if (((thrd)->tlflags & TLFLAGS_IN_TDLIST) == 0) { \ 628144518Sdavidxu TAILQ_INSERT_HEAD(&_thread_list, thrd, tle); \ 629144518Sdavidxu _thr_hash_add(thrd); \ 630144518Sdavidxu (thrd)->tlflags |= TLFLAGS_IN_TDLIST; \ 631144518Sdavidxu } \ 632144518Sdavidxu} while (0) 633144518Sdavidxu#define THR_LIST_REMOVE(thrd) do { \ 634144518Sdavidxu if (((thrd)->tlflags & TLFLAGS_IN_TDLIST) != 0) { \ 635144518Sdavidxu TAILQ_REMOVE(&_thread_list, thrd, tle); \ 636144518Sdavidxu _thr_hash_remove(thrd); \ 637144518Sdavidxu (thrd)->tlflags &= ~TLFLAGS_IN_TDLIST; \ 638144518Sdavidxu } \ 639144518Sdavidxu} while (0) 640144518Sdavidxu#define THR_GCLIST_ADD(thrd) do { \ 641212629Sdavidxu if (((thrd)->tlflags & TLFLAGS_IN_GCLIST) == 0) { \ 642144518Sdavidxu TAILQ_INSERT_HEAD(&_thread_gc_list, thrd, gcle);\ 643212629Sdavidxu (thrd)->tlflags |= TLFLAGS_IN_GCLIST; \ 644144518Sdavidxu _gc_count++; \ 645144518Sdavidxu } \ 646144518Sdavidxu} while (0) 647144518Sdavidxu#define THR_GCLIST_REMOVE(thrd) do { \ 648212629Sdavidxu if (((thrd)->tlflags & TLFLAGS_IN_GCLIST) != 0) { \ 649144518Sdavidxu TAILQ_REMOVE(&_thread_gc_list, thrd, gcle); \ 650212629Sdavidxu (thrd)->tlflags &= ~TLFLAGS_IN_GCLIST; \ 651144518Sdavidxu _gc_count--; \ 652144518Sdavidxu } \ 653144518Sdavidxu} while (0) 654112918Sjeff 655212536Sdavidxu#define THR_REF_ADD(curthread, pthread) { \ 656212536Sdavidxu THR_CRITICAL_ENTER(curthread); \ 657212536Sdavidxu pthread->refcount++; \ 658212536Sdavidxu} while (0) 659212536Sdavidxu 660212536Sdavidxu#define THR_REF_DEL(curthread, pthread) { \ 661212536Sdavidxu pthread->refcount--; \ 662212536Sdavidxu THR_CRITICAL_LEAVE(curthread); \ 663212536Sdavidxu} while (0) 664212536Sdavidxu 665144518Sdavidxu#define GC_NEEDED() (_gc_count >= 5) 666112918Sjeff 667144921Sdavidxu#define SHOULD_REPORT_EVENT(curthr, e) \ 668144921Sdavidxu (curthr->report_events && \ 669144921Sdavidxu (((curthr)->event_mask | _thread_event_mask ) & e) != 0) 670144921Sdavidxu 671144518Sdavidxuextern int __isthreaded; 672112918Sjeff 673115305Smtm/* 674144518Sdavidxu * Global variables for the pthread kernel. 675115305Smtm */ 676115305Smtm 677157457Sdavidxuextern char *_usrstack __hidden; 678153593Sdavidxuextern struct pthread *_thr_initial __hidden; 679144921Sdavidxu 680144518Sdavidxu/* For debugger */ 681153593Sdavidxuextern int _libthr_debug; 682153593Sdavidxuextern int _thread_event_mask; 683153593Sdavidxuextern struct pthread *_thread_last_event; 684115305Smtm 685144518Sdavidxu/* List of all threads: */ 686153593Sdavidxuextern pthreadlist _thread_list; 687112918Sjeff 688144518Sdavidxu/* List of threads needing GC: */ 689153593Sdavidxuextern pthreadlist _thread_gc_list __hidden; 690131181Smtm 691153593Sdavidxuextern int _thread_active_threads; 692153593Sdavidxuextern atfork_head _thr_atfork_list __hidden; 693212077Sdavidxuextern struct urwlock _thr_atfork_lock __hidden; 694144518Sdavidxu 695112918Sjeff/* Default thread attributes: */ 696153593Sdavidxuextern struct pthread_attr _pthread_attr_default __hidden; 697112918Sjeff 698112918Sjeff/* Default mutex attributes: */ 699153593Sdavidxuextern struct pthread_mutex_attr _pthread_mutexattr_default __hidden; 700213241Sdavidxuextern struct pthread_mutex_attr _pthread_mutexattr_adaptive_default __hidden; 701112918Sjeff 702112918Sjeff/* Default condition variable attributes: */ 703153593Sdavidxuextern struct pthread_cond_attr _pthread_condattr_default __hidden; 704112918Sjeff 705158073Sdavidxuextern struct pthread_prio _thr_priorities[] __hidden; 706158073Sdavidxu 707153593Sdavidxuextern pid_t _thr_pid __hidden; 708165241Sdavidxuextern int _thr_is_smp __hidden; 709161068Sdavidxu 710157457Sdavidxuextern size_t _thr_guard_default __hidden; 711157457Sdavidxuextern size_t _thr_stack_default __hidden; 712157457Sdavidxuextern size_t _thr_stack_initial __hidden; 713153593Sdavidxuextern int _thr_page_size __hidden; 714173173Sdavidxuextern int _thr_spinloops __hidden; 715173173Sdavidxuextern int _thr_yieldloops __hidden; 716234947Sdavidxuextern int _thr_queuefifo __hidden; 717173173Sdavidxu 718144518Sdavidxu/* Garbage thread count. */ 719153593Sdavidxuextern int _gc_count __hidden; 720112918Sjeff 721162061Sdavidxuextern struct umutex _mutex_static_lock __hidden; 722162061Sdavidxuextern struct umutex _cond_static_lock __hidden; 723162061Sdavidxuextern struct umutex _rwlock_static_lock __hidden; 724162061Sdavidxuextern struct umutex _keytable_lock __hidden; 725212536Sdavidxuextern struct urwlock _thr_list_lock __hidden; 726162061Sdavidxuextern struct umutex _thr_event_lock __hidden; 727239718Sdavidxuextern struct umutex _suspend_all_lock __hidden; 728239718Sdavidxuextern int _suspend_all_waiters __hidden; 729239718Sdavidxuextern int _suspend_all_cycle __hidden; 730239718Sdavidxuextern struct pthread *_single_thread __hidden; 731117026Sjdp 732112918Sjeff/* 733112918Sjeff * Function prototype definitions. 734112918Sjeff */ 735112918Sjeff__BEGIN_DECLS 736153593Sdavidxuint _thr_setthreaded(int) __hidden; 737239200Sdavidxuint _mutex_cv_lock(struct pthread_mutex *, int) __hidden; 738239200Sdavidxuint _mutex_cv_unlock(struct pthread_mutex *, int *, int *) __hidden; 739239200Sdavidxuint _mutex_cv_attach(struct pthread_mutex *, int) __hidden; 740239200Sdavidxuint _mutex_cv_detach(struct pthread_mutex *, int *) __hidden; 741216641Sdavidxuint _mutex_owned(struct pthread *, const struct pthread_mutex *) __hidden; 742153593Sdavidxuint _mutex_reinit(pthread_mutex_t *) __hidden; 743153593Sdavidxuvoid _mutex_fork(struct pthread *curthread) __hidden; 744153593Sdavidxuvoid _libpthread_init(struct pthread *) __hidden; 745153593Sdavidxustruct pthread *_thr_alloc(struct pthread *) __hidden; 746157457Sdavidxuvoid _thread_exit(const char *, int, const char *) __hidden __dead2; 747153593Sdavidxuint _thr_ref_add(struct pthread *, struct pthread *, int) __hidden; 748153593Sdavidxuvoid _thr_ref_delete(struct pthread *, struct pthread *) __hidden; 749154055Sdavidxuvoid _thr_ref_delete_unlocked(struct pthread *, struct pthread *) __hidden; 750153593Sdavidxuint _thr_find_thread(struct pthread *, struct pthread *, int) __hidden; 751153593Sdavidxuvoid _thr_rtld_init(void) __hidden; 752212076Sdavidxuvoid _thr_rtld_postfork_child(void) __hidden; 753153593Sdavidxuint _thr_stack_alloc(struct pthread_attr *) __hidden; 754153593Sdavidxuvoid _thr_stack_free(struct pthread_attr *) __hidden; 755153593Sdavidxuvoid _thr_free(struct pthread *, struct pthread *) __hidden; 756153593Sdavidxuvoid _thr_gc(struct pthread *) __hidden; 757153593Sdavidxuvoid _thread_cleanupspecific(void) __hidden; 758153593Sdavidxuvoid _thread_printf(int, const char *, ...) __hidden; 759153593Sdavidxuvoid _thr_spinlock_init(void) __hidden; 760164583Sdavidxuvoid _thr_cancel_enter(struct pthread *) __hidden; 761212076Sdavidxuvoid _thr_cancel_enter2(struct pthread *, int) __hidden; 762212076Sdavidxuvoid _thr_cancel_leave(struct pthread *, int) __hidden; 763164583Sdavidxuvoid _thr_testcancel(struct pthread *) __hidden; 764153593Sdavidxuvoid _thr_signal_block(struct pthread *) __hidden; 765153593Sdavidxuvoid _thr_signal_unblock(struct pthread *) __hidden; 766153593Sdavidxuvoid _thr_signal_init(void) __hidden; 767153593Sdavidxuvoid _thr_signal_deinit(void) __hidden; 768153593Sdavidxuint _thr_send_sig(struct pthread *, int sig) __hidden; 769153593Sdavidxuvoid _thr_list_init(void) __hidden; 770153593Sdavidxuvoid _thr_hash_add(struct pthread *) __hidden; 771153593Sdavidxuvoid _thr_hash_remove(struct pthread *) __hidden; 772153593Sdavidxustruct pthread *_thr_hash_find(struct pthread *) __hidden; 773154055Sdavidxuvoid _thr_link(struct pthread *, struct pthread *) __hidden; 774154055Sdavidxuvoid _thr_unlink(struct pthread *, struct pthread *) __hidden; 775153593Sdavidxuvoid _thr_assert_lock_level(void) __hidden __dead2; 776154055Sdavidxuvoid _thr_ast(struct pthread *) __hidden; 777155739Sdavidxuvoid _thr_once_init(void) __hidden; 778144921Sdavidxuvoid _thr_report_creation(struct pthread *curthread, 779157457Sdavidxu struct pthread *newthread) __hidden; 780153593Sdavidxuvoid _thr_report_death(struct pthread *curthread) __hidden; 781162499Sdavidxuint _thr_getscheduler(lwpid_t, int *, struct sched_param *) __hidden; 782162499Sdavidxuint _thr_setscheduler(lwpid_t, int, const struct sched_param *) __hidden; 783212076Sdavidxuvoid _thr_signal_prefork(void) __hidden; 784212076Sdavidxuvoid _thr_signal_postfork(void) __hidden; 785212076Sdavidxuvoid _thr_signal_postfork_child(void) __hidden; 786239718Sdavidxuvoid _thr_suspend_all_lock(struct pthread *) __hidden; 787239718Sdavidxuvoid _thr_suspend_all_unlock(struct pthread *) __hidden; 788212536Sdavidxuvoid _thr_try_gc(struct pthread *, struct pthread *) __hidden; 789162499Sdavidxuint _rtp_to_schedparam(const struct rtprio *rtp, int *policy, 790162499Sdavidxu struct sched_param *param) __hidden; 791162499Sdavidxuint _schedparam_to_rtp(int policy, const struct sched_param *param, 792162499Sdavidxu struct rtprio *rtp) __hidden; 793144921Sdavidxuvoid _thread_bp_create(void); 794144921Sdavidxuvoid _thread_bp_death(void); 795173173Sdavidxuint _sched_yield(void); 796112918Sjeff 797179662Sdavidxuvoid _pthread_cleanup_push(void (*)(void *), void *); 798179662Sdavidxuvoid _pthread_cleanup_pop(int); 799212076Sdavidxuvoid _pthread_exit_mask(void *status, sigset_t *mask) __dead2 __hidden; 800213153Sdavidxuvoid _pthread_cancel_enter(int maycancel); 801213153Sdavidxuvoid _pthread_cancel_leave(int maycancel); 802179662Sdavidxu 803144518Sdavidxu/* #include <fcntl.h> */ 804144518Sdavidxu#ifdef _SYS_FCNTL_H_ 805144518Sdavidxuint __sys_fcntl(int, int, ...); 806144518Sdavidxuint __sys_open(const char *, int, ...); 807197968Sjillesint __sys_openat(int, const char *, int, ...); 808112918Sjeff#endif 809112918Sjeff 810144518Sdavidxu/* #include <signal.h> */ 811144518Sdavidxu#ifdef _SIGNAL_H_ 812144518Sdavidxuint __sys_kill(pid_t, int); 813144518Sdavidxuint __sys_sigaction(int, const struct sigaction *, struct sigaction *); 814144518Sdavidxuint __sys_sigpending(sigset_t *); 815144518Sdavidxuint __sys_sigprocmask(int, const sigset_t *, sigset_t *); 816144518Sdavidxuint __sys_sigsuspend(const sigset_t *); 817212076Sdavidxuint __sys_sigreturn(const ucontext_t *); 818144518Sdavidxuint __sys_sigaltstack(const struct sigaltstack *, struct sigaltstack *); 819157457Sdavidxuint __sys_sigwait(const sigset_t *, int *); 820157457Sdavidxuint __sys_sigtimedwait(const sigset_t *, siginfo_t *, 821157457Sdavidxu const struct timespec *); 822157457Sdavidxuint __sys_sigwaitinfo(const sigset_t *set, siginfo_t *info); 823112918Sjeff#endif 824112918Sjeff 825144518Sdavidxu/* #include <time.h> */ 826144518Sdavidxu#ifdef _TIME_H_ 827144518Sdavidxuint __sys_nanosleep(const struct timespec *, struct timespec *); 828112918Sjeff#endif 829112918Sjeff 830211737Sdavidxu/* #include <sys/ucontext.h> */ 831211737Sdavidxu#ifdef _SYS_UCONTEXT_H_ 832211737Sdavidxuint __sys_setcontext(const ucontext_t *ucp); 833211737Sdavidxuint __sys_swapcontext(ucontext_t *oucp, const ucontext_t *ucp); 834211737Sdavidxu#endif 835211737Sdavidxu 836144518Sdavidxu/* #include <unistd.h> */ 837144518Sdavidxu#ifdef _UNISTD_H_ 838144518Sdavidxuint __sys_close(int); 839144518Sdavidxuint __sys_fork(void); 840144518Sdavidxupid_t __sys_getpid(void); 841144518Sdavidxussize_t __sys_read(int, void *, size_t); 842144518Sdavidxussize_t __sys_write(int, const void *, size_t); 843144518Sdavidxuvoid __sys_exit(int); 844112918Sjeff#endif 845112918Sjeff 846144518Sdavidxustatic inline int 847144518Sdavidxu_thr_isthreaded(void) 848144518Sdavidxu{ 849144518Sdavidxu return (__isthreaded != 0); 850144518Sdavidxu} 851112918Sjeff 852144518Sdavidxustatic inline int 853144518Sdavidxu_thr_is_inited(void) 854144518Sdavidxu{ 855144518Sdavidxu return (_thr_initial != NULL); 856144518Sdavidxu} 857112918Sjeff 858144518Sdavidxustatic inline void 859144518Sdavidxu_thr_check_init(void) 860144518Sdavidxu{ 861144518Sdavidxu if (_thr_initial == NULL) 862144518Sdavidxu _libpthread_init(NULL); 863144518Sdavidxu} 864144518Sdavidxu 865216641Sdavidxustruct wake_addr *_thr_alloc_wake_addr(void); 866216641Sdavidxuvoid _thr_release_wake_addr(struct wake_addr *); 867216641Sdavidxuint _thr_sleep(struct pthread *, int, const struct timespec *); 868216641Sdavidxu 869216641Sdavidxuvoid _thr_wake_addr_init(void) __hidden; 870216641Sdavidxu 871216641Sdavidxustatic inline void 872216641Sdavidxu_thr_clear_wake(struct pthread *td) 873216641Sdavidxu{ 874216641Sdavidxu td->wake_addr->value = 0; 875216641Sdavidxu} 876216641Sdavidxu 877216641Sdavidxustatic inline int 878216641Sdavidxu_thr_is_woken(struct pthread *td) 879216641Sdavidxu{ 880216641Sdavidxu return td->wake_addr->value != 0; 881216641Sdavidxu} 882216641Sdavidxu 883216641Sdavidxustatic inline void 884216641Sdavidxu_thr_set_wake(unsigned int *waddr) 885216641Sdavidxu{ 886216641Sdavidxu *waddr = 1; 887216641Sdavidxu _thr_umtx_wake(waddr, INT_MAX, 0); 888216641Sdavidxu} 889216641Sdavidxu 890216641Sdavidxuvoid _thr_wake_all(unsigned int *waddrs[], int) __hidden; 891216641Sdavidxu 892216641Sdavidxustatic inline struct pthread * 893216641Sdavidxu_sleepq_first(struct sleepqueue *sq) 894216641Sdavidxu{ 895216641Sdavidxu return TAILQ_FIRST(&sq->sq_blocked); 896216641Sdavidxu} 897216641Sdavidxu 898216641Sdavidxuvoid _sleepq_init(void) __hidden; 899216641Sdavidxustruct sleepqueue *_sleepq_alloc(void) __hidden; 900216641Sdavidxuvoid _sleepq_free(struct sleepqueue *) __hidden; 901216641Sdavidxuvoid _sleepq_lock(void *) __hidden; 902216641Sdavidxuvoid _sleepq_unlock(void *) __hidden; 903216641Sdavidxustruct sleepqueue *_sleepq_lookup(void *) __hidden; 904216641Sdavidxuvoid _sleepq_add(void *, struct pthread *) __hidden; 905216641Sdavidxuint _sleepq_remove(struct sleepqueue *, struct pthread *) __hidden; 906216641Sdavidxuvoid _sleepq_drop(struct sleepqueue *, 907216641Sdavidxu void (*cb)(struct pthread *, void *arg), void *) __hidden; 908216641Sdavidxu 909211706Skibstruct dl_phdr_info; 910211706Skibvoid __pthread_cxa_finalize(struct dl_phdr_info *phdr_info); 911211860Sdavidxuvoid _thr_tsd_unload(struct dl_phdr_info *phdr_info) __hidden; 912212076Sdavidxuvoid _thr_sigact_unload(struct dl_phdr_info *phdr_info) __hidden; 913217191Skibvoid _thr_stack_fix_protection(struct pthread *thrd); 914211706Skib 915112918Sjeff__END_DECLS 916112918Sjeff 917144518Sdavidxu#endif /* !_THR_PRIVATE_H */ 918