Use stdatomic.h for atomic_counter_t where available.

Closes ticket 23953.
This commit is contained in:
Nick Mathewson 2017-10-23 12:35:30 -04:00
parent 880d596f4d
commit 25f882a9cf
4 changed files with 78 additions and 11 deletions

3
changes/bug23953 Normal file
View File

@ -0,0 +1,3 @@
o Minor features (performance):
- Use stdatomic.h where available, rather than mutexes, to implement
atomic_counter_t. Closes ticket 23953.

View File

@ -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 \

View File

@ -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

View File

@ -14,6 +14,10 @@
#include <pthread.h>
#endif
#ifdef HAVE_STDATOMIC_H
#include <stdatomic.h>
#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) */