[BACK]Return to pthread.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libpthread

Annotation of src/lib/libpthread/pthread.c, Revision 1.151.4.2

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

CVSweb <webmaster@jp.NetBSD.org>