From f449f278dd3c70e479a035f50a9bb817a9b433ba Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 17:24:08 +0200 Subject: Adding upstream version 3.2.6. Signed-off-by: Daniel Baumann --- src/contrib/spinlock.h | 133 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 src/contrib/spinlock.h (limited to 'src/contrib/spinlock.h') diff --git a/src/contrib/spinlock.h b/src/contrib/spinlock.h new file mode 100644 index 0000000..837f500 --- /dev/null +++ b/src/contrib/spinlock.h @@ -0,0 +1,133 @@ +/* Copyright (C) 2021 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +/*! + * \brief Multiplatform spinlock. + */ + +#pragma once + +#if (__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_ATOMICS__) +/* Not tested and activated yet. */ +/* #define HAVE_STDATOMIC */ +#endif + +#if defined(__APPLE__) +# if defined(MAC_OS_X_VERSION_10_12) || \ + MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 +# define APPLE_SPIN_NEW +# else +# define APPLE_SPIN_OLD +# endif /* MAC_OS_X_VERSION_10_12 ... */ +#endif /* __APPLE__ */ + +#if defined(HAVE_SYNC_ATOMIC) || defined(HAVE_ATOMIC) +# include +#elif defined(HAVE_STDATOMIC) +# include +# include +#elif defined(APPLE_SPIN_NEW) +# include +#elif defined(APPLE_SPIN_OLD) +# include +#else /* POSIX pthread spinlock. */ +# include +#endif + +/*! \brief Spinlock lock variable type. */ +typedef +#if defined(HAVE_SYNC_ATOMIC) || defined(HAVE_ATOMIC) + bool /*!< Spinlock lock - a simple & fast atomic version. */ +#elif defined(HAVE_STDATOMIC) + atomic_bool /*!< Spinlock lock - a simple & fast atomic version, C11 */ +#elif defined(APPLE_SPIN_NEW) + os_unfair_lock /*!< Spinlock lock - a newer macOS version (macOS >= 10.12). */ +#elif defined(APPLE_SPIN_OLD) + OSSpinLock /*!< Spinlock lock - an older macOS version (macOS < 10.12). */ +#else /* POSIX */ + pthread_spinlock_t /*!< Spinlock lock - a POSIX pthread version. */ +#endif + knot_spin_t; + +/*! \brief Initialize the spinlock pointed to by the parameter "lock". */ +static inline void knot_spin_init(knot_spin_t *lock) +{ +#if defined(HAVE_SYNC_ATOMIC) || defined(HAVE_ATOMIC) + *lock = false; +#elif defined(HAVE_STDATOMIC) + atomic_init(lock, false); +#elif defined(APPLE_SPIN_NEW) + *lock = OS_UNFAIR_LOCK_INIT; +#elif defined(APPLE_SPIN_OLD) + *lock = OS_SPINLOCK_INIT; +#else /* POSIX */ + pthread_spin_init(lock, PTHREAD_PROCESS_PRIVATE); +#endif +} + +/*! \brief Destroy the spinlock pointed to by the parameter "lock". */ +static inline void knot_spin_destroy(knot_spin_t *lock) +{ +#if defined(HAVE_SYNC_ATOMIC) || defined(HAVE_ATOMIC) || defined(HAVE_STDATOMIC) || \ + defined(APPLE_SPIN_NEW) || defined(APPLE_SPIN_OLD) + /* Nothing needed here. */ +#else /* POSIX */ + pthread_spin_destroy(lock); +#endif +} + +/*! \brief Lock the spinlock pointed to by the parameter "lock". */ +static inline void knot_spin_lock(knot_spin_t *lock) +{ +#if defined(HAVE_SYNC_ATOMIC) + while (__sync_lock_test_and_set(lock, 1)) { + } +#elif defined(HAVE_ATOMIC) + int expected = 0; + while (!__atomic_compare_exchange_n(lock, &expected, 1, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) { + expected = 0; + } +#elif defined(HAVE_STDATOMIC) + int expected = 0; + while (!atomic_compare_exchange_strong(lock, &expected, false)) { + expected = 0; + } +#elif defined(APPLE_SPIN_NEW) + os_unfair_lock_lock(lock); +#elif defined(APPLE_SPIN_OLD) + OSSpinLockLock(lock); +#else /* POSIX */ + pthread_spin_lock(lock); +#endif +} + +/*! \brief Unlock the spinlock pointed to by the parameter "lock". */ +static inline void knot_spin_unlock(knot_spin_t *lock) +{ +#if defined(HAVE_SYNC_ATOMIC) + __sync_lock_release(lock); +#elif defined(HAVE_ATOMIC) + __atomic_clear(lock, __ATOMIC_RELAXED); +#elif defined(HAVE_STDATOMIC) + atomic_store(lock, false); +#elif defined(APPLE_SPIN_NEW) + os_unfair_lock_unlock(lock); +#elif defined(APPLE_SPIN_OLD) + OSSpinLockUnlock(lock); +#else /* POSIX */ + pthread_spin_unlock(lock); +#endif +} -- cgit v1.2.3