@@ -27,6 +27,12 @@ Major new features:
several APIs have been annotated with GCC 'access' attribute. This
should help GCC 10 issue better warnings.
+* The GNU C Library now provides the header file <sys/single_threaded.h>
+ which declares the variable __libc_single_threaded. Applications are
+ encouraged to use this variable for single-thread optimizations,
+ instead of weak references to symbols historically defined in
+ libpthread.
+
Deprecated and removed features, and other changes affecting compatibility:
* The deprecated <sys/sysctl.h> header and the sysctl function have been
@@ -155,7 +155,9 @@ endif
tests-static-normal := tst-leaks1-static tst-array1-static tst-array5-static \
tst-dl-iter-static \
tst-tlsalign-static tst-tlsalign-extern-static \
- tst-linkall-static tst-env-setuid tst-env-setuid-tunables
+ tst-linkall-static tst-env-setuid tst-env-setuid-tunables \
+ tst-single_threaded-static tst-single_threaded-pthread-static
+
tests-static-internal := tst-tls1-static tst-tls2-static \
tst-ptrguard1-static tst-stackguard1-static \
tst-tls1-static-non-pie tst-libc_dlvsym-static
@@ -174,9 +176,11 @@ tests-internal := tst-tls1 tst-tls2 $(tests-static-internal)
tests-static := $(tests-static-normal) $(tests-static-internal)
ifeq (yes,$(build-shared))
-tests-static += tst-tls9-static
-tst-tls9-static-ENV = \
- LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)dlfcn
+tests-static += tst-tls9-static tst-single_threaded-static-dlopen
+static-dlopen-environment = \
+ LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)dlfcn
+tst-tls9-static-ENV = $(static-dlopen-environment)
+tst-single_threaded-static-dlopen-ENV = $(static-dlopen-environment)
tests += restest1 preloadtest loadfail multiload origtest resolvfail \
constload1 order noload filter \
@@ -204,7 +208,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
tst-dlopen-self tst-auditmany tst-initfinilazyfail tst-dlopenfail \
tst-dlopenfail-2 \
tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen \
- tst-audit14 tst-audit15 tst-audit16
+ tst-audit14 tst-audit15 tst-audit16 \
+ tst-single_threaded tst-single_threaded-pthread
# reldep9
tests-internal += loadtest unload unload2 circleload1 \
neededtest neededtest2 neededtest3 neededtest4 \
@@ -317,7 +322,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \
tst-dlopenfailmod3 tst-ldconfig-ld-mod \
tst-filterobj-flt tst-filterobj-aux tst-filterobj-filtee \
- tst-auditlogmod-1 tst-auditlogmod-2 tst-auditlogmod-3
+ tst-auditlogmod-1 tst-auditlogmod-2 tst-auditlogmod-3 \
+ tst-single_threaded-mod1 tst-single_threaded-mod2 \
+ tst-single_threaded-mod3 tst-single_threaded-mod4
# Most modules build with _ISOMAC defined, but those filtered out
# depend on internal headers.
modules-names-tests = $(filter-out ifuncmod% tst-libc_dlvsym-dso tst-tlsmod%,\
@@ -1748,3 +1755,17 @@ $(objpfx)tst-auxobj: $(objpfx)tst-filterobj-aux.so
$(objpfx)tst-auxobj-dlopen: $(libdl)
$(objpfx)tst-auxobj.out: $(objpfx)tst-filterobj-filtee.so
$(objpfx)tst-auxobj-dlopen.out: $(objpfx)tst-filterobj-filtee.so
+
+$(objpfx)tst-single_threaded: $(objpfx)tst-single_threaded-mod1.so $(libdl)
+$(objpfx)tst-single_threaded.out: \
+ $(objpfx)tst-single_threaded-mod2.so $(objpfx)tst-single_threaded-mod3.so
+$(objpfx)tst-single_threaded-static-dlopen: \
+ $(objpfx)tst-single_threaded-mod1.o $(common-objpfx)dlfcn/libdl.a
+$(objpfx)tst-single_threaded-static-dlopen.out: \
+ $(objpfx)tst-single_threaded-mod2.so
+$(objpfx)tst-single_threaded-pthread: \
+ $(objpfx)tst-single_threaded-mod1.so $(libdl) $(shared-thread-library)
+$(objpfx)tst-single_threaded-pthread.out: \
+ $(objpfx)tst-single_threaded-mod2.so $(objpfx)tst-single_threaded-mod3.so \
+ $(objpfx)tst-single_threaded-mod4.so
+$(objpfx)tst-single_threaded-pthread-static: $(static-thread-library)
@@ -18,10 +18,14 @@
#include <ctype.h>
#include <libc-early-init.h>
+#include <sys/single_threaded.h>
void
__libc_early_init (_Bool initial)
{
/* Initialize ctype data. */
__ctype_init ();
+
+ /* Only the outer namespace is marked as single-threaded. */
+ __libc_single_threaded = initial;
}
new file mode 100644
@@ -0,0 +1,25 @@
+/* Test support for single-thread optimizations. Shared object 1.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/single_threaded.h>
+
+_Bool
+single_threaded_1 (void)
+{
+ return __libc_single_threaded;
+}
new file mode 100644
@@ -0,0 +1,25 @@
+/* Test support for single-thread optimizations. Shared object 2.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/single_threaded.h>
+
+_Bool
+single_threaded_2 (void)
+{
+ return __libc_single_threaded;
+}
new file mode 100644
@@ -0,0 +1,25 @@
+/* Test support for single-thread optimizations. Shared object 3.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/single_threaded.h>
+
+_Bool
+single_threaded_3 (void)
+{
+ return __libc_single_threaded;
+}
new file mode 100644
@@ -0,0 +1,25 @@
+/* Test support for single-thread optimizations. Shared object 4.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/single_threaded.h>
+
+_Bool
+single_threaded_4 (void)
+{
+ return __libc_single_threaded;
+}
new file mode 100644
@@ -0,0 +1,86 @@
+/* Test support for single-thread optimizations. With threads, static version.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+/* This test is a stripped-down version of
+ tst-single_threaded-pthread.c, without any loading of dynamic
+ objects. */
+
+#include <stdio.h>
+#include <support/check.h>
+#include <support/xthread.h>
+#include <sys/single_threaded.h>
+
+/* First barrier synchronizes main thread, thread 1, thread 2. */
+static pthread_barrier_t barrier1;
+
+/* Second barrier synchronizes main thread, thread 2. */
+static pthread_barrier_t barrier2;
+
+static void *
+threadfunc (void *closure)
+{
+ TEST_VERIFY (!__libc_single_threaded);
+
+ /* Wait for the main thread and the other thread. */
+ xpthread_barrier_wait (&barrier1);
+ TEST_VERIFY (!__libc_single_threaded);
+
+ /* Second thread waits on second barrier, too. */
+ if (closure != NULL)
+ xpthread_barrier_wait (&barrier2);
+ TEST_VERIFY (!__libc_single_threaded);
+
+ return NULL;
+}
+
+static int
+do_test (void)
+{
+ TEST_VERIFY (__libc_single_threaded);
+
+ /* Two threads plus main thread. */
+ xpthread_barrier_init (&barrier1, NULL, 3);
+
+ /* Main thread and second thread. */
+ xpthread_barrier_init (&barrier2, NULL, 2);
+
+ pthread_t thr1 = xpthread_create (NULL, threadfunc, NULL);
+ TEST_VERIFY (!__libc_single_threaded);
+
+ pthread_t thr2 = xpthread_create (NULL, threadfunc, &thr2);
+ TEST_VERIFY (!__libc_single_threaded);
+
+ xpthread_barrier_wait (&barrier1);
+ TEST_VERIFY (!__libc_single_threaded);
+
+ /* Join first thread. This should not bring us back into
+ single-threaded mode. */
+ xpthread_join (thr1);
+ TEST_VERIFY (!__libc_single_threaded);
+
+ /* We may be back in single-threaded mode after joining both
+ threads, but this is not guaranteed. */
+ xpthread_barrier_wait (&barrier2);
+ xpthread_join (thr2);
+ printf ("info: __libc_single_threaded after joining all threads: %d\n",
+ __libc_single_threaded);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,174 @@
+/* Test support for single-thread optimizations. With threads.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <support/check.h>
+#include <support/namespace.h>
+#include <support/xdlfcn.h>
+#include <support/xthread.h>
+#include <sys/single_threaded.h>
+
+/* First barrier synchronizes main thread, thread 1, thread 2. */
+static pthread_barrier_t barrier1;
+
+/* Second barrier synchronizes main thread, thread 2. */
+static pthread_barrier_t barrier2;
+
+/* Defined in tst-single-threaded-mod1.so. */
+_Bool single_threaded_1 (void);
+
+/* Initialized via dlsym. */
+static _Bool (*single_threaded_2) (void);
+static _Bool (*single_threaded_3) (void);
+static _Bool (*single_threaded_4) (void);
+
+static void *
+threadfunc (void *closure)
+{
+ TEST_VERIFY (!__libc_single_threaded);
+ TEST_VERIFY (!single_threaded_1 ());
+ TEST_VERIFY (!single_threaded_2 ());
+
+ /* Wait until the main thread loads more functions. */
+ xpthread_barrier_wait (&barrier1);
+
+ TEST_VERIFY (!__libc_single_threaded);
+ TEST_VERIFY (!single_threaded_1 ());
+ TEST_VERIFY (!single_threaded_2 ());
+ TEST_VERIFY (!single_threaded_3 ());
+ TEST_VERIFY (!single_threaded_4 ());
+
+ /* Second thread waits on second barrier, too. */
+ if (closure != NULL)
+ xpthread_barrier_wait (&barrier2);
+ TEST_VERIFY (!__libc_single_threaded);
+ TEST_VERIFY (!single_threaded_1 ());
+ TEST_VERIFY (!single_threaded_2 ());
+ TEST_VERIFY (!single_threaded_3 ());
+ TEST_VERIFY (!single_threaded_4 ());
+
+ return NULL;
+}
+
+/* Used for closure arguments to the subprocess function. */
+static char expected_false = 0;
+static char expected_true = 1;
+
+/* A subprocess inherits currently inherits the single-threaded state
+ of the parent process. */
+static void
+subprocess (void *closure)
+{
+ const char *expected = closure;
+ TEST_COMPARE (__libc_single_threaded, *expected);
+ TEST_COMPARE (single_threaded_1 (), *expected);
+ if (single_threaded_2 != NULL)
+ TEST_COMPARE (single_threaded_2 (), *expected);
+ if (single_threaded_3 != NULL)
+ TEST_COMPARE (single_threaded_3 (), *expected);
+ if (single_threaded_4 != NULL)
+ TEST_VERIFY (!single_threaded_4 ());
+}
+
+static int
+do_test (void)
+{
+ printf ("info: main __libc_single_threaded address: %p\n",
+ &__libc_single_threaded);
+ TEST_VERIFY (__libc_single_threaded);
+ TEST_VERIFY (single_threaded_1 ());
+ support_isolate_in_subprocess (subprocess, &expected_true);
+
+ void *handle_mod2 = xdlopen ("tst-single_threaded-mod2.so", RTLD_LAZY);
+ single_threaded_2 = xdlsym (handle_mod2, "single_threaded_2");
+ TEST_VERIFY (single_threaded_2 ());
+
+ /* Two threads plus main thread. */
+ xpthread_barrier_init (&barrier1, NULL, 3);
+
+ /* Main thread and second thread. */
+ xpthread_barrier_init (&barrier2, NULL, 2);
+
+ pthread_t thr1 = xpthread_create (NULL, threadfunc, NULL);
+ TEST_VERIFY (!__libc_single_threaded);
+ TEST_VERIFY (!single_threaded_1 ());
+ TEST_VERIFY (!single_threaded_2 ());
+ support_isolate_in_subprocess (subprocess, &expected_false);
+
+ pthread_t thr2 = xpthread_create (NULL, threadfunc, &thr2);
+ TEST_VERIFY (!__libc_single_threaded);
+ TEST_VERIFY (!single_threaded_1 ());
+ TEST_VERIFY (!single_threaded_2 ());
+ support_isolate_in_subprocess (subprocess, &expected_false);
+
+ /* Delayed library load, while already multi-threaded. */
+ void *handle_mod3 = xdlopen ("tst-single_threaded-mod3.so", RTLD_LAZY);
+ single_threaded_3 = xdlsym (handle_mod3, "single_threaded_3");
+ TEST_VERIFY (!__libc_single_threaded);
+ TEST_VERIFY (!single_threaded_1 ());
+ TEST_VERIFY (!single_threaded_2 ());
+ TEST_VERIFY (!single_threaded_3 ());
+ support_isolate_in_subprocess (subprocess, &expected_false);
+
+ /* Same with dlmopen. */
+ void *handle_mod4 = dlmopen (LM_ID_NEWLM, "tst-single_threaded-mod4.so",
+ RTLD_LAZY);
+ single_threaded_4 = xdlsym (handle_mod4, "single_threaded_4");
+ TEST_VERIFY (!__libc_single_threaded);
+ TEST_VERIFY (!single_threaded_1 ());
+ TEST_VERIFY (!single_threaded_2 ());
+ TEST_VERIFY (!single_threaded_3 ());
+ TEST_VERIFY (!single_threaded_4 ());
+ support_isolate_in_subprocess (subprocess, &expected_false);
+
+ /* Run the newly loaded functions from the other threads as
+ well. */
+ xpthread_barrier_wait (&barrier1);
+ TEST_VERIFY (!__libc_single_threaded);
+ TEST_VERIFY (!single_threaded_1 ());
+ TEST_VERIFY (!single_threaded_2 ());
+ TEST_VERIFY (!single_threaded_3 ());
+ TEST_VERIFY (!single_threaded_4 ());
+ support_isolate_in_subprocess (subprocess, &expected_false);
+
+ /* Join first thread. This should not bring us back into
+ single-threaded mode. */
+ xpthread_join (thr1);
+ TEST_VERIFY (!__libc_single_threaded);
+ TEST_VERIFY (!single_threaded_1 ());
+ TEST_VERIFY (!single_threaded_2 ());
+ TEST_VERIFY (!single_threaded_3 ());
+ TEST_VERIFY (!single_threaded_4 ());
+ support_isolate_in_subprocess (subprocess, &expected_false);
+
+ /* We may be back in single-threaded mode after joining both
+ threads, but this is not guaranteed. */
+ xpthread_barrier_wait (&barrier2);
+ xpthread_join (thr2);
+ printf ("info: __libc_single_threaded after joining all threads: %d\n",
+ __libc_single_threaded);
+
+ xdlclose (handle_mod4);
+ xdlclose (handle_mod3);
+ xdlclose (handle_mod2);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,56 @@
+/* Test support for single-thread optimizations. No threads, static dlopen.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+/* In a static dlopen scenario, the single-threaded optimization is
+ not possible because their is no globally shared dynamic linker
+ across all namespaces. */
+
+#include <stddef.h>
+#include <support/check.h>
+#include <support/xdlfcn.h>
+#include <sys/single_threaded.h>
+
+static int
+do_test (void)
+{
+ TEST_VERIFY (__libc_single_threaded);
+
+ /* Defined in tst-single-threaded-mod1.o. */
+ extern _Bool single_threaded_1 (void);
+ TEST_VERIFY (single_threaded_1 ());
+
+ /* Even after a failed dlopen, assume multi-threaded mode. */
+ TEST_VERIFY (dlopen ("tst-single_threaded-does-not-exist.so", RTLD_LAZY)
+ == NULL);
+ TEST_VERIFY (__libc_single_threaded);
+ TEST_VERIFY (single_threaded_1 ());
+
+ void *handle_mod2 = xdlopen ("tst-single_threaded-mod2.so", RTLD_LAZY);
+ _Bool (*single_threaded_2) (void)
+ = xdlsym (handle_mod2, "single_threaded_2");
+ TEST_VERIFY (__libc_single_threaded);
+ TEST_VERIFY (single_threaded_1 ());
+ /* The inner libc always assumes multi-threaded use. */
+ TEST_VERIFY (!single_threaded_2 ());
+
+ xdlclose (handle_mod2);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,29 @@
+/* Test support for single-thread optimizations. Static, no threads.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <sys/single_threaded.h>
+
+static int
+do_test (void)
+{
+ TEST_VERIFY (__libc_single_threaded);
+ return 0;
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,70 @@
+/* Test support for single-thread optimizations. No threads.
+ Copyright (C) 2020 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <support/check.h>
+#include <support/namespace.h>
+#include <support/xdlfcn.h>
+#include <sys/single_threaded.h>
+
+/* Defined in tst-single-threaded-mod1.so. */
+extern _Bool single_threaded_1 (void);
+
+/* Initialized via dlsym. */
+_Bool (*single_threaded_2) (void);
+_Bool (*single_threaded_3) (void);
+
+static void
+subprocess (void *closure)
+{
+ TEST_VERIFY (__libc_single_threaded);
+ TEST_VERIFY (single_threaded_1 ());
+ if (single_threaded_2 != NULL)
+ TEST_VERIFY (single_threaded_2 ());
+ if (single_threaded_3 != NULL)
+ TEST_VERIFY (!single_threaded_3 ());
+}
+
+static int
+do_test (void)
+{
+ TEST_VERIFY (__libc_single_threaded);
+ TEST_VERIFY (single_threaded_1 ());
+ support_isolate_in_subprocess (subprocess, NULL);
+
+ void *handle_mod2 = xdlopen ("tst-single_threaded-mod2.so", RTLD_LAZY);
+ single_threaded_2 = xdlsym (handle_mod2, "single_threaded_2");
+ TEST_VERIFY (single_threaded_2 ());
+ support_isolate_in_subprocess (subprocess, NULL);
+
+ /* The current implementation treats the inner namespace as
+ multi-threaded. */
+ void *handle_mod3 = dlmopen (LM_ID_NEWLM, "tst-single_threaded-mod3.so",
+ RTLD_LAZY);
+ single_threaded_3 = xdlsym (handle_mod3, "single_threaded_3");
+ TEST_VERIFY (!single_threaded_3 ());
+ support_isolate_in_subprocess (subprocess, NULL);
+
+ xdlclose (handle_mod3);
+ xdlclose (handle_mod2);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
@@ -24,6 +24,7 @@
#include <atomic.h>
#include <hurd/resource.h>
+#include <sys/single_threaded.h>
#include <pt-internal.h>
#include <pthreadP.h>
@@ -104,6 +105,10 @@ __pthread_create_internal (struct __pthread **thread,
sigset_t sigset;
size_t stacksize;
+ /* Avoid a data race in the multi-threaded case. */
+ if (__libc_single_threaded)
+ __libc_single_threaded = 0;
+
/* Allocate a new thread structure. */
err = __pthread_alloc (&pthread);
if (err)
new file mode 100644
@@ -0,0 +1 @@
+#include <misc/sys/single_threaded.h>
@@ -37,7 +37,8 @@ headers := sys/uio.h bits/uio-ext.h bits/uio_lim.h \
bits/syslog.h bits/syslog-ldbl.h bits/syslog-path.h bits/error.h \
bits/select2.h bits/hwcap.h sys/auxv.h \
sys/sysmacros.h bits/sysmacros.h bits/types/struct_iovec.h \
- bits/err-ldbl.h bits/error-ldbl.h
+ bits/err-ldbl.h bits/error-ldbl.h \
+ sys/single_threaded.h
routines := brk sbrk sstk ioctl \
readv writev preadv preadv64 pwritev pwritev64 \
@@ -72,7 +73,7 @@ routines := brk sbrk sstk ioctl \
fgetxattr flistxattr fremovexattr fsetxattr getxattr \
listxattr lgetxattr llistxattr lremovexattr lsetxattr \
removexattr setxattr getauxval ifunc-impl-list makedev \
- allocate_once fd_to_filename
+ allocate_once fd_to_filename single_threaded
generated += tst-error1.mtrace tst-error1-mem.out \
tst-allocate_once.mtrace tst-allocate_once-mem.out
@@ -161,6 +161,9 @@ libc {
GLIBC_2.30 {
twalk_r;
}
+ GLIBC_2.32 {
+ __libc_single_threaded;
+ }
GLIBC_PRIVATE {
__madvise;
__mktemp;
new file mode 100644
@@ -0,0 +1,27 @@
+/* Support for single-thread optimizations. Statically linked version.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/single_threaded.h>
+
+/* In dynamically linked programs, this variable is initialized in
+ __libc_early_init (as false for inner libcs). */
+#ifdef SHARED
+char __libc_single_threaded;
+#else
+char __libc_single_threaded = 1;
+#endif
new file mode 100644
@@ -0,0 +1,33 @@
+/* Support for single-thread optimizations.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _SYS_SINGLE_THREADED_H
+#define _SYS_SINGLE_THREADED_H
+
+#include <features.h>
+
+__BEGIN_DECLS
+
+/* If this variable is non-zero, then the current thread is the only
+ thread in the process image. If it is zero, the process can be
+ multi-threaded. */
+extern char __libc_single_threaded;
+
+__END_DECLS
+
+#endif /* _SYS_SINGLE_THREADED_H */
@@ -34,6 +34,7 @@
#include <futex-internal.h>
#include <tls-setup.h>
#include "libioP.h"
+#include <sys/single_threaded.h>
#include <shlib-compat.h>
@@ -611,6 +612,10 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
{
STACK_VARIABLES;
+ /* Avoid a data race in the multi-threaded case. */
+ if (__libc_single_threaded)
+ __libc_single_threaded = 0;
+
const struct pthread_attr *iattr = (struct pthread_attr *) attr;
struct pthread_attr default_attr;
bool free_cpuset = false;
@@ -482,9 +482,11 @@ struct rtld_global
# define __rtld_local_attribute__ __attribute__ ((visibility ("hidden")))
# endif
extern struct rtld_global _rtld_local __rtld_local_attribute__;
+extern char __libc_single_threaded_local __rtld_local_attribute__;
# undef __rtld_local_attribute__
# endif
extern struct rtld_global _rtld_global __rtld_global_attribute__;
+extern char __libc_single_threaded __rtld_global_attribute__;
# undef __rtld_global_attribute__
#endif
@@ -1124,6 +1126,9 @@ extern struct link_map * _dl_get_dl_main_map (void)
If libpthread is not linked in, this is an empty function. */
void __pthread_initialize_minimal (void) weak_function;
+/* Update both copies of __libc_single_threaded. */
+void _dl_single_threaded_update (char value);
+
/* Allocate memory for static TLS block (unless MEM is nonzero) and dtv. */
extern void *_dl_allocate_tls (void *mem);
rtld_hidden_proto (_dl_allocate_tls)
@@ -0,0 +1 @@
+GLIBC_2.32 __libc_single_threaded D 0x1
@@ -2181,6 +2181,7 @@ GLIBC_2.3.4 setsourcefilter F
GLIBC_2.3.4 xdr_quad_t F
GLIBC_2.3.4 xdr_u_quad_t F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 mach_print F
GLIBC_2.32 thrd_current F
GLIBC_2.32 thrd_equal F
@@ -2146,4 +2146,5 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
@@ -2226,6 +2226,7 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 _IO_fprintf F
GLIBC_2.4 _IO_printf F
@@ -133,6 +133,7 @@ GLIBC_2.30 twalk_r F
GLIBC_2.31 msgctl F
GLIBC_2.31 semctl F
GLIBC_2.31 shmctl F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 _Exit F
GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
@@ -130,6 +130,7 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 _Exit F
GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
@@ -2090,4 +2090,5 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
@@ -2047,6 +2047,7 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
@@ -2213,6 +2213,7 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
@@ -2079,6 +2079,7 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
@@ -134,6 +134,7 @@ GLIBC_2.30 twalk_r F
GLIBC_2.31 msgctl F
GLIBC_2.31 semctl F
GLIBC_2.31 shmctl F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 _Exit F
GLIBC_2.4 _IO_2_1_stderr_ D 0x98
@@ -2159,6 +2159,7 @@ GLIBC_2.30 twalk_r F
GLIBC_2.31 msgctl F
GLIBC_2.31 semctl F
GLIBC_2.31 shmctl F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
@@ -2141,4 +2141,5 @@ GLIBC_2.30 twalk_r F
GLIBC_2.31 msgctl F
GLIBC_2.31 semctl F
GLIBC_2.31 shmctl F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
@@ -2138,4 +2138,5 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
@@ -2130,6 +2130,7 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
@@ -2128,6 +2128,7 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
@@ -2136,6 +2136,7 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
@@ -2130,6 +2130,7 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
@@ -2179,4 +2179,5 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
@@ -2186,6 +2186,7 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 _IO_fprintf F
GLIBC_2.4 _IO_printf F
@@ -2219,6 +2219,7 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 _IO_fprintf F
GLIBC_2.4 _IO_printf F
@@ -2049,6 +2049,7 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 _IO_fprintf F
GLIBC_2.4 _IO_printf F
@@ -2276,6 +2276,7 @@ GLIBC_2.32 __isoc99_vsscanfieee128 F
GLIBC_2.32 __isoc99_vswscanfieee128 F
GLIBC_2.32 __isoc99_vwscanfieee128 F
GLIBC_2.32 __isoc99_wscanfieee128 F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 __obstack_printf_chkieee128 F
GLIBC_2.32 __obstack_printfieee128 F
GLIBC_2.32 __obstack_vprintf_chkieee128 F
@@ -2108,4 +2108,5 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
@@ -2184,6 +2184,7 @@ GLIBC_2.30 twalk_r F
GLIBC_2.31 msgctl F
GLIBC_2.31 semctl F
GLIBC_2.31 shmctl F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 _IO_fprintf F
GLIBC_2.4 _IO_printf F
@@ -2085,6 +2085,7 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 _IO_fprintf F
GLIBC_2.4 _IO_printf F
@@ -2054,6 +2054,7 @@ GLIBC_2.30 twalk_r F
GLIBC_2.31 msgctl F
GLIBC_2.31 semctl F
GLIBC_2.31 shmctl F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
@@ -2051,6 +2051,7 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
@@ -2175,6 +2175,7 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 _IO_fprintf F
GLIBC_2.4 _IO_printf F
@@ -2102,6 +2102,7 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
@@ -2060,6 +2060,7 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
@@ -2159,4 +2159,5 @@ GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
+GLIBC_2.32 __libc_single_threaded D 0x1
GLIBC_2.32 pthread_sigmask F