From 25f882a9cfe39ccb2942fe55f41cdcbfd1ba288e Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 23 Oct 2017 12:35:30 -0400 Subject: [PATCH] Use stdatomic.h for atomic_counter_t where available. Closes ticket 23953. --- changes/bug23953 | 3 ++ configure.ac | 1 + src/common/compat_threads.c | 19 +++++++---- src/common/compat_threads.h | 66 ++++++++++++++++++++++++++++++++++--- 4 files changed, 78 insertions(+), 11 deletions(-) create mode 100644 changes/bug23953 diff --git a/changes/bug23953 b/changes/bug23953 new file mode 100644 index 000000000..10d41a00d --- /dev/null +++ b/changes/bug23953 @@ -0,0 +1,3 @@ + o Minor features (performance): + - Use stdatomic.h where available, rather than mutexes, to implement + atomic_counter_t. Closes ticket 23953. diff --git a/configure.ac b/configure.ac index c02646426..05968fa91 100644 --- a/configure.ac +++ b/configure.ac @@ -1230,6 +1230,7 @@ AC_CHECK_HEADERS([assert.h \ pwd.h \ readpassphrase.h \ stdint.h \ + stdatomic.h \ sys/eventfd.h \ sys/file.h \ sys/ioctl.h \ diff --git a/src/common/compat_threads.c b/src/common/compat_threads.c index 208d3138d..e8a97f125 100644 --- a/src/common/compat_threads.c +++ b/src/common/compat_threads.c @@ -352,12 +352,7 @@ alert_sockets_close(alert_sockets_t *socks) socks->read_fd = socks->write_fd = -1; } -/* - * XXXX We might be smart to move to compiler intrinsics or real atomic - * XXXX operations at some point. But not yet. - * - */ - +#ifndef HAVE_STDATOMIC_H /** Initialize a new atomic counter with the value 0 */ void atomic_counter_init(atomic_counter_t *counter) @@ -397,4 +392,16 @@ atomic_counter_get(atomic_counter_t *counter) tor_mutex_release(&counter->mutex); return val; } +/** Replace the value of an atomic counter; return the old one. */ +size_t +atomic_counter_exchange(atomic_counter_t *counter, size_t newval) +{ + size_t oldval; + tor_mutex_acquire(&counter->mutex); + oldval = counter->val; + counter->val = newval; + tor_mutex_release(&counter->mutex); + return oldval; +} +#endif diff --git a/src/common/compat_threads.h b/src/common/compat_threads.h index 42f14eab2..b452648ea 100644 --- a/src/common/compat_threads.h +++ b/src/common/compat_threads.h @@ -14,6 +14,10 @@ #include #endif +#ifdef HAVE_STDATOMIC_H +#include +#endif + #if defined(_WIN32) #define USE_WIN32_THREADS #elif defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_CREATE) @@ -150,16 +154,68 @@ void tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value); /** * Atomic counter type; holds a size_t value. */ +#ifdef HAVE_STDATOMIC_H +typedef struct atomic_counter_t { + atomic_size_t val; +} atomic_counter_t; +#define ATOMIC_LINKAGE static +#else typedef struct atomic_counter_t { tor_mutex_t mutex; size_t val; } atomic_counter_t; +#define ATOMIC_LINKAGE +#endif -void atomic_counter_init(atomic_counter_t *counter); -void atomic_counter_destroy(atomic_counter_t *counter); -void atomic_counter_add(atomic_counter_t *counter, size_t add); -void atomic_counter_sub(atomic_counter_t *counter, size_t sub); -size_t atomic_counter_get(atomic_counter_t *counter); +ATOMIC_LINKAGE void atomic_counter_init(atomic_counter_t *counter); +ATOMIC_LINKAGE void atomic_counter_destroy(atomic_counter_t *counter); +ATOMIC_LINKAGE void atomic_counter_add(atomic_counter_t *counter, size_t add); +ATOMIC_LINKAGE void atomic_counter_sub(atomic_counter_t *counter, size_t sub); +ATOMIC_LINKAGE size_t atomic_counter_get(atomic_counter_t *counter); +ATOMIC_LINKAGE size_t atomic_counter_exchange(atomic_counter_t *counter, + size_t newval); +#undef ATOMIC_LINKAGE + +#ifdef HAVE_STDATOMIC_H +/** Initialize a new atomic counter with the value 0 */ +static inline void +atomic_counter_init(atomic_counter_t *counter) +{ + atomic_init(&counter->val, 0); +} +/** Clean up all resources held by an atomic counter. */ +static inline void +atomic_counter_destroy(atomic_counter_t *counter) +{ + (void)counter; +} +/** Add a value to an atomic counter. */ +static inline void +atomic_counter_add(atomic_counter_t *counter, size_t add) +{ + (void) atomic_fetch_add(&counter->val, add); +} +/** Subtract a value from an atomic counter. */ +static inline void +atomic_counter_sub(atomic_counter_t *counter, size_t sub) +{ + (void) atomic_fetch_sub(&counter->val, sub); +} +/** Return the current value of an atomic counter */ +static inline size_t +atomic_counter_get(atomic_counter_t *counter) +{ + return atomic_load(&counter->val); +} +/** Replace the value of an atomic counter; return the old one. */ +static inline size_t +atomic_counter_exchange(atomic_counter_t *counter, size_t newval) +{ + return atomic_exchange(&counter->val, newval); +} + +#else +#endif #endif /* !defined(TOR_COMPAT_THREADS_H) */