Message ID | 3ec0825ceb5514f7f94d170f40cae12a3111a3fd.1615914631.git.fweimer@redhat.com |
---|---|
State | Superseded |
Delegated to: | Adhemerval Zanella Netto |
Headers | show |
Series | libpthread removal: NPTL forwarders are gone | expand |
On 16/03/2021 14:29, Florian Weimer via Libc-alpha wrote: > This code depends on whether glibc has unwinding support for > a particular port. LGTM. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> > --- > csu/libc-start.c | 74 ++-------------------- > sysdeps/generic/libc_start_call_main.h | 24 +++++++ > sysdeps/nptl/libc_start_call_main.h | 88 ++++++++++++++++++++++++++ > 3 files changed, 116 insertions(+), 70 deletions(-) > create mode 100644 sysdeps/generic/libc_start_call_main.h > create mode 100644 sysdeps/nptl/libc_start_call_main.h > > diff --git a/csu/libc-start.c b/csu/libc-start.c > index 05ff7afddf..8688cba76d 100644 > --- a/csu/libc-start.c > +++ b/csu/libc-start.c > @@ -58,12 +58,6 @@ uintptr_t __pointer_chk_guard_local > # endif > #endif > > -#ifdef HAVE_PTR_NTHREADS > -/* We need atomic operations. */ > -# include <atomic.h> > -#endif > - > - > #ifndef SHARED > # include <link.h> > # include <dl-irel.h> > @@ -123,6 +117,9 @@ apply_irel (void) > # define ARCH_INIT_CPU_FEATURES() > #endif > > +/* Obtain the definition of __libc_start_call_main. */ > +#include <libc_start_call_main.h> > + > #ifdef SHARED > /* Initialization for dynamic executables. Find the main executable > link map and run its init functions. */ > @@ -245,9 +242,6 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), > void (*fini) (void), > void (*rtld_fini) (void), void *stack_end) > { > - /* Result of the 'main' function. */ > - int result; > - > #ifndef SHARED > char **ev = &argv[argc + 1]; > > @@ -413,68 +407,8 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), > #ifndef SHARED > _dl_debug_initialize (0, LM_ID_BASE); > #endif > -#ifdef HAVE_CLEANUP_JMP_BUF > - /* Memory for the cancellation buffer. */ > - struct pthread_unwind_buf unwind_buf; > - > - int not_first_call; > - DIAG_PUSH_NEEDS_COMMENT; > -#if __GNUC_PREREQ (7, 0) > - /* This call results in a -Wstringop-overflow warning because struct > - pthread_unwind_buf is smaller than jmp_buf. setjmp and longjmp > - do not use anything beyond the common prefix (they never access > - the saved signal mask), so that is a false positive. */ > - DIAG_IGNORE_NEEDS_COMMENT (11, "-Wstringop-overflow="); > -#endif > - not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf); > - DIAG_POP_NEEDS_COMMENT; > - if (__glibc_likely (! not_first_call)) > - { > - struct pthread *self = THREAD_SELF; > - > - /* Store old info. */ > - unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf); > - unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup); > - > - /* Store the new cleanup handler info. */ > - THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf); > - > - /* Run the program. */ > - result = main (argc, argv, __environ MAIN_AUXVEC_PARAM); > - } > - else > - { > - /* Remove the thread-local data. */ > -# ifdef SHARED > - PTHFCT_CALL (ptr__nptl_deallocate_tsd, ()); > -# else > - extern void __nptl_deallocate_tsd (void) __attribute ((weak)); > - __nptl_deallocate_tsd (); > -# endif > - > - /* One less thread. Decrement the counter. If it is zero we > - terminate the entire process. */ > - result = 0; > -# ifdef SHARED > - unsigned int *ptr = __libc_pthread_functions.ptr_nthreads; > -# ifdef PTR_DEMANGLE > - PTR_DEMANGLE (ptr); > -# endif > -# else > - extern unsigned int __nptl_nthreads __attribute ((weak)); > - unsigned int *const ptr = &__nptl_nthreads; > -# endif > - > - if (! atomic_decrement_and_test (ptr)) > - /* Not much left to do but to exit the thread, not the process. */ > - __exit_thread (); > - } > -#else > - /* Nothing fancy, just call the function. */ > - result = main (argc, argv, __environ MAIN_AUXVEC_PARAM); > -#endif > > - exit (result); > + __libc_start_call_main (main, argc, argv MAIN_AUXVEC_PARAM); > } > > /* Starting with glibc 2.34, the init parameter is always NULL. Older Ok. > diff --git a/sysdeps/generic/libc_start_call_main.h b/sysdeps/generic/libc_start_call_main.h > new file mode 100644 > index 0000000000..8a06eec4a3 > --- /dev/null > +++ b/sysdeps/generic/libc_start_call_main.h > @@ -0,0 +1,24 @@ > +/* Invoking main from __libc_start. Generic version without unwinding. > + Copyright (C) 1998-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/>. */ > + > +_Noreturn static __always_inline void > +__libc_start_call_main (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), > + int argc, char **argv MAIN_AUXVEC_DECL) > +{ > + exit (main (argc, argv, __environ MAIN_AUXVEC_PARAM)); > +} Ok. > diff --git a/sysdeps/nptl/libc_start_call_main.h b/sysdeps/nptl/libc_start_call_main.h > new file mode 100644 > index 0000000000..5218e7ab1e > --- /dev/null > +++ b/sysdeps/nptl/libc_start_call_main.h > @@ -0,0 +1,88 @@ > +/* Invoking main from __libc_start_main. nptl version. > + Copyright (C) 1998-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 <atomic.h> > + > +_Noreturn static void > +__libc_start_call_main (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), > + int argc, char **argv > +#ifdef LIBC_START_MAIN_AUXVEC_ARG > + , ElfW(auxv_t) *auxvec > +#endif > + ) > +{ > + int result; > + > + /* Memory for the cancellation buffer. */ > + struct pthread_unwind_buf unwind_buf; > + > + int not_first_call; > + DIAG_PUSH_NEEDS_COMMENT; > +#if __GNUC_PREREQ (7, 0) > + /* This call results in a -Wstringop-overflow warning because struct > + pthread_unwind_buf is smaller than jmp_buf. setjmp and longjmp > + do not use anything beyond the common prefix (they never access > + the saved signal mask), so that is a false positive. */ > + DIAG_IGNORE_NEEDS_COMMENT (11, "-Wstringop-overflow="); > +#endif > + not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf); > + DIAG_POP_NEEDS_COMMENT; > + if (__glibc_likely (! not_first_call)) > + { > + struct pthread *self = THREAD_SELF; > + > + /* Store old info. */ > + unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf); > + unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup); > + > + /* Store the new cleanup handler info. */ > + THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf); > + > + /* Run the program. */ > + result = main (argc, argv, __environ MAIN_AUXVEC_PARAM); > + } > + else > + { > + /* Remove the thread-local data. */ > +# ifdef SHARED > + PTHFCT_CALL (ptr__nptl_deallocate_tsd, ()); > +# else > + extern void __nptl_deallocate_tsd (void) __attribute ((weak)); > + __nptl_deallocate_tsd (); > +# endif > + > + /* One less thread. Decrement the counter. If it is zero we > + terminate the entire process. */ > + result = 0; > +# ifdef SHARED > + unsigned int *ptr = __libc_pthread_functions.ptr_nthreads; > +# ifdef PTR_DEMANGLE > + PTR_DEMANGLE (ptr); > +# endif > +# else > + extern unsigned int __nptl_nthreads __attribute ((weak)); > + unsigned int *const ptr = &__nptl_nthreads; > +# endif > + > + if (! atomic_decrement_and_test (ptr)) > + /* Not much left to do but to exit the thread, not the process. */ > + __exit_thread (); > + } > + > + exit (result); > +} > Ok.
diff --git a/csu/libc-start.c b/csu/libc-start.c index 05ff7afddf..8688cba76d 100644 --- a/csu/libc-start.c +++ b/csu/libc-start.c @@ -58,12 +58,6 @@ uintptr_t __pointer_chk_guard_local # endif #endif -#ifdef HAVE_PTR_NTHREADS -/* We need atomic operations. */ -# include <atomic.h> -#endif - - #ifndef SHARED # include <link.h> # include <dl-irel.h> @@ -123,6 +117,9 @@ apply_irel (void) # define ARCH_INIT_CPU_FEATURES() #endif +/* Obtain the definition of __libc_start_call_main. */ +#include <libc_start_call_main.h> + #ifdef SHARED /* Initialization for dynamic executables. Find the main executable link map and run its init functions. */ @@ -245,9 +242,6 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), void (*fini) (void), void (*rtld_fini) (void), void *stack_end) { - /* Result of the 'main' function. */ - int result; - #ifndef SHARED char **ev = &argv[argc + 1]; @@ -413,68 +407,8 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), #ifndef SHARED _dl_debug_initialize (0, LM_ID_BASE); #endif -#ifdef HAVE_CLEANUP_JMP_BUF - /* Memory for the cancellation buffer. */ - struct pthread_unwind_buf unwind_buf; - - int not_first_call; - DIAG_PUSH_NEEDS_COMMENT; -#if __GNUC_PREREQ (7, 0) - /* This call results in a -Wstringop-overflow warning because struct - pthread_unwind_buf is smaller than jmp_buf. setjmp and longjmp - do not use anything beyond the common prefix (they never access - the saved signal mask), so that is a false positive. */ - DIAG_IGNORE_NEEDS_COMMENT (11, "-Wstringop-overflow="); -#endif - not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf); - DIAG_POP_NEEDS_COMMENT; - if (__glibc_likely (! not_first_call)) - { - struct pthread *self = THREAD_SELF; - - /* Store old info. */ - unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf); - unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup); - - /* Store the new cleanup handler info. */ - THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf); - - /* Run the program. */ - result = main (argc, argv, __environ MAIN_AUXVEC_PARAM); - } - else - { - /* Remove the thread-local data. */ -# ifdef SHARED - PTHFCT_CALL (ptr__nptl_deallocate_tsd, ()); -# else - extern void __nptl_deallocate_tsd (void) __attribute ((weak)); - __nptl_deallocate_tsd (); -# endif - - /* One less thread. Decrement the counter. If it is zero we - terminate the entire process. */ - result = 0; -# ifdef SHARED - unsigned int *ptr = __libc_pthread_functions.ptr_nthreads; -# ifdef PTR_DEMANGLE - PTR_DEMANGLE (ptr); -# endif -# else - extern unsigned int __nptl_nthreads __attribute ((weak)); - unsigned int *const ptr = &__nptl_nthreads; -# endif - - if (! atomic_decrement_and_test (ptr)) - /* Not much left to do but to exit the thread, not the process. */ - __exit_thread (); - } -#else - /* Nothing fancy, just call the function. */ - result = main (argc, argv, __environ MAIN_AUXVEC_PARAM); -#endif - exit (result); + __libc_start_call_main (main, argc, argv MAIN_AUXVEC_PARAM); } /* Starting with glibc 2.34, the init parameter is always NULL. Older diff --git a/sysdeps/generic/libc_start_call_main.h b/sysdeps/generic/libc_start_call_main.h new file mode 100644 index 0000000000..8a06eec4a3 --- /dev/null +++ b/sysdeps/generic/libc_start_call_main.h @@ -0,0 +1,24 @@ +/* Invoking main from __libc_start. Generic version without unwinding. + Copyright (C) 1998-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/>. */ + +_Noreturn static __always_inline void +__libc_start_call_main (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), + int argc, char **argv MAIN_AUXVEC_DECL) +{ + exit (main (argc, argv, __environ MAIN_AUXVEC_PARAM)); +} diff --git a/sysdeps/nptl/libc_start_call_main.h b/sysdeps/nptl/libc_start_call_main.h new file mode 100644 index 0000000000..5218e7ab1e --- /dev/null +++ b/sysdeps/nptl/libc_start_call_main.h @@ -0,0 +1,88 @@ +/* Invoking main from __libc_start_main. nptl version. + Copyright (C) 1998-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 <atomic.h> + +_Noreturn static void +__libc_start_call_main (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), + int argc, char **argv +#ifdef LIBC_START_MAIN_AUXVEC_ARG + , ElfW(auxv_t) *auxvec +#endif + ) +{ + int result; + + /* Memory for the cancellation buffer. */ + struct pthread_unwind_buf unwind_buf; + + int not_first_call; + DIAG_PUSH_NEEDS_COMMENT; +#if __GNUC_PREREQ (7, 0) + /* This call results in a -Wstringop-overflow warning because struct + pthread_unwind_buf is smaller than jmp_buf. setjmp and longjmp + do not use anything beyond the common prefix (they never access + the saved signal mask), so that is a false positive. */ + DIAG_IGNORE_NEEDS_COMMENT (11, "-Wstringop-overflow="); +#endif + not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf); + DIAG_POP_NEEDS_COMMENT; + if (__glibc_likely (! not_first_call)) + { + struct pthread *self = THREAD_SELF; + + /* Store old info. */ + unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf); + unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup); + + /* Store the new cleanup handler info. */ + THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf); + + /* Run the program. */ + result = main (argc, argv, __environ MAIN_AUXVEC_PARAM); + } + else + { + /* Remove the thread-local data. */ +# ifdef SHARED + PTHFCT_CALL (ptr__nptl_deallocate_tsd, ()); +# else + extern void __nptl_deallocate_tsd (void) __attribute ((weak)); + __nptl_deallocate_tsd (); +# endif + + /* One less thread. Decrement the counter. If it is zero we + terminate the entire process. */ + result = 0; +# ifdef SHARED + unsigned int *ptr = __libc_pthread_functions.ptr_nthreads; +# ifdef PTR_DEMANGLE + PTR_DEMANGLE (ptr); +# endif +# else + extern unsigned int __nptl_nthreads __attribute ((weak)); + unsigned int *const ptr = &__nptl_nthreads; +# endif + + if (! atomic_decrement_and_test (ptr)) + /* Not much left to do but to exit the thread, not the process. */ + __exit_thread (); + } + + exit (result); +}