lkml.org 
[lkml]   [2013]   [Aug]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 01/14] kthread: Fix invalid wakeup in kthreadd
    Date
    If kthreadd is preempted at(or before) location a, and the other thread,
    such as calling kthread_create_on_node(), adds a list item to
    the kthread_create_list followed with wake_up_process(kthread). After that
    when kthreadd 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.
    ------------------------
    kthreadd()
    ------------------------
    ...
    for (;;) {
    //location a
    set_current_state(TASK_INTERRUPTIBLE);
    if (list_empty(&kthread_create_list)) {
    //location b
    schedule();
    //location c
    }
    __set_current_state(TASK_RUNNING);
    //location d
    ...
    ------------------------
    kthread_create_on_node()
    ------------------------
    ...
    spin_lock(&kthread_create_lock);
    list_add_tail(&create.list, &kthread_create_list);
    spin_unlock(&kthread_create_lock);
    ...
    wake_up_process(kthreadd_task);
    ...

    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.
    ------------------------
    kthreadd()
    ------------------------
    ...
    for (;;) {
    preempt_disable();
    set_current_state(TASK_INTERRUPTIBLE);
    if (list_empty(&kthread_create_list)) {
    preempt_enable();
    schedule();
    preempt_disable();
    }
    ...

    Signed-off-by: Libin <huawei.libin@huawei.com>
    ---
    kernel/kthread.c | 7 ++++++-
    1 file changed, 6 insertions(+), 1 deletion(-)

    diff --git a/kernel/kthread.c b/kernel/kthread.c
    index 760e86d..25c3fed 100644
    --- a/kernel/kthread.c
    +++ b/kernel/kthread.c
    @@ -456,10 +456,15 @@ int kthreadd(void *unused)
    current->flags |= PF_NOFREEZE;

    for (;;) {
    + preempt_disable();
    set_current_state(TASK_INTERRUPTIBLE);
    - if (list_empty(&kthread_create_list))
    + if (list_empty(&kthread_create_list)) {
    + preempt_enable();
    schedule();
    + preempt_disable();
    + }
    __set_current_state(TASK_RUNNING);
    + preempt_enable();

    spin_lock(&kthread_create_lock);
    while (!list_empty(&kthread_create_list)) {
    --
    1.8.2.1



    \
     
     \ /
      Last update: 2013-08-29 16:21    [W:4.172 / U:0.084 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site