From: Bruno Haible Date: Wed, 1 Jul 2020 20:13:27 +0000 (+0200) Subject: pthread-spin: Add error checking. X-Git-Tag: v1.0~3939 X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=6bf513db3802388e3fc8c40a506e23c85a8abf21;p=gnulib.git pthread-spin: Add error checking. * lib/pthread-spin.c: Include . (pthread_spin_init, pthread_spin_lock, pthread_spin_trylock, pthread_spin_unlock) [GCC>=4.7]: Prefer an implementation that verifies the unlocks. * modules/pthread-spin (Depends-on): Add stdbool. --- diff --git a/ChangeLog b/ChangeLog index 86c32ed6c7..b1d391b4ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2020-07-01 Bruno Haible + + pthread-spin: Add error checking. + * lib/pthread-spin.c: Include . + (pthread_spin_init, pthread_spin_lock, pthread_spin_trylock, + pthread_spin_unlock) [GCC>=4.7]: Prefer an implementation that verifies + the unlocks. + * modules/pthread-spin (Depends-on): Add stdbool. + 2020-07-01 Bruno Haible pthread-spin: Add tests. diff --git a/lib/pthread-spin.c b/lib/pthread-spin.c index 93e8b370ca..73eb9f31f6 100644 --- a/lib/pthread-spin.c +++ b/lib/pthread-spin.c @@ -21,6 +21,8 @@ /* Specification. */ #include +#include + #if (defined _WIN32 && ! defined __CYGWIN__) && USE_WINDOWS_THREADS # include "windows-spin.h" #endif @@ -72,6 +74,55 @@ pthread_spin_destroy (pthread_spinlock_t *lock) Documentation: */ +# if 1 +/* An implementation that verifies the unlocks. */ + +int +pthread_spin_init (pthread_spinlock_t *lock, + int shared_across_processes _GL_UNUSED) +{ + __atomic_store_n ((char *) lock, 0, __ATOMIC_SEQ_CST); + return 0; +} + +int +pthread_spin_lock (pthread_spinlock_t *lock) +{ + /* Wait until *lock becomes 0, then replace it with 1. */ + asyncsafe_spinlock_t zero; + while (!(zero = 0, + __atomic_compare_exchange_n ((char *) lock, &zero, 1, false, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))) + ; + return 0; +} + +int +pthread_spin_trylock (pthread_spinlock_t *lock) +{ + asyncsafe_spinlock_t zero; + if (!(zero = 0, + __atomic_compare_exchange_n ((char *) lock, &zero, 1, false, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))) + return EBUSY; + return 0; +} + +int +pthread_spin_unlock (pthread_spinlock_t *lock) +{ + /* If *lock is 1, then replace it with 0. */ + asyncsafe_spinlock_t one = 1; + if (!__atomic_compare_exchange_n ((char *) lock, &one, 0, false, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) + abort (); + return 0; +} + +# else +/* An implementation that is a little bit more optimized, but does not verify + the unlocks. */ + int pthread_spin_init (pthread_spinlock_t *lock, int shared_across_processes _GL_UNUSED) @@ -103,6 +154,8 @@ pthread_spin_unlock (pthread_spinlock_t *lock) return 0; } +# endif + int pthread_spin_destroy (pthread_spinlock_t *lock) { diff --git a/modules/pthread-spin b/modules/pthread-spin index 53e0051c34..ce69944021 100644 --- a/modules/pthread-spin +++ b/modules/pthread-spin @@ -7,6 +7,7 @@ m4/pthread-spin.m4 Depends-on: pthread-h +stdbool [test $HAVE_PTHREAD_SPIN_INIT = 0 || test $REPLACE_PTHREAD_SPIN_INIT = 1] windows-spin [test $gl_threads_api = windows] configure.ac: