If thread is preempted before calling set_current_state(TASK_INTERRUPTIBLE),
and the other thread set the condition followed with wake_up_process. 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.

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.

Signed-off-by: Libin <[email protected]>
---
 kernel/rcutree.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/kernel/rcutree.h b/kernel/rcutree.h
index b383258..e3f1278 100644
--- a/kernel/rcutree.h
+++ b/kernel/rcutree.h
@@ -357,13 +357,17 @@ struct rcu_data {
 
 #define rcu_wait(cond)                                                 \
 do {                                                                   \
+       preempt_disable();                                      \
        for (;;) {                                                      \
                set_current_state(TASK_INTERRUPTIBLE);                  \
                if (cond)                                               \
                        break;                                          \
+               preempt_enable();                               \
                schedule();                                             \
+               preempt_disable();                              \
        }                                                               \
        __set_current_state(TASK_RUNNING);                              \
+       preempt_enable();                               \
 } while (0)
 
 /*
-- 
1.8.2.1


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to