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 <w...@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 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel