Browse Source

Use a Thread Information Block in both single and multi-threaded programs.

This stores errno, the cancelation flags, and related bits for each thread
and is allocated by ld.so or libc.a.  This is an ABI break from 5.9-stable!
Make libpthread dlopen'able by moving the cancelation wrappers into libc
and doing locking and fork/errno handling via callbacks that libpthread
registers when it first initializes.  'errno' *must* be declared via
<errno.h> now!
Clean up libpthread's symbol exports like libc.
On powerpc, offset the TIB/TCB/TLS data from the register per the ELF spec.
Testing by various, particularly sthen@ and patrick@
ok kettenis@
OPENBSD_6_0
guenther 8 years ago
parent
commit
fd248b5fbe
2 changed files with 54 additions and 49 deletions
  1. +2
    -2
      src/include/Makefile
  2. +52
    -47
      src/include/tib.h

+ 2
- 2
src/include/Makefile View File

@ -1,4 +1,4 @@
# $OpenBSD: Makefile,v 1.210 2016/03/09 16:28:46 deraadt Exp $
# $OpenBSD: Makefile,v 1.211 2016/05/07 19:05:21 guenther Exp $
# $NetBSD: Makefile,v 1.59 1996/05/15 21:36:43 jtc Exp $
# @(#)Makefile 5.45.1.1 (Berkeley) 5/6/91
@ -18,7 +18,7 @@ FILES= a.out.h ar.h asr.h assert.h bitstring.h blf.h bsd_auth.h \
nlist.h nl_types.h paths.h poll.h pwd.h ranlib.h readpassphrase.h \
regex.h resolv.h rmd160.h search.h setjmp.h sha1.h sha2.h signal.h \
siphash.h sndio.h spawn.h stdbool.h stddef.h stdio.h stdlib.h \
string.h strings.h struct.h sysexits.h tar.h tgmath.h time.h \
string.h strings.h struct.h sysexits.h tar.h tgmath.h tib.h time.h \
ttyent.h unistd.h utime.h utmp.h uuid.h vis.h wchar.h wctype.h
MFILES= frame.h


+ 52
- 47
src/include/tib.h View File

@ -1,4 +1,4 @@
/* $OpenBSD: tib.h,v 1.2 2016/03/20 02:30:28 guenther Exp $ */
/* $OpenBSD: tib.h,v 1.3 2016/05/07 19:05:21 guenther Exp $ */
/*
* Copyright (c) 2011,2014 Philip Guenther <guenther@openbsd.org>
*
@ -46,19 +46,13 @@
* TIB_TO_TCB(tib)
* Given a TIB pointer, return the matching TCB pointer
*
* TIB_INIT(tib, dtv)
* TIB_INIT(tib, dtv, thread)
* Initializes a TIB for a new thread, using the supplied
* value for the dtv pointer
*
* TIB_TO_THREAD(tib)
* Given a TIB pointer, return a pointer to the struct pthread
* values for its dtv and thread pointers
*
* TIB_GET()
* Short-hand for TCB_TO_TIB(TCB_GET())
*
* TIB_THREAD()
* Returns a pointer to this thread's struct pthread
*
* TIB_EXTRA_ALIGN
* On TLS varaint 2 archs, what alignment is sufficient
* for the extra space that will be used for struct pthread?
@ -66,24 +60,24 @@
* 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), flags)
* _dl_allocate_tib(sizeof(struct pthread))
* Allocates a combined TIB and pthread memory region.
* The first argument is the amount of space to reserve
* for the pthread structure; the second argument is
* either zero or DAT_UPDATE_CURRENT, the latter meaning
* this call is to update/replace the current thread's
* TIB. Returns a pointer to the TIB inside the
* allocated block.
* 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_tls(). Must be passed the return
* 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.
@ -101,6 +95,23 @@
#else
# define TCB_SET(tcb) __set_tcb(tcb)
#endif
#ifndef TCB_OFFSET
# define TCB_OFFSET 0
#endif
/*
* tib_cantcancel values is non-zero is 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
@ -108,17 +119,16 @@
* 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 thread's locale there, but we place
* our thread bits before the TCB, at negative offsets from the
* TCB pointer. Ergo, memory is laid out, low to high, as:
* 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 {
* int cancel_flags
* int cancel_requested
* ...cancelation and other int-sized info...
* int errno
* void *locale
* TCB {
* TCB (- TCB_OFFSET) {
* void *dtv
* struct pthread *thread
* }
@ -127,21 +137,17 @@
*/
struct tib {
#ifdef __LP64__
int __tib_padding; /* padding for 8byte alignment */
#endif
int tib_cancel_flags;
int tib_cancel;
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;
};
#ifdef __LP64__
# define _TIB_PREP(tib) ((void)((tib)->__tib_padding = 0))
#endif
#define _TIBO_PTHREAD (- _ALIGN(sizeof(struct pthread)))
#elif TLS_VARIANT == 2
/*
@ -152,15 +158,14 @@ struct tib {
* out, low to high, as:
* static TLS data
* TIB {
* TCB {
* TCB (- TCB_OFFSET) {
* self pointer [i386/amd64 only]
* void *dtv
* }
* struct pthread *thread
* void *locale
* int errno
* int cancel_count_flags
* int cancel_requested
* ...cancelation and other int-sized info...
* }
* [pthread structure]
*/
@ -174,19 +179,20 @@ struct tib {
void *tib_thread;
void *tib_locale;
int tib_errno;
int tib_cancel; /* set to request cancelation */
int tib_cancel_flags;
#if defined(__LP64__) || defined(__i386)
int tib_canceled;
int tib_cancel_point;
int tib_cantcancel;
pid_t tib_tid;
int tib_thread_flags; /* internal to libpthread */
#if !defined(__LP64__) && !defined(__i386)
int __tib_padding; /* padding for 8byte alignment */
#endif
};
#define _TIBO_PTHREAD _ALIGN(sizeof(struct tib))
#if defined(__i386) || defined(__amd64)
# define _TIB_PREP(tib) \
((void)((tib)->__tib_self = (tib), (tib)->__tib_padding = 0))
#elif defined(__LP64__)
((void)((tib)->__tib_self = (tib)))
#elif !defined(__LP64__) && !defined(__i386)
# define _TIB_PREP(tib) ((void)((tib)->__tib_padding = 0))
#endif
@ -204,8 +210,9 @@ struct tib {
#define TIB_INIT(tib, dtv, thread) do { \
(tib)->tib_thread = (thread); \
(tib)->tib_locale = NULL; \
(tib)->tib_cancel_flags = 0; \
(tib)->tib_cancel = 0; \
(tib)->tib_cantcancel = 0; \
(tib)->tib_cancel_point = 0; \
(tib)->tib_canceled = 0; \
(tib)->tib_dtv = (dtv); \
(tib)->tib_errno = 0; \
_TIB_PREP(tib); \
@ -214,13 +221,11 @@ struct tib {
#ifndef __tib_tcb
# define __tib_tcb tib_dtv
#endif
#define _TIBO_TCB offsetof(struct tib, __tib_tcb)
#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_TO_THREAD(tib) ((struct pthread *)(tib)->tib_thread)
#define TIB_GET() TCB_TO_TIB(TCB_GET())
#define TCB_THREAD() TIB_TO_THREAD(TIB_GET())
__BEGIN_DECLS


Loading…
Cancel
Save