All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
To: Libin <huawei.libin@huawei.com>
Cc: akpm@linux-foundation.org, tj@kernel.org,
	viro@zeniv.linux.org.uk, eparis@redhat.com, tglx@linutronix.de,
	rusty@rustcorp.com.au, ebiederm@xmission.com,
	john.stultz@linaro.org, mingo@redhat.com, peterz@infradead.org,
	gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org,
	lizefan@huawei.com, jovi.zhangwei@huawei.com,
	guohanjun@huawei.com, zhangdianfang@huawei.com,
	wangyijing@huawei.com
Subject: Re: [PATCH 00/14] Fix bug about invalid wake up problem
Date: Thu, 29 Aug 2013 17:18:41 -0700	[thread overview]
Message-ID: <20130830001841.GY3871@linux.vnet.ibm.com> (raw)
In-Reply-To: <1377784669-28140-1-git-send-email-huawei.libin@huawei.com>

On Thu, Aug 29, 2013 at 09:57:35PM +0800, Libin wrote:
> 1)Problem Description:
> The prototype of invalid wakeup problem is as follows:
> ========================================================================
> ----------------------------
> Consumer Thread
> ----------------------------
> ...
> if (list_empty(&list)){
> 	//location a 
> 	set_current_state(TASK_INTERRUPTIBLE);

You need the list_empty() test here, not above.  Or you at least need
to retest here.

The reason for this is that set_current_state() has a memory
barrier following the assignment, which matches the memory barrier in
try_to_wake_up().  This means that if the test at this point sees the
list as empty, then the checks in try_to_wake_up() must see the task in
TASK_INTERRUPTIBLE state and must therefore wake it up.

							Thanx, Paul

> 	schedule();
> }
> ...
> ----------------------------
> Producer Thread
> ----------------------------
> ...
> list_add_tail(&item, &list);
> wake_up_process(A);
> ...
> ========================================================================
> 
> Invalid wakeup problem occurs in preemptable kernel environment. The list
> is empty initially, if consumer is preempted after condition validated at
> location a, and at this time producer is woken up, adding a node to the
> list and calling wake_up_process to wake up consumer. After that when
> consumer being scheduled by scheduler, it calls set_current_state to set
> itself as state TASK_INTERRUPTIBLE, and calling schedule() to request
> scheduled. After consumer being scheduled out, it has no condition to be
> woken up, and causing invalid wakeup problem.
> 
> In most cases, the kernel codes use a form similar to the following:
> --------------------------------------------
>  ...
>  //location a
>  ...
>  set_current_state(TASK_INTERRUPTIBLE);
>  //location b
>  while (list_empty(&product_list)){
> 	schedule();	//location c
> 	set_current_state(TASK_INTERRUPTIBLE);
> 	//location d
> }
> __set_current_state(TASK_RUNNING);
> ...
> --------------------------------------------
> At location a, consumer is preempted, and producer is scheduled,
> adding item to product_list and waking up consumer. After consumer is
> re-scheduled, calling set_current_state to set itself as state
> TASK_INTERRUPTIBLE, if it is preempted again before __set_current_state(TASK_RUNNING),
> also trigger the invalid wakeup problem that the consumer will not be scheduled
> and the item be added by producer can't be consumed.
> 
> The following circumstance will also trigger this issue:
> At location c, consumer is scheduled out, and be preempted after calling
> set_current_state(TASK_INTERRUPTIBLE) when it be re-schdeuled.
> 
> 2)Test:
> I have written a test module to trigger the problem by adding some
> synchronization condition. I will post it in the form of an attachment soon.
> 
> Test result as follows:
> [103135.332683] wakeup_test: create two kernel threads - producer & consumer
> [103135.332686] wakeup_test: module loaded successfully
> [103135.332692] wakeup_test: kthread producer try to wake up the kthread consumer
> [103165.299865] wakeup_test: kthread consumer have waited for 30s, indicating
> trigger an invalid wakeup problem!
> 
> 3)Solution:
> Using preempt_disable() to bound the operaion that setting the task state
> and the conditions(set by the wake thread) validation.
> 
> ----------------------------------------------
> ...
> preempt_disable();
> set_current_state(TASK_INTERRUPTIBLE);
> while (list_empty(&product_list)){
> 	preempt_enable();
> 	schedule();
> 	preempt_disable();
> 	set_current_state(TASK_INTERRUPTIBLE);
> }
> __set_current_state(TASK_RUNNING);
> preempt_enable();
> ...
> ----------------------------------------------
> And it also can be solved as follows:
> ----------------------------------------------
> ...
> preempt_disable();
> while (list_empty(&product_list)){
> 	set_current_state(TASK_INTERRUPTIBLE);
> 	preempt_enable();
> 	schedule();
> 	preempt_disable();	
> }
> preempt_enable();
> ...
> ----------------------------------------------
> 
> Libin (14):
>   kthread: Fix invalid wakeup in kthreadd
>   audit: Fix invalid wakeup in kauditd_thread
>   audit: Fix invalid wakeup in wait_for_auditd
>   exit: Fix invalid wakeup in do_wait
>   hrtimer: Fix invalid wakeup in do_nanosleep
>   irq: Fix invalid wakeup in irq_wait_for_interrupt
>   module: Fix invalid wakeup in wait_for_zero_refcount
>   namespace: Fix invalid wakeup in zap_pid_ns_processes
>   rcutree: Fix invalid wakeup in rcu_wait
>   time: Fix invalid wakeup in alarmtimer_do_nsleep
>   trace: Fix invalid wakeup in wait_to_die
>   trace: Fix invalid wakeup in ring_buffer_consumer_thread
>   workqueue: Fix invalid wakeup in rescuer_thread
>   klist: Fix invalid wakeup in klist_remove
> 
>  kernel/audit.c                       | 11 ++++-
>  kernel/exit.c                        |  7 ++-
>  kernel/hrtimer.c                     |  7 ++-
>  kernel/irq/manage.c                  |  5 ++
>  kernel/kthread.c                     |  7 ++-
>  kernel/module.c                      |  6 ++-
>  kernel/pid_namespace.c               |  4 ++
>  kernel/rcutree.h                     |  4 ++
>  kernel/time/alarmtimer.c             |  7 ++-
>  kernel/trace/ring_buffer_benchmark.c | 14 ++++++
>  kernel/workqueue.c                   | 92 +++++++++++++++++++-----------------
>  lib/klist.c                          |  4 ++
>  12 files changed, 118 insertions(+), 50 deletions(-)
> 
> -- 
> 1.8.2.1
> 
> 


      parent reply	other threads:[~2013-08-30  0:19 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-29 13:57 [PATCH 00/14] Fix bug about invalid wake up problem Libin
2013-08-29 13:57 ` [PATCH 01/14] kthread: Fix invalid wakeup in kthreadd Libin
2013-08-30  0:20   ` Paul E. McKenney
2013-08-29 13:57 ` [PATCH 02/14] audit: Fix invalid wakeup in kauditd_thread Libin
2013-08-29 13:57 ` [PATCH 03/14] audit: Fix invalid wakeup in wait_for_auditd Libin
2013-08-29 13:57 ` [PATCH 04/14] exit: Fix invalid wakeup in do_wait Libin
2013-08-29 13:57 ` [PATCH 05/14] hrtimer: Fix invalid wakeup in do_nanosleep Libin
2013-09-12 13:33   ` Thomas Gleixner
2013-08-29 13:57 ` [PATCH 06/14] irq: Fix invalid wakeup in irq_wait_for_interrupt Libin
2013-09-12 13:36   ` Thomas Gleixner
2013-08-29 13:57 ` [PATCH 07/14] module: Fix invalid wakeup in wait_for_zero_refcount Libin
2013-08-29 13:57 ` [PATCH 08/14] namespace: Fix invalid wakeup in zap_pid_ns_processes Libin
2013-08-29 13:57 ` [PATCH 09/14] rcutree: Fix invalid wakeup in rcu_wait Libin
2013-08-30  0:23   ` Paul E. McKenney
2013-08-29 13:57 ` [PATCH 10/14] time: Fix invalid wakeup in alarmtimer_do_nsleep Libin
2013-09-12 13:36   ` Thomas Gleixner
2013-08-29 13:57 ` [PATCH 11/14] trace: Fix invalid wakeup in wait_to_die Libin
2013-08-29 13:57 ` [PATCH 12/14] trace: Fix invalid wakeup in ring_buffer_consumer_thread Libin
2013-08-29 13:57 ` [PATCH 13/14] workqueue: Fix invalid wakeup in rescuer_thread Libin
2013-08-29 13:57 ` [PATCH 14/14] klist: Fix invalid wakeup in klist_remove Libin
2013-08-29 14:08 ` [PATCH 00/14] Fix bug about invalid wake up problem Libin
2013-08-29 14:12   ` Tejun Heo
2013-08-29 14:10 ` Tejun Heo
2013-08-29 23:39 ` Libin
2013-08-30  0:18 ` Paul E. McKenney [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130830001841.GY3871@linux.vnet.ibm.com \
    --to=paulmck@linux.vnet.ibm.com \
    --cc=akpm@linux-foundation.org \
    --cc=ebiederm@xmission.com \
    --cc=eparis@redhat.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=guohanjun@huawei.com \
    --cc=huawei.libin@huawei.com \
    --cc=john.stultz@linaro.org \
    --cc=jovi.zhangwei@huawei.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lizefan@huawei.com \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=rusty@rustcorp.com.au \
    --cc=tglx@linutronix.de \
    --cc=tj@kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    --cc=wangyijing@huawei.com \
    --cc=zhangdianfang@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.