unofficial mirror of libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [RFC PATCH htl v2 0/4] Rewrite THREAD_GSCOPE
@ 2021-08-30 15:26 Sergey Bugaev via Libc-alpha
  2021-08-30 15:26 ` [RFC PATCH htl v2 1/4] htl: Move thread table to ld.so Sergey Bugaev via Libc-alpha
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Sergey Bugaev via Libc-alpha @ 2021-08-30 15:26 UTC (permalink / raw
  To: libc-alpha, bug-hurd; +Cc: samuel.thibault, Sergey Bugaev

Hello,

this is a revised version of the patchset I have sent a few months ago [0].
Sending to both bug-hurd and libc-alpha this time.

[0]: https://lists.gnu.org/archive/html/bug-hurd/2021-05/msg00063.html

The goal is to get rid of the excessive (and redundant) gsync_wake () calls.
The means are rewriting how THREAD_GSCOPE_* is implemented in HTL to work more
like its NPTL counterpart. To get this working, I first have to expose HTL's
internal thread table to ld.so, a lot like NPTL already does.

Before this patchset:
$ rpctrace uname |& grep -c gsync_wake
57

With this patchset (first 3 patches):
$ ./testrun.sh --tool=rpctrace /bin/uname |& grep -c gsync_wake
0

The unsolved question with this patchset is the fate of THREAD_GSCOPE_IN_TCB.
Apparently, when it was introduced in [1], it was indeed only used to
distinguish between cases where the GSCOPE flag is in TCB or not. But as of
now, it is used mostly as a generic way to conditionally compile either HTL-
or NPTL-specific code, mostly for TLS initialization. Now that all ports have
the GSCOPE flag in TCB, this definition no longer does what it says.

[1]: https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=a5df0318ef30a4dcff3fa2cb82265f641813d9ea

I can think of two ways this can be handled:

* Code can be rewritten and reorganized to use port-specific files instead of
  conditional compilation. From looking at how glibc source is organized, this
  appears to be the generally preferred way. I'm sending one more patch that
  makes a (perhaps misguided) attempt to do this; but I'm not sure what would
  be good way to handle the definitions in <ldsodefs.h> -- please take a look.

* A more conservative approach would be to leave the code using
  THREAD_GSCOPE_IN_TCB as is for now, but change the variable's name to better
  reflect what it's used for. I haven't really been able to come up with a good
  name, though.

Alternatively, it could just be left as is for now.

Sergey Bugaev (4):
  htl: Move thread table to ld.so
  htl: Reimplement GSCOPE
  testrun.sh: Add support for --tool=rpctrace
  XXX: Attempt to get rid of most THREAD_GSCOPE_IN_TCB usages

 Makefile                                   |  9 +++-
 elf/dl-reloc.c                             | 21 ---------
 elf/dl-support.c                           | 15 ------
 elf/dl-tls.c                               | 39 ---------------
 htl/Versions                               |  2 -
 htl/pt-alloc.c                             | 50 ++++++++------------
 htl/pt-create.c                            | 11 ++---
 htl/pt-internal.h                          | 23 +++------
 sysdeps/generic/ldsodefs.h                 | 10 ++--
 sysdeps/htl/dl-support.c                   | 28 +++++++++++
 sysdeps/htl/dl-thread_gscope_wait.c        | 55 ++++++++++++++++++++++
 sysdeps/htl/dl-tls.c                       | 39 +++++++++++++++
 {elf => sysdeps/htl}/dl-tls_init_tp.c      |  4 +-
 sysdeps/htl/pt-key-delete.c                |  8 ++--
 sysdeps/htl/pthreadP.h                     |  2 -
 sysdeps/htl/raise.c                        |  8 +++-
 sysdeps/htl/thrd_current.c                 |  7 ++-
 sysdeps/mach/hurd/htl/pt-sigstate-init.c   |  2 +-
 sysdeps/mach/hurd/htl/pt-sysdep.c          |  2 +-
 sysdeps/mach/hurd/htl/pt-sysdep.h          |  2 +-
 sysdeps/mach/hurd/i386/tls.h               | 19 ++++++++
 sysdeps/mach/hurd/tls.h                    | 20 +-------
 sysdeps/nptl/dl-support.c                  | 26 ++++++++++
 sysdeps/nptl/dl-tls.c                      | 53 +++++++++++++++++++++
 sysdeps/unix/sysv/linux/alpha/dl-support.c |  2 +-
 25 files changed, 287 insertions(+), 170 deletions(-)
 create mode 100644 sysdeps/htl/dl-support.c
 create mode 100644 sysdeps/htl/dl-thread_gscope_wait.c
 create mode 100644 sysdeps/htl/dl-tls.c
 rename {elf => sysdeps/htl}/dl-tls_init_tp.c (93%)
 create mode 100644 sysdeps/nptl/dl-support.c
 create mode 100644 sysdeps/nptl/dl-tls.c

-- 
2.31.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RFC PATCH htl v2 1/4] htl: Move thread table to ld.so
  2021-08-30 15:26 [RFC PATCH htl v2 0/4] Rewrite THREAD_GSCOPE Sergey Bugaev via Libc-alpha
@ 2021-08-30 15:26 ` Sergey Bugaev via Libc-alpha
  2021-08-30 15:26 ` [RFC PATCH htl v2 2/4] htl: Reimplement GSCOPE Sergey Bugaev via Libc-alpha
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Sergey Bugaev via Libc-alpha @ 2021-08-30 15:26 UTC (permalink / raw
  To: libc-alpha, bug-hurd; +Cc: samuel.thibault, Sergey Bugaev

The next commit is going to introduce a new implementation of
THREAD_GSCOPE_WAIT which needs to access the list of threads.
Since it must be usable from the dynamic laoder, we have to move
the symbols for the list of threads into the loader.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
---
 htl/Versions                             |  2 -
 htl/pt-alloc.c                           | 50 ++++++++++--------------
 htl/pt-create.c                          | 11 ++----
 htl/pt-internal.h                        | 23 ++++-------
 sysdeps/generic/ldsodefs.h               |  8 ++++
 sysdeps/htl/dl-support.c                 | 23 +++++++++++
 sysdeps/htl/pt-key-delete.c              |  8 ++--
 sysdeps/htl/pthreadP.h                   |  2 -
 sysdeps/htl/raise.c                      |  8 +++-
 sysdeps/htl/thrd_current.c               |  7 +++-
 sysdeps/mach/hurd/htl/pt-sigstate-init.c |  2 +-
 sysdeps/mach/hurd/htl/pt-sysdep.c        |  2 +-
 sysdeps/mach/hurd/htl/pt-sysdep.h        |  2 +-
 13 files changed, 81 insertions(+), 67 deletions(-)
 create mode 100644 sysdeps/htl/dl-support.c

diff --git a/htl/Versions b/htl/Versions
index 4aea321016..4e0ebac285 100644
--- a/htl/Versions
+++ b/htl/Versions
@@ -168,8 +168,6 @@ libpthread {
   GLIBC_PRIVATE {
     __pthread_initialize_minimal;
 
-    __pthread_threads;
-
     __cthread_detach;
     __cthread_fork;
     __pthread_detach;
diff --git a/htl/pt-alloc.c b/htl/pt-alloc.c
index acc67f2711..f6708a60bf 100644
--- a/htl/pt-alloc.c
+++ b/htl/pt-alloc.c
@@ -28,19 +28,9 @@
    of the threads functions "shall fail" if "No thread could be found
    corresponding to that specified by the given thread ID."  */
 
-/* Thread ID lookup table.  */
-struct __pthread **__pthread_threads;
-
 /* The size of the thread ID lookup table.  */
 int __pthread_max_threads;
 
-/* The total number of thread IDs currently in use, or on the list of
-   available thread IDs.  */
-int __pthread_num_threads;
-
-/* A lock for the table, and the other variables above.  */
-pthread_rwlock_t __pthread_threads_lock;
-
 /* List of thread structures corresponding to free thread IDs.  */
 struct __pthread *__pthread_free_threads;
 pthread_mutex_t __pthread_free_threads_lock;
@@ -132,25 +122,25 @@ __pthread_alloc (struct __pthread **pthread)
     }
 
 retry:
-  __pthread_rwlock_wrlock (&__pthread_threads_lock);
+  lll_lock (GL (dl_pthread_threads_lock), LLL_PRIVATE);
 
-  if (__pthread_num_threads < __pthread_max_threads)
+  if (GL (dl_pthread_num_threads) < __pthread_max_threads)
     {
       /* We have a free slot.  Use the slot number plus one as the
          thread ID for the new thread.  */
-      new->thread = 1 + __pthread_num_threads++;
-      __pthread_threads[new->thread - 1] = NULL;
+      new->thread = 1 + GL (dl_pthread_num_threads)++;
+      GL (dl_pthread_threads)[new->thread - 1] = NULL;
 
-      __pthread_rwlock_unlock (&__pthread_threads_lock);
+      lll_unlock (GL (dl_pthread_threads_lock), LLL_PRIVATE);
 
       *pthread = new;
       return 0;
     }
 #ifdef PTHREAD_THREADS_MAX
-  else if (__pthread_num_threads >= PTHREAD_THREADS_MAX)
+  else if (GL (dl_pthread_num_threads) >= PTHREAD_THREADS_MAX)
     {
       /* We have reached the limit on the number of threads per process.  */
-      __pthread_rwlock_unlock (&__pthread_threads_lock);
+      lll_unlock (GL (dl_pthread_threads_lock), LLL_PRIVATE);
 
       free (new);
       return EAGAIN;
@@ -162,7 +152,7 @@ retry:
      memory allocation, since that's a potentially blocking operation.  */
   max_threads = __pthread_max_threads;
 
-  __pthread_rwlock_unlock (&__pthread_threads_lock);
+  lll_unlock (GL (dl_pthread_threads_lock), LLL_PRIVATE);
 
   /* Allocate a new lookup table that's twice as large.  */
   new_max_threads
@@ -174,13 +164,13 @@ retry:
       return ENOMEM;
     }
 
-  __pthread_rwlock_wrlock (&__pthread_threads_lock);
+  lll_lock (GL (dl_pthread_threads_lock), LLL_PRIVATE);
 
   /* Check if nobody else has already enlarged the table.  */
   if (max_threads != __pthread_max_threads)
     {
       /* Yep, they did.  */
-      __pthread_rwlock_unlock (&__pthread_threads_lock);
+      lll_unlock (GL (dl_pthread_threads_lock), LLL_PRIVATE);
 
       /* Free the newly allocated table and try again to allocate a slot.  */
       free (threads);
@@ -188,22 +178,22 @@ retry:
     }
 
   /* Copy over the contents of the old table.  */
-  memcpy (threads, __pthread_threads,
+  memcpy (threads, GL (dl_pthread_threads),
 	  __pthread_max_threads * sizeof (struct __pthread *));
 
   /* Save the location of the old table.  We want to deallocate its
      storage after we released the lock.  */
-  old_threads = __pthread_threads;
+  old_threads = GL (dl_pthread_threads);
 
   /* Replace the table with the new one.  */
   __pthread_max_threads = new_max_threads;
-  __pthread_threads = threads;
+  GL (dl_pthread_threads) = threads;
 
   /* And allocate ourselves one of the newly created slots.  */
-  new->thread = 1 + __pthread_num_threads++;
-  __pthread_threads[new->thread - 1] = NULL;
+  new->thread = 1 + GL (dl_pthread_num_threads)++;
+  GL (dl_pthread_threads)[new->thread - 1] = NULL;
 
-  __pthread_rwlock_unlock (&__pthread_threads_lock);
+  lll_unlock (GL (dl_pthread_threads_lock), LLL_PRIVATE);
 
   free (old_threads);
 
@@ -217,10 +207,10 @@ __pthread_init_static_tls (struct link_map *map)
 {
   int i;
 
-  __pthread_rwlock_wrlock (&__pthread_threads_lock);
-  for (i = 0; i < __pthread_num_threads; ++i)
+  lll_lock (GL (dl_pthread_threads_lock), LLL_PRIVATE);
+  for (i = 0; i < GL (dl_pthread_num_threads); ++i)
     {
-      struct __pthread *t = __pthread_threads[i];
+      struct __pthread *t = GL (dl_pthread_threads)[i];
 
       if (t == NULL)
 	continue;
@@ -237,5 +227,5 @@ __pthread_init_static_tls (struct link_map *map)
       memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
 	      '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
     }
-  __pthread_rwlock_unlock (&__pthread_threads_lock);
+  lll_unlock (GL (dl_pthread_threads_lock), LLL_PRIVATE);
 }
diff --git a/htl/pt-create.c b/htl/pt-create.c
index f0a1f1ab09..4e16cbbdc9 100644
--- a/htl/pt-create.c
+++ b/htl/pt-create.c
@@ -207,7 +207,7 @@ __pthread_create_internal (struct __pthread **thread,
      creating thread.  The set of signals pending for the new thread
      shall be empty."  If the currnet thread is not a pthread then we
      just inherit the process' sigmask.  */
-  if (__pthread_num_threads == 1)
+  if (GL (dl_pthread_num_threads) == 1)
     err = __sigprocmask (0, 0, &pthread->init_sigset);
   else
     err = __pthread_sigstate (_pthread_self (), 0, 0, &pthread->init_sigset, 0);
@@ -227,13 +227,8 @@ __pthread_create_internal (struct __pthread **thread,
      new thread runs.  */
   atomic_increment (&__pthread_total);
 
-  /* Store a pointer to this thread in the thread ID lookup table.  We
-     could use __thread_setid, however, we only lock for reading as no
-     other thread should be using this entry (we also assume that the
-     store is atomic).  */
-  __pthread_rwlock_rdlock (&__pthread_threads_lock);
-  __pthread_threads[pthread->thread - 1] = pthread;
-  __pthread_rwlock_unlock (&__pthread_threads_lock);
+  /* Store a pointer to this thread in the thread ID lookup table.  */
+  __pthread_setid (pthread->thread, pthread);
 
   /* At this point it is possible to guess our pthread ID.  We have to
      make sure that all functions taking a pthread_t argument can
diff --git a/htl/pt-internal.h b/htl/pt-internal.h
index 34e6da338e..7c16f8744d 100644
--- a/htl/pt-internal.h
+++ b/htl/pt-internal.h
@@ -166,33 +166,24 @@ __pthread_dequeue (struct __pthread *thread)
 /* The total number of threads currently active.  */
 extern unsigned int __pthread_total;
 
-/* The total number of thread IDs currently in use, or on the list of
-   available thread IDs.  */
-extern int __pthread_num_threads;
-
 /* Concurrency hint.  */
 extern int __pthread_concurrency;
 
-/* Array of __pthread structures and its lock.  Indexed by the pthread
-   id minus one.  (Why not just use the pthread id?  Because some
-   brain-dead users of the pthread interface incorrectly assume that 0
-   is an invalid pthread id.)  */
-extern struct __pthread **__pthread_threads;
+/* The size of the thread ID lookup table.  */
 extern int __pthread_max_threads;
-extern pthread_rwlock_t __pthread_threads_lock;
 
 #define __pthread_getid(thread) \
   ({ struct __pthread *__t = NULL;                                           \
-     __pthread_rwlock_rdlock (&__pthread_threads_lock);                      \
+     lll_lock (GL (dl_pthread_threads_lock), LLL_PRIVATE);                   \
      if (thread <= __pthread_max_threads)                                    \
-       __t = __pthread_threads[thread - 1];                                  \
-     __pthread_rwlock_unlock (&__pthread_threads_lock);                      \
+       __t = GL (dl_pthread_threads)[thread - 1];                            \
+     lll_unlock (GL (dl_pthread_threads_lock), LLL_PRIVATE);                 \
      __t; })
 
 #define __pthread_setid(thread, pthread) \
-  __pthread_rwlock_wrlock (&__pthread_threads_lock);                         \
-  __pthread_threads[thread - 1] = pthread;                                   \
-  __pthread_rwlock_unlock (&__pthread_threads_lock);
+  lll_lock (GL (dl_pthread_threads_lock), LLL_PRIVATE);                      \
+  GL (dl_pthread_threads)[thread - 1] = pthread;                             \
+  lll_unlock (GL (dl_pthread_threads_lock), LLL_PRIVATE);
 
 /* Similar to pthread_self, but returns the thread descriptor instead
    of the thread ID.  */
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 9c15259236..31c7d3945b 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -488,6 +488,14 @@ struct rtld_global
   EXTERN int _dl_stack_cache_lock;
 #else
   EXTERN int _dl_thread_gscope_count;
+
+  /* The total number of thread IDs currently in use, or on the list of
+     available thread IDs.  */
+  EXTERN int _dl_pthread_num_threads;
+
+  /* Array of __pthread structures and its lock.  */
+  EXTERN struct __pthread **_dl_pthread_threads;
+  EXTERN int _dl_pthread_threads_lock;
 #endif
 #ifdef SHARED
 };
diff --git a/sysdeps/htl/dl-support.c b/sysdeps/htl/dl-support.c
new file mode 100644
index 0000000000..21a391a59f
--- /dev/null
+++ b/sysdeps/htl/dl-support.c
@@ -0,0 +1,23 @@
+/* Support for dynamic linking code in static libc.
+   Copyright (C) 2007-2021 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <elf/dl-support.c>
+
+int _dl_pthread_num_threads;
+struct __pthread **_dl_pthread_threads;
+int _dl_pthread_threads_lock;
diff --git a/sysdeps/htl/pt-key-delete.c b/sysdeps/htl/pt-key-delete.c
index 4e77ef7521..4acd8dd755 100644
--- a/sysdeps/htl/pt-key-delete.c
+++ b/sysdeps/htl/pt-key-delete.c
@@ -39,12 +39,12 @@ __pthread_key_delete (pthread_key_t key)
       __pthread_key_destructors[key] = PTHREAD_KEY_INVALID;
       __pthread_key_invalid_count++;
 
-      __pthread_rwlock_rdlock (&__pthread_threads_lock);
-      for (i = 0; i < __pthread_num_threads; ++i)
+      lll_lock (GL (dl_pthread_threads_lock), LLL_PRIVATE);
+      for (i = 0; i < GL (dl_pthread_num_threads); ++i)
 	{
 	  struct __pthread *t;
 
-	  t = __pthread_threads[i];
+	  t = GL (dl_pthread_threads)[i];
 
 	  if (t == NULL)
 	    continue;
@@ -54,7 +54,7 @@ __pthread_key_delete (pthread_key_t key)
 	  if (key < t->thread_specifics_size)
 	    t->thread_specifics[key] = 0;
 	}
-      __pthread_rwlock_unlock (&__pthread_threads_lock);
+      lll_unlock (GL (dl_pthread_threads_lock), LLL_PRIVATE);
     }
 
   __pthread_mutex_unlock (&__pthread_key_lock);
diff --git a/sysdeps/htl/pthreadP.h b/sysdeps/htl/pthreadP.h
index 3fd774269f..8b02bef355 100644
--- a/sysdeps/htl/pthreadP.h
+++ b/sysdeps/htl/pthreadP.h
@@ -31,8 +31,6 @@ extern void __pthread_init_static_tls (struct link_map *) attribute_hidden;
 
 /* These represent the interface used by glibc itself.  */
 
-extern struct __pthread **__pthread_threads;
-
 extern int __pthread_mutex_init (pthread_mutex_t *__mutex, const pthread_mutexattr_t *__attr);
 extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex);
 extern int __pthread_mutex_lock (pthread_mutex_t *__mutex);
diff --git a/sysdeps/htl/raise.c b/sysdeps/htl/raise.c
index 6594d0870f..94d3f230e4 100644
--- a/sysdeps/htl/raise.c
+++ b/sysdeps/htl/raise.c
@@ -18,6 +18,7 @@
    License along with this program.  If not, see
    <https://www.gnu.org/licenses/>.  */
 
+#include <ldsodefs.h>
 #include <pthreadP.h>
 #include <signal.h>
 #include <unistd.h>
@@ -25,6 +26,11 @@
 #pragma weak __pthread_kill
 #pragma weak __pthread_self
 #pragma weak __pthread_threads
+
+#ifndef SHARED
+#pragma weak _dl_pthread_threads
+#endif
+
 int
 raise (int signo)
 {
@@ -32,7 +38,7 @@ raise (int signo)
      "the effect of the raise() function shall be equivalent to
      calling: pthread_kill(pthread_self(), sig);"  */
 
-  if (__pthread_kill != NULL && __pthread_threads != NULL)
+  if (__pthread_kill != NULL && GL (dl_pthread_threads) != NULL)
     {
       int err;
       err = __pthread_kill (__pthread_self (), signo);
diff --git a/sysdeps/htl/thrd_current.c b/sysdeps/htl/thrd_current.c
index eecb86af85..87359677d6 100644
--- a/sysdeps/htl/thrd_current.c
+++ b/sysdeps/htl/thrd_current.c
@@ -17,14 +17,19 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include "thrd_priv.h"
+#include <ldsodefs.h>
 
 #pragma weak __pthread_self
 #pragma weak __pthread_threads
 
+#ifndef SHARED
+#pragma weak _dl_pthread_threads
+#endif
+
 thrd_t
 thrd_current (void)
 {
-  if (__pthread_threads)
+  if (GL (dl_pthread_threads))
     return (thrd_t) __pthread_self ();
 
   return (thrd_t) 0;
diff --git a/sysdeps/mach/hurd/htl/pt-sigstate-init.c b/sysdeps/mach/hurd/htl/pt-sigstate-init.c
index 399068ca78..6f43ade653 100644
--- a/sysdeps/mach/hurd/htl/pt-sigstate-init.c
+++ b/sysdeps/mach/hurd/htl/pt-sigstate-init.c
@@ -37,7 +37,7 @@ __pthread_sigstate_init (struct __pthread *thread)
       struct hurd_sigstate *ss = _hurd_thread_sigstate (thread->kernel_thread);
       _hurd_sigstate_set_global_rcv (ss);
     }
-  else if (__pthread_num_threads >= 2)
+  else if (GL (dl_pthread_num_threads) >= 2)
     do_init_global = 1;
 
   return 0;
diff --git a/sysdeps/mach/hurd/htl/pt-sysdep.c b/sysdeps/mach/hurd/htl/pt-sysdep.c
index 03ff8079ba..2fd0a8d6e7 100644
--- a/sysdeps/mach/hurd/htl/pt-sysdep.c
+++ b/sysdeps/mach/hurd/htl/pt-sysdep.c
@@ -45,7 +45,7 @@ _init_routine (void *stack)
   int err;
   pthread_attr_t attr, *attrp = 0;
 
-  if (__pthread_threads != NULL)
+  if (GL (dl_pthread_threads) != NULL)
     /* Already initialized */
     return;
 
diff --git a/sysdeps/mach/hurd/htl/pt-sysdep.h b/sysdeps/mach/hurd/htl/pt-sysdep.h
index acd4fce9c4..d90563af0c 100644
--- a/sysdeps/mach/hurd/htl/pt-sysdep.h
+++ b/sysdeps/mach/hurd/htl/pt-sysdep.h
@@ -37,7 +37,7 @@ extern __thread struct __pthread *___pthread_self;
 	({                                                         \
 	  struct __pthread *thread;                                \
 	                                                           \
-	  assert (__pthread_threads);                              \
+	  assert (GL (dl_pthread_threads));                        \
 	  thread = ___pthread_self;                                \
 	                                                           \
 	  assert (thread);                                         \
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC PATCH htl v2 2/4] htl: Reimplement GSCOPE
  2021-08-30 15:26 [RFC PATCH htl v2 0/4] Rewrite THREAD_GSCOPE Sergey Bugaev via Libc-alpha
  2021-08-30 15:26 ` [RFC PATCH htl v2 1/4] htl: Move thread table to ld.so Sergey Bugaev via Libc-alpha
@ 2021-08-30 15:26 ` Sergey Bugaev via Libc-alpha
  2021-08-30 15:26 ` [RFC PATCH htl v2 3/4] testrun.sh: Add support for --tool=rpctrace Sergey Bugaev via Libc-alpha
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Sergey Bugaev via Libc-alpha @ 2021-08-30 15:26 UTC (permalink / raw
  To: libc-alpha, bug-hurd; +Cc: samuel.thibault, Sergey Bugaev

This is a new implementation of GSCOPE which largely mirrors its NPTL
counterpart. Same as in NPTL, instead of a global flag shared between
threads, there is now a per-thread GSCOPE flag stored in each thread's
TCB. This makes entering and exiting a GSCOPE faster at the expense of
making THREAD_GSCOPE_WAIT () slower.

The largest win is the elimination of many redundant gsync_wake () RPC
calls; previously, even simplest programs would make dozens of fully
redundant gsync_wake () calls.

Despite all ports now putting GSCOPE flag into TCP, this patch keeps
the THREAD_GSCOPE_IN_TCB preprocessor definition, with value 0 for HTL
and 1 for NPTL. It turns out that although originally this definition
was indeed used to distinguish between the cases where the GSCOPE flag
was stored in TCB or not, it has since become used as a general way to
distinguish between HTL and NPTL. It may be worthwhile to get rid of
this flag, or at least rename it to better reflect what it's used for.
This patch does neither, though.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
---
 elf/dl-support.c                    |  1 -
 sysdeps/generic/ldsodefs.h          |  4 ---
 sysdeps/htl/dl-thread_gscope_wait.c | 55 +++++++++++++++++++++++++++++
 sysdeps/mach/hurd/i386/tls.h        | 19 ++++++++++
 sysdeps/mach/hurd/tls.h             | 20 +----------
 5 files changed, 75 insertions(+), 24 deletions(-)
 create mode 100644 sysdeps/htl/dl-thread_gscope_wait.c

diff --git a/elf/dl-support.c b/elf/dl-support.c
index 0155718175..68abf606ca 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -195,7 +195,6 @@ int _dl_stack_cache_lock;
    when it was not, we do it by calling this function.
    It returns an errno code or zero on success.  */
 int (*_dl_make_stack_executable_hook) (void **) = _dl_make_stack_executable;
-int _dl_thread_gscope_count;
 void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls;
 #endif
 struct dl_scope_free_list *_dl_scope_free_list;
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 31c7d3945b..5a779ae1a3 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -487,8 +487,6 @@ struct rtld_global
   /* Mutex protecting the stack lists.  */
   EXTERN int _dl_stack_cache_lock;
 #else
-  EXTERN int _dl_thread_gscope_count;
-
   /* The total number of thread IDs currently in use, or on the list of
      available thread IDs.  */
   EXTERN int _dl_pthread_num_threads;
@@ -1379,10 +1377,8 @@ __rtld_mutex_init (void)
 }
 #endif /* !PTHREAD_IN_LIBC */
 
-#if THREAD_GSCOPE_IN_TCB
 void __thread_gscope_wait (void) attribute_hidden;
 # define THREAD_GSCOPE_WAIT() __thread_gscope_wait ()
-#endif
 
 __END_DECLS
 
diff --git a/sysdeps/htl/dl-thread_gscope_wait.c b/sysdeps/htl/dl-thread_gscope_wait.c
new file mode 100644
index 0000000000..b277217b8e
--- /dev/null
+++ b/sysdeps/htl/dl-thread_gscope_wait.c
@@ -0,0 +1,55 @@
+/* Out-of-line notification function for the GSCOPE locking mechanism.
+   Copyright (C) 2007-2021 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <ldsodefs.h>
+#include <pthread.h>
+#include <htl/pt-internal.h>
+
+void
+__thread_gscope_wait (void)
+{
+  size_t i;
+  struct __pthread *t;
+  int *gscope_flagp;
+
+  lll_lock (GL (dl_pthread_threads_lock), LLL_PRIVATE);
+
+  /* Iterate over the list of threads.  */
+  for (i = 0; i < GL (dl_pthread_num_threads); ++i)
+    {
+      t = GL (dl_pthread_threads[i]);
+      if (t == NULL || t->tcb->gscope_flag == THREAD_GSCOPE_FLAG_UNUSED)
+        continue;
+
+      gscope_flagp = &t->tcb->gscope_flag;
+
+      /* We have to wait until this thread is done with the global
+         scope.  First tell the thread that we are waiting and
+         possibly have to be woken.  */
+      if (atomic_compare_and_exchange_bool_acq (gscope_flagp,
+                                                THREAD_GSCOPE_FLAG_WAIT,
+                                                THREAD_GSCOPE_FLAG_USED))
+        continue;
+
+      do
+        lll_wait (gscope_flagp, THREAD_GSCOPE_FLAG_WAIT, LLL_PRIVATE);
+      while (*gscope_flagp == THREAD_GSCOPE_FLAG_WAIT);
+    }
+
+  lll_unlock (GL (dl_pthread_threads_lock), LLL_PRIVATE);
+}
diff --git a/sysdeps/mach/hurd/i386/tls.h b/sysdeps/mach/hurd/i386/tls.h
index 057b2613f3..c70ea73a81 100644
--- a/sysdeps/mach/hurd/i386/tls.h
+++ b/sysdeps/mach/hurd/i386/tls.h
@@ -369,6 +369,25 @@ _hurd_tls_new (thread_t child, struct i386_thread_state *state, tcbhead_t *tcb)
   return err;
 }
 
+/* Global scope switch support.  */
+# define THREAD_GSCOPE_FLAG_UNUSED 0
+# define THREAD_GSCOPE_FLAG_USED   1
+# define THREAD_GSCOPE_FLAG_WAIT   2
+
+# define THREAD_GSCOPE_SET_FLAG() \
+  THREAD_SETMEM (THREAD_SELF, gscope_flag, THREAD_GSCOPE_FLAG_USED)
+
+# define THREAD_GSCOPE_RESET_FLAG() \
+  ({                                                                         \
+    int __flag;                                                              \
+    asm volatile ("xchgl %0, %%gs:%P1"                                       \
+                  : "=r" (__flag)                                            \
+                  : "i" (offsetof (tcbhead_t, gscope_flag)),                 \
+                    "0" (THREAD_GSCOPE_FLAG_UNUSED));                        \
+    if (__flag == THREAD_GSCOPE_FLAG_WAIT)                                   \
+      lll_wake (THREAD_SELF->gscope_flag, LLL_PRIVATE);                      \
+  })
+
 #endif	/* !__ASSEMBLER__ */
 
 #endif	/* i386/tls.h */
diff --git a/sysdeps/mach/hurd/tls.h b/sysdeps/mach/hurd/tls.h
index f83956d3d7..98dc319745 100644
--- a/sysdeps/mach/hurd/tls.h
+++ b/sysdeps/mach/hurd/tls.h
@@ -52,25 +52,7 @@
 # define GET_DTV(descr) \
   (((tcbhead_t *) (descr))->dtv)
 
-/* Global scope switch support.  */
-#define THREAD_GSCOPE_IN_TCB      0
-#define THREAD_GSCOPE_GLOBAL
-#define THREAD_GSCOPE_SET_FLAG() \
-  atomic_exchange_and_add_acq (&GL(dl_thread_gscope_count), 1)
-#define THREAD_GSCOPE_RESET_FLAG() \
-  do 									      \
-    if (atomic_exchange_and_add_rel (&GL(dl_thread_gscope_count), -1) == 1)   \
-      lll_wake (GL(dl_thread_gscope_count), 0);				      \
-  while (0)
-#define THREAD_GSCOPE_WAIT() \
-  do 									      \
-    {									      \
-      int count;							      \
-      atomic_write_barrier ();						      \
-      while ((count = GL(dl_thread_gscope_count)))			      \
-        lll_wait (GL(dl_thread_gscope_count), count, 0);		      \
-    }									      \
-  while (0)
+# define THREAD_GSCOPE_IN_TCB 0
 
 #endif /* !ASSEMBLER */
 
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC PATCH htl v2 3/4] testrun.sh: Add support for --tool=rpctrace
  2021-08-30 15:26 [RFC PATCH htl v2 0/4] Rewrite THREAD_GSCOPE Sergey Bugaev via Libc-alpha
  2021-08-30 15:26 ` [RFC PATCH htl v2 1/4] htl: Move thread table to ld.so Sergey Bugaev via Libc-alpha
  2021-08-30 15:26 ` [RFC PATCH htl v2 2/4] htl: Reimplement GSCOPE Sergey Bugaev via Libc-alpha
@ 2021-08-30 15:26 ` Sergey Bugaev via Libc-alpha
  2021-08-30 15:26 ` [RFC PATCH htl v2 4/4] XXX: Attempt to get rid of most THREAD_GSCOPE_IN_TCB usages Sergey Bugaev via Libc-alpha
  2021-08-30 15:37 ` [RFC PATCH htl v2 0/4] Rewrite THREAD_GSCOPE Florian Weimer via Libc-alpha
  4 siblings, 0 replies; 7+ messages in thread
From: Sergey Bugaev via Libc-alpha @ 2021-08-30 15:26 UTC (permalink / raw
  To: libc-alpha, bug-hurd; +Cc: samuel.thibault, Sergey Bugaev

rpctrace(1) is a Hurd RPC tracer tool, which is used similar to how
strace(1) is used on GNU/Linux.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
---
 Makefile | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index f98d5a9e67..a49870d3d1 100644
--- a/Makefile
+++ b/Makefile
@@ -141,8 +141,9 @@ usage () {
 cat << EOF
 Usage: $$0 [OPTIONS] <program> [ARGUMENTS...]
 
-  --tool=TOOL  Run with the specified TOOL. It can be strace, valgrind or
-               container. The container will run within support/test-container.
+  --tool=TOOL  Run with the specified TOOL. It can be strace, rpctrace,
+               valgrind or container. The container will run within
+               support/test-container.
 EOF
 
   exit 1
@@ -177,6 +178,10 @@ case "$$toolname" in
     exec strace $(patsubst %, -E%, $(run-program-env)) \
       $(test-via-rtld-prefix) $${1+"$$@"}
     ;;
+  rpctrace)
+    exec rpctrace $(patsubst %, -E%, $(run-program-env)) \
+      $(test-via-rtld-prefix) $${1+"$$@"}
+    ;;
   valgrind)
     exec env $(run-program-env) valgrind $(test-via-rtld-prefix) $${1+"$$@"}
     ;;
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC PATCH htl v2 4/4] XXX: Attempt to get rid of most THREAD_GSCOPE_IN_TCB usages
  2021-08-30 15:26 [RFC PATCH htl v2 0/4] Rewrite THREAD_GSCOPE Sergey Bugaev via Libc-alpha
                   ` (2 preceding siblings ...)
  2021-08-30 15:26 ` [RFC PATCH htl v2 3/4] testrun.sh: Add support for --tool=rpctrace Sergey Bugaev via Libc-alpha
@ 2021-08-30 15:26 ` Sergey Bugaev via Libc-alpha
  2021-08-30 15:37 ` [RFC PATCH htl v2 0/4] Rewrite THREAD_GSCOPE Florian Weimer via Libc-alpha
  4 siblings, 0 replies; 7+ messages in thread
From: Sergey Bugaev via Libc-alpha @ 2021-08-30 15:26 UTC (permalink / raw
  To: libc-alpha, bug-hurd; +Cc: samuel.thibault, Sergey Bugaev

Try to do this by adding HTL- and NPTL-specific versions of
dl-support.c, dl-tls.c, and dl-tls_init_tp.c, and moving HTL and NPTL
specifics there.

The remaining user of THREAD_GSCOPE_IN_TCB is <ldsodefs.h>, which I'm
not sure how to handle. I see that there are sysdeps versions of it,
so it could be possible to create one for NPTL and one for HTL.

However, I don't see an existing way for these port-sepcific ldsodefs
versions to add their own members to struct rtld_global. One way to do
this would be to introduce a macro like LDSO_GLOBAL_EXTRA_MEMBERS, but
I'm not sure whether that's a good or even acceptable approach.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
---
 elf/dl-reloc.c                             | 21 ---------
 elf/dl-support.c                           | 14 ------
 elf/dl-tls.c                               | 39 ----------------
 sysdeps/htl/dl-support.c                   |  5 ++
 sysdeps/htl/dl-tls.c                       | 39 ++++++++++++++++
 {elf => sysdeps/htl}/dl-tls_init_tp.c      |  4 +-
 sysdeps/nptl/dl-support.c                  | 26 +++++++++++
 sysdeps/nptl/dl-tls.c                      | 53 ++++++++++++++++++++++
 sysdeps/unix/sysv/linux/alpha/dl-support.c |  2 +-
 9 files changed, 125 insertions(+), 78 deletions(-)
 create mode 100644 sysdeps/htl/dl-tls.c
 rename {elf => sysdeps/htl}/dl-tls_init_tp.c (93%)
 create mode 100644 sysdeps/nptl/dl-support.c
 create mode 100644 sysdeps/nptl/dl-tls.c

diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index e13a672ade..0d97af752a 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -141,27 +141,6 @@ cannot allocate memory in static TLS block"));
     }
 }
 
-#if !THREAD_GSCOPE_IN_TCB
-/* Initialize static TLS area and DTV for current (only) thread.
-   libpthread implementations should provide their own hook
-   to handle all threads.  */
-void
-_dl_nothread_init_static_tls (struct link_map *map)
-{
-#if TLS_TCB_AT_TP
-  void *dest = (char *) THREAD_SELF - map->l_tls_offset;
-#elif TLS_DTV_AT_TP
-  void *dest = (char *) THREAD_SELF + map->l_tls_offset + TLS_PRE_TCB_SIZE;
-#else
-# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
-#endif
-
-  /* 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);
-}
-#endif /* !THREAD_GSCOPE_IN_TCB */
-
 void
 _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
 		     int reloc_mode, int consider_profiling)
diff --git a/elf/dl-support.c b/elf/dl-support.c
index 68abf606ca..28d61bda51 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -183,20 +183,6 @@ uint64_t _dl_hwcap_mask;
  * executable but this isn't true for all platforms.  */
 ElfW(Word) _dl_stack_flags = DEFAULT_STACK_PERMS;
 
-#if THREAD_GSCOPE_IN_TCB
-list_t _dl_stack_used;
-list_t _dl_stack_user;
-list_t _dl_stack_cache;
-size_t _dl_stack_cache_actsize;
-uintptr_t _dl_in_flight_stack;
-int _dl_stack_cache_lock;
-#else
-/* If loading a shared object requires that we make the stack executable
-   when it was not, we do it by calling this function.
-   It returns an errno code or zero on success.  */
-int (*_dl_make_stack_executable_hook) (void **) = _dl_make_stack_executable;
-void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls;
-#endif
 struct dl_scope_free_list *_dl_scope_free_list;
 
 #ifdef NEED_DL_SYSINFO
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
index 423e380f7c..64797d2ed6 100644
--- a/elf/dl-tls.c
+++ b/elf/dl-tls.c
@@ -29,10 +29,6 @@
 #include <dl-tls.h>
 #include <ldsodefs.h>
 
-#if THREAD_GSCOPE_IN_TCB
-# include <list.h>
-#endif
-
 #define TUNABLE_NAMESPACE rtld
 #include <dl-tunables.h>
 
@@ -1057,38 +1053,3 @@ cannot create TLS data structures"));
 			    GL(dl_tls_generation) + 1);
     }
 }
-
-#if THREAD_GSCOPE_IN_TCB
-static inline void __attribute__((always_inline))
-init_one_static_tls (struct pthread *curp, struct link_map *map)
-{
-# 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
-
-  /* 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
-_dl_init_static_tls (struct link_map *map)
-{
-  lll_lock (GL (dl_stack_cache_lock), LLL_PRIVATE);
-
-  /* Iterate over the list with system-allocated threads first.  */
-  list_t *runp;
-  list_for_each (runp, &GL (dl_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, &GL (dl_stack_user))
-    init_one_static_tls (list_entry (runp, struct pthread, list), map);
-
-  lll_unlock (GL (dl_stack_cache_lock), LLL_PRIVATE);
-}
-#endif /* THREAD_GSCOPE_IN_TCB */
diff --git a/sysdeps/htl/dl-support.c b/sysdeps/htl/dl-support.c
index 21a391a59f..02c53af4c3 100644
--- a/sysdeps/htl/dl-support.c
+++ b/sysdeps/htl/dl-support.c
@@ -21,3 +21,8 @@
 int _dl_pthread_num_threads;
 struct __pthread **_dl_pthread_threads;
 int _dl_pthread_threads_lock;
+
+/* If loading a shared object requires that we make the stack executable
+   when it was not, we do it by calling this function.
+   It returns an errno code or zero on success.  */
+int (*_dl_make_stack_executable_hook) (void **) = _dl_make_stack_executable;
diff --git a/sysdeps/htl/dl-tls.c b/sysdeps/htl/dl-tls.c
new file mode 100644
index 0000000000..1ec6680c37
--- /dev/null
+++ b/sysdeps/htl/dl-tls.c
@@ -0,0 +1,39 @@
+/* Thread-local storage handling in the ELF dynamic linker.
+   Copyright (C) 2002-2021 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <elf/dl-tls.c>
+
+/* Initialize static TLS area and DTV for current (only) thread.
+   HTL provides its own hook to handle all threads.  */
+void
+_dl_nothread_init_static_tls (struct link_map *map)
+{
+#if TLS_TCB_AT_TP
+  void *dest = (char *) THREAD_SELF - map->l_tls_offset;
+#elif TLS_DTV_AT_TP
+  void *dest = (char *) THREAD_SELF + map->l_tls_offset + TLS_PRE_TCB_SIZE;
+#else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+#endif
+
+  /* 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 (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls;
diff --git a/elf/dl-tls_init_tp.c b/sysdeps/htl/dl-tls_init_tp.c
similarity index 93%
rename from elf/dl-tls_init_tp.c
rename to sysdeps/htl/dl-tls_init_tp.c
index d84adc992c..d0810a8e22 100644
--- a/elf/dl-tls_init_tp.c
+++ b/sysdeps/htl/dl-tls_init_tp.c
@@ -1,4 +1,4 @@
-/* Completion of TCB initialization after TLS_INIT_TP.  Generic version.
+/* Completion of TCB initialization after TLS_INIT_TP.
    Copyright (C) 2021 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -36,9 +36,7 @@ rtld_lock_default_unlock_recursive (void *lock)
 void
 __tls_pre_init_tp (void)
 {
-#if !THREAD_GSCOPE_IN_TCB
   GL(dl_init_static_tls) = &_dl_nothread_init_static_tls;
-#endif
 
 #if defined SHARED && defined _LIBC_REENTRANT \
     && defined __rtld_lock_default_lock_recursive
diff --git a/sysdeps/nptl/dl-support.c b/sysdeps/nptl/dl-support.c
new file mode 100644
index 0000000000..135d49b922
--- /dev/null
+++ b/sysdeps/nptl/dl-support.c
@@ -0,0 +1,26 @@
+/* Support for dynamic linking code in static libc.
+   Copyright (C) 2007-2021 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <elf/dl-support.c>
+
+list_t _dl_stack_used;
+list_t _dl_stack_user;
+list_t _dl_stack_cache;
+size_t _dl_stack_cache_actsize;
+uintptr_t _dl_in_flight_stack;
+int _dl_stack_cache_lock;
diff --git a/sysdeps/nptl/dl-tls.c b/sysdeps/nptl/dl-tls.c
new file mode 100644
index 0000000000..9e0ecfed24
--- /dev/null
+++ b/sysdeps/nptl/dl-tls.c
@@ -0,0 +1,53 @@
+/* Thread-local storage handling in the ELF dynamic linker.
+   Copyright (C) 2002-2021 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <elf/dl-tls.c>
+#include <list.h>
+
+static inline void __attribute__((always_inline))
+init_one_static_tls (struct pthread *curp, struct link_map *map)
+{
+# 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
+
+  /* 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
+_dl_init_static_tls (struct link_map *map)
+{
+  lll_lock (GL (dl_stack_cache_lock), LLL_PRIVATE);
+
+  /* Iterate over the list with system-allocated threads first.  */
+  list_t *runp;
+  list_for_each (runp, &GL (dl_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, &GL (dl_stack_user))
+    init_one_static_tls (list_entry (runp, struct pthread, list), map);
+
+  lll_unlock (GL (dl_stack_cache_lock), LLL_PRIVATE);
+}
diff --git a/sysdeps/unix/sysv/linux/alpha/dl-support.c b/sysdeps/unix/sysv/linux/alpha/dl-support.c
index 290217671c..6fde3f8d9a 100644
--- a/sysdeps/unix/sysv/linux/alpha/dl-support.c
+++ b/sysdeps/unix/sysv/linux/alpha/dl-support.c
@@ -1,2 +1,2 @@
 #include "dl-auxv.h"
-#include <elf/dl-support.c>
+#include <sysdeps/nptl/dl-support.c>
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH htl v2 0/4] Rewrite THREAD_GSCOPE
  2021-08-30 15:26 [RFC PATCH htl v2 0/4] Rewrite THREAD_GSCOPE Sergey Bugaev via Libc-alpha
                   ` (3 preceding siblings ...)
  2021-08-30 15:26 ` [RFC PATCH htl v2 4/4] XXX: Attempt to get rid of most THREAD_GSCOPE_IN_TCB usages Sergey Bugaev via Libc-alpha
@ 2021-08-30 15:37 ` Florian Weimer via Libc-alpha
  2021-08-31 18:16   ` Sergey Bugaev via Libc-alpha
  4 siblings, 1 reply; 7+ messages in thread
From: Florian Weimer via Libc-alpha @ 2021-08-30 15:37 UTC (permalink / raw
  To: Sergey Bugaev; +Cc: bug-hurd, libc-alpha, samuel.thibault

* Sergey Bugaev:

> I can think of two ways this can be handled:
>
> * Code can be rewritten and reorganized to use port-specific files instead of
>   conditional compilation. From looking at how glibc source is organized, this
>   appears to be the generally preferred way. I'm sending one more patch that
>   makes a (perhaps misguided) attempt to do this; but I'm not sure what would
>   be good way to handle the definitions in <ldsodefs.h> -- please take a look.

Yes, that's usually how things are done.

> * A more conservative approach would be to leave the code using
>   THREAD_GSCOPE_IN_TCB as is for now, but change the variable's name to
>   better reflect what it's used for. I haven't really been able to come
>   up with a good name, though.

You could kick the can down the road by switching to PTHREAD_IN_LIBC.
In some cases, that might actually be correct replacement.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH htl v2 0/4] Rewrite THREAD_GSCOPE
  2021-08-30 15:37 ` [RFC PATCH htl v2 0/4] Rewrite THREAD_GSCOPE Florian Weimer via Libc-alpha
@ 2021-08-31 18:16   ` Sergey Bugaev via Libc-alpha
  0 siblings, 0 replies; 7+ messages in thread
From: Sergey Bugaev via Libc-alpha @ 2021-08-31 18:16 UTC (permalink / raw
  To: Florian Weimer; +Cc: bug-hurd, libc-alpha, Samuel Thibault

Thanks for looking into it!

On Mon, Aug 30, 2021 at 6:37 PM Florian Weimer <fweimer@redhat.com> wrote:
> You could kick the can down the road by switching to PTHREAD_IN_LIBC.
> In some cases, that might actually be correct replacement.

Ack; that should be easy to do. Nevertheless, please do look at patch
4/4 and say if you would prefer that approach.

Do you happen to know if there's a testcase that exercises
THREAD_GSCOPE_WAIT ()? Even simple programs evidently use
THREAD_GSCOPE_SET_FLAG () / THREAD_GSCOPE_RESET_FLAG (), but I so far
haven't been able to construct a program that would trigger the WAIT.
I've tried dlopening and dlclosing libraries concurrently from several
threads; I will try dlopening hundreds of libraries next (to hopefully
trigger a reallocation of some table), but it would be handy if there
was an official ready-to-use testcase.

Sergey

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-08-31 18:16 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-08-30 15:26 [RFC PATCH htl v2 0/4] Rewrite THREAD_GSCOPE Sergey Bugaev via Libc-alpha
2021-08-30 15:26 ` [RFC PATCH htl v2 1/4] htl: Move thread table to ld.so Sergey Bugaev via Libc-alpha
2021-08-30 15:26 ` [RFC PATCH htl v2 2/4] htl: Reimplement GSCOPE Sergey Bugaev via Libc-alpha
2021-08-30 15:26 ` [RFC PATCH htl v2 3/4] testrun.sh: Add support for --tool=rpctrace Sergey Bugaev via Libc-alpha
2021-08-30 15:26 ` [RFC PATCH htl v2 4/4] XXX: Attempt to get rid of most THREAD_GSCOPE_IN_TCB usages Sergey Bugaev via Libc-alpha
2021-08-30 15:37 ` [RFC PATCH htl v2 0/4] Rewrite THREAD_GSCOPE Florian Weimer via Libc-alpha
2021-08-31 18:16   ` Sergey Bugaev via Libc-alpha

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).