Why safe using msleep with timeout=0 but not tsleep?

Marius Nünnerich marius at nuenneri.ch
Mon Dec 8 15:45:58 PST 2008


On Mon, Dec 8, 2008 at 9:17 PM, John Baldwin <jhb at freebsd.org> wrote:
> On Sunday 07 December 2008 02:00:30 pm Marius Nünnerich wrote:
>> See subject.
>> Interesting commit:
>> http://svn.freebsd.org/viewvc/base?view=revision&revision=77059
>
> Lost wakeups.   If you have code like so that doesn't use any locks:
>
> int flag;
>
> void
> foo(void)
> {
>
>        flag = 1;
>        wakeup(&flag);
> }
>
> void
> bar(void)
> {
>
>        if (flag == 0)
>                tsleep(&foo, ..., 0);
> }
>
> Then one CPU may run the 'foo' routine to completion after another CPU has
> seen 'flag == 0' but before it has put the thread to sleep in tsleep().  Even
> on UP systems with preemption you can still get this race if you get
> preempted by an interrupt (which runs foo()) in between the 'flag == 0' test
> and calling tsleep().  Using an interlock avoid this:
>
> struct mtx lock;
> int flag;
>
> void
> foo(void)
> {
>
>        mtx_lock(&lock);
>        flag = 1;
>        mtx_unlock(&lock);
>        wakeup(&flag);
> }
>
> void
> bar(void)
> {
>
>        mtx_lock(&lock);
>        if (flag == 0)
>                mtx_sleep(&foo, &lock, ..., 0);
>        mtx_unlock(&lock);
> }
>
> In this case 'lock' closes the SMP/preemption races.
>
> --
> John Baldwin
>

Thank you for the explanation, John!


More information about the freebsd-hackers mailing list