If thread is preempted before calling set_current_state(TASK_INTERRUPTIBLE), and the other thread set the condition(kthread_stop). After that when this thread is re-scheduled, calling set_current_state to set itself as state TASK_INTERRUPTIBLE, if it is preempted again after that and before __set_current_state(TASK_RUNNING), it triggers the invalid wakeup problem. ------------- wait_to_die() ------------- set_current_state(TASK_INTERRUPTIBLE); while (!kthread_should_stop()) { schedule(); set_current_state(TASK_INTERRUPTIBLE); } __set_current_state(TASK_RUNNING);
To solve this problem, using preempt_disable() to bound the operaion that setting the task state and the conditions(set by the wake thread) validation. ------------- wait_to_die() ------------- preempt_disable(); set_current_state(TASK_INTERRUPTIBLE); while (!kthread_should_stop()) { preempt_enable(); schedule(); preempt_disable(); set_current_state(TASK_INTERRUPTIBLE); } __set_current_state(TASK_RUNNING); preempt_enable(); Signed-off-by: Libin <huawei.li...@huawei.com> --- kernel/trace/ring_buffer_benchmark.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/trace/ring_buffer_benchmark.c b/kernel/trace/ring_buffer_benchmark.c index a5457d5..3c0bc03 100644 --- a/kernel/trace/ring_buffer_benchmark.c +++ b/kernel/trace/ring_buffer_benchmark.c @@ -359,12 +359,16 @@ static void ring_buffer_producer(void) static void wait_to_die(void) { + preempt_disable(); set_current_state(TASK_INTERRUPTIBLE); while (!kthread_should_stop()) { + preempt_enable(); schedule(); + preempt_disable(); set_current_state(TASK_INTERRUPTIBLE); } __set_current_state(TASK_RUNNING); + preempt_enable(); } static int ring_buffer_consumer_thread(void *arg) -- 1.8.2.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/