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

Annotation of src/lib/libpthread/pthread_int.h, Revision 1.20

1.20    ! christos    1: /*     $NetBSD: pthread_int.h,v 1.19 2003/09/12 00:37:17 christos Exp $        */
1.2       thorpej     2:
                      3: /*-
1.16      nathanw     4:  * Copyright (c) 2001,2002,2003 The NetBSD Foundation, Inc.
1.2       thorpej     5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Nathan J. Williams.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *        This product includes software developed by the NetBSD
                     21:  *        Foundation, Inc. and its contributors.
                     22:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     23:  *    contributors may be used to endorse or promote products derived
                     24:  *    from this software without specific prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     27:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     36:  * POSSIBILITY OF SUCH DAMAGE.
                     37:  */
                     38:
                     39: #ifndef _LIB_PTHREAD_INT_H
                     40: #define _LIB_PTHREAD_INT_H
                     41:
                     42: #define PTHREAD__DEBUG
                     43: #define ERRORCHECK
                     44:
                     45: #include "pthread_types.h"
                     46: #include "pthread_queue.h"
                     47: #include "pthread_debug.h"
                     48: #include "pthread_md.h"
                     49:
                     50: #include <sa.h>
                     51: #include <signal.h>
                     52:
1.15      nathanw    53: #define PTHREAD_KEYS_MAX 256
1.2       thorpej    54: /*
                     55:  * The size of this structure needs to be no larger than struct
                     56:  * __pthread_cleanup_store, defined in pthread.h.
                     57:  */
                     58: struct pt_clean_t {
                     59:        PTQ_ENTRY(pt_clean_t)   ptc_next;
                     60:        void    (*ptc_cleanup)(void *);
                     61:        void    *ptc_arg;
                     62: };
                     63:
                     64: struct pt_alarm_t {
                     65:        PTQ_ENTRY(pt_alarm_t)   pta_next;
                     66:        pthread_spin_t  pta_lock;
                     67:        const struct timespec   *pta_time;
                     68:        void    (*pta_func)(void *);
                     69:        void    *pta_arg;
                     70:        int     pta_fired;
1.16      nathanw    71: };
                     72:
                     73: /* Private data for pthread_attr_t */
                     74: struct pthread_attr_private {
                     75:        char ptap_name[PTHREAD_MAX_NAMELEN_NP];
                     76:        void *ptap_namearg;
                     77:        void *ptap_stackaddr;
                     78:        size_t ptap_stacksize;
                     79:        size_t ptap_guardsize;
1.2       thorpej    80: };
                     81:
1.15      nathanw    82: struct __pthread_st {
1.2       thorpej    83:        unsigned int    pt_magic;
1.4       nathanw    84:        /* Identifier, for debugging and for preventing recycling. */
                     85:        int             pt_num;
1.2       thorpej    86:
                     87:        int     pt_type;        /* normal, upcall, or idle */
                     88:        int     pt_state;       /* running, blocked, etc. */
                     89:        pthread_spin_t pt_statelock;    /* lock on pt_state */
                     90:        int     pt_flags;       /* see PT_FLAG_* below */
1.17      nathanw    91:        pthread_spin_t pt_flaglock;     /* lock on pt_flag */
1.2       thorpej    92:        int     pt_cancel;      /* Deferred cancellation */
                     93:        int     pt_spinlocks;   /* Number of spinlocks held. */
                     94:        int     pt_blockedlwp;  /* LWP/SA number when blocked */
                     95:
                     96:        int     pt_errno;       /* Thread-specific errno. */
                     97:
                     98:        /* Entry on the run queue */
1.15      nathanw    99:        PTQ_ENTRY(__pthread_st) pt_runq;
1.2       thorpej   100:        /* Entry on the list of all threads */
1.15      nathanw   101:        PTQ_ENTRY(__pthread_st) pt_allq;
1.2       thorpej   102:        /* Entry on the sleep queue (xxx should be same as run queue?) */
1.15      nathanw   103:        PTQ_ENTRY(__pthread_st) pt_sleep;
1.2       thorpej   104:        /* Object we're sleeping on */
1.6       jdolecek  105:        void                    *pt_sleepobj;
1.2       thorpej   106:        /* Queue we're sleeping on */
1.6       jdolecek  107:        struct pthread_queue_t  *pt_sleepq;
1.2       thorpej   108:        /* Lock protecting that queue */
                    109:        pthread_spin_t          *pt_sleeplock;
                    110:
                    111:        stack_t         pt_stack;       /* Our stack */
                    112:        ucontext_t      *pt_uc;         /* Saved context when we're stopped */
1.14      nathanw   113:        ucontext_t      *pt_trapuc;     /* Kernel-saved context */
1.2       thorpej   114:
                    115:        sigset_t        pt_sigmask;     /* Signals we won't take. */
                    116:        sigset_t        pt_siglist;     /* Signals pending for us. */
1.4       nathanw   117:        sigset_t        pt_sigblocked;  /* Signals delivered while blocked. */
1.8       jdolecek  118:        sigset_t        *pt_sigwait;    /* Signals waited for in sigwait */
                    119:        siginfo_t       *pt_wsig;
1.2       thorpej   120:        pthread_spin_t  pt_siglock;     /* Lock on above */
                    121:
                    122:        void *          pt_exitval;     /* Read by pthread_join() */
                    123:
                    124:        /* Stack of cancellation cleanup handlers and their arguments */
                    125:        PTQ_HEAD(, pt_clean_t)  pt_cleanup_stack;
                    126:
1.9       thorpej   127:        /* Thread's name, set by the application. */
                    128:        char*           pt_name;
                    129:
1.2       thorpej   130:        /* Other threads trying to pthread_join() us. */
                    131:        struct pthread_queue_t  pt_joiners;
                    132:        /* Lock for above, and for changing pt_state to ZOMBIE or DEAD,
1.9       thorpej   133:         * and for setting the DETACHED flag.  Also protects pt_name.
1.2       thorpej   134:         */
                    135:        pthread_spin_t  pt_join_lock;
                    136:
                    137:        /* Thread we were going to switch to before we were preempted
                    138:         * ourselves. Will be used by the upcall that's continuing us.
                    139:         */
                    140:        pthread_t       pt_switchto;
                    141:        ucontext_t*     pt_switchtouc;
                    142:
                    143:        /* Threads that are preempted with spinlocks held will be
                    144:         * continued until they unlock their spinlock. When they do
                    145:         * so, they should jump ship to the thread pointed to by
                    146:         * pt_next.
                    147:         */
                    148:        pthread_t       pt_next;
                    149:
                    150:        /* The upcall that is continuing this thread */
                    151:        pthread_t       pt_parent;
                    152:
                    153:        /* A queue lock that this thread held while trying to
                    154:         * context switch to another process.
                    155:         */
                    156:        pthread_spin_t* pt_heldlock;
                    157:
                    158:        /* Thread-specific data */
                    159:        void*           pt_specific[PTHREAD_KEYS_MAX];
                    160:
                    161: #ifdef PTHREAD__DEBUG
                    162:        int     blocks;
                    163:        int     preempts;
                    164:        int     rescheds;
                    165: #endif
                    166: };
                    167:
                    168: struct pthread_lock_ops {
                    169:        void    (*plo_init)(__cpu_simple_lock_t *);
                    170:        int     (*plo_try)(__cpu_simple_lock_t *);
                    171:        void    (*plo_unlock)(__cpu_simple_lock_t *);
                    172: };
                    173:
                    174: /* Thread types */
                    175: #define PT_THREAD_NORMAL       1
                    176: #define PT_THREAD_UPCALL       2
                    177: #define PT_THREAD_IDLE         3
                    178:
                    179: /* Thread states */
                    180: #define PT_STATE_RUNNING       1
                    181: #define PT_STATE_RUNNABLE      2
                    182: #define PT_STATE_BLOCKED_SYS   3
                    183: #define PT_STATE_BLOCKED_QUEUE 4
                    184: #define PT_STATE_ZOMBIE                5
                    185: #define PT_STATE_DEAD          6
1.20    ! christos  186: #define PT_STATE_SUSPENDED     7
1.2       thorpej   187:
                    188: /* Flag values */
                    189:
                    190: #define PT_FLAG_DETACHED       0x0001
                    191: #define PT_FLAG_IDLED          0x0002
                    192: #define PT_FLAG_CS_DISABLED    0x0004  /* Cancellation disabled */
                    193: #define PT_FLAG_CS_ASYNC       0x0008  /* Cancellation is async */
                    194: #define PT_FLAG_CS_PENDING     0x0010
1.4       nathanw   195: #define PT_FLAG_SIGDEFERRED     0x0020 /* There are signals to take */
1.15      nathanw   196: #define PT_FLAG_SCOPE_SYSTEM   0x0040
                    197: #define PT_FLAG_EXPLICIT_SCHED 0x0080
1.20    ! christos  198: #define        PT_FLAG_SUSPENDED       0x0100  /* In the suspended queue */
1.2       thorpej   199:
                    200: #define PT_MAGIC       0x11110001
                    201: #define PT_DEAD                0xDEAD0001
                    202:
                    203: #define PT_ATTR_MAGIC  0x22220002
                    204: #define PT_ATTR_DEAD   0xDEAD0002
                    205:
1.15      nathanw   206: #define PT_STACKSIZE_LG        18
                    207: #define PT_STACKSIZE   (1<<(PT_STACKSIZE_LG))
1.2       thorpej   208: #define PT_STACKMASK   (PT_STACKSIZE-1)
                    209:
                    210: #define PT_UPCALLSTACKS        16
                    211:
                    212: #define PT_ALARMTIMER_MAGIC    0x88880010
                    213: #define PT_RRTIMER_MAGIC       0x88880020
                    214: #define NIDLETHREADS   4
                    215: #define IDLESPINS      1000
                    216:
                    217: /* Flag to be used in a ucontext_t's uc_flags indicating that
                    218:  * the saved register state is "user" state only, not full
                    219:  * trap state.
                    220:  */
                    221: #define _UC_USER_BIT           30
                    222: #define _UC_USER               (1LU << _UC_USER_BIT)
                    223:
                    224: void   pthread_init(void)  __attribute__ ((__constructor__));
                    225:
                    226: /* Utility functions */
                    227:
                    228: /* Set up/clean up a thread's basic state. */
                    229: void   pthread__initthread(pthread_t self, pthread_t t);
                    230:
                    231: /* Go do something else. Don't go back on the run queue */
                    232: void   pthread__block(pthread_t self, pthread_spin_t* queuelock);
1.20    ! christos  233: /* Put a thread back on the suspended queue */
        !           234: void   pthread__suspend(pthread_t self, pthread_t thread);
1.2       thorpej   235: /* Put a thread back on the run queue */
                    236: void   pthread__sched(pthread_t self, pthread_t thread);
1.5       nathanw   237: void   pthread__sched_sleepers(pthread_t self, struct pthread_queue_t *threadq);
1.2       thorpej   238: void   pthread__sched_idle(pthread_t self, pthread_t thread);
                    239: void   pthread__sched_idle2(pthread_t self);
                    240:
                    241: void   pthread__sched_bulk(pthread_t self, pthread_t qhead);
                    242:
                    243: void   pthread__idle(void);
                    244:
                    245: /* Get the next thread */
                    246: pthread_t pthread__next(pthread_t self);
                    247:
                    248: int    pthread__stackalloc(pthread_t *t);
                    249: void   pthread__initmain(pthread_t *t);
                    250:
                    251: void   pthread__sa_start(void);
                    252: void   pthread__sa_recycle(pthread_t old, pthread_t new);
                    253:
                    254: /* Alarm code */
                    255: void   pthread__alarm_init(void);
                    256: void   pthread__alarm_add(pthread_t, struct pt_alarm_t *,
                    257:     const struct timespec *, void (*)(void *), void *);
                    258: void   pthread__alarm_del(pthread_t, struct pt_alarm_t *);
                    259: int    pthread__alarm_fired(struct pt_alarm_t *);
                    260: void   pthread__alarm_process(pthread_t self, void *arg);
                    261:
                    262: /* Internal locking primitives */
                    263: void   pthread__lockprim_init(void);
                    264: void   pthread_lockinit(pthread_spin_t *lock);
                    265: void   pthread_spinlock(pthread_t thread, pthread_spin_t *lock);
                    266: int    pthread_spintrylock(pthread_t thread, pthread_spin_t *lock);
                    267: void   pthread_spinunlock(pthread_t thread, pthread_spin_t *lock);
                    268:
                    269: extern const struct pthread_lock_ops *pthread__lock_ops;
                    270:
                    271: #define        pthread__simple_lock_init(alp)  (*pthread__lock_ops->plo_init)(alp)
                    272: #define        pthread__simple_lock_try(alp)   (*pthread__lock_ops->plo_try)(alp)
                    273: #define        pthread__simple_unlock(alp)     (*pthread__lock_ops->plo_unlock)(alp)
                    274:
                    275: #ifndef _getcontext_u
                    276: int    _getcontext_u(ucontext_t *);
                    277: #endif
                    278: #ifndef _setcontext_u
                    279: int    _setcontext_u(const ucontext_t *);
                    280: #endif
                    281: #ifndef _swapcontext_u
                    282: int    _swapcontext_u(ucontext_t *, const ucontext_t *);
                    283: #endif
                    284:
                    285: void   pthread__testcancel(pthread_t self);
                    286: int    pthread__find(pthread_t self, pthread_t target);
                    287:
                    288: #ifndef PTHREAD_MD_INIT
                    289: #define PTHREAD_MD_INIT
                    290: #endif
                    291:
                    292: #ifndef _INITCONTEXT_U_MD
                    293: #define _INITCONTEXT_U_MD(ucp)
                    294: #endif
                    295:
                    296: #define _INITCONTEXT_U(ucp) do {                                       \
                    297:        (ucp)->uc_flags = _UC_CPU | _UC_STACK;                          \
                    298:        _INITCONTEXT_U_MD(ucp)                                          \
1.3       christos  299:        } while (/*CONSTCOND*/0)
1.2       thorpej   300:
                    301: #ifdef __PTHREAD_SIGNAL_PRIVATE
1.19      christos  302: #ifndef __HAVE_SIGINFO
1.2       thorpej   303:
                    304: /*
                    305:  * Macros for converting from ucontext to sigcontext and vice-versa.
                    306:  * Note that going from sigcontext->ucontext is only safe for a
                    307:  * sigcontext that was first created from a ucontext.
                    308:  *
                    309:  * Arch-specific code can override this, if necessary.  It may also
                    310:  * be necessary for arch-specific code to include extra info along with
                    311:  * the sigcontext.
                    312:  */
                    313: #ifndef PTHREAD_SIGCONTEXT_EXTRA
                    314: #define        PTHREAD_SIGCONTEXT_EXTRA
                    315: #endif
                    316:
                    317: struct pthread__sigcontext {
                    318:        struct sigcontext       psc_context;
                    319:        PTHREAD_SIGCONTEXT_EXTRA
                    320: };
                    321:
                    322: #ifndef PTHREAD_UCONTEXT_TO_SIGCONTEXT
                    323: #define        PTHREAD_UCONTEXT_TO_SIGCONTEXT(mask, uc, psc)                   \
                    324: do {                                                                   \
                    325:        (uc)->uc_sigmask = *(mask);                                     \
                    326:        /*                                                              \
                    327:         * XXX We may want to check for _UC_USER here and do a          \
                    328:         * XXX _INITCONTEXT_U_MD() and clearing _UC_USER on such        \
                    329:         * XXX contexts before converting to a signcontext, thus        \
                    330:         * XXX allowing signal handlers to modify the non-_UC_USER      \
                    331:         * XXX registers.  Hazy territory; ignore it for now.           \
                    332:         */                                                             \
                    333:        _UCONTEXT_TO_SIGCONTEXT((uc), &(psc)->psc_context);             \
                    334: } while (/*CONSTCOND*/0)
                    335:
                    336: #define        PTHREAD_SIGCONTEXT_TO_UCONTEXT(psc, uc)                         \
                    337: do {                                                                   \
                    338:        _SIGCONTEXT_TO_UCONTEXT(&(psc)->psc_context, (uc));             \
                    339:        (uc)->uc_flags &= ~_UC_SIGMASK;                                 \
                    340: } while (/*CONSTCOND*/0)
                    341: #else
                    342: void   pthread__ucontext_to_sigcontext(const sigset_t *, ucontext_t *,
                    343:            struct pthread__sigcontext *);
                    344: void   pthread__sigcontext_to_ucontext(const struct pthread__sigcontext *,
                    345:            ucontext_t *);
                    346: #endif /* PTHREAD_UCONTEXT_TO_SIGCONTEXT */
                    347:
1.19      christos  348: #endif /* __HAVE_SIGINFO */
                    349:
1.2       thorpej   350: #endif /* __PTHREAD_SIGNAL_PRIVATE */
                    351:
1.13      nathanw   352: #ifdef PTHREAD_MACHINE_HAS_ID_REGISTER
                    353: #define pthread__id(reg) (reg)
                    354: #else
1.2       thorpej   355: /* Stack location of pointer to a particular thread */
                    356: #define pthread__id(sp) \
                    357:        ((pthread_t) (((vaddr_t)(sp)) & ~PT_STACKMASK))
                    358:
1.13      nathanw   359: #define pthread__id_reg() pthread__sp()
                    360: #endif
                    361:
                    362: #define pthread__self() (pthread__id(pthread__id_reg()))
1.2       thorpej   363:
1.12      christos  364: #define pthread__abort()                                               \
                    365:        pthread__assertfunc(__FILE__, __LINE__, __func__, "unreachable")
                    366:
1.11      nathanw   367: #define pthread__assert(e) do {                                                \
                    368:        if (__predict_false(!(e)))                                      \
                    369:                       pthread__assertfunc(__FILE__, __LINE__, __func__, #e);   \
1.12      christos  370:         } while (/*CONSTCOND*/0)
1.11      nathanw   371:
                    372: #define pthread__error(err, msg, e) do {                               \
                    373:        if (__predict_false(!(e))) {                                    \
                    374:                       pthread__errorfunc(__FILE__, __LINE__, __func__, msg);   \
                    375:               return (err);                                            \
                    376:        }                                                               \
1.12      christos  377:         } while (/*CONSTCOND*/0)
1.11      nathanw   378:
1.7       nathanw   379:
                    380:
1.2       thorpej   381: /* These three routines are defined in processor-specific code. */
                    382: void   pthread__upcall_switch(pthread_t self, pthread_t next);
                    383: void   pthread__switch(pthread_t self, pthread_t next);
                    384: void   pthread__locked_switch(pthread_t self, pthread_t next,
                    385:     pthread_spin_t *lock);
                    386:
                    387: void   pthread__signal_init(void);
                    388:
1.19      christos  389: void   pthread__signal(pthread_t self, pthread_t t, siginfo_t *si);
                    390: void   pthread__deliver_signal(pthread_t self, pthread_t t, siginfo_t *si);
1.4       nathanw   391: void   pthread__signal_deferred(pthread_t self, pthread_t t);
1.2       thorpej   392:
                    393: void   pthread__destroy_tsd(pthread_t self);
1.7       nathanw   394: void   pthread__assertfunc(char *file, int line, char *function, char *expr);
1.11      nathanw   395: void   pthread__errorfunc(char *file, int line, char *function, char *msg);
1.2       thorpej   396:
                    397: #endif /* _LIB_PTHREAD_INT_H */

CVSweb <webmaster@jp.NetBSD.org>