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:
parent
a5110e6b7d
commit
f147e876b7
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user