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