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

John Baldwin jhb at freebsd.org
Mon Dec 8 12:52:19 PST 2008


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


More information about the freebsd-hackers mailing list