Skip to content

Commit 37aadc6

Browse files
author
Peter Zijlstra
committed
sched: Unbreak wakeups
Remove broken task->state references and let wake_up_process() DTRT. The anti-pattern in these patches breaks the ordering of ->state vs COND as described in the comment near set_current_state() and can lead to missed wakeups: (OoO load, observes RUNNING)<-. for (;;) { | t->state = UNINTERRUPTIBLE; | smp_mb(); ,-----> | (observes !COND) | / if (COND) ---------' | COND = 1; break; `- if (t->state != RUNNING) wake_up_process(t); // not done schedule(); // forever waiting } t->state = TASK_RUNNING; Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Davidlohr Bueso <dbueso@suse.de> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Acked-by: Will Deacon <will@kernel.org> Link: https://lore.kernel.org/r/20210611082838.160855222@infradead.org
1 parent b2c0931 commit 37aadc6

4 files changed

Lines changed: 9 additions & 17 deletions

File tree

drivers/net/ethernet/qualcomm/qca_spi.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -653,8 +653,7 @@ qcaspi_intr_handler(int irq, void *data)
653653
struct qcaspi *qca = data;
654654

655655
qca->intr_req++;
656-
if (qca->spi_thread &&
657-
qca->spi_thread->state != TASK_RUNNING)
656+
if (qca->spi_thread)
658657
wake_up_process(qca->spi_thread);
659658

660659
return IRQ_HANDLED;
@@ -777,8 +776,7 @@ qcaspi_netdev_xmit(struct sk_buff *skb, struct net_device *dev)
777776

778777
netif_trans_update(dev);
779778

780-
if (qca->spi_thread &&
781-
qca->spi_thread->state != TASK_RUNNING)
779+
if (qca->spi_thread)
782780
wake_up_process(qca->spi_thread);
783781

784782
return NETDEV_TX_OK;

drivers/usb/gadget/udc/max3420_udc.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -509,8 +509,7 @@ static irqreturn_t max3420_vbus_handler(int irq, void *dev_id)
509509
? USB_STATE_POWERED : USB_STATE_NOTATTACHED);
510510
spin_unlock_irqrestore(&udc->lock, flags);
511511

512-
if (udc->thread_task &&
513-
udc->thread_task->state != TASK_RUNNING)
512+
if (udc->thread_task)
514513
wake_up_process(udc->thread_task);
515514

516515
return IRQ_HANDLED;
@@ -529,8 +528,7 @@ static irqreturn_t max3420_irq_handler(int irq, void *dev_id)
529528
}
530529
spin_unlock_irqrestore(&udc->lock, flags);
531530

532-
if (udc->thread_task &&
533-
udc->thread_task->state != TASK_RUNNING)
531+
if (udc->thread_task)
534532
wake_up_process(udc->thread_task);
535533

536534
return IRQ_HANDLED;
@@ -1093,8 +1091,7 @@ static int max3420_wakeup(struct usb_gadget *gadget)
10931091

10941092
spin_unlock_irqrestore(&udc->lock, flags);
10951093

1096-
if (udc->thread_task &&
1097-
udc->thread_task->state != TASK_RUNNING)
1094+
if (udc->thread_task)
10981095
wake_up_process(udc->thread_task);
10991096
return ret;
11001097
}
@@ -1117,8 +1114,7 @@ static int max3420_udc_start(struct usb_gadget *gadget,
11171114
udc->todo |= UDC_START;
11181115
spin_unlock_irqrestore(&udc->lock, flags);
11191116

1120-
if (udc->thread_task &&
1121-
udc->thread_task->state != TASK_RUNNING)
1117+
if (udc->thread_task)
11221118
wake_up_process(udc->thread_task);
11231119

11241120
return 0;
@@ -1137,8 +1133,7 @@ static int max3420_udc_stop(struct usb_gadget *gadget)
11371133
udc->todo |= UDC_START;
11381134
spin_unlock_irqrestore(&udc->lock, flags);
11391135

1140-
if (udc->thread_task &&
1141-
udc->thread_task->state != TASK_RUNNING)
1136+
if (udc->thread_task)
11421137
wake_up_process(udc->thread_task);
11431138

11441139
return 0;

drivers/usb/host/max3421-hcd.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,8 +1169,7 @@ max3421_irq_handler(int irq, void *dev_id)
11691169
struct spi_device *spi = to_spi_device(hcd->self.controller);
11701170
struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
11711171

1172-
if (max3421_hcd->spi_thread &&
1173-
max3421_hcd->spi_thread->state != TASK_RUNNING)
1172+
if (max3421_hcd->spi_thread)
11741173
wake_up_process(max3421_hcd->spi_thread);
11751174
if (!test_and_set_bit(ENABLE_IRQ, &max3421_hcd->todo))
11761175
disable_irq_nosync(spi->irq);

kernel/softirq.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ static void wakeup_softirqd(void)
7676
/* Interrupts are disabled: no need to stop preemption */
7777
struct task_struct *tsk = __this_cpu_read(ksoftirqd);
7878

79-
if (tsk && tsk->state != TASK_RUNNING)
79+
if (tsk)
8080
wake_up_process(tsk);
8181
}
8282

0 commit comments

Comments
 (0)