[BACK]Return to tib.h CVS log [TXT][DIR] Up to [local] / src / include

Annotation of src/include/tib.h, Revision 1.2

1.2     ! guenther    1: /*     $OpenBSD: tib.h,v 1.1 2015/09/14 08:16:14 guenther Exp $        */
1.1       guenther    2: /*
                      3:  * Copyright (c) 2011,2014 Philip Guenther <guenther@openbsd.org>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17:
                     18: /*
                     19:  * Thread Information Block (TIB) and Thread Local Storage (TLS) handling
                     20:  * (the TCB, Thread Control Block, is part of the TIB)
                     21:  */
                     22:
                     23: #ifndef        _TIB_H_
                     24: #define        _TIB_H_
                     25:
                     26: #include <sys/types.h>
                     27: #include <machine/tcb.h>
                     28:
                     29: #include <stddef.h>
                     30:
                     31:
                     32: /*
                     33:  * This header defines struct tib and at least eight macros:
                     34:  *     TLS_VARIANT
                     35:  *             Either 1 or 2  (Actually defined by <machine/tcb.h>)
                     36:  *
                     37:  *     TCB_SET(tcb)
                     38:  *             Set the TCB pointer for this thread to 'tcb'
                     39:  *
                     40:  *     TCB_GET()
                     41:  *             Return the TCB pointer for this thread
                     42:  *
                     43:  *     TCB_TO_TIB(tcb)
                     44:  *             Given a TCB pointer, return the matching TIB pointer
                     45:  *
                     46:  *     TIB_TO_TCB(tib)
                     47:  *             Given a TIB pointer, return the matching TCB pointer
                     48:  *
                     49:  *     TIB_INIT(tib, dtv)
                     50:  *             Initializes a TIB for a new thread, using the supplied
                     51:  *             value for the dtv pointer
                     52:  *
                     53:  *     TIB_TO_THREAD(tib)
                     54:  *             Given a TIB pointer, return a pointer to the struct pthread
                     55:  *
                     56:  *     TIB_GET()
                     57:  *             Short-hand for TCB_TO_TIB(TCB_GET())
                     58:  *
                     59:  *     TIB_THREAD()
                     60:  *             Returns a pointer to this thread's struct pthread
                     61:  *
                     62:  *     TIB_EXTRA_ALIGN
                     63:  *             On TLS varaint 2 archs, what alignment is sufficient
                     64:  *             for the extra space that will be used for struct pthread?
                     65:  *
                     66:  * The following functions are provided by either ld.so (dynamic) or
                     67:  * libc (static) for allocating and freeing a common memory block that
                     68:  * will hold both the TIB and the pthread structure:
                     69:  *     _dl_allocate_tib(sizeof(struct pthread), flags)
                     70:  *             Allocates a combined TIB and pthread memory region.
                     71:  *             The first argument is the amount of space to reserve
                     72:  *             for the pthread structure; the second argument is
                     73:  *             either zero or DAT_UPDATE_CURRENT, the latter meaning
                     74:  *             this call is to update/replace the current thread's
                     75:  *             TIB.  Returns a pointer to the TIB inside the
                     76:  *             allocated block.
                     77:  *
                     78:  *     _dl_free_tib(tib, sizeof(struct pthread))
                     79:  *             Frees a TIB and pthread block previously allocated
                     80:  *             with _dl_allocate_tls().  Must be passed the return
                     81:  *             value of that previous call.
                     82:  */
                     83:
                     84: /*
                     85:  * Regarding <machine/tcb.h>:
                     86:  *  - it must define the TLS_VARIANT macro
                     87:  *  - if there's a faster way to get or set the TCB pointer for the thread
                     88:  *    than the __{get,set}_tcb() syscalls, it should define either or both
                     89:  *    the TCB_{GET,SET} macros to do so.
                     90:  */
                     91:
                     92:
                     93: /* If <machine/tcb.h> doesn't provide a better way, then use the default */
1.2     ! guenther   94: #ifdef TCB_GET
        !            95: # define TCB_HAVE_MD_GET       1
        !            96: #else
        !            97: # define TCB_GET()             __get_tcb()
1.1       guenther   98: #endif
1.2     ! guenther   99: #ifdef TCB_SET
        !           100: # define TCB_HAVE_MD_SET       1
        !           101: #else
        !           102: # define TCB_SET(tcb)          __set_tcb(tcb)
1.1       guenther  103: #endif
                    104:
                    105:
                    106: #if TLS_VARIANT == 1
                    107: /*
                    108:  * ABI specifies that the static TLS data starts two words after the
                    109:  * (notional) thread pointer, with the first of those two words being
                    110:  * the TLS dtv pointer.  The other (second) word is reserved for the
                    111:  * implementation, so we place the thread's locale there, but we place
                    112:  * our thread bits before the TCB, at negative offsets from the
                    113:  * TCB pointer.  Ergo, memory is laid out, low to high, as:
                    114:  *
1.2     ! guenther  115:  *     [pthread structure]
1.1       guenther  116:  *     TIB {
                    117:  *             int cancel_flags
                    118:  *             int cancel_requested
                    119:  *             int errno
1.2     ! guenther  120:  *             void *locale
1.1       guenther  121:  *             TCB {
                    122:  *                     void *dtv
1.2     ! guenther  123:  *                     struct pthread *thread
1.1       guenther  124:  *             }
                    125:  *     }
                    126:  *     static TLS data
                    127:  */
                    128:
                    129: struct tib {
1.2     ! guenther  130: #ifdef __LP64__
        !           131:        int     __tib_padding;          /* padding for 8byte alignment */
        !           132: #endif
1.1       guenther  133:        int     tib_cancel_flags;
                    134:        int     tib_cancel;
                    135:        int     tib_errno;
1.2     ! guenther  136:        void    *tib_locale;
1.1       guenther  137:        void    *tib_dtv;               /* internal to the runtime linker */
1.2     ! guenther  138:        void    *tib_thread;
1.1       guenther  139: };
1.2     ! guenther  140: #ifdef __LP64__
        !           141: # define _TIB_PREP(tib)        ((void)((tib)->__tib_padding = 0))
        !           142: #endif
1.1       guenther  143:
                    144: #define        _TIBO_PTHREAD           (- _ALIGN(sizeof(struct pthread)))
                    145:
                    146: #elif TLS_VARIANT == 2
                    147: /*
                    148:  * ABI specifies that the static TLS data occupies the memory before
                    149:  * the TCB pointer, at negative offsets, and that on i386 and amd64
                    150:  * the word the TCB points to contains a pointer to itself.  So,
                    151:  * we place errno and our thread bits after that.  Memory is laid
                    152:  * out, low to high, as:
                    153:  *     static TLS data
                    154:  *     TIB {
                    155:  *             TCB {
                    156:  *                     self pointer [i386/amd64 only]
                    157:  *                     void *dtv
                    158:  *             }
1.2     ! guenther  159:  *             struct pthread *thread
1.1       guenther  160:  *             void *locale
                    161:  *             int errno
                    162:  *             int cancel_count_flags
                    163:  *             int cancel_requested
                    164:  *     }
1.2     ! guenther  165:  *     [pthread structure]
1.1       guenther  166:  */
                    167:
                    168: struct tib {
                    169: #if defined(__i386) || defined(__amd64)
                    170:        struct  tib *__tib_self;
1.2     ! guenther  171: # define __tib_tcb __tib_self
1.1       guenther  172: #endif
                    173:        void    *tib_dtv;               /* internal to the runtime linker */
1.2     ! guenther  174:        void    *tib_thread;
1.1       guenther  175:        void    *tib_locale;
                    176:        int     tib_errno;
                    177:        int     tib_cancel;             /* set to request cancelation */
                    178:        int     tib_cancel_flags;
1.2     ! guenther  179: #if defined(__LP64__) || defined(__i386)
1.1       guenther  180:        int     __tib_padding;          /* padding for 8byte alignment */
                    181: #endif
                    182: };
                    183:
                    184: #define        _TIBO_PTHREAD           _ALIGN(sizeof(struct tib))
                    185:
1.2     ! guenther  186: #if defined(__i386) || defined(__amd64)
        !           187: # define _TIB_PREP(tib)        \
1.1       guenther  188:        ((void)((tib)->__tib_self = (tib), (tib)->__tib_padding = 0))
1.2     ! guenther  189: #elif defined(__LP64__)
        !           190: # define _TIB_PREP(tib)        ((void)((tib)->__tib_padding = 0))
1.1       guenther  191: #endif
                    192:
                    193: #define        TIB_EXTRA_ALIGN         sizeof(void *)
                    194:
                    195: #else
                    196: # error "unknown TLS variant"
                    197: #endif
                    198:
                    199: /* nothing to do by default */
                    200: #ifndef        _TIB_PREP
1.2     ! guenther  201: # define _TIB_PREP(tib)        ((void)0)
1.1       guenther  202: #endif
                    203:
1.2     ! guenther  204: #define        TIB_INIT(tib, dtv, thread)      do {            \
        !           205:                (tib)->tib_thread       = (thread);     \
1.1       guenther  206:                (tib)->tib_locale       = NULL;         \
                    207:                (tib)->tib_cancel_flags = 0;            \
                    208:                (tib)->tib_cancel       = 0;            \
                    209:                (tib)->tib_dtv          = (dtv);        \
                    210:                (tib)->tib_errno        = 0;            \
                    211:                _TIB_PREP(tib);                         \
                    212:        } while (0)
                    213:
                    214: #ifndef        __tib_tcb
1.2     ! guenther  215: # define __tib_tcb             tib_dtv
1.1       guenther  216: #endif
                    217: #define        _TIBO_TCB               offsetof(struct tib, __tib_tcb)
                    218:
                    219: #define        TCB_TO_TIB(tcb)         ((struct tib *)((char *)(tcb) - _TIBO_TCB))
                    220: #define        TIB_TO_TCB(tib)         ((char *)(tib) + _TIBO_TCB)
1.2     ! guenther  221: #define        TIB_TO_THREAD(tib)      ((struct pthread *)(tib)->tib_thread)
1.1       guenther  222: #define        TIB_GET()               TCB_TO_TIB(TCB_GET())
1.2     ! guenther  223: #define        TCB_THREAD()            TIB_TO_THREAD(TIB_GET())
1.1       guenther  224:
                    225:
                    226: __BEGIN_DECLS
1.2     ! guenther  227: void   *_dl_allocate_tib(size_t _extra) __dso_public;
1.1       guenther  228: void   _dl_free_tib(void *_tib, size_t _extra) __dso_public;
                    229:
                    230: /* The actual syscalls */
                    231: void   *__get_tcb(void);
                    232: void   __set_tcb(void *_tcb);
                    233: __END_DECLS
                    234:
                    235: #endif /* _TIB_H_ */