1
0
mirror of https://https.git.savannah.gnu.org/git/gnulib.git synced 2026-04-28 06:33:36 +00:00
Files
gnulib/lib/asyncsafe-spin.c
Bruno Haible e4100b4078 asyncsafe-spin: Prefer pthread_sigmask over sigprocmask.
Suggested by Paul Eggert.

* lib/asyncsafe-spin.c (asyncsafe_spin_lock, asyncsafe_spin_unlock): Use
pthread_sigmask instead of sigprocmask.
* modules/asyncsafe-spin (Depends-on): Add pthread_sigmask. Remove
sigprocmask.
(Link): New section.
* modules/asyncsafe-spin-tests (Makefile.am): Link test-asyncsafe-spin1
with $(PTHREAD_SIGMASK_LIB).
* modules/jit/cache-tests (Makefile.am): Link test-cache with
$(PTHREAD_SIGMASK_LIB).
2026-04-04 22:44:10 +02:00

81 lines
2.8 KiB
C

/* Spin locks for communication between threads and signal handlers.
Copyright (C) 2020-2026 Free Software Foundation, Inc.
This file 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.
This file 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 this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Bruno Haible <bruno@clisp.org>, 2020. */
#include <config.h>
/* Specification. */
#include "asyncsafe-spin.h"
#include <stdlib.h>
void
asyncsafe_spin_init (asyncsafe_spinlock_t *lock)
{
glthread_spinlock_init (lock);
}
void
asyncsafe_spin_lock (asyncsafe_spinlock_t *lock,
bool from_signal_handler,
const sigset_t *mask, sigset_t *saved_mask)
{
/* On all platforms, when not running in a signal handler, we need to block
the signals until the corresponding asyncsafe_spin_unlock() invocation.
This is needed because if, during that period, a signal occurred and it
happened to run in the current thread and it were to wait on this spin
lock, it would hang.
On platforms other than native Windows, it is useful to do the same
thing also within a signal handler, since signals may remain enabled
while a signal handler runs. It is possible to do this because
pthread_sigmask() is safe to call from within a signal handler, see
POSIX section "Signal Actions"
<https://pubs.opengroup.org/onlinepubs/9799919799/functions/V2_chap02.html#tag_16_04_03>.
(In other words, pthread_sigmask() is atomic, because it is implemented as a
system call.)
Whereas on native Windows, pthread_sigmask() = sigprocmask() is not atomic,
because it manipulates global variables. Therefore in this case, we are
*not* allowed to call it from within a signal handler. */
#if defined _WIN32 && !defined __CYGWIN__
if (!from_signal_handler)
#endif
pthread_sigmask (SIG_BLOCK, mask, saved_mask);
glthread_spinlock_lock (lock);
}
void
asyncsafe_spin_unlock (asyncsafe_spinlock_t *lock,
bool from_signal_handler,
const sigset_t *saved_mask)
{
if (glthread_spinlock_unlock (lock))
abort ();
#if defined _WIN32 && !defined __CYGWIN__
if (!from_signal_handler)
#endif
pthread_sigmask (SIG_SETMASK, saved_mask, NULL);
}
void
asyncsafe_spin_destroy (asyncsafe_spinlock_t *lock)
{
glthread_spinlock_destroy (lock);
}