[FFmpeg-devel] [PATCH] Add the relaxed and acquire/releae flavors of avpriv_atomic_int_get and avpriv_atomic_int_set.

Wan-Teh Chang wtc at google.com
Tue Mar 1 18:54:20 CET 2016


Correct the order of the load/store operation and the memory barrier in
avpriv_atomic_int_get and avpriv_atomic_int_set.

Signed-off-by: Wan-Teh Chang <wtc at google.com>
---
 libavutil/atomic.c       | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 libavutil/atomic.h       | 45 +++++++++++++++++++++++++++++++++++++++++++--
 libavutil/atomic_gcc.h   | 44 ++++++++++++++++++++++++++++++++++++++++++++
 libavutil/atomic_suncc.h | 30 +++++++++++++++++++++++++++++-
 libavutil/atomic_win32.h | 28 ++++++++++++++++++++++++++++
 5 files changed, 192 insertions(+), 3 deletions(-)

diff --git a/libavutil/atomic.c b/libavutil/atomic.c
index b13725d..3dc9062 100644
--- a/libavutil/atomic.c
+++ b/libavutil/atomic.c
@@ -40,6 +40,16 @@ int avpriv_atomic_int_get(volatile int *ptr)
     return res;
 }
 
+int avpriv_atomic_int_get_relaxed(volatile int *ptr)
+{
+    return avpriv_atomic_int_get(ptr);
+}
+
+int avpriv_atomic_int_get_acquire(volatile int *ptr)
+{
+    return avpriv_atomic_int_get(ptr);
+}
+
 void avpriv_atomic_int_set(volatile int *ptr, int val)
 {
     pthread_mutex_lock(&atomic_lock);
@@ -47,6 +57,16 @@ void avpriv_atomic_int_set(volatile int *ptr, int val)
     pthread_mutex_unlock(&atomic_lock);
 }
 
+void avpriv_atomic_int_set_relaxed(volatile int *ptr, int val)
+{
+    avpriv_atomic_int_set(ptr, val);
+}
+
+void avpriv_atomic_int_set_release(volatile int *ptr, int val)
+{
+    avpriv_atomic_int_set(ptr, val);
+}
+
 int avpriv_atomic_int_add_and_fetch(volatile int *ptr, int inc)
 {
     int res;
@@ -77,11 +97,31 @@ int avpriv_atomic_int_get(volatile int *ptr)
     return *ptr;
 }
 
+int avpriv_atomic_int_get_relaxed(volatile int *ptr)
+{
+    return avpriv_atomic_int_get(ptr);
+}
+
+int avpriv_atomic_int_get_acquire(volatile int *ptr)
+{
+    return avpriv_atomic_int_get(ptr);
+}
+
 void avpriv_atomic_int_set(volatile int *ptr, int val)
 {
     *ptr = val;
 }
 
+void avpriv_atomic_int_set_relaxed(volatile int *ptr, int val)
+{
+    avpriv_atomic_int_set(ptr, val);
+}
+
+void avpriv_atomic_int_set_release(volatile int *ptr, int val)
+{
+    avpriv_atomic_int_set(ptr, val);
+}
+
 int avpriv_atomic_int_add_and_fetch(volatile int *ptr, int inc)
 {
     *ptr += inc;
@@ -121,6 +161,14 @@ int main(void)
     avpriv_atomic_int_set(&val, 3);
     res = avpriv_atomic_int_get(&val);
     av_assert0(res == 3);
+    avpriv_atomic_int_set_relaxed(&val, 5);
+    res = avpriv_atomic_int_get_relaxed(&val);
+    av_assert0(res == 5);
+    res = avpriv_atomic_int_add_and_fetch(&val, -1);
+    av_assert0(res == 4);
+    avpriv_atomic_int_set_release(&val, 3);
+    res = avpriv_atomic_int_get_acquire(&val);
+    av_assert0(res == 3);
 
     return 0;
 }
diff --git a/libavutil/atomic.h b/libavutil/atomic.h
index 15906d2..e0e67d2 100644
--- a/libavutil/atomic.h
+++ b/libavutil/atomic.h
@@ -40,20 +40,61 @@
  *
  * @param ptr atomic integer
  * @return the current value of the atomic integer
- * @note This acts as a memory barrier.
+ * @note This acts as a full memory barrier.
  */
 int avpriv_atomic_int_get(volatile int *ptr);
 
 /**
+ * Load the current value stored in an atomic integer, with no memory barrier.
+ *
+ * @param ptr atomic integer
+ * @return the current value of the atomic integer
+ * @note This does NOT act as a memory barrier.
+ */
+int avpriv_atomic_int_get_relaxed(volatile int *ptr);
+
+/**
+ * Load the current value stored in an atomic integer, with an acquire memory
+ * barrier.
+ *
+ * @param ptr atomic integer
+ * @return the current value of the atomic integer
+ * @note This acts as an acquire memory barrier. When used with a release
+ *       operation on the same value, this establishes a happens-before
+ *       relationship between threads.
+ */
+int avpriv_atomic_int_get_acquire(volatile int *ptr);
+
+/**
  * Store a new value in an atomic integer.
  *
  * @param ptr atomic integer
  * @param val the value to store in the atomic integer
- * @note This acts as a memory barrier.
+ * @note This acts as a full memory barrier.
  */
 void avpriv_atomic_int_set(volatile int *ptr, int val);
 
 /**
+ * Store a new value in an atomic integer, with no memory barrier.
+ *
+ * @param ptr atomic integer
+ * @param val the value to store in the atomic integer
+ * @note This does NOT act as a memory barrier.
+ */
+void avpriv_atomic_int_set_relaxed(volatile int *ptr, int val);
+
+/**
+ * Store a new value in an atomic integer, with a release memory barrier.
+ *
+ * @param ptr atomic integer
+ * @param val the value to store in the atomic integer
+ * @note This acts as a release memory barrier. When used with an acquire
+ *       operation on the same value, this establishes a happens-before
+ *       relationship between threads.
+ */
+void avpriv_atomic_int_set_release(volatile int *ptr, int val);
+
+/**
  * Add a value to an atomic integer.
  *
  * @param ptr atomic integer
diff --git a/libavutil/atomic_gcc.h b/libavutil/atomic_gcc.h
index 5f9fc49..34a6a8e 100644
--- a/libavutil/atomic_gcc.h
+++ b/libavutil/atomic_gcc.h
@@ -31,19 +31,63 @@ static inline int atomic_int_get_gcc(volatile int *ptr)
 #if HAVE_ATOMIC_COMPARE_EXCHANGE
     return __atomic_load_n(ptr, __ATOMIC_SEQ_CST);
 #else
+    int val = *ptr;
     __sync_synchronize();
+    return val;
+#endif
+}
+
+#define avpriv_atomic_int_get_relaxed atomic_int_get_gcc_relaxed
+static inline int atomic_int_get_gcc_relaxed(volatile int *ptr)
+{
+#if HAVE_ATOMIC_COMPARE_EXCHANGE
+    return __atomic_load_n(ptr, __ATOMIC_RELAXED);
+#else
     return *ptr;
 #endif
 }
 
+#define avpriv_atomic_int_get_acquire atomic_int_get_gcc_acquire
+static inline int atomic_int_get_gcc_acquire(volatile int *ptr)
+{
+#if HAVE_ATOMIC_COMPARE_EXCHANGE
+    return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
+#else
+    int val = *ptr;
+    __sync_synchronize();
+    return val;
+#endif
+}
+
 #define avpriv_atomic_int_set atomic_int_set_gcc
 static inline void atomic_int_set_gcc(volatile int *ptr, int val)
 {
 #if HAVE_ATOMIC_COMPARE_EXCHANGE
     __atomic_store_n(ptr, val, __ATOMIC_SEQ_CST);
 #else
+    __sync_synchronize();
+    *ptr = val;
+#endif
+}
+
+#define avpriv_atomic_int_set_relaxed atomic_int_set_gcc_relaxed
+static inline void atomic_int_set_gcc_relaxed(volatile int *ptr, int val)
+{
+#if HAVE_ATOMIC_COMPARE_EXCHANGE
+    __atomic_store_n(ptr, val, __ATOMIC_RELAXED);
+#else
     *ptr = val;
+#endif
+}
+
+#define avpriv_atomic_int_set_release atomic_int_set_gcc_release
+static inline void atomic_int_set_gcc_release(volatile int *ptr, int val)
+{
+#if HAVE_ATOMIC_COMPARE_EXCHANGE
+    __atomic_store_n(ptr, val, __ATOMIC_RELEASE);
+#else
     __sync_synchronize();
+    *ptr = val;
 #endif
 }
 
diff --git a/libavutil/atomic_suncc.h b/libavutil/atomic_suncc.h
index a75a37b..9b58db5 100644
--- a/libavutil/atomic_suncc.h
+++ b/libavutil/atomic_suncc.h
@@ -27,15 +27,43 @@
 #define avpriv_atomic_int_get atomic_int_get_suncc
 static inline int atomic_int_get_suncc(volatile int *ptr)
 {
+    int val = *ptr;
     __machine_rw_barrier();
+    return val;
+}
+
+#define avpriv_atomic_int_get_relaxed atomic_int_get_suncc_relaxed
+static inline int atomic_int_get_suncc_relaxed(volatile int *ptr)
+{
     return *ptr;
 }
 
+#define avpriv_atomic_int_get_acquire atomic_int_get_suncc_acquire
+static inline int atomic_int_get_suncc_acquire(volatile int *ptr)
+{
+    int val = *ptr;
+    __machine_acq_barrier()
+    return val;
+}
+
 #define avpriv_atomic_int_set atomic_int_set_suncc
 static inline void atomic_int_set_suncc(volatile int *ptr, int val)
 {
-    *ptr = val;
     __machine_rw_barrier();
+    *ptr = val;
+}
+
+#define avpriv_atomic_int_set_relaxed atomic_int_set_suncc_relaxed
+static inline void atomic_int_set_suncc_relaxed(volatile int *ptr, int val)
+{
+    *ptr = val;
+}
+
+#define avpriv_atomic_int_set_release atomic_int_set_suncc_release
+static inline void atomic_int_set_suncc_release(volatile int *ptr, int val)
+{
+    __machine_rel_barrier()
+    *ptr = val;
 }
 
 #define avpriv_atomic_int_add_and_fetch atomic_int_add_and_fetch_suncc
diff --git a/libavutil/atomic_win32.h b/libavutil/atomic_win32.h
index f729933..5af8847 100644
--- a/libavutil/atomic_win32.h
+++ b/libavutil/atomic_win32.h
@@ -27,15 +27,43 @@
 #define avpriv_atomic_int_get atomic_int_get_win32
 static inline int atomic_int_get_win32(volatile int *ptr)
 {
+    int val = *ptr;
     MemoryBarrier();
+    return val;
+}
+
+#define avpriv_atomic_int_get_relaxed atomic_int_get_win32_relaxed
+static inline int atomic_int_get_win32_relaxed(volatile int *ptr)
+{
     return *ptr;
 }
 
+#define avpriv_atomic_int_get_acquire atomic_int_get_win32_acquire
+static inline int atomic_int_get_win32_acquire(volatile int *ptr)
+{
+    int val = *ptr;
+    MemoryBarrier();
+    return val;
+}
+
 #define avpriv_atomic_int_set atomic_int_set_win32
 static inline void atomic_int_set_win32(volatile int *ptr, int val)
 {
+    MemoryBarrier();
+    *ptr = val;
+}
+
+#define avpriv_atomic_int_set_relaxed atomic_int_set_win32_relaxed
+static inline void atomic_int_set_win32_relaxed(volatile int *ptr, int val)
+{
     *ptr = val;
+}
+
+#define avpriv_atomic_int_set_release atomic_int_set_win32_release
+static inline void atomic_int_set_win32_release(volatile int *ptr, int val)
+{
     MemoryBarrier();
+    *ptr = val;
 }
 
 #define avpriv_atomic_int_add_and_fetch atomic_int_add_and_fetch_win32
-- 
2.7.0.rc3.207.g0ac5344



More information about the ffmpeg-devel mailing list