diff options
author | Brooks Moses <bmoses@google.com> | 2014-02-24 11:04:49 -0800 |
---|---|---|
committer | Fangrui Song <i@maskray.me> | 2021-08-27 17:23:11 -0700 |
commit | 3e9a530aaeb891ed13b8b2c44df7b0d040f1096a (patch) | |
tree | 5e04dc382740f9603ae174c8ea2ade8cc5aefc19 /sysdeps | |
parent | 74f10c8aad08cc2e687f6f93f7ef17fd0581070e (diff) | |
download | glibc-3e9a530aaeb891ed13b8b2c44df7b0d040f1096a.zip glibc-3e9a530aaeb891ed13b8b2c44df7b0d040f1096a.tar.gz glibc-3e9a530aaeb891ed13b8b2c44df7b0d040f1096a.tar.bz2 |
Revert upstream removal of async-safe TLS patches.
Diffstat (limited to 'sysdeps')
-rw-r--r-- | sysdeps/generic/ldsodefs.h | 16 | ||||
-rw-r--r-- | sysdeps/mach/hurd/dl-sysdep.h | 7 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/dl-sysdep.c | 46 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/dl-sysdep.h | 4 |
4 files changed, 73 insertions, 0 deletions
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 5e7224b..7326e11 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -257,6 +257,11 @@ extern unsigned long int _dl_higher_prime_number (unsigned long int n) /* A stripped down strtoul-like implementation. */ uint64_t _dl_strtoul (const char *, char **) attribute_hidden; +/* Mask every signal, returning the previous sigmask in OLD. */ +extern void _dl_mask_all_signals (sigset_t *old) internal_function; +/* Undo _dl_mask_all_signals. */ +extern void _dl_unmask_signals (sigset_t *old) internal_function; + /* Function used as argument for `_dl_receive_error' function. The arguments are the error code, error string, and the objname the error occurred in. */ @@ -1096,6 +1101,17 @@ extern void *_dl_allocate_tls_storage (void) attribute_hidden; extern void *_dl_allocate_tls_init (void *); rtld_hidden_proto (_dl_allocate_tls_init) +/* Remove all allocated dynamic TLS regions from a DTV + for reuse by new thread. */ +extern void _dl_clear_dtv (dtv_t *dtv) internal_function; +rtld_hidden_proto (_dl_clear_dtv) + +extern void *__signal_safe_memalign (size_t boundary, size_t size); +extern void *__signal_safe_malloc (size_t size); +extern void __signal_safe_free (void *ptr); +extern void *__signal_safe_realloc (void *ptr, size_t size); +extern void *__signal_safe_calloc (size_t nmemb, size_t size); + /* Deallocate memory allocated with _dl_allocate_tls. */ extern void _dl_deallocate_tls (void *tcb, bool dealloc_tcb); rtld_hidden_proto (_dl_deallocate_tls) diff --git a/sysdeps/mach/hurd/dl-sysdep.h b/sysdeps/mach/hurd/dl-sysdep.h index 9a1f353..dff8b9b 100644 --- a/sysdeps/mach/hurd/dl-sysdep.h +++ b/sysdeps/mach/hurd/dl-sysdep.h @@ -29,3 +29,10 @@ # define DL_ARGV_NOT_RELRO 1 # define LIBC_STACK_END_NOT_RELRO 1 #endif + +#include <signal.h> +inline void _dl_mask_all_signals (sigset_t *) internal_function; +inline void _dl_mask_all_signals (sigset_t *) { } + +inline void _dl_unmask_all_signals (sigset_t *) internal_function; +inline void _dl_unmask_all_signals (sigset_t *) { } diff --git a/sysdeps/unix/sysv/linux/dl-sysdep.c b/sysdeps/unix/sysv/linux/dl-sysdep.c index b4cda34..f8d1d5d 100644 --- a/sysdeps/unix/sysv/linux/dl-sysdep.c +++ b/sysdeps/unix/sysv/linux/dl-sysdep.c @@ -19,6 +19,7 @@ /* Linux needs some special initialization, but otherwise uses the generic dynamic linker system interface code. */ +#include <assert.h> #include <string.h> #include <fcntl.h> #include <unistd.h> @@ -130,3 +131,48 @@ _dl_discover_osversion (void) return version; } + +/* Mask every signal, returning the previous sigmask in OLD. */ +void +internal_function +_dl_mask_all_signals (sigset_t *old) +{ + int ret; + sigset_t new; + + sigfillset (&new); + + /* This function serves as a replacement to pthread_sigmask, which + isn't available from within the dynamic linker since it would require + linking with libpthread. We duplicate some of the functionality here + to avoid requiring libpthread. This isn't quite identical to + pthread_sigmask in that we do not mask internal signals used for + cancellation and setxid handling. This disables asynchronous + cancellation for the duration the signals are disabled, but it's a + small window, and prevents any problems with the use of TLS variables + in the signal handlers that would have executed. */ + + /* It's very important we don't touch errno here, as that's TLS; since this + gets called from get_tls_addr we might end up recursing. */ + + INTERNAL_SYSCALL_DECL (err); + + ret = INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &new, old, + _NSIG / 8); + + assert (ret == 0); +} + +/* Return sigmask to what it was before a call to _dl_mask_all_signals. */ +void +internal_function +_dl_unmask_signals (sigset_t *old) +{ + int ret; + INTERNAL_SYSCALL_DECL (err); + + ret = INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, old, NULL, + _NSIG / 8); + + assert (ret == 0); +} diff --git a/sysdeps/unix/sysv/linux/dl-sysdep.h b/sysdeps/unix/sysv/linux/dl-sysdep.h index 9750145..0c64545 100644 --- a/sysdeps/unix/sysv/linux/dl-sysdep.h +++ b/sysdeps/unix/sysv/linux/dl-sysdep.h @@ -30,4 +30,8 @@ /* Get version of the OS. */ extern int _dl_discover_osversion (void) attribute_hidden; # define HAVE_DL_DISCOVER_OSVERSION 1 + +#include <signal.h> +void _dl_mask_all_signals (sigset_t *) internal_function; +void _dl_unmask_all_signals (sigset_t *) internal_function; #endif |