Re: condvar and mutexes

From: Robert Watson (rwatson_at_freebsd.org)
Date: 06/27/04

  • Next message: Tim Kientzle: "RFC: bsdtar in 5.3"
    Date: Sat, 26 Jun 2004 22:15:09 -0400 (EDT)
    To: Nicolas Souchu <nsouch@free.fr>
    
    

    On Sat, 26 Jun 2004, Nicolas Souchu wrote:

    > Why is condvar(9) API not part of the mutex(9) one? A condvar is nothing
    > more than a mutex with a queue of waiting threads.
    >
    > I would simply imagine some wait calls applied to mutexes with the queue
    > in the mutex struct.

    A few observations:

    - Combining it all into one man page would lead to an awfully long man
      page :-).

    - If you use a condition variable, you must use a mutex. However, if you
      use a mutex, there's no obligation to use a condition variable. Most of
      our mutexes don't involve using condition variables, actually, I
      suspect. Note that the wait queue for a mutex is not the same as a wait
      queue for a condition variable associated with the mutex. As it stands,
      we get to choose when we do (and don't) want the additional overhead.

    - I've used Mach's wait queue and mutex APIs, which seems to have a split
      more like what you're suggesting, and I have to say they are
      abysmal in terms of usability and avoiding races. In fact, in some
      recent work to port some FreeBSD piecess to Darwin, which uses Mach's
      mutexes and wait queues, I implemented the FreeBSD condition variable
      API in terms of the Mach primitives rather than use the Mach primitives
      directly. In particular, the cv_wait() interface in our API is much
      easier to use:

    void
    cv_wait(struct cv *cvp, mutex_t *mp)
    {
            int ret;

            mutex_unlock(mp);
            ret = wait_queue_assert_wait(cvp->cv_wait_queue, 0, THREAD_UNINT);
            if (ret != THREAD_WAITING)
                    panic("cv_wait: wait_queue_assert_wait failed");
            ret = thread_block(THREAD_CONTINUE_NULL);
            if (ret != THREAD_AWAKENED)
                    panic("cv_wait: thread_block failed");
            mutex_lock(mp);
    }

    - By using an API that's congurent to the POSIX threads API in user space,
      we make it easier for developers familiar with existing synchronization
      primitives in user space to adapt to kernel synchronization. And when
      someone says "How should I perform synchronization in kernel?", we can
      point them at the volumes of documentation on pthreads. Note that our
      API is quite a bit simpler than pthreads, but most of the same issues
      apply (how to use condition variables, for example).

    Robert N M Watson FreeBSD Core Team, TrustedBSD Projects
    robert@fledge.watson.org Principal Research Scientist, McAfee Research

    _______________________________________________
    freebsd-arch@freebsd.org mailing list
    http://lists.freebsd.org/mailman/listinfo/freebsd-arch
    To unsubscribe, send any mail to "freebsd-arch-unsubscribe@freebsd.org"


  • Next message: Tim Kientzle: "RFC: bsdtar in 5.3"

    Relevant Pages

    • Re: Non-busy waiting for threads?
      ... release mutex ... queue variables). ... The usual pattern is thus: ...
      (comp.programming)
    • Re: Non-busy waiting for threads?
      ... and the main program can push on requests to this ... queue to do work. ... Some else posted an example using condition variables. ... Release mutex. ...
      (comp.programming)
    • Re: Non-busy waiting for threads?
      ... the jobs they do, and the main program can push on requests to this ... queue to do work. ... Some else posted an example using condition variables. ... Release mutex. ...
      (comp.programming)
    • Re: Non-busy waiting for threads?
      ... release mutex ... queue variables). ... The usual pattern is thus: ...
      (comp.programming)
    • Re: Recursive mutex that can be waited upon (pthread)
      ... While you can use a mutex to avoid that data is changed, for me having a mutex does not mean that data is not changed, it only means that data is not changed by a different thread. ... My own thread may of course change the data, hence functions I call may want to change the data and if they do so, they must be sure that these changes are atomically, hence they must lock the object and they simply can't rely that I locked the object before -> thus I need recursive locks. ... Then I could as well throw out threads of my code and just use a single thread going through an event queue. ... you have a predicate condition on an invariant. ...
      (comp.programming.threads)