1 /* Spin locks for communication between threads and signal handlers. 2 Copyright (C) 2020-2021 Free Software Foundation, Inc. 3 4 This file is free software: you can redistribute it and/or modify 5 it under the terms of the GNU Lesser General Public License as 6 published by the Free Software Foundation; either version 2.1 of the 7 License, or (at your option) any later version. 8 9 This file is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public License 15 along with this program. If not, see <https://www.gnu.org/licenses/>. */ 16 17 /* Written by Bruno Haible <bruno@clisp.org>, 2020. */ 18 19 #ifndef _ASYNCSAFE_SPIN_H 20 #define _ASYNCSAFE_SPIN_H 21 22 /* Usual spin locks are not allowed for communication between threads and signal 23 handlers, because the pthread_spin_* functions are not async-safe; see 24 <https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html> 25 section 2.4.3 Signal Actions. 26 27 This module provides spin locks with a similar API. It can be used like this, 28 both in regular multithreaded code and in signal handlers: 29 30 sigset_t saved_mask; 31 asyncsafe_spin_lock (&lock, &mask, &saved_mask); 32 do_something_contentious (); 33 asyncsafe_spin_unlock (&lock, &saved_mask); 34 35 The mask you specify here is the set of signals whose handlers might want to 36 take the same lock. 37 38 asyncsafe_spin_lock/unlock use pthread_sigmask, to ensure that while a thread 39 is executing such code, no signal handler will start such code for the same 40 lock *in the same thread* (because if this happened, the signal handler would 41 hang!). */ 42 43 #include <signal.h> 44 45 #if defined _WIN32 && ! defined __CYGWIN__ 46 # include "windows-spin.h" 47 typedef glwthread_spinlock_t asyncsafe_spinlock_t; 48 # define ASYNCSAFE_SPIN_INIT GLWTHREAD_SPIN_INIT 49 #else 50 typedef unsigned int asyncsafe_spinlock_t; 51 # define ASYNCSAFE_SPIN_INIT 0 52 #endif 53 54 #ifdef __cplusplus 55 extern "C" { 56 #endif 57 58 extern void asyncsafe_spin_init (asyncsafe_spinlock_t *lock); 59 extern void asyncsafe_spin_lock (asyncsafe_spinlock_t *lock, 60 const sigset_t *mask, sigset_t *saved_mask); 61 extern void asyncsafe_spin_unlock (asyncsafe_spinlock_t *lock, 62 const sigset_t *saved_mask); 63 extern void asyncsafe_spin_destroy (asyncsafe_spinlock_t *lock); 64 65 #ifdef __cplusplus 66 } 67 #endif 68 69 #endif /* _ASYNCSAFE_SPIN_H */