Module Name: src Committed By: joerg Date: Thu Mar 10 14:27:32 UTC 2011
Modified Files: src/libexec/ld.elf_so: README.TLS rtld.h tls.c Log Message: Fix prototype for __tls_get_addr. Add a generic implementation of it using __tls_get_addr. Update TLS notes. To generate a diff of this commit: cvs rdiff -u -r1.1 -r1.2 src/libexec/ld.elf_so/README.TLS \ src/libexec/ld.elf_so/tls.c cvs rdiff -u -r1.101 -r1.102 src/libexec/ld.elf_so/rtld.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/libexec/ld.elf_so/README.TLS diff -u src/libexec/ld.elf_so/README.TLS:1.1 src/libexec/ld.elf_so/README.TLS:1.2 --- src/libexec/ld.elf_so/README.TLS:1.1 Wed Mar 9 23:10:07 2011 +++ src/libexec/ld.elf_so/README.TLS Thu Mar 10 14:27:31 2011 @@ -3,11 +3,7 @@ (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 @@ 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: - -#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] +The generic implementation can be found in tls.c and is used with +__HAVE_COMMON___TLS_GET_ADDR. It depends on ___lwp_getprivate_fast. -(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 @@ 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 Index: src/libexec/ld.elf_so/tls.c diff -u src/libexec/ld.elf_so/tls.c:1.1 src/libexec/ld.elf_so/tls.c:1.2 --- src/libexec/ld.elf_so/tls.c:1.1 Wed Mar 9 23:10:07 2011 +++ src/libexec/ld.elf_so/tls.c Thu Mar 10 14:27:31 2011 @@ -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 @@ 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 */ Index: src/libexec/ld.elf_so/rtld.h diff -u src/libexec/ld.elf_so/rtld.h:1.101 src/libexec/ld.elf_so/rtld.h:1.102 --- src/libexec/ld.elf_so/rtld.h:1.101 Wed Mar 9 23:10:07 2011 +++ src/libexec/ld.elf_so/rtld.h Thu Mar 10 14:27:31 2011 @@ -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 @@ 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 */