Messages in this thread Patch in this message | | | From | Libin <> | Subject | [PATCH 14/14] klist: Fix invalid wakeup in klist_remove | Date | Thu, 29 Aug 2013 21:57:49 +0800 |
| |
If thread is preempted before calling set_current_state(TASK_UNINTERRUPTIBLE), 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_UNINTERRUPTIBLE, if it is preempted again after that and before __set_current_state(TASK_RUNNING), it triggers the invalid wakeup problem. -------------- klist_remove() -------------- ... for (;;) { set_current_state(TASK_UNINTERRUPTIBLE); if (waiter.woken) break; schedule(); } __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. -------------- klist_remove() -------------- ... preempt_disable(); for (;;) { set_current_state(TASK_UNINTERRUPTIBLE); if (waiter.woken) break; preempt_enable(); schedule(); preempt_disable(); } __set_current_state(TASK_RUNNING); preempt_enable(); ...
Signed-off-by: Libin <huawei.libin@huawei.com> --- lib/klist.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/lib/klist.c b/lib/klist.c index 358a368..e7c7208 100644 --- a/lib/klist.c +++ b/lib/klist.c @@ -249,13 +249,17 @@ void klist_remove(struct klist_node *n) klist_del(n); + preempt_disable(); for (;;) { set_current_state(TASK_UNINTERRUPTIBLE); if (waiter.woken) break; + preempt_enable(); schedule(); + preempt_disable(); } __set_current_state(TASK_RUNNING); + preempt_enable(); } EXPORT_SYMBOL_GPL(klist_remove); -- 1.8.2.1
| |