Update.
authorUlrich Drepper <drepper@redhat.com>
Thu, 31 Jul 2003 07:42:20 +0000 (07:42 +0000)
committerUlrich Drepper <drepper@redhat.com>
Thu, 31 Jul 2003 07:42:20 +0000 (07:42 +0000)
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.

17 files changed:
ChangeLog
elf/dl-open.c
elf/dl-support.c
elf/rtld.c
elf/tls-macros.h
include/link.h
linuxthreads/ChangeLog
linuxthreads/pthread.c
nptl/ChangeLog
nptl/Makefile
nptl/allocatestack.c
nptl/init.c
nptl/pthreadP.h
nptl/tst-tls4.c [new file with mode: 0644]
nptl/tst-tls4moda.c [new file with mode: 0644]
nptl/tst-tls4modb.c [new file with mode: 0644]
sysdeps/generic/ldsodefs.h

index ae719fa21eed9e242f51fc6037de9aec59dfafff..d09516591eb0c407ce096d210cf8818f3cb98859 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+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.
+
 2003-07-31  Alexandre Oliva  <aoliva@redhat.com>
 
        * elf/dynamic-link.h (elf_machine_rel, elf_machine_rela,
@@ -26,7 +43,7 @@
        * sysdeps/s390/s390-32/dl-machine.h (elf_machine_rela,
        elf_machine_rela_relative): Adjust.
        * sysdeps/s390/s390-64/dl-machine.h (elf_machine_rela,
-       elf_machine_rela_relative): 
+       elf_machine_rela_relative): Adjust.
        * sysdeps/sh/dl-machine.h (elf_machine_rela,
        elf_machine_rela_relative): Adjust.
        * sysdeps/sparc/sparc32/dl-machine.h (elf_machine_rela,
        * elf/rtld.c (_dl_start_final, _dl_start, dl_main): Likewise.
        * elf/dl-reloc.c (_dl_allocate_static_tls): Change return type to int.
        Take l_tls_firstbyte_offset information into account.
-       (CHECK_STATIS_TLS): _dl_allocate_static_tls can fail now.
+       (CHECK_STATIC_TLS): _dl_allocate_static_tls can fail now.
        * sysdeps/generic/ldsodefs.h: Adjust _dl_allocate_static_tls prototype.
        * elf/Makefile: Add rules to build and run tst-tls14.
        * elf/tst-tls14.c: New file.
index aadd8f55f69f69ca6846e69353199d31afd0b9e4..fcda37676d5a07926d882b3e631e827b9f620a04 100644 (file)
@@ -303,6 +303,16 @@ dl_open_worker (void *a)
     }
 
 #ifdef USE_TLS
+  /* Do static TLS initialization now if it has been delayed because
+     the TLS template might not be fully relocated at _dl_allocate_static_tls
+     time.  */
+  for (l = new; l; l = l->l_next)
+    if (l->l_need_tls_init)
+      {
+       l->l_need_tls_init = 0;
+       GL(dl_init_static_tls) (l);
+      }
+
   /* We normally don't bump the TLS generation counter.  There must be
      actually a need to do this.  */
   any_tls = false;
index 52447f489a11ee7436523625c965cc63554646fc..8c58b2ba696c23d30fb7595d42f98c398c748b06 100644 (file)
@@ -98,6 +98,10 @@ int _dl_starting_up = 1;
 hp_timing_t _dl_cpuclock_offset;
 #endif
 
+#ifdef USE_TLS
+void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls;
+#endif
+
 /* This is zero at program start to signal that the global scope map is
    allocated by rtld.  Later it keeps the size of the map.  It might be
    reset if in _dl_close if the last global object is removed.  */
index c63405ac99e8d647eda660a6a782304bba312f6d..54e568804d6bc08622a977ee6a95082317897ac3 100644 (file)
@@ -622,6 +622,10 @@ dl_main (const ElfW(Phdr) *phdr,
   GL(dl_error_catch_tsd) = &_dl_initial_error_catch_tsd;
 #endif
 
+#ifdef USE_TLS
+  GL(dl_init_static_tls) = &_dl_nothread_init_static_tls;
+#endif
+
   /* Process the environment variable which control the behaviour.  */
   process_envvars (&mode);
 
index bb243d819d1aa2b85f1f7c2ad3655fc10506cb76..7c2542400a366d90200939df1eb0de1dcbc32e0c 100644 (file)
@@ -9,6 +9,7 @@
 #define VAR_INT_DEF(x) \
   asm (".section .tdata\n\t"                                                 \
        ".globl " #x "\n"                                                     \
+       ".balign 4\n"                                                         \
        #x ":\t.long 0\n\t"                                                   \
        ".size " #x ",4\n\t"                                                  \
        ".previous")
index cd662227956c3e374799e8fb420f7709a35277f2..5d10bd6679bc4439f33aaeadb9b4cc72e37978c5 100644 (file)
@@ -186,7 +186,9 @@ struct link_map
                                      the l_libname list.  */
     unsigned int l_faked:1;    /* Nonzero if this is a faked descriptor
                                   without associated file.  */
-
+    unsigned int l_need_tls_init:1; /* Nonzero if GL(dl_init_static_tls)
+                                      should be called on this link map
+                                      when relocation finishes.  */
     /* Array with version names.  */
     unsigned int l_nversions;
     struct r_found_version *l_versions;
index b151dc3406e712a725bcd62120909462a3a508cb..288d3523ab5806369e67f4b37ea9444ecc41a9b8 100644 (file)
@@ -1,3 +1,9 @@
+2003-07-30  Jakub Jelinek  <jakub@redhat.com>
+
+       * pthread.c (init_one_static_tls, __pthread_init_static_tls): New
+       functions.
+       (pthread_initialize): Initialize GL(dl_init_static_tls).
+
 2003-06-19  Daniel Jacobowitz  <drow@mvista.com>
 
        * sysdeps/pthread/timer_create.c (timer_create): Call timer_delref
index 6211124b313a46f36c388bdc071316496bd61b2e..f7081139b2a73b814e4ca329093e7fe0b20a19d5 100644 (file)
@@ -462,6 +462,44 @@ __libc_dl_error_tsd (void)
 # endif
 #endif
 
+#ifdef USE_TLS
+static inline void __attribute__((always_inline))
+init_one_static_tls (pthread_descr descr, struct link_map *map)
+{
+# if TLS_TCB_AT_TP
+  dtv_t *dtv = GET_DTV (descr);
+  void *dest = (char *) descr - map->l_tls_offset;
+# elif TLS_DTV_AT_TP
+  dtv_t *dtv = GET_DTV ((pthread_descr) ((char *) descr + TLS_PRE_TCB_SIZE));
+  void *dest = (char *) descr + 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);
+}
+
+static void
+__pthread_init_static_tls (struct link_map *map)
+{
+  size_t i;
+
+  for (i = 0; i < PTHREAD_THREADS_MAX; ++i)
+    if (__pthread_handles[i].h_descr != NULL && i != 1)
+      {
+        __pthread_lock (&__pthread_handles[i].h_lock, NULL);
+       if (__pthread_handles[i].h_descr != NULL)
+         init_one_static_tls (__pthread_handles[i].h_descr, map);
+        __pthread_unlock (&__pthread_handles[i].h_lock);
+      }
+}
+#endif
+
 static void pthread_initialize(void)
 {
   struct sigaction sa;
@@ -551,6 +589,10 @@ static void pthread_initialize(void)
   *__libc_dl_error_tsd () = *(*GL(dl_error_catch_tsd)) ();
   GL(dl_error_catch_tsd) = &__libc_dl_error_tsd;
 #endif
+
+#ifdef USE_TLS
+  GL(dl_init_static_tls) = &__pthread_init_static_tls;
+#endif
 }
 
 void __pthread_initialize(void)
index 45037eb6155a8c020b091e0d10e73143dbf297d4..d79e7988fd96831f355ceeec660b5a69247df993 100644 (file)
@@ -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
index 6beacdc40b48b4cee82d913e9ed642ba06dbe09c..cfb82e920ba8fa73e0bd968ba02c882c6adfff66 100644 (file)
@@ -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))
index e042cf4840f1311f0ee44f138741a1ef0b8e7983..729f3b85427e749ff9976788ee7e6341cf2102d1 100644 (file)
@@ -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);
+}
index 9c76773504bc707ae39bd36f197cb4ba99571c66..dae24f1eac59bbdaecbf6b20aa0253466a14edfb 100644 (file)
@@ -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 =
index a8cefabc4cc24ab8968a72613d1edfc14ac9fa41..b07c6da96140decc7967e202779243e9451b7016 100644 (file)
@@ -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 (file)
index 0000000..52775de
--- /dev/null
@@ -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 (file)
index 0000000..ff7ee56
--- /dev/null
@@ -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 (file)
index 0000000..99f3b54
--- /dev/null
@@ -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
index 565edb3fd83a6a787874f93b206e737cd6cef7e2..b647ea45e73c976f4f55e054ff8940a7cf8c8e34 100644 (file)
@@ -390,6 +390,8 @@ struct rtld_global
   EXTERN void *_dl_initial_dtv;
   /* Generation counter for the dtv.  */
   EXTERN size_t _dl_tls_generation;
+
+  EXTERN void (*_dl_init_static_tls) (struct link_map *);
 #endif
 
 #ifdef NEED_DL_SYSINFO
@@ -797,7 +799,7 @@ rtld_hidden_proto (_dl_allocate_tls)
 extern void _dl_get_tls_static_info (size_t *sizep, size_t *alignp)
      internal_function;
 
-extern int _dl_allocate_static_tls (struct link_map *map)
+extern void _dl_allocate_static_tls (struct link_map *map)
      internal_function attribute_hidden;
 
 /* These are internal entry points to the two halves of _dl_allocate_tls,
@@ -816,6 +818,10 @@ rtld_hidden_proto (_dl_deallocate_tls)
 extern void *_dl_tls_symaddr (struct link_map *map, const ElfW(Sym) *ref)
      internal_function;
 
+#if defined USE_TLS
+extern void _dl_nothread_init_static_tls (struct link_map *) attribute_hidden;
+#endif
+
 __END_DECLS
 
 #endif /* ldsodefs.h */