- /* $OpenBSD: tib.h,v 1.7 2019/05/10 13:29:21 guenther Exp $ */
- /*
- * Copyright (c) 2011,2014 Philip Guenther <guenther@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
- /*
- * Thread Information Block (TIB) and Thread Local Storage (TLS) handling
- * (the TCB, Thread Control Block, is part of the TIB)
- */
-
- #ifndef _TIB_H_
- #define _TIB_H_
-
- #include <sys/types.h>
- #include <machine/tcb.h>
-
- #include <stddef.h>
-
-
- /*
- * This header defines struct tib and at least eight macros:
- * TLS_VARIANT
- * Either 1 or 2 (Actually defined by <machine/tcb.h>)
- *
- * TCB_SET(tcb)
- * Set the TCB pointer for this thread to 'tcb'
- *
- * TCB_GET()
- * Return the TCB pointer for this thread
- *
- * TCB_TO_TIB(tcb)
- * Given a TCB pointer, return the matching TIB pointer
- *
- * TIB_TO_TCB(tib)
- * Given a TIB pointer, return the matching TCB pointer
- *
- * TIB_INIT(tib, dtv, thread)
- * Initializes a TIB for a new thread, using the supplied
- * values for its dtv and thread pointers
- *
- * TIB_GET()
- * Short-hand for TCB_TO_TIB(TCB_GET())
- *
- * TIB_EXTRA_ALIGN
- * On TLS varaint 2 archs, what alignment is sufficient
- * for the extra space that will be used for struct pthread?
- *
- * The following functions are provided by either ld.so (dynamic) or
- * libc (static) for allocating and freeing a common memory block that
- * will hold both the TIB and the pthread structure:
- * _dl_allocate_tib(sizeof(struct pthread))
- * Allocates a combined TIB and pthread memory region.
- * The argument is the amount of space to reserve
- * for the pthread structure. Returns a pointer to
- * the TIB inside the allocated block.
- *
- * _dl_free_tib(tib, sizeof(struct pthread))
- * Frees a TIB and pthread block previously allocated
- * with _dl_allocate_tib(). Must be passed the return
- * value of that previous call.
- */
-
- /*
- * Regarding <machine/tcb.h>:
- * - it must define the TLS_VARIANT macro
- * - it may define TCB_OFFSET if the TCB address in the kernel and/or
- * register is offset from the actual TCB address. TCB_OFFSET > 0
- * means the kernel/register points to *after* the real data.
- * - if there's a faster way to get or set the TCB pointer for the thread
- * than the __{get,set}_tcb() syscalls, it should define either or both
- * the TCB_{GET,SET} macros to do so.
- */
-
-
- /* All archs but mips64 have fast TCB_GET() and don't need caching */
- #ifndef __mips64__
- # define TCB_HAVE_MD_GET 1
- #endif
- #ifdef TCB_SET
- # define TCB_HAVE_MD_SET 1
- #else
- # define TCB_SET(tcb) __set_tcb(tcb)
- #endif
- #ifndef TCB_OFFSET
- # define TCB_OFFSET 0
- #endif
-
- /*
- * tib_cantcancel values is non-zero if the thread should skip all
- * cancellation processing
- */
- #define CANCEL_DISABLED 1
- #define CANCEL_DYING 2
-
- /*
- * tib_cancel_point is non-zero if we're in a cancel point; its modified
- * by the cancel point code and read by the cancellation signal handler
- */
- #define CANCEL_POINT 1
- #define CANCEL_POINT_DELAYED 2
-
-
- #if TLS_VARIANT == 1
- /*
- * ABI specifies that the static TLS data starts two words after the
- * (notional) thread pointer, with the first of those two words being
- * the TLS dtv pointer. The other (second) word is reserved for the
- * implementation, so we place the pointer to the thread structure there,
- * but we place our actual thread bits before the TCB, at negative offsets
- * from the TCB pointer. Ergo, memory is laid out, low to high, as:
- *
- * [pthread structure]
- * TIB {
- * ...cancelation and other int-sized info...
- * int errno
- * void *locale
- * TCB (- TCB_OFFSET) {
- * void *dtv
- * struct pthread *thread
- * }
- * }
- * static TLS data
- */
-
- struct tib {
- void *tib_atexit;
- int tib_thread_flags; /* internal to libpthread */
- pid_t tib_tid;
- int tib_cantcancel;
- int tib_cancel_point;
- int tib_canceled;
- int tib_errno;
- void *tib_locale;
- void *tib_dtv; /* internal to the runtime linker */
- void *tib_thread;
- };
-
-
- #elif TLS_VARIANT == 2
- /*
- * ABI specifies that the static TLS data occupies the memory before
- * the TCB pointer, at negative offsets, and that on i386 and amd64
- * the word the TCB points to contains a pointer to itself. So,
- * we place errno and our thread bits after that. Memory is laid
- * out, low to high, as:
- * static TLS data
- * TIB {
- * TCB (- TCB_OFFSET) {
- * self pointer [i386/amd64 only]
- * void *dtv
- * }
- * struct pthread *thread
- * void *locale
- * int errno
- * ...cancelation and other int-sized info...
- * }
- * [pthread structure]
- */
-
- struct tib {
- #if defined(__i386) || defined(__amd64)
- struct tib *__tib_self;
- # define __tib_tcb __tib_self
- #endif
- void *tib_dtv; /* internal to the runtime linker */
- void *tib_thread;
- void *tib_locale;
- int tib_errno;
- int tib_canceled;
- int tib_cancel_point;
- int tib_cantcancel;
- pid_t tib_tid;
- int tib_thread_flags; /* internal to libpthread */
- void *tib_atexit;
- };
-
- #if defined(__i386) || defined(__amd64)
- # define _TIB_PREP(tib) \
- ((void)((tib)->__tib_self = (tib)))
- #endif
-
- #define TIB_EXTRA_ALIGN sizeof(void *)
-
- #else
- # error "unknown TLS variant"
- #endif
-
- /* nothing to do by default */
- #ifndef _TIB_PREP
- # define _TIB_PREP(tib) ((void)0)
- #endif
-
- #define TIB_INIT(tib, dtv, thread) do { \
- (tib)->tib_thread = (thread); \
- (tib)->tib_atexit = NULL; \
- (tib)->tib_locale = NULL; \
- (tib)->tib_cantcancel = 0; \
- (tib)->tib_cancel_point = 0; \
- (tib)->tib_canceled = 0; \
- (tib)->tib_dtv = (dtv); \
- (tib)->tib_errno = 0; \
- _TIB_PREP(tib); \
- } while (0)
-
- #ifndef __tib_tcb
- # define __tib_tcb tib_dtv
- #endif
- #define _TIBO_TCB (offsetof(struct tib, __tib_tcb) + TCB_OFFSET)
-
- #define TCB_TO_TIB(tcb) ((struct tib *)((char *)(tcb) - _TIBO_TCB))
- #define TIB_TO_TCB(tib) ((char *)(tib) + _TIBO_TCB)
- #define TIB_GET() TCB_TO_TIB(TCB_GET())
-
-
- __BEGIN_DECLS
- struct dl_info;
- struct dl_phdr_info;
- struct dl_cb_0 {
- void *(*dl_allocate_tib)(size_t);
- void (*dl_free_tib)(void *, size_t);
- void (*dl_clean_boot)(void);
- void *(*dlopen)(const char *, int);
- int (*dlclose)(void *);
- void *(*dlsym)(void *, const char *);
- int (*dladdr)(const void *, struct dl_info *);
- int (*dlctl)(void *, int, void *);
- char *(*dlerror)(void);
- int (*dl_iterate_phdr)(int (*)(struct dl_phdr_info *,
- size_t, void *), void *);
- };
-
- #define DL_CB_CUR 0
- typedef struct dl_cb_0 dl_cb;
-
- /* type of function passed to init functions that returns a dl_cb */
- typedef const void *dl_cb_cb(int _version);
-
- void *_dl_allocate_tib(size_t _extra) __dso_public;
- void _dl_free_tib(void *_tib, size_t _extra) __dso_public;
-
- /* The actual syscalls */
- void *__get_tcb(void);
- void __set_tcb(void *_tcb);
- __END_DECLS
-
- #endif /* _TIB_H_ */
|