Message ID | 8df69dbc6cc31456a99ef4165fd0eeffc4de4678.1618301209.git.szabolcs.nagy@arm.com |
---|---|
State | New |
Headers | show |
Series | Dynamic TLS related data race fixes | expand |
On 13/04/2021 05:19, Szabolcs Nagy via Libc-alpha wrote: > Test concurrent dlopen and pthread_create when the loaded modules have > TLS. This triggers dl-tls assertion failures more reliably than the > nptl/tst-stack4 test. > > The dlopened module has 100 DT_NEEDED dependencies with TLS, they were > reused from an existing TLS test. The number of created threads during > dlopen depends on filesystem speed and hardware, but at most 3 threads > are alive at a time to limit resource usage. > > --- > v5: > - moved from nptl/ to elf/ > - use many tls modules from another test (affects the timing a bit as > these need more relocation processing, but still detects the race) > - use xdlopen > - use stdatomic.h > - moved from tests-internal back to tests > - use acq/rel atomics instead of relaxed, this works too and cleaner. > - moved after bug fix patch. > > v4: > - rebased, updated copyright year. > - moved to tests-internal because of <atomic.h> > > v3: > - use the new test support code. > - better Makefile usage so modules are cleaned properly. > > v2: > - undef NDEBUG. > - join nop threads so at most 3 threads exist at a time. > - remove stack size setting (resource usage is no longer a concern). > - stop creating threads after dlopen observably finished. > - print the number of threads created for debugging. LGTM, thanks. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> > --- > elf/Makefile | 9 ++++-- > elf/tst-tls21.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++ > elf/tst-tls21mod.c | 1 + > 3 files changed, 76 insertions(+), 2 deletions(-) > create mode 100644 elf/tst-tls21.c > create mode 100644 elf/tst-tls21mod.c > > diff --git a/elf/Makefile b/elf/Makefile > index b1344f1133..e9377608eb 100644 > --- a/elf/Makefile > +++ b/elf/Makefile > @@ -223,7 +223,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ > tst-single_threaded tst-single_threaded-pthread \ > tst-tls-ie tst-tls-ie-dlmopen argv0test \ > tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \ > - tst-tls20 > + tst-tls20 tst-tls21 > # reldep9 > tests-internal += loadtest unload unload2 circleload1 \ > neededtest neededtest2 neededtest3 neededtest4 \ Ok. > @@ -345,7 +345,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ > libmarkermod2-1 libmarkermod2-2 \ > libmarkermod3-1 libmarkermod3-2 libmarkermod3-3 \ > libmarkermod4-1 libmarkermod4-2 libmarkermod4-3 libmarkermod4-4 \ > - tst-tls20mod-bad > + tst-tls20mod-bad tst-tls21mod > > # Most modules build with _ISOMAC defined, but those filtered out > # depend on internal headers. Ok. > @@ -1932,3 +1932,8 @@ tst-tls20mod-bad.so-no-z-defs = yes > $(objpfx)tst-tls20: $(libdl) $(shared-thread-library) > $(objpfx)tst-tls20.out: $(objpfx)tst-tls20mod-bad.so \ > $(tst-tls-many-dynamic-modules:%=$(objpfx)%.so) > + > +# Reuses tst-tls-many-dynamic-modules > +$(objpfx)tst-tls21: $(libdl) $(shared-thread-library) > +$(objpfx)tst-tls21.out: $(objpfx)tst-tls21mod.so > +$(objpfx)tst-tls21mod.so: $(tst-tls-many-dynamic-modules:%=$(objpfx)%.so) Ok. > diff --git a/elf/tst-tls21.c b/elf/tst-tls21.c > new file mode 100644 > index 0000000000..560bf5813a > --- /dev/null > +++ b/elf/tst-tls21.c > @@ -0,0 +1,68 @@ > +/* Test concurrent dlopen and pthread_create: BZ 19329. > + Copyright (C) 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 > + <http://www.gnu.org/licenses/>. */ > + > +#include <dlfcn.h> > +#include <pthread.h> > +#include <stdio.h> > +#include <stdatomic.h> > +#include <support/xdlfcn.h> > +#include <support/xthread.h> > + > +#define THREADS 10000 > + > +static atomic_int done; > + > +static void * > +start (void *a) > +{ > + /* Load a module with many dependencies that each have TLS. */ > + xdlopen ("tst-tls21mod.so", RTLD_LAZY); > + atomic_store_explicit (&done, 1, memory_order_release); > + return 0; > +} > + > +static void * > +nop (void *a) > +{ > + return 0; > +} > + > +static int > +do_test (void) > +{ > + pthread_t t1, t2; > + int i; > + > + /* Load a module with lots of dependencies and TLS. */ > + t1 = xpthread_create (0, start, 0); > + > + /* Concurrently create lots of threads until dlopen is observably done. */ > + for (i = 0; i < THREADS; i++) > + { > + if (atomic_load_explicit (&done, memory_order_acquire) != 0) > + break; > + t2 = xpthread_create (0, nop, 0); > + xpthread_join (t2); > + } > + > + xpthread_join (t1); > + printf ("threads created during dlopen: %d\n", i); > + return 0; > +} > + > +#include <support/test-driver.c> Ok, > diff --git a/elf/tst-tls21mod.c b/elf/tst-tls21mod.c > new file mode 100644 > index 0000000000..206ece4fb3 > --- /dev/null > +++ b/elf/tst-tls21mod.c > @@ -0,0 +1 @@ > +int __thread x; > Ok.
diff --git a/elf/Makefile b/elf/Makefile index b1344f1133..e9377608eb 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -223,7 +223,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ tst-single_threaded tst-single_threaded-pthread \ tst-tls-ie tst-tls-ie-dlmopen argv0test \ tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \ - tst-tls20 + tst-tls20 tst-tls21 # reldep9 tests-internal += loadtest unload unload2 circleload1 \ neededtest neededtest2 neededtest3 neededtest4 \ @@ -345,7 +345,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ libmarkermod2-1 libmarkermod2-2 \ libmarkermod3-1 libmarkermod3-2 libmarkermod3-3 \ libmarkermod4-1 libmarkermod4-2 libmarkermod4-3 libmarkermod4-4 \ - tst-tls20mod-bad + tst-tls20mod-bad tst-tls21mod # Most modules build with _ISOMAC defined, but those filtered out # depend on internal headers. @@ -1932,3 +1932,8 @@ tst-tls20mod-bad.so-no-z-defs = yes $(objpfx)tst-tls20: $(libdl) $(shared-thread-library) $(objpfx)tst-tls20.out: $(objpfx)tst-tls20mod-bad.so \ $(tst-tls-many-dynamic-modules:%=$(objpfx)%.so) + +# Reuses tst-tls-many-dynamic-modules +$(objpfx)tst-tls21: $(libdl) $(shared-thread-library) +$(objpfx)tst-tls21.out: $(objpfx)tst-tls21mod.so +$(objpfx)tst-tls21mod.so: $(tst-tls-many-dynamic-modules:%=$(objpfx)%.so) diff --git a/elf/tst-tls21.c b/elf/tst-tls21.c new file mode 100644 index 0000000000..560bf5813a --- /dev/null +++ b/elf/tst-tls21.c @@ -0,0 +1,68 @@ +/* Test concurrent dlopen and pthread_create: BZ 19329. + Copyright (C) 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 + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <pthread.h> +#include <stdio.h> +#include <stdatomic.h> +#include <support/xdlfcn.h> +#include <support/xthread.h> + +#define THREADS 10000 + +static atomic_int done; + +static void * +start (void *a) +{ + /* Load a module with many dependencies that each have TLS. */ + xdlopen ("tst-tls21mod.so", RTLD_LAZY); + atomic_store_explicit (&done, 1, memory_order_release); + return 0; +} + +static void * +nop (void *a) +{ + return 0; +} + +static int +do_test (void) +{ + pthread_t t1, t2; + int i; + + /* Load a module with lots of dependencies and TLS. */ + t1 = xpthread_create (0, start, 0); + + /* Concurrently create lots of threads until dlopen is observably done. */ + for (i = 0; i < THREADS; i++) + { + if (atomic_load_explicit (&done, memory_order_acquire) != 0) + break; + t2 = xpthread_create (0, nop, 0); + xpthread_join (t2); + } + + xpthread_join (t1); + printf ("threads created during dlopen: %d\n", i); + return 0; +} + +#include <support/test-driver.c> diff --git a/elf/tst-tls21mod.c b/elf/tst-tls21mod.c new file mode 100644 index 0000000000..206ece4fb3 --- /dev/null +++ b/elf/tst-tls21mod.c @@ -0,0 +1 @@ +int __thread x;