| Commit | Line | Data |
|---|---|---|
| 71b3fa15 DX |
1 | /* |
| 2 | * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>. | |
| 3 | * All rights reserved. | |
| 4 | * | |
| 5 | * Redistribution and use in source and binary forms, with or without | |
| 6 | * modification, are permitted provided that the following conditions | |
| 7 | * are met: | |
| 8 | * 1. Redistributions of source code must retain the above copyright | |
| 9 | * notice, this list of conditions and the following disclaimer. | |
| 10 | * 2. Redistributions in binary form must reproduce the above copyright | |
| 11 | * notice, this list of conditions and the following disclaimer in the | |
| 12 | * documentation and/or other materials provided with the distribution. | |
| 13 | * 3. All advertising materials mentioning features or use of this software | |
| 14 | * must display the following acknowledgement: | |
| 15 | * This product includes software developed by John Birrell. | |
| 16 | * 4. Neither the name of the author nor the names of any co-contributors | |
| 17 | * may be used to endorse or promote products derived from this software | |
| 18 | * without specific prior written permission. | |
| 19 | * | |
| 20 | * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND | |
| 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
| 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| 26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 30 | * SUCH DAMAGE. | |
| 31 | * | |
| 32 | * Private thread definitions for the uthread kernel. | |
| 33 | * | |
| 34 | * $FreeBSD: src/lib/libpthread/thread/thr_private.h,v 1.120 2004/11/01 10:49:34 davidxu Exp $ | |
| 64524f1c | 35 | * $DragonFly: src/lib/libthread_xu/thread/thr_private.h,v 1.19 2008/07/15 01:18:53 dillon Exp $ |
| 71b3fa15 DX |
36 | */ |
| 37 | ||
| 38 | #ifndef _THR_PRIVATE_H | |
| 39 | #define _THR_PRIVATE_H | |
| 40 | ||
| 41 | /* | |
| 42 | * Include files. | |
| 43 | */ | |
| 44 | #include <sys/types.h> | |
| 45 | #include <sys/time.h> | |
| 46 | #include <sys/cdefs.h> | |
| 47 | #include <sys/queue.h> | |
| 48 | #include <machine/atomic.h> | |
| 49 | #include <errno.h> | |
| 50 | #include <limits.h> | |
| 51 | #include <signal.h> | |
| 52 | #include <stdio.h> | |
| c4dd4100 | 53 | #include <sys/sched.h> |
| 71b3fa15 DX |
54 | #include <unistd.h> |
| 55 | #include <pthread.h> | |
| 56 | #include <pthread_np.h> | |
| 57 | ||
| 58 | #include "pthread_md.h" | |
| 59 | #include "thr_umtx.h" | |
| 3cd47da3 | 60 | #include "thread_db.h" |
| 71b3fa15 | 61 | |
| 71b3fa15 DX |
62 | /* Signal to do cancellation */ |
| 63 | #define SIGCANCEL 32 | |
| 64 | ||
| 65 | /* | |
| 66 | * Kernel fatal error handler macro. | |
| 67 | */ | |
| 68 | #define PANIC(string) _thread_exit(__FILE__,__LINE__,string) | |
| 69 | ||
| 70 | /* Output debug messages like this: */ | |
| 71 | #define stdout_debug(args...) _thread_printf(STDOUT_FILENO, ##args) | |
| 72 | #define stderr_debug(args...) _thread_printf(STDOUT_FILENO, ##args) | |
| 73 | ||
| 71b3fa15 DX |
74 | #ifdef _PTHREADS_INVARIANTS |
| 75 | #define THR_ASSERT(cond, msg) do { \ | |
| 76 | if (__predict_false(!(cond))) \ | |
| 77 | PANIC(msg); \ | |
| 78 | } while (0) | |
| 79 | #else | |
| 80 | #define THR_ASSERT(cond, msg) | |
| 81 | #endif | |
| 82 | ||
| 22d6e608 DX |
83 | #ifdef PIC |
| 84 | #define STATIC_LIB_REQUIRE(name) | |
| 85 | #else | |
| 86 | #define STATIC_LIB_REQUIRE(name) __asm(".globl " #name) | |
| 87 | #endif | |
| 88 | ||
| e8382b15 DX |
89 | TAILQ_HEAD(thread_head, pthread) thread_head; |
| 90 | TAILQ_HEAD(atfork_head, pthread_atfork) atfork_head; | |
| 91 | ||
| 71b3fa15 DX |
92 | #define TIMESPEC_ADD(dst, src, val) \ |
| 93 | do { \ | |
| 94 | (dst)->tv_sec = (src)->tv_sec + (val)->tv_sec; \ | |
| 95 | (dst)->tv_nsec = (src)->tv_nsec + (val)->tv_nsec; \ | |
| 9d8e0254 | 96 | if ((dst)->tv_nsec >= 1000000000) { \ |
| 71b3fa15 DX |
97 | (dst)->tv_sec++; \ |
| 98 | (dst)->tv_nsec -= 1000000000; \ | |
| 99 | } \ | |
| 100 | } while (0) | |
| 101 | ||
| 102 | #define TIMESPEC_SUB(dst, src, val) \ | |
| 103 | do { \ | |
| 104 | (dst)->tv_sec = (src)->tv_sec - (val)->tv_sec; \ | |
| 105 | (dst)->tv_nsec = (src)->tv_nsec - (val)->tv_nsec; \ | |
| 106 | if ((dst)->tv_nsec < 0) { \ | |
| 107 | (dst)->tv_sec--; \ | |
| 108 | (dst)->tv_nsec += 1000000000; \ | |
| 109 | } \ | |
| 110 | } while (0) | |
| 111 | ||
| 112 | struct pthread_mutex { | |
| 113 | /* | |
| 114 | * Lock for accesses to this structure. | |
| 115 | */ | |
| 116 | volatile umtx_t m_lock; | |
| 117 | enum pthread_mutextype m_type; | |
| 118 | int m_protocol; | |
| 119 | TAILQ_HEAD(mutex_head, pthread) m_queue; | |
| 120 | struct pthread *m_owner; | |
| 121 | long m_flags; | |
| 122 | int m_count; | |
| 123 | int m_refcount; | |
| 124 | ||
| 125 | /* | |
| 126 | * Used for priority inheritence and protection. | |
| 127 | * | |
| 128 | * m_prio - For priority inheritence, the highest active | |
| 129 | * priority (threads locking the mutex inherit | |
| 130 | * this priority). For priority protection, the | |
| 131 | * ceiling priority of this mutex. | |
| 132 | * m_saved_prio - mutex owners inherited priority before | |
| 133 | * taking the mutex, restored when the owner | |
| 134 | * unlocks the mutex. | |
| 135 | */ | |
| 136 | int m_prio; | |
| 137 | int m_saved_prio; | |
| 138 | ||
| 139 | /* | |
| 140 | * Link for list of all mutexes a thread currently owns. | |
| 141 | */ | |
| 142 | TAILQ_ENTRY(pthread_mutex) m_qe; | |
| 143 | }; | |
| 144 | ||
| 145 | #define TAILQ_INITIALIZER { NULL, NULL } | |
| 146 | ||
| 147 | #define PTHREAD_MUTEX_STATIC_INITIALIZER \ | |
| 148 | {0, PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, TAILQ_INITIALIZER, \ | |
| 149 | NULL, { NULL }, MUTEX_FLAGS_PRIVATE, 0, 0, 0, TAILQ_INITIALIZER } | |
| 150 | /* | |
| 151 | * Flags for mutexes. | |
| 152 | */ | |
| 153 | #define MUTEX_FLAGS_PRIVATE 0x01 | |
| 154 | #define MUTEX_FLAGS_INITED 0x02 | |
| 71b3fa15 DX |
155 | |
| 156 | struct pthread_mutex_attr { | |
| 157 | enum pthread_mutextype m_type; | |
| 158 | int m_protocol; | |
| 159 | int m_ceiling; | |
| 7ab4b9f8 | 160 | int m_flags; |
| 71b3fa15 DX |
161 | }; |
| 162 | ||
| 163 | #define PTHREAD_MUTEXATTR_STATIC_INITIALIZER \ | |
| 164 | { PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, 0, MUTEX_FLAGS_PRIVATE } | |
| 165 | ||
| 166 | struct pthread_cond { | |
| 167 | /* | |
| 168 | * Lock for accesses to this structure. | |
| 169 | */ | |
| 170 | volatile umtx_t c_lock; | |
| 171 | volatile umtx_t c_seqno; | |
| 172 | volatile int c_waiters; | |
| 3db51647 | 173 | volatile int c_broadcast; |
| 71b3fa15 DX |
174 | int c_pshared; |
| 175 | int c_clockid; | |
| 176 | }; | |
| 177 | ||
| 178 | struct pthread_cond_attr { | |
| 179 | int c_pshared; | |
| 180 | int c_clockid; | |
| 181 | }; | |
| 182 | ||
| 7ab4b9f8 DX |
183 | /* |
| 184 | * Flags for condition variables. | |
| 185 | */ | |
| 186 | #define COND_FLAGS_PRIVATE 0x01 | |
| 187 | #define COND_FLAGS_INITED 0x02 | |
| 188 | ||
| 71b3fa15 DX |
189 | struct pthread_barrier { |
| 190 | volatile umtx_t b_lock; | |
| 191 | volatile umtx_t b_cycle; | |
| 192 | volatile int b_count; | |
| 193 | volatile int b_waiters; | |
| 194 | }; | |
| 195 | ||
| 196 | struct pthread_barrierattr { | |
| 197 | int pshared; | |
| 198 | }; | |
| 199 | ||
| 200 | struct pthread_spinlock { | |
| 201 | volatile umtx_t s_lock; | |
| 202 | }; | |
| 203 | ||
| 204 | /* | |
| 71b3fa15 DX |
205 | * Cleanup definitions. |
| 206 | */ | |
| 207 | struct pthread_cleanup { | |
| 208 | struct pthread_cleanup *next; | |
| fc71f871 | 209 | void (*routine)(void *); |
| 71b3fa15 DX |
210 | void *routine_arg; |
| 211 | int onstack; | |
| 212 | }; | |
| 213 | ||
| 214 | #define THR_CLEANUP_PUSH(td, func, arg) { \ | |
| 215 | struct pthread_cleanup __cup; \ | |
| 216 | \ | |
| 217 | __cup.routine = func; \ | |
| 218 | __cup.routine_arg = arg; \ | |
| 219 | __cup.onstack = 1; \ | |
| 220 | __cup.next = (td)->cleanup; \ | |
| 221 | (td)->cleanup = &__cup; | |
| 222 | ||
| 223 | #define THR_CLEANUP_POP(td, exec) \ | |
| 224 | (td)->cleanup = __cup.next; \ | |
| 225 | if ((exec) != 0) \ | |
| 226 | __cup.routine(__cup.routine_arg); \ | |
| 227 | } | |
| 228 | ||
| 229 | struct pthread_atfork { | |
| 230 | TAILQ_ENTRY(pthread_atfork) qe; | |
| 231 | void (*prepare)(void); | |
| 232 | void (*parent)(void); | |
| 233 | void (*child)(void); | |
| 234 | }; | |
| 235 | ||
| 236 | struct pthread_attr { | |
| 237 | int sched_policy; | |
| 238 | int sched_inherit; | |
| 71b3fa15 DX |
239 | int prio; |
| 240 | int suspend; | |
| 241 | #define THR_STACK_USER 0x100 /* 0xFF reserved for <pthread.h> */ | |
| 242 | int flags; | |
| 71b3fa15 DX |
243 | void *stackaddr_attr; |
| 244 | size_t stacksize_attr; | |
| 245 | size_t guardsize_attr; | |
| 246 | }; | |
| 247 | ||
| 248 | /* | |
| 249 | * Thread creation state attributes. | |
| 250 | */ | |
| 251 | #define THR_CREATE_RUNNING 0 | |
| 252 | #define THR_CREATE_SUSPENDED 1 | |
| 253 | ||
| 254 | /* | |
| 255 | * Miscellaneous definitions. | |
| 256 | */ | |
| eddabc99 | 257 | #define THR_STACK_DEFAULT (sizeof(void *) / 4 * 1024 * 1024) |
| 71b3fa15 DX |
258 | |
| 259 | /* | |
| 260 | * Maximum size of initial thread's stack. This perhaps deserves to be larger | |
| 261 | * than the stacks of other threads, since many applications are likely to run | |
| 262 | * almost entirely on this stack. | |
| 263 | */ | |
| eddabc99 | 264 | #define THR_STACK_INITIAL (THR_STACK_DEFAULT * 2) |
| 71b3fa15 DX |
265 | |
| 266 | /* | |
| 267 | * Define the different priority ranges. All applications have thread | |
| 268 | * priorities constrained within 0-31. The threads library raises the | |
| 269 | * priority when delivering signals in order to ensure that signal | |
| 270 | * delivery happens (from the POSIX spec) "as soon as possible". | |
| 271 | * In the future, the threads library will also be able to map specific | |
| 272 | * threads into real-time (cooperating) processes or kernel threads. | |
| 273 | * The RT and SIGNAL priorities will be used internally and added to | |
| 274 | * thread base priorities so that the scheduling queue can handle both | |
| 275 | * normal and RT priority threads with and without signal handling. | |
| 276 | * | |
| 277 | * The approach taken is that, within each class, signal delivery | |
| 278 | * always has priority over thread execution. | |
| 279 | */ | |
| 64524f1c MD |
280 | #define THR_DEFAULT_PRIORITY 0 |
| 281 | #define THR_MUTEX_CEIL_PRIORITY 31 /* dummy */ | |
| 71b3fa15 DX |
282 | |
| 283 | /* | |
| 284 | * Time slice period in microseconds. | |
| 285 | */ | |
| 286 | #define TIMESLICE_USEC 20000 | |
| 287 | ||
| 288 | struct pthread_rwlockattr { | |
| 289 | int pshared; | |
| 290 | }; | |
| 291 | ||
| 292 | struct pthread_rwlock { | |
| 293 | pthread_mutex_t lock; /* monitor lock */ | |
| 294 | pthread_cond_t read_signal; | |
| 295 | pthread_cond_t write_signal; | |
| 296 | int state; /* 0 = idle >0 = # of readers -1 = writer */ | |
| 297 | int blocked_writers; | |
| 298 | }; | |
| 299 | ||
| 300 | /* | |
| 301 | * Thread states. | |
| 302 | */ | |
| 303 | enum pthread_state { | |
| 304 | PS_RUNNING, | |
| 305 | PS_DEAD | |
| 306 | }; | |
| 307 | ||
| 71b3fa15 DX |
308 | struct pthread_specific_elem { |
| 309 | const void *data; | |
| 310 | int seqno; | |
| 311 | }; | |
| 312 | ||
| 313 | struct pthread_key { | |
| 314 | volatile int allocated; | |
| 315 | volatile int count; | |
| 316 | int seqno; | |
| 317 | void (*destructor)(void *); | |
| 318 | }; | |
| 319 | ||
| 320 | /* | |
| 321 | * Thread structure. | |
| 322 | */ | |
| 323 | struct pthread { | |
| 324 | /* | |
| 325 | * Magic value to help recognize a valid thread structure | |
| 326 | * from an invalid one: | |
| 327 | */ | |
| 328 | #define THR_MAGIC ((u_int32_t) 0xd09ba115) | |
| 329 | u_int32_t magic; | |
| 330 | char *name; | |
| 331 | u_int64_t uniqueid; /* for gdb */ | |
| 332 | ||
| 333 | /* | |
| 334 | * Lock for accesses to this thread structure. | |
| 335 | */ | |
| 336 | umtx_t lock; | |
| 337 | ||
| 338 | /* Thread is terminated in kernel, written by kernel. */ | |
| 339 | long terminated; | |
| 340 | ||
| 341 | /* Kernel thread id. */ | |
| 342 | long tid; | |
| 343 | ||
| 344 | /* Internal condition variable cycle number. */ | |
| 345 | umtx_t cycle; | |
| 346 | ||
| 347 | /* How many low level locks the thread held. */ | |
| 348 | int locklevel; | |
| 349 | ||
| fd4288bd DX |
350 | /* |
| 351 | * Set to non-zero when this thread has entered a critical | |
| 352 | * region. We allow for recursive entries into critical regions. | |
| 353 | */ | |
| 354 | int critical_count; | |
| 355 | ||
| 71b3fa15 DX |
356 | /* Signal blocked counter. */ |
| 357 | int sigblock; | |
| 358 | ||
| 359 | /* Queue entry for list of all threads. */ | |
| 360 | TAILQ_ENTRY(pthread) tle; /* link for all threads in process */ | |
| 361 | ||
| 362 | /* Queue entry for GC lists. */ | |
| 363 | TAILQ_ENTRY(pthread) gcle; | |
| 364 | ||
| 365 | /* Hash queue entry. */ | |
| 366 | LIST_ENTRY(pthread) hle; | |
| 367 | ||
| 368 | /* Threads reference count. */ | |
| 369 | int refcount; | |
| 370 | ||
| 371 | /* | |
| 372 | * Thread start routine, argument, stack pointer and thread | |
| 373 | * attributes. | |
| 374 | */ | |
| 375 | void *(*start_routine)(void *); | |
| 376 | void *arg; | |
| 377 | struct pthread_attr attr; | |
| 378 | ||
| 379 | /* | |
| 380 | * Cancelability flags | |
| 381 | */ | |
| 382 | #define THR_CANCEL_DISABLE 0x0001 | |
| 383 | #define THR_CANCEL_EXITING 0x0002 | |
| 384 | #define THR_CANCEL_AT_POINT 0x0004 | |
| 385 | #define THR_CANCEL_NEEDED 0x0008 | |
| 386 | #define SHOULD_CANCEL(val) \ | |
| 387 | (((val) & (THR_CANCEL_DISABLE | THR_CANCEL_EXITING | \ | |
| 388 | THR_CANCEL_NEEDED)) == THR_CANCEL_NEEDED) | |
| 389 | ||
| 390 | #define SHOULD_ASYNC_CANCEL(val) \ | |
| 391 | (((val) & (THR_CANCEL_DISABLE | THR_CANCEL_EXITING | \ | |
| 392 | THR_CANCEL_NEEDED | THR_CANCEL_AT_POINT)) == \ | |
| 393 | (THR_CANCEL_NEEDED | THR_CANCEL_AT_POINT)) | |
| 394 | int cancelflags; | |
| 395 | ||
| 396 | /* Thread temporary signal mask. */ | |
| 397 | sigset_t sigmask; | |
| 398 | ||
| 399 | /* Thread state: */ | |
| 400 | umtx_t state; | |
| 401 | ||
| 402 | /* | |
| 67837f3a | 403 | * Error variable used instead of errno, used for internal. |
| 71b3fa15 DX |
404 | */ |
| 405 | int error; | |
| 406 | ||
| 407 | /* | |
| 408 | * The joiner is the thread that is joining to this thread. The | |
| 409 | * join status keeps track of a join operation to another thread. | |
| 410 | */ | |
| 411 | struct pthread *joiner; | |
| 412 | ||
| 413 | /* | |
| 414 | * The current thread can belong to a priority mutex queue. | |
| 415 | * This is the synchronization queue link. | |
| 416 | */ | |
| 417 | TAILQ_ENTRY(pthread) sqe; | |
| 418 | ||
| 71b3fa15 DX |
419 | /* Miscellaneous flags; only set with scheduling lock held. */ |
| 420 | int flags; | |
| 421 | #define THR_FLAGS_PRIVATE 0x0001 | |
| 422 | #define THR_FLAGS_NEED_SUSPEND 0x0002 /* thread should be suspended */ | |
| 423 | #define THR_FLAGS_SUSPENDED 0x0004 /* thread is suspended */ | |
| 424 | ||
| 425 | /* Thread list flags; only set with thread list lock held. */ | |
| 426 | int tlflags; | |
| 427 | #define TLFLAGS_GC_SAFE 0x0001 /* thread safe for cleaning */ | |
| 428 | #define TLFLAGS_IN_TDLIST 0x0002 /* thread in all thread list */ | |
| 429 | #define TLFLAGS_IN_GCLIST 0x0004 /* thread in gc list */ | |
| 430 | #define TLFLAGS_DETACHED 0x0008 /* thread is detached */ | |
| 431 | ||
| 432 | /* | |
| 433 | * Base priority is the user setable and retrievable priority | |
| 434 | * of the thread. It is only affected by explicit calls to | |
| 435 | * set thread priority and upon thread creation via a thread | |
| 436 | * attribute or default priority. | |
| 437 | */ | |
| 438 | char base_priority; | |
| 439 | ||
| 440 | /* | |
| 441 | * Inherited priority is the priority a thread inherits by | |
| 442 | * taking a priority inheritence or protection mutex. It | |
| 443 | * is not affected by base priority changes. Inherited | |
| 444 | * priority defaults to and remains 0 until a mutex is taken | |
| 445 | * that is being waited on by any other thread whose priority | |
| 446 | * is non-zero. | |
| 447 | */ | |
| 448 | char inherited_priority; | |
| 449 | ||
| 450 | /* | |
| 451 | * Active priority is always the maximum of the threads base | |
| 452 | * priority and inherited priority. When there is a change | |
| 453 | * in either the base or inherited priority, the active | |
| 454 | * priority must be recalculated. | |
| 455 | */ | |
| 456 | char active_priority; | |
| 457 | ||
| 458 | /* Number of priority ceiling or protection mutexes owned. */ | |
| 459 | int priority_mutex_count; | |
| 460 | ||
| 461 | /* Queue of currently owned simple type mutexes. */ | |
| 462 | TAILQ_HEAD(, pthread_mutex) mutexq; | |
| 463 | ||
| 71b3fa15 DX |
464 | void *ret; |
| 465 | struct pthread_specific_elem *specific; | |
| 466 | int specific_data_count; | |
| 467 | ||
| 468 | /* Number rwlocks rdlocks held. */ | |
| 469 | int rdlock_count; | |
| 470 | ||
| 471 | /* | |
| 472 | * Current locks bitmap for rtld. */ | |
| 473 | int rtld_bits; | |
| 474 | ||
| 475 | /* Thread control block */ | |
| 9e2ee207 | 476 | struct tls_tcb *tcb; |
| 71b3fa15 DX |
477 | |
| 478 | /* Cleanup handlers Link List */ | |
| 479 | struct pthread_cleanup *cleanup; | |
| 3cd47da3 DX |
480 | |
| 481 | /* Enable event reporting */ | |
| 482 | int report_events; | |
| 483 | ||
| 484 | /* Event mask */ | |
| 485 | td_thr_events_t event_mask; | |
| 486 | ||
| 487 | /* Event */ | |
| 488 | td_event_msg_t event_buf; | |
| 71b3fa15 DX |
489 | }; |
| 490 | ||
| fd4288bd DX |
491 | #define THR_IN_CRITICAL(thrd) \ |
| 492 | (((thrd)->locklevel > 0) || \ | |
| 493 | ((thrd)->critical_count > 0)) | |
| 494 | ||
| 71b3fa15 DX |
495 | #define THR_UMTX_TRYLOCK(thrd, lck) \ |
| 496 | _thr_umtx_trylock((lck), (thrd)->tid) | |
| 497 | ||
| 498 | #define THR_UMTX_LOCK(thrd, lck) \ | |
| 499 | _thr_umtx_lock((lck), (thrd)->tid) | |
| 500 | ||
| 501 | #define THR_UMTX_TIMEDLOCK(thrd, lck, timo) \ | |
| 502 | _thr_umtx_timedlock((lck), (thrd)->tid, (timo)) | |
| 503 | ||
| 504 | #define THR_UMTX_UNLOCK(thrd, lck) \ | |
| 505 | _thr_umtx_unlock((lck), (thrd)->tid) | |
| 506 | ||
| 507 | #define THR_LOCK_ACQUIRE(thrd, lck) \ | |
| 508 | do { \ | |
| 509 | (thrd)->locklevel++; \ | |
| fc71f871 | 510 | _thr_umtx_lock((lck), (thrd)->tid); \ |
| 71b3fa15 DX |
511 | } while (0) |
| 512 | ||
| fd4288bd DX |
513 | #ifdef _PTHREADS_INVARIANTS |
| 514 | #define THR_ASSERT_LOCKLEVEL(thrd) \ | |
| 71b3fa15 | 515 | do { \ |
| fd4288bd | 516 | if (__predict_false((thrd)->locklevel <= 0)) \ |
| 71b3fa15 | 517 | _thr_assert_lock_level(); \ |
| fd4288bd DX |
518 | } while (0) |
| 519 | #else | |
| 520 | #define THR_ASSERT_LOCKLEVEL(thrd) | |
| 521 | #endif | |
| 522 | ||
| 523 | #define THR_LOCK_RELEASE(thrd, lck) \ | |
| 524 | do { \ | |
| 525 | THR_ASSERT_LOCKLEVEL(thrd); \ | |
| 526 | _thr_umtx_unlock((lck), (thrd)->tid); \ | |
| 527 | (thrd)->locklevel--; \ | |
| 528 | _thr_ast(thrd); \ | |
| 71b3fa15 DX |
529 | } while (0) |
| 530 | ||
| 531 | #define THR_LOCK(curthrd) THR_LOCK_ACQUIRE(curthrd, &(curthrd)->lock) | |
| 532 | #define THR_UNLOCK(curthrd) THR_LOCK_RELEASE(curthrd, &(curthrd)->lock) | |
| 533 | #define THR_THREAD_LOCK(curthrd, thr) THR_LOCK_ACQUIRE(curthrd, &(thr)->lock) | |
| 534 | #define THR_THREAD_UNLOCK(curthrd, thr) THR_LOCK_RELEASE(curthrd, &(thr)->lock) | |
| 535 | ||
| 536 | #define THREAD_LIST_LOCK(curthrd) \ | |
| 537 | do { \ | |
| 538 | THR_LOCK_ACQUIRE((curthrd), &_thr_list_lock); \ | |
| 539 | } while (0) | |
| 540 | ||
| 541 | #define THREAD_LIST_UNLOCK(curthrd) \ | |
| 542 | do { \ | |
| 543 | THR_LOCK_RELEASE((curthrd), &_thr_list_lock); \ | |
| 544 | } while (0) | |
| 545 | ||
| 546 | /* | |
| 547 | * Macros to insert/remove threads to the all thread list and | |
| 548 | * the gc list. | |
| 549 | */ | |
| 550 | #define THR_LIST_ADD(thrd) do { \ | |
| 551 | if (((thrd)->tlflags & TLFLAGS_IN_TDLIST) == 0) { \ | |
| 552 | TAILQ_INSERT_HEAD(&_thread_list, thrd, tle); \ | |
| 553 | _thr_hash_add(thrd); \ | |
| 554 | (thrd)->tlflags |= TLFLAGS_IN_TDLIST; \ | |
| 555 | } \ | |
| 556 | } while (0) | |
| 557 | #define THR_LIST_REMOVE(thrd) do { \ | |
| 558 | if (((thrd)->tlflags & TLFLAGS_IN_TDLIST) != 0) { \ | |
| 559 | TAILQ_REMOVE(&_thread_list, thrd, tle); \ | |
| 560 | _thr_hash_remove(thrd); \ | |
| 561 | (thrd)->tlflags &= ~TLFLAGS_IN_TDLIST; \ | |
| 562 | } \ | |
| 563 | } while (0) | |
| 564 | #define THR_GCLIST_ADD(thrd) do { \ | |
| 565 | if (((thrd)->tlflags & TLFLAGS_IN_GCLIST) == 0) { \ | |
| 566 | TAILQ_INSERT_HEAD(&_thread_gc_list, thrd, gcle);\ | |
| 567 | (thrd)->tlflags |= TLFLAGS_IN_GCLIST; \ | |
| e8382b15 | 568 | _thr_gc_count++; \ |
| 71b3fa15 DX |
569 | } \ |
| 570 | } while (0) | |
| 571 | #define THR_GCLIST_REMOVE(thrd) do { \ | |
| 572 | if (((thrd)->tlflags & TLFLAGS_IN_GCLIST) != 0) { \ | |
| 573 | TAILQ_REMOVE(&_thread_gc_list, thrd, gcle); \ | |
| 574 | (thrd)->tlflags &= ~TLFLAGS_IN_GCLIST; \ | |
| e8382b15 | 575 | _thr_gc_count--; \ |
| 71b3fa15 DX |
576 | } \ |
| 577 | } while (0) | |
| 578 | ||
| e8382b15 | 579 | #define GC_NEEDED() (_thr_gc_count >= 5) |
| 71b3fa15 DX |
580 | |
| 581 | #define THR_IN_SYNCQ(thrd) (((thrd)->sflags & THR_FLAGS_IN_SYNCQ) != 0) | |
| 582 | ||
| 3cd47da3 DX |
583 | #define SHOULD_REPORT_EVENT(curthr, e) \ |
| 584 | (curthr->report_events && \ | |
| 585 | (((curthr)->event_mask | _thread_event_mask ) & e) != 0) | |
| 586 | ||
| 71b3fa15 DX |
587 | extern int __isthreaded; |
| 588 | ||
| 589 | /* | |
| e8382b15 | 590 | * Global variables for the pthread library. |
| 71b3fa15 | 591 | */ |
| fc71f871 | 592 | extern char *_usrstack; |
| e8382b15 DX |
593 | extern struct pthread *_thr_initial; |
| 594 | extern int _thread_scope_system; | |
| 3cd47da3 | 595 | |
| 71b3fa15 | 596 | /* For debugger */ |
| e8382b15 DX |
597 | extern int _libthread_xu_debug; |
| 598 | extern int _thread_event_mask; | |
| 599 | extern struct pthread *_thread_last_event; | |
| 600 | ||
| 601 | /* List of all threads */ | |
| 602 | extern struct thread_head _thread_list; | |
| 603 | ||
| 604 | /* List of threads needing GC */ | |
| 605 | extern struct thread_head _thread_gc_list; | |
| 606 | ||
| 607 | extern int _thread_active_threads; | |
| 608 | ||
| 609 | extern struct atfork_head _thr_atfork_list; | |
| 610 | extern umtx_t _thr_atfork_lock; | |
| 611 | ||
| 612 | /* Default thread attributes */ | |
| 613 | extern struct pthread_attr _pthread_attr_default; | |
| 614 | ||
| 615 | /* Default mutex attributes */ | |
| 616 | extern struct pthread_mutex_attr _pthread_mutexattr_default; | |
| 617 | ||
| 618 | /* Default condition variable attributes */ | |
| 619 | extern struct pthread_cond_attr _pthread_condattr_default; | |
| 620 | ||
| 621 | extern pid_t _thr_pid; | |
| fc71f871 DX |
622 | extern size_t _thr_guard_default; |
| 623 | extern size_t _thr_stack_default; | |
| 624 | extern size_t _thr_stack_initial; | |
| e8382b15 DX |
625 | extern int _thr_page_size; |
| 626 | extern int _thr_gc_count; | |
| 627 | ||
| 628 | extern umtx_t _mutex_static_lock; | |
| 629 | extern umtx_t _cond_static_lock; | |
| 630 | extern umtx_t _rwlock_static_lock; | |
| 631 | extern umtx_t _keytable_lock; | |
| 632 | extern umtx_t _thr_list_lock; | |
| 633 | extern umtx_t _thr_event_lock; | |
| 71b3fa15 DX |
634 | |
| 635 | /* | |
| 636 | * Function prototype definitions. | |
| 637 | */ | |
| 638 | __BEGIN_DECLS | |
| 639 | int _thr_setthreaded(int); | |
| a8851a0f DX |
640 | int _mutex_cv_lock(pthread_mutex_t *, int count); |
| 641 | int _mutex_cv_unlock(pthread_mutex_t *, int *count); | |
| 71b3fa15 DX |
642 | void _mutex_notify_priochange(struct pthread *, struct pthread *, int); |
| 643 | int _mutex_reinit(pthread_mutex_t *); | |
| 644 | void _mutex_fork(struct pthread *curthread); | |
| 645 | void _mutex_unlock_private(struct pthread *); | |
| 646 | void _libpthread_init(struct pthread *); | |
| 71b3fa15 | 647 | struct pthread *_thr_alloc(struct pthread *); |
| fc71f871 | 648 | void _thread_exit(const char *, int, const char *) __dead2; |
| 71b3fa15 DX |
649 | void _thr_exit_cleanup(void); |
| 650 | int _thr_ref_add(struct pthread *, struct pthread *, int); | |
| 651 | void _thr_ref_delete(struct pthread *, struct pthread *); | |
| c9ad2203 | 652 | void _thr_ref_delete_unlocked(struct pthread *, struct pthread *); |
| 71b3fa15 DX |
653 | int _thr_find_thread(struct pthread *, struct pthread *, int); |
| 654 | void _thr_rtld_init(void); | |
| 655 | void _thr_rtld_fini(void); | |
| 656 | int _thr_stack_alloc(struct pthread_attr *); | |
| 657 | void _thr_stack_free(struct pthread_attr *); | |
| 658 | void _thr_free(struct pthread *, struct pthread *); | |
| 659 | void _thr_gc(struct pthread *); | |
| 660 | void _thread_cleanupspecific(void); | |
| 661 | void _thread_dump_info(void); | |
| 662 | void _thread_printf(int, const char *, ...); | |
| 663 | void _thr_spinlock_init(void); | |
| 664 | int _thr_cancel_enter(struct pthread *); | |
| 665 | void _thr_cancel_leave(struct pthread *, int); | |
| 666 | void _thr_signal_block(struct pthread *); | |
| 667 | void _thr_signal_unblock(struct pthread *); | |
| 668 | void _thr_signal_init(void); | |
| 669 | void _thr_signal_deinit(void); | |
| 670 | int _thr_send_sig(struct pthread *, int sig); | |
| fc71f871 | 671 | void _thr_list_init(void); |
| 71b3fa15 DX |
672 | void _thr_hash_add(struct pthread *); |
| 673 | void _thr_hash_remove(struct pthread *); | |
| 674 | struct pthread *_thr_hash_find(struct pthread *); | |
| 675 | void _thr_link(struct pthread *curthread, struct pthread *thread); | |
| 676 | void _thr_unlink(struct pthread *curthread, struct pthread *thread); | |
| 677 | void _thr_suspend_check(struct pthread *curthread); | |
| fc71f871 | 678 | void _thr_assert_lock_level(void) __dead2; |
| fd4288bd | 679 | void _thr_ast(struct pthread *); |
| 71b3fa15 | 680 | int _thr_get_tid(void); |
| 3cd47da3 DX |
681 | void _thr_report_creation(struct pthread *curthread, |
| 682 | struct pthread *newthread); | |
| 683 | void _thr_report_death(struct pthread *curthread); | |
| 684 | void _thread_bp_create(void); | |
| 685 | void _thread_bp_death(void); | |
| a31d0705 MD |
686 | int _thr_getscheduler(lwpid_t, int *, struct sched_param *); |
| 687 | int _thr_setscheduler(lwpid_t, int, const struct sched_param *); | |
| 688 | int _thr_set_sched_other_prio(struct pthread *, int); | |
| ec7c2f67 MD |
689 | int _umtx_sleep_err(volatile const int *, int, int); |
| 690 | int _umtx_wakeup_err(volatile const int *, int); | |
| 71b3fa15 | 691 | |
| 71b3fa15 DX |
692 | /* #include <sys/aio.h> */ |
| 693 | #ifdef _SYS_AIO_H_ | |
| 694 | int __sys_aio_suspend(const struct aiocb * const[], int, const struct timespec *); | |
| 695 | #endif | |
| 696 | ||
| 697 | /* #include <fcntl.h> */ | |
| 698 | #ifdef _SYS_FCNTL_H_ | |
| 699 | int __sys_fcntl(int, int, ...); | |
| 700 | int __sys_open(const char *, int, ...); | |
| 701 | #endif | |
| 702 | ||
| 703 | /* #include <sys/ioctl.h> */ | |
| 704 | #ifdef _SYS_IOCTL_H_ | |
| 705 | int __sys_ioctl(int, unsigned long, ...); | |
| 706 | #endif | |
| 707 | ||
| 708 | /* #inclde <sched.h> */ | |
| 709 | #ifdef _SCHED_H_ | |
| 710 | int __sys_sched_yield(void); | |
| 711 | #endif | |
| 712 | ||
| 713 | /* #include <signal.h> */ | |
| 714 | #ifdef _SIGNAL_H_ | |
| 715 | int __sys_kill(pid_t, int); | |
| 716 | int __sys_sigaction(int, const struct sigaction *, struct sigaction *); | |
| 717 | int __sys_sigpending(sigset_t *); | |
| 718 | int __sys_sigprocmask(int, const sigset_t *, sigset_t *); | |
| 719 | int __sys_sigsuspend(const sigset_t *); | |
| 720 | int __sys_sigreturn(ucontext_t *); | |
| 721 | int __sys_sigaltstack(const struct sigaltstack *, struct sigaltstack *); | |
| 722 | #endif | |
| 723 | ||
| 724 | /* #include <sys/socket.h> */ | |
| 725 | #ifdef _SYS_SOCKET_H_ | |
| 726 | int __sys_accept(int, struct sockaddr *, socklen_t *); | |
| 727 | int __sys_connect(int, const struct sockaddr *, socklen_t); | |
| 728 | ssize_t __sys_recv(int, void *, size_t, int); | |
| 729 | ssize_t __sys_recvfrom(int, void *, size_t, int, struct sockaddr *, socklen_t *); | |
| 730 | ssize_t __sys_recvmsg(int, struct msghdr *, int); | |
| 731 | int __sys_sendfile(int, int, off_t, size_t, struct sf_hdtr *, | |
| 732 | off_t *, int); | |
| 733 | ssize_t __sys_sendmsg(int, const struct msghdr *, int); | |
| 734 | ssize_t __sys_sendto(int, const void *,size_t, int, const struct sockaddr *, socklen_t); | |
| 735 | #endif | |
| 736 | ||
| 737 | /* #include <sys/uio.h> */ | |
| 738 | #ifdef _SYS_UIO_H_ | |
| 739 | ssize_t __sys_readv(int, const struct iovec *, int); | |
| 740 | ssize_t __sys_writev(int, const struct iovec *, int); | |
| 741 | #endif | |
| 742 | ||
| 743 | /* #include <time.h> */ | |
| 744 | #ifdef _TIME_H_ | |
| 745 | int __sys_nanosleep(const struct timespec *, struct timespec *); | |
| 746 | #endif | |
| 747 | ||
| 748 | /* #include <unistd.h> */ | |
| 749 | #ifdef _UNISTD_H_ | |
| 750 | int __sys_close(int); | |
| 751 | int __sys_execve(const char *, char * const *, char * const *); | |
| 752 | int __sys_fork(void); | |
| 753 | int __sys_fsync(int); | |
| 754 | pid_t __sys_getpid(void); | |
| 755 | int __sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); | |
| 756 | ssize_t __sys_read(int, void *, size_t); | |
| 757 | ssize_t __sys_write(int, const void *, size_t); | |
| 758 | void __sys_exit(int); | |
| 759 | int __sys_sigwait(const sigset_t *, int *); | |
| 760 | int __sys_sigtimedwait(const sigset_t *, siginfo_t *, | |
| 761 | const struct timespec *); | |
| 762 | int __sys_sigwaitinfo(const sigset_t *set, siginfo_t *info); | |
| 763 | #endif | |
| 764 | ||
| 765 | /* #include <poll.h> */ | |
| 766 | #ifdef _SYS_POLL_H_ | |
| 767 | int __sys_poll(struct pollfd *, unsigned, int); | |
| 768 | #endif | |
| 769 | ||
| 770 | /* #include <sys/mman.h> */ | |
| 771 | #ifdef _SYS_MMAN_H_ | |
| 772 | int __sys_msync(void *, size_t, int); | |
| 773 | #endif | |
| 774 | ||
| 775 | static inline int | |
| 776 | _thr_isthreaded(void) | |
| 777 | { | |
| 778 | return (__isthreaded != 0); | |
| 779 | } | |
| 780 | ||
| 781 | static inline int | |
| 782 | _thr_is_inited(void) | |
| 783 | { | |
| 784 | return (_thr_initial != 0); | |
| 785 | } | |
| 786 | ||
| 787 | static inline void | |
| 788 | _thr_check_init(void) | |
| 789 | { | |
| 790 | if (_thr_initial == 0) | |
| 791 | _libpthread_init(0); | |
| 792 | } | |
| 793 | ||
| 794 | __END_DECLS | |
| 795 | ||
| 796 | #endif /* !_THR_PRIVATE_H */ |