[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