Browse Source

Merge branch 'ticket23953_033_squashed'

Nick Mathewson 6 years ago
parent
commit
5da0a73838
4 changed files with 78 additions and 11 deletions
  1. 3 0
      changes/bug23953
  2. 1 0
      configure.ac
  3. 13 6
      src/common/compat_threads.c
  4. 61 5
      src/common/compat_threads.h

+ 3 - 0
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.

+ 1 - 0
configure.ac

@@ -1233,6 +1233,7 @@ AC_CHECK_HEADERS([assert.h \
                   pwd.h \
                   readpassphrase.h \
                   stdint.h \
+                  stdatomic.h \
                   sys/eventfd.h \
                   sys/file.h \
                   sys/ioctl.h \

+ 13 - 6
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
 

+ 61 - 5
src/common/compat_threads.h

@@ -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
+
+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);
+}
 
-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);
+#else
+#endif
 
 #endif /* !defined(TOR_COMPAT_THREADS_H) */