aboutsummaryrefslogtreecommitdiff
path: root/include/tib.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/tib.h')
-rw-r--r--include/tib.h258
1 files changed, 258 insertions, 0 deletions
diff --git a/include/tib.h b/include/tib.h
new file mode 100644
index 0000000..8d9216f
--- /dev/null
+++ b/include/tib.h
@@ -0,0 +1,258 @@
+/* $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_ */