/* 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 . */ /* Written by Bruno Haible , 2020. */ #include /* Specification. */ #include "asyncsafe-spin.h" #include 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 sigprocmask() is safe to call from within a signal handler, see POSIX section "Signal Actions" . (In other words, sigprocmask() is atomic, because it is implemented as a system call.) Whereas on native Windows, 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 sigprocmask (SIG_BLOCK, mask, saved_mask); /* equivalent to pthread_sigmask */ 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 sigprocmask (SIG_SETMASK, saved_mask, NULL); /* equivalent to pthread_sigmask */ } void asyncsafe_spin_destroy (asyncsafe_spinlock_t *lock) { glthread_spinlock_destroy (lock); }