libc - Implement sigblockall() and sigunblockall()

Operating Systems / DragonFlyBSD - Matthew Dillon [] - 12 November 2019 01:46 UTC

- Signal safety is becoming a defacto requirement for most of libc and pthreads. In particular, the memory allocator. Given the chances of teaching tens of thousands of programmers about signal safety, and just making it work in libc and pthreads, only one of these two possibilities is actually realizable.

In particular, high-level languages have become so complex, and some applications (chrome, firefox, etc) have become so complex, that the code is regularly tripping over signal safety issues.

However, implementing signal safety with current mechanisms is extremely expensive due to the need for multiple system calls. To whit, DragonFlyBSD now has a mechanism that does not require system calls in the critical path.

- Implement sigblockall() and sigunblockall(). These functions leverage the new /dev/lpmap per-thread shared page mechanism to provide a way to temporary block the dispatch of all maskable signals without having to make any system calls.

These are extremely fast routines.

- Reentrant / Recursable

- Temporarily blocks any dispatch of a maskable asynchronous signal to the calling thread. Other threads are not affected... this is a per-thread mechanism.

- The last sigunblockall() will immediately dispatch any blocked signals.

- The normal signal mask is not affected by these routines.

- Does not block signals caused by synchronous traps.

- The current recursion count is retained on [v]fork() to ease coding and to also allow signals to be temporarily blocked across a fork until the child process is ready to deal with them, if desired.

- Implement signal safety for most of pthreads. All temporary internal mutexes are now wrapped with sigblockall() and sigunblockall().

- Implement signal safety for the malloc subsystem. All functions are wrawpped with sigblockall() and sigunblockall().

These implementations make lang/mono and lang/rust far more reliable than they were before. Where 9 out of 10 builds used to fail, now they succeed.

721505dec2 libc - Implement sigblockall() and sigunblockall()
lib/libc/gen/_thread_init.c | 33 +++++-
lib/libc/include/libc_private.h | 15 +++
lib/libc/stdlib/ | 2 +-
lib/libc/stdlib/nmalloc.c | 182 ++++++++++++++++++++++----------
lib/libc/upmap/ | 4 +-
lib/libc/upmap/ | 8 ++
lib/libc/upmap/ukp_blocksigs.c | 100 ++++++++++++++++++
lib/libc/upmap/upmap.c | 154 ++++++++++++++++++++++++---
lib/libc/upmap/upmap.h | 7 +-
lib/libstand/Makefile | 2 +
lib/libthread_xu/thread/thr_create.c | 2 +-
lib/libthread_xu/thread/thr_init.c | 1 +
lib/libthread_xu/thread/thr_mutex.c | 19 ++--
lib/libthread_xu/thread/thr_private.h | 35 ++++--
lib/libthread_xu/thread/thr_pspinlock.c | 6 +-
lib/libthread_xu/thread/thr_spinlock.c | 6 +-
lib/libthread_xu/thread/thr_umtx.h | 32 ++++--
libexec/rtld-elf/rtld.c | 2 +
18 files changed, 509 insertions(+), 101 deletions(-)


  • Share