diff --git a/include/pthread_np.h b/include/pthread_np.h --- a/include/pthread_np.h +++ b/include/pthread_np.h @@ -59,6 +59,8 @@ int pthread_peekjoin_np(pthread_t, void **); void pthread_set_name_np(pthread_t, const char *); int pthread_setaffinity_np(pthread_t, size_t, const cpuset_t *); +void pthread_signals_block_np(void); +void pthread_signals_unblock_np(void); int pthread_single_np(void); void pthread_suspend_all_np(void); int pthread_suspend_np(pthread_t); diff --git a/lib/libthr/pthread.map b/lib/libthr/pthread.map --- a/lib/libthr/pthread.map +++ b/lib/libthr/pthread.map @@ -339,5 +339,7 @@ }; FBSD_1.8 { + pthread_signals_block_np; + pthread_signals_unblock_np; pthread_sigqueue; }; diff --git a/lib/libthr/thread/thr_sig.c b/lib/libthr/thread/thr_sig.c --- a/lib/libthr/thread/thr_sig.c +++ b/lib/libthr/thread/thr_sig.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "un-namespace.h" #include "libc_private.h" @@ -163,6 +164,24 @@ __sys_sigfastblock(SIGFASTBLOCK_SETPTR, &curthread->fsigblock); } +void +pthread_signals_block_np(void) +{ + struct pthread *curthread; + + curthread = _get_curthread(); + _thr_signal_block(curthread); +} + +void +pthread_signals_unblock_np(void) +{ + struct pthread *curthread; + + curthread = _get_curthread(); + _thr_signal_unblock(curthread); +} + int _thr_send_sig(struct pthread *thread, int sig) { diff --git a/share/man/man3/Makefile b/share/man/man3/Makefile --- a/share/man/man3/Makefile +++ b/share/man/man3/Makefile @@ -458,6 +458,7 @@ pthread_setspecific.3 \ pthread_sigmask.3 \ pthread_sigqueue.3 \ + pthread_signals_block_np.3 \ pthread_spin_init.3 \ pthread_spin_lock.3 \ pthread_suspend_all_np.3 \ @@ -523,6 +524,8 @@ PTHREAD_MLINKS+=pthread_set_name_np.3 pthread_get_name_np.3 \ pthread_set_name_np.3 pthread_getname_np.3 \ pthread_set_name_np.3 pthread_setname_np.3 +PTHREAD_MLINKS+=pthread_signals_block_np.3 \ + pthread_signals_unblock_np.3 PTHREAD_MLINKS+=pthread_spin_init.3 pthread_spin_destroy.3 \ pthread_spin_lock.3 pthread_spin_trylock.3 \ pthread_spin_lock.3 pthread_spin_unlock.3 diff --git a/share/man/man3/pthread_np.3 b/share/man/man3/pthread_np.3 --- a/share/man/man3/pthread_np.3 +++ b/share/man/man3/pthread_np.3 @@ -116,6 +116,11 @@ .Xc Sets the specified thread's name. .It Xo +.Ft void +.Fn pthread_signals_block_np void +.Xc +Blocks all asynchronous signals, quickly. +.It Xo .Ft int .Fn pthread_single_np void .Xc @@ -213,6 +218,7 @@ .Xr pthread_resume_all_np 3 , .Xr pthread_resume_np 3 , .Xr pthread_set_name_np 3 , +.Xr pthread_signals_block_np 3 , .Xr pthread_suspend_all_np 3 , .Xr pthread_suspend_np 3 , .Xr pthread_switch_add_np 3 diff --git a/share/man/man3/pthread_signals_block_np.3 b/share/man/man3/pthread_signals_block_np.3 new file mode 100644 --- /dev/null +++ b/share/man/man3/pthread_signals_block_np.3 @@ -0,0 +1,81 @@ +.\" Copyright (c) 2025 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.\" This documentation was written by +.\" Konstantin Belousov under sponsorship +.\" from the FreeBSD Foundation. +.\" +.Dd May 16, 2025 +.Dt PTHREAD_SIGNALS_BLOCK_NP 3 +.Os +.Sh NAME +.Nm pthread_signals_block_np , +.Nm pthread_signals_unblock_np +.Nd fast asynchronous signals blocking and unblocking +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread_np.h +.Ft void +.Fn pthread_signals_block_np "void" +.Ft void +.Fn pthread_signals_unblock_np "void" +.Sh DESCRIPTION +The +.Fn pthread_signals_block_np +and +.Fn pthread_signals_unblock_np +functions provide user programs an interface to the fast asynchronous +signals blocking facility +.Xr sigfastblock 2 . +.Pp +Blocking signals with +.Fn pthread_signals_block_np +disables delivery of any asynchronous signal, until unblocked. +Signal blocking establishes a critical section where the execution +flow of the thread cannot be diverted into a signal handler. +Blocking signals is fast, it is performed by a single memory write into +a location established with the kernel. +.Pp +Synchronous signal delivery cannot be blocked in general, including with +these functions. +.Pp +The blocked state established by the +.Fn pthread_signals_block_np +is not completely POSIX-compliant. +Specifically, system calls executed while in a blocked section, +might abort sleep and return +.Er EINTR +upon queuing of an asynchronous signal to the thread, +but the signal handler is not called until the last unblock is done. +.Pp +Calls to +.Nm pthread_signals_block_np +can be nested, and must be complemented by the equal count of +calls to +.Nm pthread_signals_unblock_np +to return the calling thread into the standard mode of signal receiving. +.Pp +An example of the function usage might be a construction of the CPU +state that cannot be done atomically, and which includes stages where +the state of the thread is not ABI compliant. +If a signal is delivered while such state is not yet finished, signal +handlers would misbehave. +Using standard functions +.Pq Fn sigprocmask +to establish critical section might be much slower, because +.Fn sigprocmask +is syscall, while +.Fn pthread_signals_block_np +consists of a single atomic memory write. +.Sh RETURN VALUES +The functions do not return a value. +.Sh ERRORS +There are no errors reported by the functions. +.Sh SEE ALSO +.Xr sigfastblock 2 , +.Xr sigprocmask 2 , +.Xr pthread_sigmask 3 , +.Xr pthread_np 3