On 26/07/22 12:17, Jason A. Donenfeld wrote:
if (rc <= 0) {
pr_warn("hwrng: no data available\n");
msleep_interruptible(10000);
set_current_state(TASK_INTERRUPTIBLE);
if (kthread_should_stop())
__set_current_state(TASK_RUNNING);
schedule_timeout(10 * HZ); continue; }
Here you made a change whose utility I don't understand. My original hunk was:
if (kthread_should_stop())
break;
schedule_timeout_interruptible(HZ * 10);
Which I think is a bit cleaner, as schedule_timeout_interruptible sets the state to INTERRUPTIBLE and such.
For any sort of wait loop, you need the state write to happen before the loop-break condition is checked.
Consider:
READ kthread_should_stop() == false kthread_stop() set_bit(KTHREAD_SHOULD_STOP, &kthread->flags); wake_up_process(k); // Reads TASK_RUNNING, schedule_timeout_interruptible(); // does nothing // We're now blocked, having missed a wakeup
That's why the canonical wait loop pattern is:
for (;;) { set_current_state(TASK_UNINTERRUPTIBLE);
if (CONDITION) break;
schedule(); } __set_current_state(TASK_RUNNING);
(grep "wait loop" in kernel/sched/core.c)
Regards, Jason