[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