[PATCH 1/4] misc: Optimize internal usage of __libc_single_threaded

Adhemerval Zanella adhemerval.zanella@linaro.org
Wed Jun 8 16:49:38 GMT 2022


To avoid a GOT indirection for internal usages.  On some architecture,
__libc_single_thread can be accessed through copy relocations so it
requires to update both copies, which is done through finding the
new with dlsym.

Checked on x86_64-linux-gnu and i686-linux-gnu.
---
 dlfcn/dlsym.c                 |  1 +
 elf/libc_early_init.c         |  9 +++++++++
 include/dlfcn.h               |  4 ++++
 include/sys/single_threaded.h | 11 +++++++++++
 misc/single_threaded.c        |  2 ++
 nptl/pthread_create.c         |  6 +++++-
 6 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/dlfcn/dlsym.c b/dlfcn/dlsym.c
index 2e9ff98e79..43c7ee8c4d 100644
--- a/dlfcn/dlsym.c
+++ b/dlfcn/dlsym.c
@@ -88,3 +88,4 @@ ___dlsym (void *handle, const char *name)
 }
 weak_alias (___dlsym, dlsym)
 #endif /* !SHARED */
+libc_hidden_def (___dlsym)
diff --git a/elf/libc_early_init.c b/elf/libc_early_init.c
index 3c4a19cf6b..18966900c4 100644
--- a/elf/libc_early_init.c
+++ b/elf/libc_early_init.c
@@ -16,7 +16,9 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
+#include <assert.h>
 #include <ctype.h>
+#include <dlfcn.h>
 #include <elision-conf.h>
 #include <libc-early-init.h>
 #include <libc-internal.h>
@@ -38,6 +40,13 @@ __libc_early_init (_Bool initial)
   __libc_single_threaded = initial;
 
 #ifdef SHARED
+  /* _libc_single_thread can be accessed through copy relocations, so it
+     requires to update the external copy.  */
+  __libc_external_single_threaded = ___dlsym (RTLD_DEFAULT,
+					      "__libc_single_threaded");
+  assert (__libc_external_single_threaded != NULL);
+  *__libc_external_single_threaded = initial;
+
   __libc_initial = initial;
 #endif
 
diff --git a/include/dlfcn.h b/include/dlfcn.h
index ae25f05303..95b8756770 100644
--- a/include/dlfcn.h
+++ b/include/dlfcn.h
@@ -135,5 +135,9 @@ extern int __dladdr1 (const void *address, Dl_info *info,
 extern int __dlinfo (void *handle, int request, void *arg);
 extern char *__dlerror (void);
 
+/* Internal interfaces to avoid intra-PLT calls.  */
+extern __typeof (dlsym) ___dlsym;
+libc_hidden_proto (___dlsym);
+
 #endif
 #endif
diff --git a/include/sys/single_threaded.h b/include/sys/single_threaded.h
index 18f6972482..258b01e0b2 100644
--- a/include/sys/single_threaded.h
+++ b/include/sys/single_threaded.h
@@ -1 +1,12 @@
 #include <misc/sys/single_threaded.h>
+
+#ifndef _ISOMAC
+
+libc_hidden_proto (__libc_single_threaded);
+
+# ifdef SHARED
+extern __typeof (__libc_single_threaded) *__libc_external_single_threaded
+  attribute_hidden;
+# endif
+
+#endif
diff --git a/misc/single_threaded.c b/misc/single_threaded.c
index 96ada9137b..201d86a273 100644
--- a/misc/single_threaded.c
+++ b/misc/single_threaded.c
@@ -22,6 +22,8 @@
    __libc_early_init (as false for inner libcs).  */
 #ifdef SHARED
 char __libc_single_threaded;
+__typeof (__libc_single_threaded) *__libc_external_single_threaded;
 #else
 char __libc_single_threaded = 1;
 #endif
+libc_hidden_data_def (__libc_single_threaded)
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index e7a099acb7..5633d01c62 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -627,7 +627,11 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
   if (__libc_single_threaded)
     {
       late_init ();
-      __libc_single_threaded = 0;
+      __libc_single_threaded =
+#ifdef SHARED
+        *__libc_external_single_threaded =
+#endif
+	0;
     }
 
   const struct pthread_attr *iattr = (struct pthread_attr *) attr;
-- 
2.34.1



More information about the Libc-alpha mailing list