[gst-devel] Multi-threaded queueing locking issues

Brent Bradburn brentb at ridgerun.com
Tue Mar 20 22:07:05 CET 2001


Matt Howell wrote:

> note comments inline...
>
> > > OK, I think I've got the locking code to work properly, and even be quite
> > > efficient.  This is accomplished with the use of interleaved signals and
> > > cond-waits.  You have something like this:
> > >
> > > thread A:                             thread B:
> > > g_mutex_lock(lock);                   g_mutex_lock(lock);
> > > g_cond_signal(cond);                  g_cond_wait(cond,lock);
> > > g_cond_wait(cond,lock);                       g_cond_signal(lock);
> > > g_mutex_unlock(lock);                 g_mutex_unlock(lock);
> >
> > The above is good, makes it all atomic.
> >
> > >
> > > This is the best way to do interlocking sync points, afaict.  Thanks to
> > > matth for teaching me about it!  How exactly it works is left as an
> > > excercise for the reader <g>
> >
> > What happens, in thread A is that a lock is requested, a signal is sent
> > (notifying of some change in something) and then it sleeps until it
> > receives a signal (while waiting for a signal, the lock is released) and
> > then unlocks the lock.
> >
> > In thread B, the lock is requested and then it sleeps until it receives a
> > signal and then sends a signal out and then unlocks the lock.
> >
> > The problem with this approach, is that a signal on a condition variable
> > is only caught if some thread is already waiting on that signal.
> >
> > So if thread B is not on the piece of code given above when thread A
> > signals then a deadlock WILL occur.  I think you are trying to address it
> > in some of the paragraphs below.
>
> you're right: if B isn't waiting on cond, and A signals cond, you'll get out
> of sync.  you can only use it when you know someone's waiting.  e.g.,
>
> thread A (creator):
> { g_mutex_lock(lock);
>   g_thread_create(B);
>   g_cond_wait(cond, lock); // wait for thread B to get started up
>   // B has started
>   // do A stuff
> }
>

The Linux man page for pthread_cond_wait() describes this fairly well...

       pthread_cond_wait  atomically unlocks the mutex (as per
pthread_unlock_mutex) and waits for the condition variable
       cond to be signaled. The thread execution is suspended and does not consume
any CPU time until the condition vari­
       able is signaled. The mutex must be locked by the calling thread on entrance
to pthread_cond_wait.  Before return­
       ing to the calling thread, pthread_cond_wait re-acquires mutex (as per
pthread_lock_mutex).

       Unlocking the mutex and suspending on the condition variable is done
atomically.  Thus,  if  all  threads  always
       acquire  the mutex before signaling the condition, this guarantees that the
condition cannot be signaled (and thus
       ignored) between the time a thread locks the mutex and the time it waits on
the condition variable.

In other words, to avoid a deadlock, verify that you still WANT to wait AFTER you
acquire the lock.  Don't wait if you don't have anything to wait on (the logical
condition is already satisfied):

              pthread_mutex_lock(&mut);
              while (x <= y) {
                      pthread_cond_wait(&cond, &mut);
              }
              /* operate on x and y */
              pthread_mutex_unlock(&mut);


> thread B (created):
> { g_mutex_lock(lock); // blocks thread B until thread A calls wait
>   // startup stuff
>   g_signal(cond); // signal B has done startup... this works only in those cases
>
>                             // when you know someone is waiting
>   g_mutex_unlock(lock); // now A can return from wait(cond, lock)
>
>   while(...) // do B stuff
> }
>
> the deadlock problem in gstreamer queue code is something different.
> (or at least that what it looks like to me ;-)
> it's not that 2 threads are out of sync with their wait / signal stuff.
> instead, signal needs to be called more often, and queue_get() and
> queue_chain() need to check for a pending state change in their
> while(cond not true, wait) loops and break out.
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: brentb.vcf
Type: text/x-vcard
Size: 237 bytes
Desc: Card for Brent Bradburn
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20010320/2a795a0a/attachment.vcf>


More information about the gstreamer-devel mailing list