[FFmpeg-devel] [PATCH 3/3] pthread : Protect progress & progress_used access with progress_mutex.

Aaron Colwell acolwell at chromium.org
Thu Mar 22 17:58:17 CET 2012


Here I am just protecting progress & progress_used with progress_mutex. I
expect this to be one of the most controversial changes because I believe
this may cause a noticable performance drop.

Questions:
Why is the existing code considered safe?
How are thread protected from accidentally observing a MAX_INT progress
right before progress gets set to -1? It seems like this could cause
ff_thread_await_progress() calls to return early.

---
 libavcodec/pthread.c |   17 +++++++++++++++--
 1 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/libavcodec/pthread.c b/libavcodec/pthread.c
index 9e4686b..e874016 100644
--- a/libavcodec/pthread.c
+++ b/libavcodec/pthread.c
@@ -525,7 +525,9 @@ static void free_progress(AVFrame *f)
     PerThreadContext *p = f->owner->thread_opaque;
     int *progress = f->thread_opaque;

+    pthread_mutex_lock(&p->progress_mutex);
     p->progress_used[(progress - p->progress[0]) / 2] = 0;
+    pthread_mutex_unlock(&p->progress_mutex);
 }

 /// Releases the buffers that this decoding thread was the last user of.
@@ -693,7 +695,7 @@ void ff_thread_report_progress(AVFrame *f, int n, int
field)
     PerThreadContext *p;
     int *progress = f->thread_opaque;

-    if (!progress || progress[field] >= n) return;
+    if (!progress) return;

     p = f->owner->thread_opaque;

@@ -701,6 +703,10 @@ void ff_thread_report_progress(AVFrame *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);
+    if (progress[field] >= n) {
+      pthread_mutex_unlock(&p->progress_mutex);
+      return;
+    }
     progress[field] = n;
     pthread_cond_broadcast(&p->progress_cond);
     pthread_mutex_unlock(&p->progress_mutex);
@@ -711,7 +717,7 @@ void ff_thread_await_progress(AVFrame *f, int n, int
field)
     PerThreadContext *p;
     int *progress = f->thread_opaque;

-    if (!progress || progress[field] >= n) return;
+    if (!progress) return;

     p = f->owner->thread_opaque;

@@ -719,6 +725,10 @@ void ff_thread_await_progress(AVFrame *f, int n, int
field)
         av_log(f->owner, AV_LOG_DEBUG, "thread awaiting %d field %d from
%p\n", n, field, progress);

     pthread_mutex_lock(&p->progress_mutex);
+    if (progress[field] >= n) {
+      pthread_mutex_unlock(&p->progress_mutex);
+      return;
+    }
     while (progress[field] < n)
         pthread_cond_wait(&p->progress_cond, &p->progress_mutex);
     pthread_mutex_unlock(&p->progress_mutex);
@@ -929,15 +939,18 @@ static int *allocate_progress(PerThreadContext *p)
 {
     int i;

+    pthread_mutex_lock(&p->progress_mutex);
     for (i = 0; i < MAX_BUFFERS; i++)
         if (!p->progress_used[i]) break;

     if (i == MAX_BUFFERS) {
         av_log(p->avctx, AV_LOG_ERROR, "allocate_progress() overflow\n");
+        pthread_mutex_unlock(&p->progress_mutex);
         return NULL;
     }

     p->progress_used[i] = 1;
+    pthread_mutex_unlock(&p->progress_mutex);

     return p->progress[i];
 }

-- 
1.7.7.3


More information about the ffmpeg-devel mailing list