[FFmpeg-devel] [PATCH] pthread: Avoid crashes/odd behavior caused by spurious wakeups

Ben Jackson ben at ben.com
Thu Sep 13 22:35:08 CEST 2012


On Thu, Sep 13, 2012 at 09:41:37PM +0200, Michael Niedermayer wrote:
> 
> > @@ -214,7 +216,9 @@ static void* attribute_align_arg worker(void *v)
> >              if (c->current_job == thread_count + c->job_count)
> >                  pthread_cond_signal(&c->last_job_cond);
> >  
> > -            pthread_cond_wait(&c->current_job_cond, &c->current_job_lock);
> > +            while (last_execute == c->current_execute && !c->done)
> > +                pthread_cond_wait(&c->current_job_cond, &c->current_job_lock);
> > +            last_execute = c->current_execute;
> >              our_job = self_id;
> >  
> >              if (c->done) {
> 
> this will fail in 1 of 1<<32 cases due to current_execute being 0

All of the threads are made at the same time as ThreadContext.  Both
last_execute (in all workers) and current_execute start as 0.  Thereafter
all last_execute track current_execute.  Even if it wraps it doesn't
matter.

> > @@ -234,7 +238,8 @@ static void* attribute_align_arg worker(void *v)
> >  
> >  static av_always_inline void avcodec_thread_park_workers(ThreadContext *c, int thread_count)
> >  {
> > -    pthread_cond_wait(&c->last_job_cond, &c->current_job_lock);
> > +    while (c->current_job != thread_count + c->job_count)
> > +        pthread_cond_wait(&c->last_job_cond, &c->current_job_lock);
> >      pthread_mutex_unlock(&c->current_job_lock);
> >  }
> 
> I somehow think this should reset job_count to 0
> and then job_count can be used in the other test avoiding the
> current_execute issues

The job_count is tied up with stopping the workers.  The mechanism that
controls the workers is strange and I didn't want to mess with it.  I
found it interesting that thread_count (not available through
ThreadContext *c but necessary to test for completeness) was already
passed in -- I wondered if someone had deleted code like mine in the
past not understanding the necessity.

> > @@ -283,6 +288,7 @@ static int avcodec_thread_execute(AVCodecContext *avctx, action_func* func, void
> >          c->rets = &dummy_ret;
> >          c->rets_count = 1;
> >      }
> > +    c->current_execute++;
> 
> signed integer overflow and undefined behavior

Really?  Remember it only matters that it changes the value from execute
to execute.  I could just as easily have written '^= 1' instead of '++'.

I was just trying to make a minimal change to fix the problem.  To me
these comments treat the patch more harshly than the original code.  If
you'll only be happy with a rewrite of the slice worker code please say
so directly...

-- 
Ben Jackson AD7GD
<ben at ben.com>
http://www.ben.com/


More information about the ffmpeg-devel mailing list