Correct the order of the load/store operation and the memory barrier in avpriv_atomic_int_get and avpriv_atomic_int_set.
Use the atomic get and set functions in ff_thread_report_progress and ff_thread_await_progress. --- libavcodec/pthread_frame.c | 11 +++++++---- libavutil/atomic.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++ libavutil/atomic.h | 33 +++++++++++++++++++++++++++++++ libavutil/atomic_gcc.h | 44 ++++++++++++++++++++++++++++++++++++++++++ libavutil/atomic_suncc.h | 30 ++++++++++++++++++++++++++++- libavutil/atomic_win32.h | 28 +++++++++++++++++++++++++++ 6 files changed, 189 insertions(+), 5 deletions(-) diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index b77dd1e..34f9207 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -32,6 +32,7 @@ #include "thread.h" #include "version.h" +#include "libavutil/atomic.h" #include "libavutil/avassert.h" #include "libavutil/buffer.h" #include "libavutil/common.h" @@ -474,7 +475,7 @@ void ff_thread_report_progress(ThreadFrame *f, int n, int field) PerThreadContext *p; volatile int *progress = f->progress ? (int*)f->progress->data : NULL; - if (!progress || progress[field] >= n) return; + if (!progress || avpriv_atomic_int_get_relaxed(&progress[field]) >= n) return; p = f->owner->internal->thread_ctx; @@ -482,8 +483,10 @@ void ff_thread_report_progress(ThreadFrame *f, int n, int field) av_log(f->owner, AV_LOG_DEBUG, "%p finished %d field %d\n", progress, n, field); pthread_mutex_lock(&p->progress_mutex); - progress[field] = n; - pthread_cond_broadcast(&p->progress_cond); + if (progress[field] < n) { + avpriv_atomic_int_set_release(&progress[field], n); + pthread_cond_broadcast(&p->progress_cond); + } pthread_mutex_unlock(&p->progress_mutex); } @@ -492,7 +495,7 @@ void ff_thread_await_progress(ThreadFrame *f, int n, int field) PerThreadContext *p; volatile int *progress = f->progress ? (int*)f->progress->data : NULL; - if (!progress || progress[field] >= n) return; + if (!progress || avpriv_atomic_int_get_acquire(&progress[field]) >= n) return; p = f->owner->internal->thread_ctx; 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..1921095 100644 --- a/libavutil/atomic.h +++ b/libavutil/atomic.h @@ -45,6 +45,23 @@ 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 + */ +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 + */ +int avpriv_atomic_int_get_acquire(volatile int *ptr); + +/** * Store a new value in an atomic integer. * * @param ptr atomic integer @@ -54,6 +71,22 @@ int avpriv_atomic_int_get(volatile int *ptr); 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 + */ +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 + */ +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