1 /* $NetBSD: pthread.c,v 1.196 2026/05/05 12:27:25 yamt Exp $ */ 2 3 /*- 4 * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008, 2020 5 * The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Nathan J. Williams and Andrew Doran. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __RCSID("$NetBSD: pthread.c,v 1.196 2026/05/05 12:27:25 yamt Exp $"); 35 36 #define __EXPOSE_STACK 1 37 38 /* Need to use libc-private names for atomic operations. */ 39 #include "../../common/lib/libc/atomic/atomic_op_namespace.h" 40 41 #include <sys/param.h> 42 #include <sys/exec_elf.h> 43 #include <sys/mman.h> 44 #include <sys/lwp.h> 45 #include <sys/lwpctl.h> 46 #include <sys/resource.h> 47 #include <sys/sysctl.h> 48 #include <sys/tls.h> 49 #include <uvm/uvm_param.h> 50 51 #include <assert.h> 52 #include <dlfcn.h> 53 #include <err.h> 54 #include <errno.h> 55 #include <lwp.h> 56 #include <signal.h> 57 #include <stdatomic.h> 58 #include <stdio.h> 59 #include <stdlib.h> 60 #include <stddef.h> 61 #include <string.h> 62 #include <syslog.h> 63 #include <ucontext.h> 64 #include <unistd.h> 65 #include <sched.h> 66 67 #include "atexit.h" 68 #include "pthread.h" 69 #include "pthread_int.h" 70 #include "pthread_makelwp.h" 71 #include "reentrant.h" 72 73 #define atomic_load_relaxed(p) \ 74 atomic_load_explicit(p, memory_order_relaxed) 75 76 #define atomic_store_relaxed(p, v) \ 77 atomic_store_explicit(p, v, memory_order_relaxed) 78 79 #define atomic_store_release(p, v) \ 80 atomic_store_explicit(p, v, memory_order_release) 81 82 __BEGIN_DECLS 83 void _malloc_thread_cleanup(void) __weak; 84 __END_DECLS 85 86 pthread_rwlock_t pthread__alltree_lock = PTHREAD_RWLOCK_INITIALIZER; 87 static rb_tree_t pthread__alltree; 88 89 static signed int pthread__cmp(void *, const void *, const void *); 90 91 static const rb_tree_ops_t pthread__alltree_ops = { 92 .rbto_compare_nodes = pthread__cmp, 93 .rbto_compare_key = pthread__cmp, 94 .rbto_node_offset = offsetof(struct __pthread_st, pt_alltree), 95 .rbto_context = NULL 96 }; 97 98 static void pthread__create_tramp(void *); 99 static void pthread__initthread(pthread_t); 100 static void pthread__scrubthread(pthread_t, char *, int); 101 static void pthread__initmain(pthread_t *); 102 static void pthread__reap(pthread_t); 103 104 void pthread__init(void); 105 106 int pthread__started; 107 int __uselibcstub = 1; 108 pthread_mutex_t pthread__deadqueue_lock = PTHREAD_MUTEX_INITIALIZER; 109 pthread_queue_t pthread__deadqueue; 110 pthread_queue_t pthread__allqueue; /* only for ancient libpthread_dbg */ 111 112 static pthread_attr_t pthread_default_attr; 113 static lwpctl_t pthread__dummy_lwpctl = { .lc_curcpu = LWPCTL_CPU_NONE }; 114 115 enum { 116 DIAGASSERT_ABORT = 1<<0, 117 DIAGASSERT_STDERR = 1<<1, 118 DIAGASSERT_SYSLOG = 1<<2 119 }; 120 121 static int pthread__diagassert; 122 123 int pthread__concurrency; 124 int pthread__nspins; 125 size_t pthread__unpark_max = PTHREAD__UNPARK_MAX; 126 int pthread__dbg; /* set by libpthread_dbg if active */ 127 128 size_t pthread__stacksize; 129 size_t pthread__guardsize; 130 size_t pthread__pagesize; 131 static struct __pthread_st *pthread__main; 132 static size_t __pthread_st_size; 133 134 int _sys___sigprocmask14(int, const sigset_t *, sigset_t *); 135 136 __strong_alias(__libc_thr_self,pthread_self) 137 __strong_alias(__libc_thr_create,pthread_create) 138 __strong_alias(__libc_thr_detach,pthread_detach) 139 __strong_alias(__libc_thr_join,pthread_join) 140 __strong_alias(__libc_thr_exit,pthread_exit) 141 __strong_alias(__libc_thr_errno,pthread__errno) 142 __strong_alias(__libc_thr_setcancelstate,pthread_setcancelstate) 143 __strong_alias(__libc_thr_equal,pthread_equal) 144 __strong_alias(__libc_thr_init,pthread__init) 145 146 /* 147 * Static library kludge. Place a reference to a symbol any library 148 * file which does not already have a reference here. 149 */ 150 extern int pthread__cancel_stub_binder; 151 152 void *pthread__static_lib_binder[] = { 153 &pthread__cancel_stub_binder, 154 pthread_cond_init, 155 pthread_mutex_init, 156 pthread_rwlock_init, 157 pthread_barrier_init, 158 pthread_key_create, 159 pthread_setspecific, 160 }; 161 162 #define NHASHLOCK 64 163 164 static union hashlock { 165 pthread_mutex_t mutex; 166 char pad[64]; 167 } hashlocks[NHASHLOCK] __aligned(64); 168 169 static void 170 pthread__prefork(void) 171 { 172 pthread_mutex_lock(&pthread__deadqueue_lock); 173 } 174 175 static void 176 pthread__fork_parent(void) 177 { 178 pthread_mutex_unlock(&pthread__deadqueue_lock); 179 } 180 181 static void 182 pthread__fork_child(void) 183 { 184 struct __pthread_st *self = pthread__self(); 185 186 pthread_mutex_init(&pthread__deadqueue_lock, NULL); 187 188 /* lwpctl state is not copied across fork. */ 189 if (_lwp_ctl(LWPCTL_FEATURE_CURCPU, &self->pt_lwpctl)) { 190 err(EXIT_FAILURE, "_lwp_ctl"); 191 } 192 self->pt_lid = _lwp_self(); 193 } 194 195 /* 196 * This needs to be started by the library loading code, before main() 197 * gets to run, for various things that use the state of the initial thread 198 * to work properly (thread-specific data is an application-visible example; 199 * spinlock counts for mutexes is an internal example). 200 */ 201 void 202 pthread__init(void) 203 { 204 pthread_t first; 205 char *p; 206 int mib[2]; 207 unsigned int value; 208 ssize_t slen; 209 size_t len; 210 extern int __isthreaded; 211 212 /* 213 * Allocate pthread_keys descriptors before 214 * resetting __uselibcstub because otherwise 215 * malloc() will call pthread_keys_create() 216 * while pthread_keys descriptors are not 217 * yet allocated. 218 */ 219 pthread__main = pthread_tsd_init(&__pthread_st_size); 220 if (pthread__main == NULL) 221 err(EXIT_FAILURE, "Cannot allocate pthread storage"); 222 223 __uselibcstub = 0; 224 225 pthread__pagesize = (size_t)sysconf(_SC_PAGESIZE); 226 pthread__concurrency = (int)sysconf(_SC_NPROCESSORS_CONF); 227 228 mib[0] = CTL_VM; 229 mib[1] = VM_THREAD_GUARD_SIZE; 230 len = sizeof(value); 231 if (sysctl(mib, __arraycount(mib), &value, &len, NULL, 0) == 0) 232 pthread__guardsize = value; 233 else 234 pthread__guardsize = pthread__pagesize; 235 236 /* Initialize locks first; they're needed elsewhere. */ 237 pthread__lockprim_init(); 238 for (int i = 0; i < NHASHLOCK; i++) { 239 pthread_mutex_init(&hashlocks[i].mutex, NULL); 240 } 241 242 /* Fetch parameters. */ 243 slen = _lwp_unpark_all(NULL, 0, NULL); 244 if (slen < 0) 245 err(EXIT_FAILURE, "_lwp_unpark_all"); 246 if ((size_t)slen < pthread__unpark_max) 247 pthread__unpark_max = slen; 248 249 /* Basic data structure setup */ 250 pthread_attr_init(&pthread_default_attr); 251 PTQ_INIT(&pthread__allqueue); 252 PTQ_INIT(&pthread__deadqueue); 253 254 rb_tree_init(&pthread__alltree, &pthread__alltree_ops); 255 256 /* Create the thread structure corresponding to main() */ 257 pthread__initmain(&first); 258 pthread__initthread(first); 259 pthread__scrubthread(first, NULL, 0); 260 261 first->pt_lid = _lwp_self(); 262 PTQ_INSERT_HEAD(&pthread__allqueue, first, pt_allq); 263 (void)rb_tree_insert_node(&pthread__alltree, first); 264 265 if (_lwp_ctl(LWPCTL_FEATURE_CURCPU, &first->pt_lwpctl) != 0) { 266 err(EXIT_FAILURE, "_lwp_ctl"); 267 } 268 269 /* Start subsystems */ 270 PTHREAD_MD_INIT 271 272 for (p = pthread__getenv("PTHREAD_DIAGASSERT"); p && *p; p++) { 273 switch (*p) { 274 case 'a': 275 pthread__diagassert |= DIAGASSERT_ABORT; 276 break; 277 case 'A': 278 pthread__diagassert &= ~DIAGASSERT_ABORT; 279 break; 280 case 'e': 281 pthread__diagassert |= DIAGASSERT_STDERR; 282 break; 283 case 'E': 284 pthread__diagassert &= ~DIAGASSERT_STDERR; 285 break; 286 case 'l': 287 pthread__diagassert |= DIAGASSERT_SYSLOG; 288 break; 289 case 'L': 290 pthread__diagassert &= ~DIAGASSERT_SYSLOG; 291 break; 292 } 293 } 294 295 /* Tell libc that we're here and it should role-play accordingly. */ 296 pthread_atfork(pthread__prefork, pthread__fork_parent, pthread__fork_child); 297 __isthreaded = 1; 298 } 299 300 /* General-purpose thread data structure sanitization. */ 301 /* ARGSUSED */ 302 static void 303 pthread__initthread(pthread_t t) 304 { 305 306 t->pt_self = t; 307 t->pt_magic = PT_MAGIC; 308 t->pt_sleepobj = NULL; 309 t->pt_havespecific = 0; 310 t->pt_lwpctl = &pthread__dummy_lwpctl; 311 312 memcpy(&t->pt_lockops, pthread__lock_ops, sizeof(t->pt_lockops)); 313 pthread_mutex_init(&t->pt_lock, NULL); 314 PTQ_INIT(&t->pt_cleanup_stack); 315 } 316 317 static void 318 pthread__scrubthread(pthread_t t, char *name, int flags) 319 { 320 321 t->pt_state = PT_STATE_RUNNING; 322 t->pt_exitval = NULL; 323 t->pt_flags = flags; 324 t->pt_cancel = 0; 325 t->pt_errno = 0; 326 t->pt_name = name; 327 t->pt_lid = 0; 328 } 329 330 static int 331 pthread__getstack(pthread_t newthread, const pthread_attr_t *attr) 332 { 333 void *stackbase, *stackbase2, *redzone; 334 size_t stacksize, guardsize; 335 bool allocated; 336 337 if (attr != NULL) { 338 pthread_attr_getstack(attr, &stackbase, &stacksize); 339 if (stackbase == NULL) 340 pthread_attr_getguardsize(attr, &guardsize); 341 else 342 guardsize = 0; 343 } else { 344 stackbase = NULL; 345 stacksize = 0; 346 guardsize = pthread__guardsize; 347 } 348 if (stacksize == 0) 349 stacksize = pthread__stacksize; 350 351 if (newthread->pt_stack_allocated) { 352 if (stackbase == NULL && 353 newthread->pt_stack.ss_size == stacksize && 354 newthread->pt_guardsize == guardsize) 355 return 0; 356 stackbase2 = newthread->pt_stack.ss_sp; 357 #ifndef __MACHINE_STACK_GROWS_UP 358 stackbase2 = (char *)stackbase2 - newthread->pt_guardsize; 359 #endif 360 munmap(stackbase2, 361 newthread->pt_stack.ss_size + newthread->pt_guardsize); 362 newthread->pt_stack.ss_sp = NULL; 363 newthread->pt_stack.ss_size = 0; 364 newthread->pt_guardsize = 0; 365 newthread->pt_stack_allocated = false; 366 } 367 368 if (stackbase == NULL) { 369 stacksize = ((stacksize - 1) | (pthread__pagesize - 1)) + 1; 370 guardsize = ((guardsize - 1) | (pthread__pagesize - 1)) + 1; 371 stackbase = mmap(NULL, stacksize + guardsize, 372 PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, (off_t)0); 373 if (stackbase == MAP_FAILED) 374 return ENOMEM; 375 allocated = true; 376 } else { 377 allocated = false; 378 } 379 #ifdef __MACHINE_STACK_GROWS_UP 380 redzone = (char *)stackbase + stacksize; 381 stackbase2 = (char *)stackbase; 382 #else 383 redzone = (char *)stackbase; 384 stackbase2 = (char *)stackbase + guardsize; 385 #endif 386 if (allocated && guardsize && 387 mprotect(redzone, guardsize, PROT_NONE) == -1) { 388 munmap(stackbase, stacksize + guardsize); 389 return EPERM; 390 } 391 newthread->pt_stack.ss_size = stacksize; 392 newthread->pt_stack.ss_sp = stackbase2; 393 newthread->pt_guardsize = guardsize; 394 newthread->pt_stack_allocated = allocated; 395 return 0; 396 } 397 398 int 399 pthread_create(pthread_t *thread, const pthread_attr_t *attr, 400 void *(*startfunc)(void *), void *arg) 401 { 402 pthread_t newthread; 403 pthread_attr_t nattr; 404 struct pthread_attr_private *p; 405 char * volatile name; 406 unsigned long flag; 407 void *private_area; 408 int ret; 409 410 if (__predict_false(__uselibcstub)) { 411 pthread__errorfunc(__FILE__, __LINE__, __func__, 412 "pthread_create() requires linking with -lpthread"); 413 return __libc_thr_create_stub(thread, attr, startfunc, arg); 414 } 415 416 if (attr == NULL) 417 nattr = pthread_default_attr; 418 else if (attr->pta_magic == PT_ATTR_MAGIC) 419 nattr = *attr; 420 else 421 return EINVAL; 422 423 if (!pthread__started) { 424 /* 425 * Force the _lwp_park symbol to be resolved before we 426 * begin any activity that might rely on concurrent 427 * wakeups. 428 * 429 * This is necessary because rtld itself uses _lwp_park 430 * and _lwp_unpark internally for its own locking: If 431 * we wait to resolve _lwp_park until there is an 432 * _lwp_unpark from another thread pending in the 433 * current lwp (for example, pthread_mutex_unlock or 434 * pthread_cond_signal), rtld's internal use of 435 * _lwp_park might consume the pending unpark. The 436 * result is a deadlock where libpthread and rtld have 437 * both correctly used _lwp_park and _lwp_unpark for 438 * themselves, but rtld has consumed the wakeup meant 439 * for libpthread so it is lost to libpthread. 440 * 441 * For the very first thread, before pthread__started 442 * is set to true, pthread__self()->pt_lid should have 443 * been initialized in pthread__init by the time we get 444 * here to the correct lid so we go to sleep and wake 445 * ourselves at the same time as a no-op. 446 */ 447 _lwp_park(CLOCK_REALTIME, 0, NULL, pthread__self()->pt_lid, 448 NULL, NULL); 449 } 450 451 pthread__started = 1; 452 453 /* Fetch misc. attributes from the attr structure. */ 454 name = NULL; 455 if ((p = nattr.pta_private) != NULL) 456 if (p->ptap_name[0] != '\0') 457 if ((name = strdup(p->ptap_name)) == NULL) 458 return ENOMEM; 459 460 newthread = NULL; 461 462 /* 463 * Try to reclaim a dead thread. 464 */ 465 if (!PTQ_EMPTY(&pthread__deadqueue)) { 466 pthread_mutex_lock(&pthread__deadqueue_lock); 467 PTQ_FOREACH(newthread, &pthread__deadqueue, pt_deadq) { 468 /* Still running? */ 469 if (_lwp_kill(newthread->pt_lid, 0) == -1 && 470 errno == ESRCH) 471 break; 472 } 473 if (newthread) 474 PTQ_REMOVE(&pthread__deadqueue, newthread, pt_deadq); 475 pthread_mutex_unlock(&pthread__deadqueue_lock); 476 if (newthread) { 477 newthread->pt_is_main = false; 478 #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) 479 if (newthread->pt_tls) { 480 _rtld_tls_free(newthread->pt_tls); 481 newthread->pt_tls = NULL; 482 } 483 #endif 484 } 485 } 486 487 /* 488 * If necessary set up a stack, allocate space for a pthread_st, 489 * and initialize it. 490 */ 491 if (newthread == NULL) { 492 newthread = calloc(1, __pthread_st_size); 493 if (newthread == NULL) { 494 free(name); 495 return ENOMEM; 496 } 497 newthread->pt_stack_allocated = false; 498 499 if (pthread__getstack(newthread, attr)) { 500 free(newthread); 501 free(name); 502 return ENOMEM; 503 } 504 505 #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) 506 newthread->pt_tls = NULL; 507 #endif 508 509 /* Add to list of all threads. */ 510 pthread_rwlock_wrlock(&pthread__alltree_lock); 511 PTQ_INSERT_TAIL(&pthread__allqueue, newthread, pt_allq); 512 (void)rb_tree_insert_node(&pthread__alltree, newthread); 513 pthread_rwlock_unlock(&pthread__alltree_lock); 514 515 /* Will be reset by the thread upon exit. */ 516 pthread__initthread(newthread); 517 } else { 518 if (pthread__getstack(newthread, attr)) { 519 pthread_mutex_lock(&pthread__deadqueue_lock); 520 PTQ_INSERT_TAIL(&pthread__deadqueue, newthread, pt_deadq); 521 pthread_mutex_unlock(&pthread__deadqueue_lock); 522 return ENOMEM; 523 } 524 } 525 526 /* 527 * Create the new LWP. 528 */ 529 pthread__scrubthread(newthread, name, nattr.pta_flags); 530 newthread->pt_func = startfunc; 531 newthread->pt_arg = arg; 532 #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) 533 private_area = newthread->pt_tls = _rtld_tls_allocate(); 534 newthread->pt_tls->tcb_pthread = newthread; 535 #else 536 private_area = newthread; 537 #endif 538 539 flag = 0; 540 if ((newthread->pt_flags & PT_FLAG_SUSPENDED) != 0 || 541 (nattr.pta_flags & PT_FLAG_EXPLICIT_SCHED) != 0) 542 flag |= LWP_SUSPENDED; 543 if ((newthread->pt_flags & PT_FLAG_DETACHED) != 0) 544 flag |= LWP_DETACHED; 545 546 ret = pthread__makelwp(pthread__create_tramp, newthread, private_area, 547 newthread->pt_stack.ss_sp, newthread->pt_stack.ss_size, 548 flag, &newthread->pt_lid); 549 if (ret != 0) { 550 ret = errno; 551 pthread_mutex_lock(&newthread->pt_lock); 552 /* Will unlock and free name. */ 553 pthread__reap(newthread); 554 return ret; 555 } 556 557 if ((nattr.pta_flags & PT_FLAG_EXPLICIT_SCHED) != 0) { 558 if (p != NULL) { 559 (void)pthread_setschedparam(newthread, p->ptap_policy, 560 &p->ptap_sp); 561 } 562 if ((newthread->pt_flags & PT_FLAG_SUSPENDED) == 0) { 563 (void)_lwp_continue(newthread->pt_lid); 564 } 565 } 566 567 *thread = newthread; 568 569 return 0; 570 } 571 572 573 __dead static void 574 pthread__create_tramp(void *cookie) 575 { 576 pthread_t self; 577 void *retval; 578 void *junk __unused; 579 580 self = cookie; 581 582 /* 583 * Throw away some stack in a feeble attempt to reduce cache 584 * thrash. May help for SMT processors. XXX We should not 585 * be allocating stacks on fixed 2MB boundaries. Needs a 586 * thread register or decent thread local storage. 587 */ 588 junk = alloca(((unsigned)self->pt_lid & 7) << 8); 589 590 if (self->pt_name != NULL) { 591 pthread_mutex_lock(&self->pt_lock); 592 if (self->pt_name != NULL) 593 (void)_lwp_setname(0, self->pt_name); 594 pthread_mutex_unlock(&self->pt_lock); 595 } 596 597 if (_lwp_ctl(LWPCTL_FEATURE_CURCPU, &self->pt_lwpctl)) { 598 err(EXIT_FAILURE, "_lwp_ctl"); 599 } 600 601 retval = (*self->pt_func)(self->pt_arg); 602 603 pthread_exit(retval); 604 605 /*NOTREACHED*/ 606 pthread__abort(); 607 } 608 609 int 610 pthread_suspend_np(pthread_t thread) 611 { 612 pthread_t self; 613 614 pthread__error(EINVAL, "Invalid thread", 615 thread->pt_magic == PT_MAGIC); 616 617 self = pthread__self(); 618 if (self == thread) { 619 return EDEADLK; 620 } 621 if (pthread__find(thread) != 0) 622 return ESRCH; 623 if (_lwp_suspend(thread->pt_lid) == 0) 624 return 0; 625 return errno; 626 } 627 628 int 629 pthread_resume_np(pthread_t thread) 630 { 631 632 pthread__error(EINVAL, "Invalid thread", 633 thread->pt_magic == PT_MAGIC); 634 635 if (pthread__find(thread) != 0) 636 return ESRCH; 637 if (_lwp_continue(thread->pt_lid) == 0) 638 return 0; 639 return errno; 640 } 641 642 void 643 pthread_exit(void *retval) 644 { 645 pthread_t self; 646 struct pt_clean_t *cleanup; 647 648 if (__predict_false(__uselibcstub)) { 649 __libc_thr_exit_stub(retval); 650 goto out; 651 } 652 653 self = pthread__self(); 654 655 /* Disable cancellability. */ 656 atomic_store_relaxed(&self->pt_cancel, PT_CANCEL_DISABLED); 657 658 /* Call any cancellation cleanup handlers */ 659 if (!PTQ_EMPTY(&self->pt_cleanup_stack)) { 660 while (!PTQ_EMPTY(&self->pt_cleanup_stack)) { 661 cleanup = PTQ_FIRST(&self->pt_cleanup_stack); 662 PTQ_REMOVE(&self->pt_cleanup_stack, cleanup, ptc_next); 663 (*cleanup->ptc_cleanup)(cleanup->ptc_arg); 664 } 665 } 666 667 __cxa_thread_run_atexit(); 668 669 /* Perform cleanup of thread-specific data */ 670 pthread__destroy_tsd(self); 671 672 if (_malloc_thread_cleanup) 673 _malloc_thread_cleanup(); 674 675 /* 676 * Signal our exit. Our stack and pthread_t won't be reused until 677 * pthread_create() can see from kernel info that this LWP is gone. 678 */ 679 pthread_mutex_lock(&self->pt_lock); 680 self->pt_exitval = retval; 681 if (self->pt_flags & PT_FLAG_DETACHED) { 682 /* pthread__reap() will drop the lock. */ 683 pthread__reap(self); 684 _lwp_exit(); 685 } else { 686 self->pt_state = PT_STATE_ZOMBIE; 687 pthread_mutex_unlock(&self->pt_lock); 688 /* Note: name will be freed by the joiner. */ 689 _lwp_exit(); 690 } 691 692 out: 693 /*NOTREACHED*/ 694 pthread__abort(); 695 exit(1); 696 } 697 698 699 int 700 pthread_join(pthread_t thread, void **valptr) 701 { 702 pthread_t self; 703 704 pthread__error(EINVAL, "Invalid thread", 705 thread->pt_magic == PT_MAGIC); 706 707 self = pthread__self(); 708 709 if (pthread__find(thread) != 0) 710 return ESRCH; 711 712 if (thread == self) 713 return EDEADLK; 714 715 /* IEEE Std 1003.1 says pthread_join() never returns EINTR. */ 716 for (;;) { 717 pthread__testcancel(self); 718 if (_lwp_wait(thread->pt_lid, NULL) == 0) 719 break; 720 if (errno != EINTR) 721 return errno; 722 } 723 724 /* 725 * Don't test for cancellation again. The spec is that if 726 * cancelled, pthread_join() must not have succeeded. 727 */ 728 pthread_mutex_lock(&thread->pt_lock); 729 if (thread->pt_state != PT_STATE_ZOMBIE) { 730 pthread__errorfunc(__FILE__, __LINE__, __func__, 731 "not a zombie"); 732 } 733 if (valptr != NULL) 734 *valptr = thread->pt_exitval; 735 736 /* pthread__reap() will drop the lock. */ 737 pthread__reap(thread); 738 return 0; 739 } 740 741 static void 742 pthread__reap(pthread_t thread) 743 { 744 char *name; 745 746 name = thread->pt_name; 747 thread->pt_name = NULL; 748 thread->pt_state = PT_STATE_DEAD; 749 pthread_mutex_unlock(&thread->pt_lock); 750 751 pthread_mutex_lock(&pthread__deadqueue_lock); 752 PTQ_INSERT_HEAD(&pthread__deadqueue, thread, pt_deadq); 753 pthread_mutex_unlock(&pthread__deadqueue_lock); 754 755 if (name != NULL) 756 free(name); 757 } 758 759 int 760 pthread_equal(pthread_t t1, pthread_t t2) 761 { 762 763 if (__predict_false(__uselibcstub)) 764 return __libc_thr_equal_stub(t1, t2); 765 766 pthread__error(0, "Invalid thread", 767 (t1 != NULL) && (t1->pt_magic == PT_MAGIC)); 768 769 pthread__error(0, "Invalid thread", 770 (t2 != NULL) && (t2->pt_magic == PT_MAGIC)); 771 772 /* Nothing special here. */ 773 return (t1 == t2); 774 } 775 776 777 int 778 pthread_detach(pthread_t thread) 779 { 780 int error; 781 782 pthread__error(EINVAL, "Invalid thread", 783 thread->pt_magic == PT_MAGIC); 784 785 if (pthread__find(thread) != 0) 786 return ESRCH; 787 788 pthread_mutex_lock(&thread->pt_lock); 789 if ((thread->pt_flags & PT_FLAG_DETACHED) != 0) { 790 error = EINVAL; 791 } else { 792 error = _lwp_detach(thread->pt_lid); 793 if (error == 0) 794 thread->pt_flags |= PT_FLAG_DETACHED; 795 else 796 error = errno; 797 } 798 if (thread->pt_state == PT_STATE_ZOMBIE) { 799 /* pthread__reap() will drop the lock. */ 800 pthread__reap(thread); 801 } else 802 pthread_mutex_unlock(&thread->pt_lock); 803 return error; 804 } 805 806 807 int 808 pthread_getname_np(pthread_t thread, char *name, size_t len) 809 { 810 811 pthread__error(EINVAL, "Invalid thread", 812 thread->pt_magic == PT_MAGIC); 813 814 if (pthread__find(thread) != 0) 815 return ESRCH; 816 817 pthread_mutex_lock(&thread->pt_lock); 818 if (thread->pt_name == NULL) 819 name[0] = '\0'; 820 else 821 strlcpy(name, thread->pt_name, len); 822 pthread_mutex_unlock(&thread->pt_lock); 823 824 return 0; 825 } 826 827 828 int 829 pthread_setname_np(pthread_t thread, const char *name, void *arg) 830 { 831 char *oldname, *cp, newname[PTHREAD_MAX_NAMELEN_NP]; 832 int namelen; 833 834 pthread__error(EINVAL, "Invalid thread", 835 thread->pt_magic == PT_MAGIC); 836 837 if (pthread__find(thread) != 0) 838 return ESRCH; 839 840 namelen = snprintf(newname, sizeof(newname), name, arg); 841 if (namelen >= PTHREAD_MAX_NAMELEN_NP) 842 return EINVAL; 843 844 cp = strdup(newname); 845 if (cp == NULL) 846 return ENOMEM; 847 848 pthread_mutex_lock(&thread->pt_lock); 849 oldname = thread->pt_name; 850 thread->pt_name = cp; 851 (void)_lwp_setname(thread->pt_lid, cp); 852 pthread_mutex_unlock(&thread->pt_lock); 853 854 if (oldname != NULL) 855 free(oldname); 856 857 return 0; 858 } 859 860 861 pthread_t 862 pthread_self(void) 863 { 864 if (__predict_false(__uselibcstub)) 865 return (pthread_t)__libc_thr_self_stub(); 866 867 return pthread__self(); 868 } 869 870 871 int 872 pthread_cancel(pthread_t thread) 873 { 874 unsigned old, new; 875 bool wake; 876 877 pthread__error(EINVAL, "Invalid thread", 878 thread->pt_magic == PT_MAGIC); 879 880 if (pthread__find(thread) != 0) 881 return ESRCH; 882 883 /* 884 * membar_release matches membar_acquire in 885 * pthread_setcancelstate and pthread__testcancel. 886 */ 887 membar_release(); 888 889 do { 890 old = atomic_load_relaxed(&thread->pt_cancel); 891 new = old | PT_CANCEL_PENDING; 892 wake = false; 893 if ((old & PT_CANCEL_DISABLED) == 0) { 894 new |= PT_CANCEL_CANCELLED; 895 wake = true; 896 } 897 } while (__predict_false(!atomic_compare_exchange_weak_explicit( 898 &thread->pt_cancel, &old, new, 899 memory_order_relaxed, memory_order_relaxed))); 900 901 if (wake) 902 _lwp_wakeup(thread->pt_lid); 903 904 return 0; 905 } 906 907 908 int 909 pthread_setcancelstate(int state, int *oldstate) 910 { 911 pthread_t self; 912 unsigned flags, old, new; 913 bool cancelled; 914 915 if (__predict_false(__uselibcstub)) 916 return __libc_thr_setcancelstate_stub(state, oldstate); 917 918 self = pthread__self(); 919 920 switch (state) { 921 case PTHREAD_CANCEL_ENABLE: 922 flags = 0; 923 break; 924 case PTHREAD_CANCEL_DISABLE: 925 flags = PT_CANCEL_DISABLED; 926 break; 927 default: 928 return EINVAL; 929 } 930 931 do { 932 old = atomic_load_relaxed(&self->pt_cancel); 933 new = (old & ~PT_CANCEL_DISABLED) | flags; 934 /* 935 * If we disable while cancelled, switch back to 936 * pending so future cancellation tests will not fire 937 * until enabled again. 938 * 939 * If a cancellation was requested while cancellation 940 * was disabled, note that fact for future 941 * cancellation tests. 942 */ 943 cancelled = false; 944 if (__predict_false((flags | (old & PT_CANCEL_CANCELLED)) == 945 (PT_CANCEL_DISABLED|PT_CANCEL_CANCELLED))) { 946 new &= ~PT_CANCEL_CANCELLED; 947 new |= PT_CANCEL_PENDING; 948 } else if (__predict_false((flags | 949 (old & PT_CANCEL_PENDING)) == 950 PT_CANCEL_PENDING)) { 951 new |= PT_CANCEL_CANCELLED; 952 /* This is not a deferred cancellation point. */ 953 if (__predict_false(old & PT_CANCEL_ASYNC)) 954 cancelled = true; 955 } 956 } while (__predict_false(!atomic_compare_exchange_weak_explicit( 957 &self->pt_cancel, &old, new, 958 memory_order_relaxed, memory_order_relaxed))); 959 960 /* 961 * If we transitioned from PTHREAD_CANCEL_DISABLED to 962 * PTHREAD_CANCEL_ENABLED, there was a pending cancel, and we 963 * are configured with asynchronous cancellation, we are now 964 * cancelled -- make it happen. 965 */ 966 if (__predict_false(cancelled)) { 967 /* 968 * membar_acquire matches membar_release in 969 * pthread_cancel. 970 */ 971 membar_acquire(); 972 pthread__cancelled(); 973 } 974 975 if (oldstate) { 976 if (old & PT_CANCEL_DISABLED) 977 *oldstate = PTHREAD_CANCEL_DISABLE; 978 else 979 *oldstate = PTHREAD_CANCEL_ENABLE; 980 } 981 982 return 0; 983 } 984 985 986 int 987 pthread_setcanceltype(int type, int *oldtype) 988 { 989 pthread_t self; 990 unsigned flags, old, new; 991 bool cancelled; 992 993 self = pthread__self(); 994 995 switch (type) { 996 case PTHREAD_CANCEL_DEFERRED: 997 flags = 0; 998 break; 999 case PTHREAD_CANCEL_ASYNCHRONOUS: 1000 flags = PT_CANCEL_ASYNC; 1001 break; 1002 default: 1003 return EINVAL; 1004 } 1005 1006 do { 1007 old = atomic_load_relaxed(&self->pt_cancel); 1008 new = (old & ~PT_CANCEL_ASYNC) | flags; 1009 cancelled = false; 1010 if (__predict_false((flags | (old & PT_CANCEL_CANCELLED)) == 1011 (PT_CANCEL_ASYNC|PT_CANCEL_CANCELLED))) 1012 cancelled = true; 1013 } while (__predict_false(!atomic_compare_exchange_weak_explicit( 1014 &self->pt_cancel, &old, new, 1015 memory_order_relaxed, memory_order_relaxed))); 1016 1017 if (__predict_false(cancelled)) { 1018 membar_acquire(); 1019 pthread__cancelled(); 1020 } 1021 1022 if (oldtype != NULL) { 1023 if (old & PT_CANCEL_ASYNC) 1024 *oldtype = PTHREAD_CANCEL_ASYNCHRONOUS; 1025 else 1026 *oldtype = PTHREAD_CANCEL_DEFERRED; 1027 } 1028 1029 return 0; 1030 } 1031 1032 1033 void 1034 pthread_testcancel(void) 1035 { 1036 pthread_t self; 1037 1038 self = pthread__self(); 1039 1040 pthread__testcancel(self); 1041 } 1042 1043 1044 /* 1045 * POSIX requires that certain functions return an error rather than 1046 * invoking undefined behavior even when handed completely bogus 1047 * pthread_t values, e.g. stack garbage. 1048 */ 1049 int 1050 pthread__find(pthread_t id) 1051 { 1052 pthread_t target; 1053 int error; 1054 1055 pthread_rwlock_rdlock(&pthread__alltree_lock); 1056 target = rb_tree_find_node(&pthread__alltree, id); 1057 error = (target && target->pt_state != PT_STATE_DEAD) ? 0 : ESRCH; 1058 pthread_rwlock_unlock(&pthread__alltree_lock); 1059 1060 return error; 1061 } 1062 1063 1064 void 1065 pthread__testcancel(pthread_t self) 1066 { 1067 1068 /* 1069 * We use atomic_load_relaxed and then a conditional 1070 * membar_acquire, rather than atomic_load_acquire, in order to 1071 * avoid incurring the cost of an acquire barrier in the common 1072 * case of not having been cancelled. 1073 * 1074 * membar_acquire matches membar_release in pthread_cancel. 1075 */ 1076 if (__predict_false(atomic_load_relaxed(&self->pt_cancel) & 1077 PT_CANCEL_CANCELLED)) { 1078 membar_acquire(); 1079 pthread__cancelled(); 1080 } 1081 } 1082 1083 1084 void 1085 pthread__cancelled(void) 1086 { 1087 1088 pthread_exit(PTHREAD_CANCELED); 1089 } 1090 1091 1092 void 1093 pthread__cleanup_push(void (*cleanup)(void *), void *arg, void *store) 1094 { 1095 pthread_t self; 1096 struct pt_clean_t *entry; 1097 1098 self = pthread__self(); 1099 entry = store; 1100 entry->ptc_cleanup = cleanup; 1101 entry->ptc_arg = arg; 1102 PTQ_INSERT_HEAD(&self->pt_cleanup_stack, entry, ptc_next); 1103 } 1104 1105 1106 void 1107 pthread__cleanup_pop(int ex, void *store) 1108 { 1109 pthread_t self; 1110 struct pt_clean_t *entry; 1111 1112 self = pthread__self(); 1113 entry = store; 1114 1115 PTQ_REMOVE(&self->pt_cleanup_stack, entry, ptc_next); 1116 if (ex) 1117 (*entry->ptc_cleanup)(entry->ptc_arg); 1118 } 1119 1120 1121 int * 1122 pthread__errno(void) 1123 { 1124 pthread_t self; 1125 1126 if (__predict_false(__uselibcstub)) { 1127 pthread__errorfunc(__FILE__, __LINE__, __func__, 1128 "pthread__errno() requires linking with -lpthread"); 1129 return __libc_thr_errno_stub(); 1130 } 1131 1132 self = pthread__self(); 1133 1134 return &(self->pt_errno); 1135 } 1136 1137 ssize_t _sys_write(int, const void *, size_t); 1138 1139 void 1140 pthread__assertfunc(const char *file, int line, const char *function, 1141 const char *expr) 1142 { 1143 char buf[1024]; 1144 int len; 1145 1146 /* 1147 * snprintf_ss should not acquire any locks, or we could 1148 * end up deadlocked if the assert caller held locks. 1149 */ 1150 len = snprintf_ss(buf, 1024, 1151 "assertion \"%s\" failed: file \"%s\", line %d%s%s%s\n", 1152 expr, file, line, 1153 function ? ", function \"" : "", 1154 function ? function : "", 1155 function ? "\"" : ""); 1156 1157 _sys_write(STDERR_FILENO, buf, (size_t)len); 1158 (void)raise(SIGABRT); 1159 _exit(1); 1160 } 1161 1162 1163 void 1164 pthread__errorfunc(const char *file, int line, const char *function, 1165 const char *msg, ...) 1166 { 1167 char buf[1024]; 1168 char buf2[1024]; 1169 size_t len; 1170 va_list ap; 1171 1172 if (pthread__diagassert == 0) 1173 return; 1174 1175 va_start(ap, msg); 1176 vsnprintf_ss(buf2, sizeof(buf2), msg, ap); 1177 va_end(ap); 1178 1179 /* 1180 * snprintf_ss should not acquire any locks, or we could 1181 * end up deadlocked if the assert caller held locks. 1182 */ 1183 len = snprintf_ss(buf, sizeof(buf), 1184 "%s: Error detected by libpthread: %s.\n" 1185 "Detected by file \"%s\", line %d%s%s%s.\n" 1186 "See pthread(3) for information.\n", 1187 getprogname(), buf2, file, line, 1188 function ? ", function \"" : "", 1189 function ? function : "", 1190 function ? "\"" : ""); 1191 1192 if (pthread__diagassert & DIAGASSERT_STDERR) 1193 _sys_write(STDERR_FILENO, buf, len); 1194 1195 if (pthread__diagassert & DIAGASSERT_SYSLOG) 1196 syslog(LOG_DEBUG | LOG_USER, "%s", buf); 1197 1198 if (pthread__diagassert & DIAGASSERT_ABORT) { 1199 (void)raise(SIGABRT); 1200 _exit(1); 1201 } 1202 } 1203 1204 /* 1205 * Thread park/unpark operations. The kernel operations are 1206 * modelled after a brief description from "Multithreading in 1207 * the Solaris Operating Environment": 1208 * 1209 * http://www.sun.com/software/whitepapers/solaris9/multithread.pdf 1210 */ 1211 1212 int 1213 pthread__park(pthread_t self, pthread_mutex_t *lock, 1214 pthread_queue_t *queue, const struct timespec *abstime, 1215 int cancelpt) 1216 { 1217 int rv, error; 1218 1219 pthread_mutex_unlock(lock); 1220 1221 /* 1222 * Wait until we are awoken by a pending unpark operation, 1223 * a signal, an unpark posted after we have gone asleep, 1224 * or an expired timeout. 1225 * 1226 * It is fine to test the value of pt_sleepobj without 1227 * holding any locks, because: 1228 * 1229 * o Only the blocking thread (this thread) ever sets it 1230 * to a non-NULL value. 1231 * 1232 * o Other threads may set it NULL, but if they do so they 1233 * must also make this thread return from _lwp_park. 1234 * 1235 * o _lwp_park, _lwp_unpark and _lwp_unpark_all are system 1236 * calls and all make use of spinlocks in the kernel. So 1237 * these system calls act as full memory barriers. 1238 */ 1239 rv = 0; 1240 do { 1241 /* 1242 * If we deferred unparking a thread, arrange to 1243 * have _lwp_park() restart it before blocking. 1244 */ 1245 error = _lwp_park(CLOCK_REALTIME, TIMER_ABSTIME, 1246 __UNCONST(abstime), 0, NULL, NULL); 1247 if (error != 0) { 1248 switch (rv = errno) { 1249 case EINTR: 1250 case EALREADY: 1251 rv = 0; 1252 break; 1253 case ETIMEDOUT: 1254 break; 1255 default: 1256 pthread__errorfunc(__FILE__, __LINE__, 1257 __func__, "_lwp_park failed: %d", errno); 1258 break; 1259 } 1260 } 1261 /* Check for cancellation. */ 1262 if (cancelpt && 1263 (atomic_load_relaxed(&self->pt_cancel) & 1264 PT_CANCEL_CANCELLED)) 1265 rv = EINTR; 1266 } while (self->pt_sleepobj != NULL && rv == 0); 1267 return rv; 1268 } 1269 1270 void 1271 pthread__unpark(pthread_queue_t *queue, pthread_t self, 1272 pthread_mutex_t *interlock) 1273 { 1274 pthread_t target; 1275 1276 target = PTQ_FIRST(queue); 1277 target->pt_sleepobj = NULL; 1278 PTQ_REMOVE(queue, target, pt_sleep); 1279 (void)_lwp_unpark(target->pt_lid, NULL); 1280 } 1281 1282 void 1283 pthread__unpark_all(pthread_queue_t *queue, pthread_t self, 1284 pthread_mutex_t *interlock) 1285 { 1286 lwpid_t lids[PTHREAD__UNPARK_MAX]; 1287 const size_t mlid = pthread__unpark_max; 1288 pthread_t target; 1289 size_t nlid = 0; 1290 1291 PTQ_FOREACH(target, queue, pt_sleep) { 1292 if (nlid == mlid) { 1293 (void)_lwp_unpark_all(lids, nlid, NULL); 1294 nlid = 0; 1295 } 1296 target->pt_sleepobj = NULL; 1297 lids[nlid++] = target->pt_lid; 1298 } 1299 PTQ_INIT(queue); 1300 if (nlid == 1) { 1301 (void)_lwp_unpark(lids[0], NULL); 1302 } else if (nlid > 1) { 1303 (void)_lwp_unpark_all(lids, nlid, NULL); 1304 } 1305 } 1306 1307 #undef OOPS 1308 1309 static void 1310 pthread__initmainstack(void) 1311 { 1312 struct rlimit slimit; 1313 const AuxInfo *aux; 1314 size_t size, len; 1315 int mib[2]; 1316 unsigned int value; 1317 1318 _DIAGASSERT(_dlauxinfo() != NULL); 1319 1320 if (getrlimit(RLIMIT_STACK, &slimit) == -1) 1321 err(EXIT_FAILURE, 1322 "Couldn't get stack resource consumption limits"); 1323 size = slimit.rlim_cur; 1324 pthread__main->pt_stack.ss_size = size; 1325 pthread__main->pt_guardsize = pthread__pagesize; 1326 1327 mib[0] = CTL_VM; 1328 mib[1] = VM_GUARD_SIZE; 1329 len = sizeof(value); 1330 if (sysctl(mib, __arraycount(mib), &value, &len, NULL, 0) == 0) 1331 pthread__main->pt_guardsize = value; 1332 1333 for (aux = _dlauxinfo(); aux->a_type != AT_NULL; ++aux) { 1334 if (aux->a_type == AT_STACKBASE) { 1335 #ifdef __MACHINE_STACK_GROWS_UP 1336 pthread__main->pt_stack.ss_sp = (void *)aux->a_v; 1337 #else 1338 pthread__main->pt_stack.ss_sp = (char *)aux->a_v - size; 1339 #endif 1340 break; 1341 } 1342 } 1343 pthread__copy_tsd(pthread__main); 1344 } 1345 1346 /* 1347 * Set up the slightly special stack for the "initial" thread, which 1348 * runs on the normal system stack, and thus gets slightly different 1349 * treatment. 1350 */ 1351 static void 1352 pthread__initmain(pthread_t *newt) 1353 { 1354 char *value; 1355 1356 pthread__initmainstack(); 1357 1358 value = pthread__getenv("PTHREAD_STACKSIZE"); 1359 if (value != NULL) { 1360 pthread__stacksize = atoi(value) * 1024; 1361 if (pthread__stacksize > pthread__main->pt_stack.ss_size) 1362 pthread__stacksize = pthread__main->pt_stack.ss_size; 1363 } 1364 if (pthread__stacksize == 0) 1365 pthread__stacksize = pthread__main->pt_stack.ss_size; 1366 pthread__stacksize += pthread__pagesize - 1; 1367 pthread__stacksize &= ~(pthread__pagesize - 1); 1368 if (pthread__stacksize < 4 * pthread__pagesize) 1369 errx(1, "Stacksize limit is too low, minimum %zd kbyte.", 1370 4 * pthread__pagesize / 1024); 1371 1372 pthread__main->pt_is_main = true; 1373 *newt = pthread__main; 1374 #if defined(_PTHREAD_GETTCB_EXT) 1375 pthread__main->pt_tls = _PTHREAD_GETTCB_EXT(); 1376 #elif defined(__HAVE___LWP_GETTCB_FAST) 1377 pthread__main->pt_tls = __lwp_gettcb_fast(); 1378 #else 1379 pthread__main->pt_tls = _lwp_getprivate(); 1380 #endif 1381 pthread__main->pt_tls->tcb_pthread = pthread__main; 1382 } 1383 1384 static signed int 1385 /*ARGSUSED*/ 1386 pthread__cmp(void *ctx, const void *n1, const void *n2) 1387 { 1388 const uintptr_t p1 = (const uintptr_t)n1; 1389 const uintptr_t p2 = (const uintptr_t)n2; 1390 1391 if (p1 < p2) 1392 return -1; 1393 if (p1 > p2) 1394 return 1; 1395 return 0; 1396 } 1397 1398 /* Because getenv() wants to use locks. */ 1399 char * 1400 pthread__getenv(const char *name) 1401 { 1402 extern char **environ; 1403 size_t l_name, offset; 1404 1405 if (issetugid()) 1406 return (NULL); 1407 1408 l_name = strlen(name); 1409 for (offset = 0; environ[offset] != NULL; offset++) { 1410 if (strncmp(name, environ[offset], l_name) == 0 && 1411 environ[offset][l_name] == '=') { 1412 return environ[offset] + l_name + 1; 1413 } 1414 } 1415 1416 return NULL; 1417 } 1418 1419 pthread_mutex_t * 1420 pthread__hashlock(volatile const void *p) 1421 { 1422 uintptr_t v; 1423 1424 v = (uintptr_t)p; 1425 return &hashlocks[((v >> 9) ^ (v >> 3)) & (NHASHLOCK - 1)].mutex; 1426 } 1427 1428 int 1429 pthread__checkpri(int pri) 1430 { 1431 static int havepri; 1432 static long min, max; 1433 1434 if (!havepri) { 1435 min = sysconf(_SC_SCHED_PRI_MIN); 1436 max = sysconf(_SC_SCHED_PRI_MAX); 1437 havepri = 1; 1438 } 1439 return (pri < min || pri > max) ? EINVAL : 0; 1440 } 1441 1442 int 1443 pthread_main_np(void) 1444 { 1445 if (__predict_false(__uselibcstub)) 1446 return -1; 1447 return pthread_self()->pt_is_main; 1448 } 1449