diff options
author | Stan Shebs <stanshebs@google.com> | 2015-07-28 10:17:46 -0700 |
---|---|---|
committer | Stan Shebs <stanshebs@google.com> | 2015-07-28 10:17:46 -0700 |
commit | b2b6bfcde6ac2950c57df60ccd235dfe6de89824 (patch) | |
tree | c568fdb0827964bd24988ba13868a6c7cd0aeff9 | |
parent | 3532d2e2bcbe2f7f2bb63fe4633f67acf1c11ed6 (diff) | |
download | glibc-b2b6bfcde6ac2950c57df60ccd235dfe6de89824.zip glibc-b2b6bfcde6ac2950c57df60ccd235dfe6de89824.tar.gz glibc-b2b6bfcde6ac2950c57df60ccd235dfe6de89824.tar.bz2 |
Fix b/19824366 with a local patch (as upstream is fixed unmergeably), and add a new test.
-rw-r--r-- | README.google | 9 | ||||
-rw-r--r-- | elf/dl-tls.c | 15 | ||||
-rw-r--r-- | nptl/Makefile | 10 | ||||
-rw-r--r-- | nptl/tst-tls77.c | 107 | ||||
-rw-r--r-- | nptl/tst-tls77mod.c | 41 |
5 files changed, 175 insertions, 7 deletions
diff --git a/README.google b/README.google index 9c43bde..cd604a3 100644 --- a/README.google +++ b/README.google @@ -452,3 +452,12 @@ misc/sys/cdefs.h PLT and improves the performance of some of our code via better icache and iTLB performance. (tmsriram, google-local) + +elf/dl-tls.c +nptl/Makefile +nptl/tst-tls77.c +nptl/tst-tls77mod.c + Fix b/19824366 with tweaks to TLS dynamic loading, and add a test. Note that + upstream commit + https://sourceware.org/git/?p=glibc.git&a=commit&h=f8aeae347377f3dfa8cbadde057adf1827fb1d44 + fixes this problem in a different way, so this patch is not needed upstream. diff --git a/elf/dl-tls.c b/elf/dl-tls.c index 50ec876..3fbdd45 100644 --- a/elf/dl-tls.c +++ b/elf/dl-tls.c @@ -695,10 +695,15 @@ _dl_update_slotinfo (unsigned long int req_modid) memalign and not malloc. */ __signal_safe_free (dtv[modid].pointer.val); - /* This module is loaded dynamically- We defer memory - allocation. */ - dtv[modid].pointer.is_static = false; - dtv[modid].pointer.val = TLS_DTV_UNALLOCATED; + /* Google-local fix for issues solved differently upstream. */ + if (map->l_tls_offset == NO_TLS_OFFSET + || map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET) + { + /* This module is loaded dynamically- We defer memory + allocation. */ + dtv[modid].pointer.is_static = false; + dtv[modid].pointer.val = TLS_DTV_UNALLOCATED; + } if (modid == req_modid) the_map = map; @@ -769,7 +774,7 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map) } else { - void **pp = &dtv[GET_ADDR_MODULE].pointer.val; + void ** volatile pp = &dtv[GET_ADDR_MODULE].pointer.val; while (atomic_forced_read (*pp) == TLS_DTV_UNALLOCATED) { /* for lack of a better (safe) thing to do, just spin. diff --git a/nptl/Makefile b/nptl/Makefile index 4c9015a..f57b0b8 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -300,7 +300,7 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \ endif ifeq ($(build-shared),yes) tests += tst-atfork2 tst-tls3 tst-tls4 tst-tls5 tst-tls7 tst-_res1 tst-fini1 \ - tst-stackguard1 + tst-stackguard1 tst-tls77 tests-nolibpthread += tst-fini1 ifeq ($(have-z-execstack),yes) tests += tst-execstack @@ -311,7 +311,7 @@ modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \ tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \ tst-tls5modd tst-tls5mode tst-tls5modf \ tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod \ - tst-tls7mod + tst-tls7mod tst-tls77mod extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) tst-cleanup4aux.o test-extras += $(modules-names) tst-cleanup4aux test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names))) @@ -326,6 +326,7 @@ tst-tls5modd.so-no-z-defs = yes tst-tls5mode.so-no-z-defs = yes tst-tls5modf.so-no-z-defs = yes tst-tls7mod.so-no-z-defs = yes +tst-tls77mod.so-no-z-defs = yes ifeq ($(build-shared),yes) # Build all the modules even when not actually running test programs. @@ -506,6 +507,11 @@ $(objpfx)tst-tls6.out: tst-tls6.sh $(objpfx)tst-tls5 \ '$(test-wrapper-env)' endif +$(objpfx)tst-tls77: $(libdl) $(shared-thread-library) +LDFLAGS-tst-tls77 = -rdynamic +$(objpfx)tst-tls77.out: $(objpfx)tst-tls77mod.so +$(objpfx)tst-tls77mod.so: $(shared-thread-library) + $(objpfx)tst-dlsym1: $(libdl) $(shared-thread-library) $(objpfx)tst-fini1: $(shared-thread-library) $(objpfx)tst-fini1mod.so diff --git a/nptl/tst-tls77.c b/nptl/tst-tls77.c new file mode 100644 index 0000000..84cf21b --- /dev/null +++ b/nptl/tst-tls77.c @@ -0,0 +1,107 @@ +/* Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <errno.h> +#include <pthread.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <pthreaddef.h> + +static pthread_t th; + +pthread_barrier_t b; + +void *(*dfp)(void*) = NULL; + +void * +caller(void *x) +{ + pthread_barrier_wait (&b); + + if (dfp) + dfp(NULL); + + return NULL; +} + +int +do_test (void) +{ + if (pthread_barrier_init (&b, NULL, 2) != 0) + { + puts ("barrier_init failed"); + exit (1); + } + + pthread_attr_t a; + + if (pthread_attr_init (&a) != 0) + { + puts ("attr_init failed"); + exit (1); + } + + if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0) + { + puts ("attr_setstacksize failed"); + return 1; + } + + if (pthread_create (&th, &a, caller, 0) != 0) + { + puts ("pthread_create failed"); + exit (1); + } + + void *h = dlopen ("tst-tls77mod.so", RTLD_LAZY); + if (h == NULL) + { + puts ("dlopen failed"); + exit (1); + } + + dfp = dlsym (h, "toucher"); + if (dfp == NULL) + { + printf ("dlsym for toucher failed %s\n", dlerror ()); + return 1; + } + + pthread_barrier_wait (&b); + + if (pthread_join (th, NULL) != 0) + { + puts ("join failed"); + exit (1); + } + + if (pthread_attr_destroy (&a) != 0) + { + puts ("attr_destroy failed"); + exit (1); + } + + return 0; +} + + +#define TIMEOUT 5 +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/nptl/tst-tls77mod.c b/nptl/tst-tls77mod.c new file mode 100644 index 0000000..1a541f2 --- /dev/null +++ b/nptl/tst-tls77mod.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <pthread.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <pthreaddef.h> + +__thread int tlsvar; + +__thread int iexecvar __attribute__ ((tls_model ("initial-exec"))); + +void * +toucher (void *arg) +{ + tlsvar++; + + printf ("tlsvar=%d iexecvar=%d\n", tlsvar, iexecvar); + + iexecvar++; + + printf ("tlsvar=%d iexecvar=%d\n", tlsvar, iexecvar); + + return NULL; +} |