[FFmpeg-devel] [PATCH] Always read frame progress values under progress_mutex.

Michael Niedermayer michael at niedermayer.cc
Fri Feb 26 05:14:47 CET 2016


On Thu, Feb 25, 2016 at 04:42:22PM -0800, Wan-Teh Chang wrote:
> On Thu, Feb 25, 2016 at 4:15 PM, Hendrik Leppkes <h.leppkes at gmail.com> wrote:
> >
> > Similar to the other patch, please explain what this actually fixes,
> > those sanitizer tools produce a lot of false positives and nonsensical
> > warnings.
> 
> Yes, certainly.
> 
> In libavcodec/pthread_frame.c, we have:
> 
>  46 /**
>  47  * Context used by codec threads and stored in their
> AVCodecInternal thread_    ctx.
>  48  */
>  49 typedef struct PerThreadContext {
>  ...
>  59     pthread_mutex_t progress_mutex; ///< Mutex used to protect
> frame progress values and progress_cond.
> 
> The comment on line 59 documents that progress_mutex guards frame
> progress values and progress_cond. (In fact, progress_mutex also
> guards the |state| field in many places, but that's not the subject of
> this patch.)
> 
> I assume "frame progess values" mean f->progress->data, where |f|
> points to a ThreadFrame. I inspected libavcodec/pthread_frame.c and
> concluded the code (ff_thread_report_progress and
> ff_thread_await_progress) matches that comment, except that it also
> does a double-checked locking style performance optimization. For
> example, here is ff_thread_report_progress:
> 
> 472 void ff_thread_report_progress(ThreadFrame *f, int n, int field)
> 473 {
> 474     PerThreadContext *p;
> 475     volatile int *progress = f->progress ? (int*)f->progress->data : NULL;
> 476
> 477     if (!progress || progress[field] >= n) return;
> 478
> 479     p = f->owner->internal->thread_ctx;
> 480
> 481     if (f->owner->debug&FF_DEBUG_THREADS)
> 482         av_log(f->owner, AV_LOG_DEBUG, "%p finished %d field
> %d\n", progress    , n, field);
> 483
> 484     pthread_mutex_lock(&p->progress_mutex);
> 485     progress[field] = n;
> 486     pthread_cond_broadcast(&p->progress_cond);
> 487     pthread_mutex_unlock(&p->progress_mutex);
> 488 }
> 
> progress[field] can only increase. So, both ff_thread_report_progress
> and ff_thread_await_progress have a fast code path (line 477 and line
> 495, respectively) that reads progress[field] without acquiring
> progress_mutex. If the speculatively read value of progress[field] is
> >= |n|, then the functions return immediately. Otherwise, the
> functions take the slow code path, which acquires progress_mutex
> properly and does what the functions need to do.
> 
> The fast code path is in the style of double-checked locking and has a
> data race. ThreadSanitizer is right in this case.

ThreadSanitizer is right about that this is a data race yes, but
isnt all lock-free code technically containing a data race

But is there a bug?
Its basically a simple 2 thread thing, one says "iam finished" the
other checks if that is set.
In what case does this benefit from a lock ?
also note the write is always under a lock, which id assume does
any needed memory barriers

also considering this is performance relevant code, please provide
a benchmark

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Why not whip the teacher when the pupil misbehaves? -- Diogenes of Sinope
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20160226/e39f4dc7/attachment.sig>


More information about the ffmpeg-devel mailing list