[linux-audio-dev] realtimeness: pthread_cond_signal vs. pipe write

Stefan Westerfeld stefan at space.twc.de
Mon Jun 19 21:11:07 UTC 2006


   Hi!

On Fri, Jun 09, 2006 at 10:03:14PM -0400, Dave Robillard wrote:
> > > The big question is: who cares? :)  sem_post() is.  A mutex/cond pair is
> > > just a big ugly slow non-RT-safe semaphore anyway.
> > 
> > As far as I understand from the linux-2.6.16.16 and glibc-2.3.6 code,
> > a semaphore has similar problems, as sem_post() is implemented in terms
> > of futexes on newer linuxes, and futexes have a list of waiters, which
> > is protected by a lock within the kernel.
> 
> Well, sem_post is supposed to be async-signal safe (meaning it can't be
> preempted, meaning it's realtime safe).  If the Linux people have broken
> that, they have done an evil stupid thing.  POSIX semaphores are great,
> especially since you can (or at least should, apparently)  signal things
> from signal callbacks and realtime threads with them (they work great
> for event-driven systems).
> 
> Are you sure?  Link?

The userspace code of sem_post() can be found in
glibc-2.3.6/nptl/sysdeps/unix/sysv/linux/sem_post.c:

int
__new_sem_post (sem_t *sem)
{
  int *futex = (int *) sem;

  int nr = atomic_increment_val (futex);
  int err = lll_futex_wake (futex, nr);
  if (__builtin_expect (err, 0) < 0)
    {
      __set_errno (-err);
      return -1;
    }
  return 0;
}

There are assembler versions, but they also need the futex_wake syscall,
so it doesn't matter which version you read.

And here is the kernel code from linux-2.6.16.16/kernel/futex.c:

static int futex_wake(unsigned long uaddr, int nr_wake)
{
        union futex_key key;
        struct futex_hash_bucket *bh;
        struct list_head *head;
        struct futex_q *this, *next;
        int ret;

        down_read(&current->mm->mmap_sem);

        ret = get_futex_key(uaddr, &key);
        if (unlikely(ret != 0))
                goto out;

        bh = hash_futex(&key);
        spin_lock(&bh->lock);
        head = &bh->chain;

        list_for_each_entry_safe(this, next, head, list) {
                if (match_futex (&this->key, &key)) {
                        wake_futex(this);
                        if (++ret >= nr_wake)
                                break;
                }
        }

        spin_unlock(&bh->lock);
out:
        up_read(&current->mm->mmap_sem);
        return ret;
}

The spin_lock(&bh->lock) is the one I was referring to in my earlier
mail.

   Cu... Stefan
-- 
Stefan Westerfeld, Hamburg/Germany, http://space.twc.de/~stefan



More information about the Linux-audio-dev mailing list