[PATCH 2 of 2] Core: add ngx_atomic_store() and ngx_atomic_load()

Piotr Sikora piotrsikora at google.com
Thu Aug 18 00:29:32 UTC 2016


# HG changeset patch
# User Piotr Sikora <piotrsikora at google.com>
# Date 1471265532 25200
#      Mon Aug 15 05:52:12 2016 -0700
# Node ID 40765d8ee4dd29089b0e60ed5b6099ac624e804e
# Parent  2f2ec92c3af93c11e195fb6d805df57518fede7c
Core: add ngx_atomic_store() and ngx_atomic_load().

Those functions must be used to prevent data races between
threads operating concurrently on the same variables.

No performance loss measured in microbenchmarks on x86_64.

No binary changes when compiled without __atomic intrinsics.

Found with ThreadSanitizer.

Signed-off-by: Piotr Sikora <piotrsikora at google.com>

diff -r 2f2ec92c3af9 -r 40765d8ee4dd auto/cc/conf
--- a/auto/cc/conf
+++ b/auto/cc/conf
@@ -178,7 +178,7 @@ if [ "$NGX_PLATFORM" != win32 ]; then
     fi
 
 
-    ngx_feature="gcc builtin atomic operations"
+    ngx_feature="gcc builtin __sync operations"
     ngx_feature_name=NGX_HAVE_GCC_ATOMIC
     ngx_feature_run=yes
     ngx_feature_incs=
@@ -195,6 +195,19 @@ if [ "$NGX_PLATFORM" != win32 ]; then
     . auto/feature
 
 
+    ngx_feature="gcc builtin __atomic operations"
+    ngx_feature_name=NGX_HAVE_GCC_ATOMIC_STORE_AND_LOAD
+    ngx_feature_run=yes
+    ngx_feature_incs=
+    ngx_feature_path=
+    ngx_feature_libs=
+    ngx_feature_test="long  n = 0;
+                      __atomic_store_n(&n, 1, __ATOMIC_RELEASE);
+                      if (__atomic_load_n(&n, __ATOMIC_ACQUIRE) != 1)
+                          return 1"
+    . auto/feature
+
+
     if [ "$NGX_CC_NAME" = "ccc" ]; then
         echo "checking for C99 variadic macros ... disabled"
     else
diff -r 2f2ec92c3af9 -r 40765d8ee4dd src/core/ngx_rwlock.c
--- a/src/core/ngx_rwlock.c
+++ b/src/core/ngx_rwlock.c
@@ -53,7 +53,7 @@ ngx_rwlock_rlock(ngx_atomic_t *lock)
     ngx_atomic_uint_t  readers;
 
     for ( ;; ) {
-        readers = *lock;
+        readers = ngx_atomic_load(lock);
 
         if (readers != NGX_RWLOCK_WLOCK
             && ngx_atomic_cmp_set(lock, readers, readers + 1))
@@ -69,7 +69,7 @@ ngx_rwlock_rlock(ngx_atomic_t *lock)
                     ngx_cpu_pause();
                 }
 
-                readers = *lock;
+                readers = ngx_atomic_load(lock);
 
                 if (readers != NGX_RWLOCK_WLOCK
                     && ngx_atomic_cmp_set(lock, readers, readers + 1))
@@ -89,10 +89,10 @@ ngx_rwlock_unlock(ngx_atomic_t *lock)
 {
     ngx_atomic_uint_t  readers;
 
-    readers = *lock;
+    readers = ngx_atomic_load(lock);
 
     if (readers == NGX_RWLOCK_WLOCK) {
-        *lock = 0;
+        ngx_atomic_store(lock, 0);
         return;
     }
 
@@ -102,7 +102,7 @@ ngx_rwlock_unlock(ngx_atomic_t *lock)
             return;
         }
 
-        readers = *lock;
+        readers = ngx_atomic_load(lock);
     }
 }
 
diff -r 2f2ec92c3af9 -r 40765d8ee4dd src/core/ngx_shmtx.c
--- a/src/core/ngx_shmtx.c
+++ b/src/core/ngx_shmtx.c
@@ -171,7 +171,7 @@ ngx_shmtx_wakeup(ngx_shmtx_t *mtx)
 
     for ( ;; ) {
 
-        wait = *mtx->wait;
+        wait = ngx_atomic_load(mtx->wait);
 
         if ((ngx_atomic_int_t) wait <= 0) {
             return;
diff -r 2f2ec92c3af9 -r 40765d8ee4dd src/core/ngx_thread_pool.c
--- a/src/core/ngx_thread_pool.c
+++ b/src/core/ngx_thread_pool.c
@@ -164,9 +164,9 @@ ngx_thread_pool_init(ngx_thread_pool_t *
 static void
 ngx_thread_pool_destroy(ngx_thread_pool_t *tp)
 {
-    ngx_uint_t           n;
-    ngx_thread_task_t    task;
-    volatile ngx_uint_t  lock;
+    ngx_uint_t         n;
+    ngx_atomic_t       lock;
+    ngx_thread_task_t  task;
 
     ngx_memzero(&task, sizeof(ngx_thread_task_t));
 
@@ -174,13 +174,13 @@ ngx_thread_pool_destroy(ngx_thread_pool_
     task.ctx = (void *) &lock;
 
     for (n = 0; n < tp->threads; n++) {
-        lock = 1;
+        ngx_atomic_store(&lock, 1);
 
         if (ngx_thread_task_post(tp, &task) != NGX_OK) {
             return;
         }
 
-        while (lock) {
+        while (ngx_atomic_load(&lock) != 0) {
             ngx_sched_yield();
         }
 
@@ -196,9 +196,9 @@ ngx_thread_pool_destroy(ngx_thread_pool_
 static void
 ngx_thread_pool_exit_handler(void *data, ngx_log_t *log)
 {
-    ngx_uint_t *lock = data;
+    ngx_atomic_uint_t  *lock = data;
 
-    *lock = 0;
+    ngx_atomic_store(lock, 0);
 
     pthread_exit(0);
 }
diff -r 2f2ec92c3af9 -r 40765d8ee4dd src/os/unix/ngx_atomic.h
--- a/src/os/unix/ngx_atomic.h
+++ b/src/os/unix/ngx_atomic.h
@@ -304,12 +304,25 @@ ngx_atomic_fetch_add(ngx_atomic_t *value
 #endif
 
 
+#if (NGX_HAVE_GCC_ATOMIC_STORE_AND_LOAD)
+
+#define ngx_atomic_store(x, value)  __atomic_store_n(x, value, __ATOMIC_RELEASE)
+#define ngx_atomic_load(x)          __atomic_load_n(x, __ATOMIC_ACQUIRE)
+
+#else
+
+#define ngx_atomic_store(x, value)  *(x) = value
+#define ngx_atomic_load(x)          *(x)
+
+#endif
+
+
 void ngx_spinlock(ngx_atomic_t *lock, ngx_atomic_int_t value, ngx_uint_t spin);
 
 #define ngx_trylock(lock, value)                                              \
-    (*(lock) == 0 && ngx_atomic_cmp_set(lock, 0, value))
+    (ngx_atomic_load(lock) == 0 && ngx_atomic_cmp_set(lock, 0, value))
 
-#define ngx_unlock(lock)    *(lock) = 0
+#define ngx_unlock(lock)    ngx_atomic_store(lock, 0)
 
 
 #endif /* _NGX_ATOMIC_H_INCLUDED_ */
diff -r 2f2ec92c3af9 -r 40765d8ee4dd src/os/win32/ngx_atomic.h
--- a/src/os/win32/ngx_atomic.h
+++ b/src/os/win32/ngx_atomic.h
@@ -60,12 +60,16 @@ typedef volatile ngx_atomic_uint_t  ngx_
 #endif
 
 
+#define ngx_atomic_store(x, value)  *(x) = value
+#define ngx_atomic_load(x)          *(x)
+
+
 void ngx_spinlock(ngx_atomic_t *lock, ngx_atomic_int_t value, ngx_uint_t spin);
 
 #define ngx_trylock(lock, value)                                              \
-    (*(lock) == 0 && ngx_atomic_cmp_set(lock, 0, value))
+    (ngx_atomic_load(lock) == 0 && ngx_atomic_cmp_set(lock, 0, value))
 
-#define ngx_unlock(lock)    *(lock) = 0
+#define ngx_unlock(lock)    ngx_atomic_store(lock, 0)
 
 
 #endif /* _NGX_ATOMIC_H_INCLUDED_ */



More information about the nginx-devel mailing list