Close a race in sleepq_broadcast() where the sleepq could be reused after

it had been assigned to the last sleeping thread.  That thread might have
started running on another CPU and have reused that sleep queue.  Fix it
by just walking the thread queue using TAILQ_FOREACH_SAFE() rather than
a while loop.

PR:		amd64/124200
Discovered by:	tegge
Tested by:	benjsc
MFC after:	1 week
This commit is contained in:
jhb 2008-09-08 19:44:57 +00:00
parent a5110e6b7d
commit f147e876b7

View File

@ -779,7 +779,7 @@ int
sleepq_broadcast(void *wchan, int flags, int pri, int queue)
{
struct sleepqueue *sq;
struct thread *td;
struct thread *td, *tdn;
int wakeup_swapper;
CTR2(KTR_PROC, "sleepq_broadcast(%p, %d)", wchan, flags);
@ -793,8 +793,7 @@ sleepq_broadcast(void *wchan, int flags, int pri, int queue)
/* Resume all blocked threads on the sleep queue. */
wakeup_swapper = 0;
while (!TAILQ_EMPTY(&sq->sq_blocked[queue])) {
td = TAILQ_FIRST(&sq->sq_blocked[queue]);
TAILQ_FOREACH_SAFE(td, &sq->sq_blocked[queue], td_slpq, tdn) {
thread_lock(td);
if (sleepq_resume_thread(sq, td, pri))
wakeup_swapper = 1;