Fix prototype for __tls_get_addr. Add a generic implementation of it
using __tls_get_addr. Update TLS notes.
This commit is contained in:
parent
9eacb1b321
commit
de4cf97515
|
@ -3,11 +3,7 @@ Steps for adding TLS support for a new platform:
|
|||
(1) Declare TLS variant in machine/types.h by defining either
|
||||
__HAVE_TLS_VARIANT_I or __HAVE_TLS_VARIANT_II.
|
||||
|
||||
(2) crt0.o has to call _rtld_tls_static_setup() if _DYNAMIC == NULL.
|
||||
This part is already done if the new src/lib/csu/arch layout is used
|
||||
by the architecture.
|
||||
|
||||
(3) _lwp_makecontext has to set the reserved register or kernel transfer
|
||||
(2) _lwp_makecontext has to set the reserved register or kernel transfer
|
||||
variable in uc_mcontext to the provided value of 'private'.
|
||||
|
||||
This is not possible on the VAX as there is no free space in ucontext_t.
|
||||
|
@ -15,38 +11,21 @@ This requires either a special version of _lwp_create or versioning
|
|||
everything using ucontext_t. Debug support depends on getting the data from
|
||||
ucontext_t, so the second option is possibly required.
|
||||
|
||||
(4) _lwp_setprivate(2) has to update the same register as
|
||||
(3) _lwp_setprivate(2) has to update the same register as
|
||||
_lwp_makecontext. cpu_lwp_setprivate has to call _lwp_setprivate(2) to
|
||||
reflect the kernel view. cpu_switch has to update the mapping.
|
||||
|
||||
_lwp_setprivate is used for the initial thread, all other threads
|
||||
created by libpthread use _lwp_makecontext for this purpose.
|
||||
|
||||
(5) Provide __tls_get_addr and possible other MD functions for dynamic
|
||||
(4) Provide __tls_get_addr and possible other MD functions for dynamic
|
||||
TLS offset computation. If such alternative entry points exist (currently
|
||||
only i386), also add a weak reference to 0 in src/lib/libc/tls/tls.c.
|
||||
|
||||
The generic implementation is:
|
||||
The generic implementation can be found in tls.c and is used with
|
||||
__HAVE_COMMON___TLS_GET_ADDR. It depends on ___lwp_getprivate_fast.
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/tls.h>
|
||||
#include <lwp.h>
|
||||
|
||||
/* Weak entry is overriden by ld.elf_so for dynamic linkage */
|
||||
weak_alias(__tls_get_addr, __libc__tls_get_addr)
|
||||
|
||||
void *
|
||||
__libc__tls_get_addr(size_t idx[2])
|
||||
{
|
||||
struct tls_tcb *tcb;
|
||||
|
||||
tcb = _lwp_getprivate();
|
||||
return _rtld_tls_get_addr(tcb, idx[0], idx[1]);
|
||||
}
|
||||
|
||||
XXX Document optimisations based idx[0]
|
||||
|
||||
(6) Implement the necessary relocation records in mdreloc.c. There are
|
||||
(5) Implement the necessary relocation records in mdreloc.c. There are
|
||||
typically three relocation types found in dynamic binaries:
|
||||
|
||||
(a) R_TYPE(TLS_DTPOFF): Offset inside the module. The common TLS code
|
||||
|
@ -73,7 +52,7 @@ def->st_value - defobj->tlsoffset + rela->r_addend
|
|||
|
||||
e.g. starting offset is counting down from the TCB.
|
||||
|
||||
(7) Implement _lwp_getprivate_fast() in machine/mcontext.h and set
|
||||
(6) Implement _lwp_getprivate_fast() in machine/mcontext.h and set
|
||||
__HAVE___LWP_GETPRIVATE_FAST.
|
||||
|
||||
(8) Test using src/tests/lib/libc/tls. Make sure with "objdump -R" that
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: rtld.h,v 1.101 2011/03/09 23:10:07 joerg Exp $ */
|
||||
/* $NetBSD: rtld.h,v 1.102 2011/03/10 14:27:31 joerg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 1996 John D. Polstra.
|
||||
|
@ -374,7 +374,7 @@ void _rtld_tls_offset_free(Obj_Entry *);
|
|||
extern size_t _rtld_tls_dtv_generation;
|
||||
extern size_t _rtld_tls_max_index;
|
||||
|
||||
__dso_public extern void __tls_get_addr(void *);
|
||||
__dso_public extern void *__tls_get_addr(void *);
|
||||
#endif
|
||||
|
||||
/* map_object.c */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: tls.c,v 1.1 2011/03/09 23:10:07 joerg Exp $ */
|
||||
/* $NetBSD: tls.c,v 1.2 2011/03/10 14:27:31 joerg Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
|
@ -29,9 +29,10 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: tls.c,v 1.1 2011/03/09 23:10:07 joerg Exp $");
|
||||
__RCSID("$NetBSD: tls.c,v 1.2 2011/03/10 14:27:31 joerg Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ucontext.h>
|
||||
#include <lwp.h>
|
||||
#include <string.h>
|
||||
#include "rtld.h"
|
||||
|
@ -232,4 +233,28 @@ _rtld_tls_offset_free(Obj_Entry *obj)
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef __HAVE_COMMON___TLS_GET_ADDR
|
||||
/*
|
||||
* The fast path is access to an already allocated DTV entry.
|
||||
* This checks the current limit and the entry without needing any
|
||||
* locking. Entries are only freed on dlclose() and it is an application
|
||||
* bug if code of the module is still running at that point.
|
||||
*/
|
||||
void *
|
||||
__tls_get_addr(void *arg_)
|
||||
{
|
||||
size_t *arg = (size_t *)arg_;
|
||||
void **dtv;
|
||||
struct tls_tcb *tcb = __lwp_getprivate_fast();
|
||||
size_t idx = arg[0], offset = arg[1];
|
||||
|
||||
dtv = tcb->tcb_dtv;
|
||||
|
||||
if (__predict_true(idx < DTV_MAX_INDEX(dtv) && dtv[idx] != NULL))
|
||||
return (uint8_t *)dtv[idx] + offset;
|
||||
|
||||
return _rtld_tls_get_addr(tcb, idx, offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __HAVE_TLS_VARIANT_I || __HAVE_TLS_VARIANT_II */
|
||||
|
|
Loading…
Reference in New Issue