aboutsummaryrefslogtreecommitdiff
path: root/nptl
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2003-07-31 07:42:20 +0000
committerUlrich Drepper <drepper@redhat.com>2003-07-31 07:42:20 +0000
commitadc12574e555ec7d6ba3969eed4f829705c235ab (patch)
treecaff1741b560ff8258ace64120781354e62b56c2 /nptl
parent9722e6f3e26822835542c1c49048d855a5881510 (diff)
downloadglibc-adc12574e555ec7d6ba3969eed4f829705c235ab.zip
glibc-adc12574e555ec7d6ba3969eed4f829705c235ab.tar.gz
glibc-adc12574e555ec7d6ba3969eed4f829705c235ab.tar.bz2
Update.
2003-07-30 Jakub Jelinek <jakub@redhat.com> * elf/dl-reloc.c (_dl_allocate_static_tls): Don't return any value, call dl_signal_error directly. If already relocated, call GL(dl_init_static_tls) directly, otherwise queue it for later. (CHECK_STATIC_TLS): Undo 2003-07-24 change. * elf/rtld.c (dl_main): Initialize GL(dl_init_static_tls). * elf/dl-open.c (dl_open_worker): Call GL_dl_init_static_tls for all static TLS initializations delayed in _dl_allocate_static_tls. * elf/dl-support.c (_dl_init_static_tls): New variable. * include/link.h (struct link_map): Add l_need_tls_init. * sysdeps/generic/ldsodefs.h (_rtld_global): Add _dl_init_static_tls. (_dl_nothread_init_static_tls): New prototype. (_dl_allocate_static_tls): Adjust prototype. * elf/tls-macros.h (VAR_INT_DEF): Add alignment directive. elf_machine_rela_relative): Adjust. (CHECK_STATIC_TLS): _dl_allocate_static_tls can fail now.
Diffstat (limited to 'nptl')
-rw-r--r--nptl/ChangeLog16
-rw-r--r--nptl/Makefile8
-rw-r--r--nptl/allocatestack.c38
-rw-r--r--nptl/init.c2
-rw-r--r--nptl/pthreadP.h2
-rw-r--r--nptl/tst-tls4.c191
-rw-r--r--nptl/tst-tls4moda.c56
-rw-r--r--nptl/tst-tls4modb.c65
8 files changed, 376 insertions, 2 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 45037eb..d79e798 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,19 @@
+2003-07-30 Jakub Jelinek <jakub@redhat.com>
+
+ * init.c (__pthread_initialize_minimal_internal): Initialize
+ GL(dl_init_static_tls).
+ * pthreadP.h (__pthread_init_static_tls): New prototype.
+ * allocatestack.c (init_one_static_tls, __pthread_init_static_tls):
+ New functions.
+ * Makefile (tests): Add tst-tls4.
+ (modules-names): Add tst-tls4moda and tst-tls4modb.
+ ($(objpfx)tst-tls4): Link against libdl and libpthread.
+ ($(objpfx)tst-tls4.out): Depend on tst-tls4moda.so and
+ tst-tls4modb.so.
+ * tst-tls4.c: New file.
+ * tst-tls4moda.c: New file.
+ * tst-tls4modb.c: New file.
+
2003-06-19 Daniel Jacobowitz <drow@mvista.com>
* sysdeps/pthread/timer_create.c (timer_create): Call timer_delref
diff --git a/nptl/Makefile b/nptl/Makefile
index 6beacdc..cfb82e9 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -251,10 +251,11 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \
tst-oncex3 tst-oncex4
endif
ifeq ($(build-shared),yes)
-tests += tst-atfork2 tst-tls3 tst-_res1
+tests += tst-atfork2 tst-tls3 tst-tls4 tst-_res1
endif
-modules-names = tst-atfork2mod tst-tls3mod tst-_res1mod1 tst-_res1mod2
+modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \
+ tst-_res1mod1 tst-_res1mod2
extra-objs += $(addsuffix .os,$(strip $(modules-names)))
test-extras += $(modules-names)
test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names)))
@@ -395,6 +396,9 @@ LDFLAGS-tst-tls3 = -rdynamic
$(objpfx)tst-tls3.out: $(objpfx)tst-tls3mod.so
$(objpfx)tst-tls3mod.so: $(shared-thread-library)
+$(objpfx)tst-tls4: $(libdl) $(shared-thread-library)
+$(objpfx)tst-tls4.out: $(objpfx)tst-tls4moda.so $(objpfx)tst-tls4modb.so
+
$(objpfx)tst-dlsym1: $(libdl) $(shared-thread-library)
ifeq (yes,$(build-shared))
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
index e042cf4..729f3b8 100644
--- a/nptl/allocatestack.c
+++ b/nptl/allocatestack.c
@@ -710,3 +710,41 @@ __find_thread_by_id (pid_t tid)
return result;
}
#endif
+
+static inline void __attribute__((always_inline))
+init_one_static_tls (struct pthread *curp, struct link_map *map)
+{
+ dtv_t *dtv = GET_DTV (TLS_TPADJ (curp));
+# if TLS_TCB_AT_TP
+ void *dest = (char *) curp - map->l_tls_offset;
+# elif TLS_DTV_AT_TP
+ void *dest = (char *) curp + map->l_tls_offset + TLS_PRE_TCB_SIZE;
+# else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+# endif
+
+ /* Fill in the DTV slot so that a later LD/GD access will find it. */
+ dtv[map->l_tls_modid].pointer = dest;
+
+ /* Initialize the memory. */
+ memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
+ '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
+}
+
+void
+attribute_hidden
+__pthread_init_static_tls (struct link_map *map)
+{
+ lll_lock (stack_cache_lock);
+
+ /* Iterate over the list with system-allocated threads first. */
+ list_t *runp;
+ list_for_each (runp, &stack_used)
+ init_one_static_tls (list_entry (runp, struct pthread, list), map);
+
+ /* Now the list with threads using user-allocated stacks. */
+ list_for_each (runp, &__stack_user)
+ init_one_static_tls (list_entry (runp, struct pthread, list), map);
+
+ lll_unlock (stack_cache_lock);
+}
diff --git a/nptl/init.c b/nptl/init.c
index 9c76773..dae24f1 100644
--- a/nptl/init.c
+++ b/nptl/init.c
@@ -272,6 +272,8 @@ __pthread_initialize_minimal_internal (void)
GL(dl_error_catch_tsd) = &__libc_dl_error_tsd;
#endif
+ GL(dl_init_static_tls) = &__pthread_init_static_tls;
+
/* Register the fork generation counter with the libc. */
#ifndef TLS_MULTIPLE_THREADS_IN_TCB
__libc_multiple_threads_ptr =
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index a8cefab..b07c6da 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -257,6 +257,8 @@ extern int *__libc_multiple_threads_ptr attribute_hidden;
/* Find a thread given its TID. */
extern struct pthread *__find_thread_by_id (pid_t tid) attribute_hidden;
+extern void __pthread_init_static_tls (struct link_map *) attribute_hidden;
+
/* Namespace save aliases. */
extern int __pthread_getschedparam (pthread_t thread_id, int *policy,
diff --git a/nptl/tst-tls4.c b/nptl/tst-tls4.c
new file mode 100644
index 0000000..52775de
--- /dev/null
+++ b/nptl/tst-tls4.c
@@ -0,0 +1,191 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+ 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <tls.h>
+
+#if HAVE___THREAD && defined HAVE_TLS_MODEL_ATTRIBUTE
+
+#define N 3
+
+void (*test1) (void), (*test2) (void);
+
+pthread_barrier_t b2, b3;
+
+static void *
+tf (void *arg)
+{
+ int i;
+
+ for (i = 0; i <= (uintptr_t) arg; ++i)
+ {
+ int r = pthread_barrier_wait (&b3);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf: barrier_wait failed");
+ exit (1);
+ }
+ }
+
+ test1 ();
+
+ for (i = 0; i < 3; ++i)
+ {
+ int r = pthread_barrier_wait (&b3);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf: barrier_wait failed");
+ exit (1);
+ }
+ }
+
+ test2 ();
+
+ for (i = 0; i < 3 - (uintptr_t) arg; ++i)
+ {
+ int r = pthread_barrier_wait (&b3);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf: barrier_wait failed");
+ exit (1);
+ }
+ }
+
+ return NULL;
+}
+
+static void *
+tf2 (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf2: barrier_wait failed");
+ exit (1);
+ }
+
+ int i;
+ for (i = 0; i < N; ++i)
+ tf (arg);
+ return NULL;
+}
+
+int
+do_test (void)
+{
+ pthread_t th[2];
+ const char *modules[N]
+ = { "tst-tls4moda.so", "tst-tls4moda.so", "tst-tls4modb.so" };
+
+ if (pthread_barrier_init (&b2, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ if (pthread_barrier_init (&b3, NULL, 3) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ if (pthread_create (&th[0], NULL, tf2, (void *) (uintptr_t) 1))
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ return 1;
+ }
+
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ void *h = dlopen (modules[i], RTLD_LAZY);
+ if (h == NULL)
+ {
+ printf ("dlopen failed %s\n", dlerror ());
+ return 1;
+ }
+
+ test1 = dlsym (h, "test1");
+ if (test1 == NULL)
+ {
+ printf ("dlsym for test1 failed %s\n", dlerror ());
+ return 1;
+ }
+
+ test2 = dlsym (h, "test2");
+ if (test2 == NULL)
+ {
+ printf ("dlsym for test2 failed %s\n", dlerror ());
+ return 1;
+ }
+
+ if (pthread_create (&th[1], NULL, tf, (void *) (uintptr_t) 2))
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+
+ tf ((void *) (uintptr_t) 0);
+
+ if (pthread_join (th[1], NULL) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (dlclose (h))
+ {
+ puts ("dlclose failed");
+ return 1;
+ }
+
+ printf ("test %d with %s succeeded\n", i, modules[i]);
+ }
+
+ if (pthread_join (th[0], NULL) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+
+#else
+
+#define TEST_FUNCTION 0
+
+#endif
+
+#include "../test-skeleton.c"
diff --git a/nptl/tst-tls4moda.c b/nptl/tst-tls4moda.c
new file mode 100644
index 0000000..ff7ee56
--- /dev/null
+++ b/nptl/tst-tls4moda.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+ 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <tls.h>
+
+#if HAVE___THREAD && defined HAVE_TLS_MODEL_ATTRIBUTE
+
+static __thread unsigned char foo [32]
+ __attribute__ ((tls_model ("initial-exec"), aligned (sizeof (void *))));
+
+void
+test1 (void)
+{
+ size_t s;
+
+ for (s = 0; s < sizeof (foo); ++s)
+ {
+ if (foo [s])
+ abort ();
+ foo [s] = s;
+ }
+}
+
+void
+test2 (void)
+{
+ size_t s;
+
+ for (s = 0; s < sizeof (foo); ++s)
+ {
+ if (foo [s] != s)
+ abort ();
+ foo [s] = sizeof (foo) - s;
+ }
+}
+
+#endif
diff --git a/nptl/tst-tls4modb.c b/nptl/tst-tls4modb.c
new file mode 100644
index 0000000..99f3b54
--- /dev/null
+++ b/nptl/tst-tls4modb.c
@@ -0,0 +1,65 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
+
+ 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <tls.h>
+
+#if HAVE___THREAD && defined HAVE_TLS_MODEL_ATTRIBUTE
+
+static int i;
+int bar;
+
+static __thread void *foo [32 / sizeof (void *)]
+ __attribute__ ((tls_model ("initial-exec"), aligned (sizeof (void *))))
+ = { &i, &bar };
+
+void
+test1 (void)
+{
+ size_t s;
+
+ if (foo [0] != &i || foo [1] != &bar)
+ abort ();
+
+ foo [0] = NULL;
+ foo [1] = NULL;
+ for (s = 0; s < sizeof (foo) / sizeof (void *); ++s)
+ {
+ if (foo [s])
+ abort ();
+ foo [s] = &foo[s];
+ }
+}
+
+void
+test2 (void)
+{
+ size_t s;
+
+ for (s = 0; s < sizeof (foo) / sizeof (void *); ++s)
+ {
+ if (foo [s] != &foo [s])
+ abort ();
+ foo [s] = &foo [s ^ 1];
+ }
+}
+
+#endif