Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 8 Dec 2008 15:17:39 -0500
From:      John Baldwin <jhb@freebsd.org>
To:        freebsd-hackers@freebsd.org
Cc:        Marius =?iso-8859-1?q?N=FCnnerich?= <marius@nuenneri.ch>
Subject:   Re: Why safe using msleep with timeout=0 but not tsleep?
Message-ID:  <200812081517.39375.jhb@freebsd.org>
In-Reply-To: <b649e5e0812071100v2bf7b377n63e85b3f2b123c24@mail.gmail.com>
References:  <b649e5e0812071100v2bf7b377n63e85b3f2b123c24@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sunday 07 December 2008 02:00:30 pm Marius N=FCnnerich wrote:
> See subject.
> Interesting commit:
> http://svn.freebsd.org/viewvc/base?view=3Drevision&revision=3D77059

Lost wakeups.   If you have code like so that doesn't use any locks:

int flag;

void
foo(void)
{

	flag =3D 1;
	wakeup(&flag);
}

void
bar(void)
{

	if (flag =3D=3D 0)
		tsleep(&foo, ..., 0);
}

Then one CPU may run the 'foo' routine to completion after another CPU has=
=20
seen 'flag =3D=3D 0' but before it has put the thread to sleep in tsleep().=
  Even=20
on UP systems with preemption you can still get this race if you get=20
preempted by an interrupt (which runs foo()) in between the 'flag =3D=3D 0'=
 test=20
and calling tsleep().  Using an interlock avoid this:

struct mtx lock;
int flag;

void
foo(void)
{

	mtx_lock(&lock);
	flag =3D 1;
	mtx_unlock(&lock);
	wakeup(&flag);
}

void
bar(void)
{

	mtx_lock(&lock);
	if (flag =3D=3D 0)
		mtx_sleep(&foo, &lock, ..., 0);
	mtx_unlock(&lock);
}

In this case 'lock' closes the SMP/preemption races.

=2D-=20
John Baldwin



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200812081517.39375.jhb>