public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Gautham R Shenoy <ego@in.ibm.com>
To: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: pm list <linux-pm@lists.linux-foundation.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	LKML <linux-kernel@vger.kernel.org>,
	Cedric Le Goater <clg@fr.ibm.com>, Ingo Molnar <mingo@elte.hu>,
	Paul Menage <menage@google.com>
Subject: Re: [linux-pm] [RFC][PATCH 1/2] Freezer: Introduce PF_FREEZER_NOSIG
Date: Wed, 7 May 2008 06:08:29 +0530	[thread overview]
Message-ID: <20080507003829.GA13608@in.ibm.com> (raw)
In-Reply-To: <200805070005.20403.rjw@sisk.pl>

Hi Rafael,

On Wed, May 07, 2008 at 12:05:19AM +0200, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rjw@sisk.pl>
> 
> The freezer currently attempts to distinguish kernel threads from
> user space tasks by checking if their mm pointer is unset and it
> does not send fake signals to kernel threads.  However, there are
> kernel threads, mostly related to networking, that behave like
> user space tasks and may want to be sent a fake signal to be frozen.
> 
> Introduce the new process flag PF_FREEZER_NOSIG that will be set
> by default for all kernel threads and make the freezer only send
> fake signals to the tasks having PF_FREEZER_NOSIG unset.  Provide
> the set_freezable_with_signal() function to be called by the kernel
> threads that want to be sent a fake signal for freezing.
> 
> This patch should not change the freezer's observable behavior.
> 
> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
> ---
>  include/linux/freezer.h |   10 ++++
>  include/linux/sched.h   |    1 
>  kernel/kthread.c        |    2 
>  kernel/power/process.c  |   97 ++++++++++++++++++++----------------------------
>  4 files changed, 54 insertions(+), 56 deletions(-)
> 
> Index: linux-2.6/include/linux/freezer.h
> ===================================================================
> --- linux-2.6.orig/include/linux/freezer.h
> +++ linux-2.6/include/linux/freezer.h
> @@ -128,6 +128,15 @@ static inline void set_freezable(void)
>  }
> 
>  /*
> + * Tell the freezer that the current task should be frozen by it and that it
> + * should send a fake signal to the task to freeze it.
> + */
> +static inline void set_freezable_with_signal(void)
> +{
> +	current->flags &= ~(PF_NOFREEZE | PF_FREEZER_NOSIG);
> +}
> +
> +/*
>   * Freezer-friendly wrappers around wait_event_interruptible() and
>   * wait_event_interruptible_timeout(), originally defined in <linux/wait.h>
>   */
> @@ -174,6 +183,7 @@ static inline void freezer_do_not_count(
>  static inline void freezer_count(void) {}
>  static inline int freezer_should_skip(struct task_struct *p) { return 0; }
>  static inline void set_freezable(void) {}
> +static inline void set_freezable_with_signal(void) {}
> 
>  #define wait_event_freezable(wq, condition)				\
>  		wait_event_interruptible(wq, condition)
> Index: linux-2.6/include/linux/sched.h
> ===================================================================
> --- linux-2.6.orig/include/linux/sched.h
> +++ linux-2.6/include/linux/sched.h
> @@ -1508,6 +1508,7 @@ static inline void put_task_struct(struc
>  #define PF_MEMPOLICY	0x10000000	/* Non-default NUMA mempolicy */
>  #define PF_MUTEX_TESTER	0x20000000	/* Thread belongs to the rt mutex tester */
>  #define PF_FREEZER_SKIP	0x40000000	/* Freezer should not count it as freezeable */
> +#define PF_FREEZER_NOSIG 0x80000000	/* Freezer won't send signals to it */
> 
>  /*
>   * Only the _current_ task can read/write to tsk->flags, but other
> Index: linux-2.6/kernel/power/process.c
> ===================================================================
> --- linux-2.6.orig/kernel/power/process.c
> +++ linux-2.6/kernel/power/process.c
> @@ -19,9 +19,6 @@
>   */
>  #define TIMEOUT	(20 * HZ)
> 
> -#define FREEZER_KERNEL_THREADS 0
> -#define FREEZER_USER_SPACE 1
> -
>  static inline int freezeable(struct task_struct * p)
>  {
>  	if ((p == current) ||
> @@ -84,63 +81,53 @@ static void fake_signal_wake_up(struct t
>  	spin_unlock_irqrestore(&p->sighand->siglock, flags);
>  }
> 
> -static int has_mm(struct task_struct *p)
> +static inline bool should_send_signal(struct task_struct *p)
>  {
> -	return (p->mm && !(p->flags & PF_BORROWED_MM));
> +	return !(current->flags & PF_FREEZER_NOSIG);
		^^^^^^^^^^^^^^
		p->flags ?


>  }
> 
>  /**
>   *	freeze_task - send a freeze request to given task
>   *	@p: task to send the request to
> - *	@with_mm_only: if set, the request will only be sent if the task has its
> - *		own mm
> - *	Return value: 0, if @with_mm_only is set and the task has no mm of its
> - *		own or the task is frozen, 1, otherwise
> + *	@sig_only: if set, the request will only be sent if the task has the
> + *		PF_FREEZER_NOSIG flag unset
> + *	Return value: 'false', if @sig_only is set and the task has
> + *		PF_FREEZER_NOSIG set or the task is frozen, 'true', otherwise
>   *
> - *	The freeze request is sent by seting the tasks's TIF_FREEZE flag and
> + *	The freeze request is sent by setting the tasks's TIF_FREEZE flag and
>   *	either sending a fake signal to it or waking it up, depending on whether
> - *	or not it has its own mm (ie. it is a user land task).  If @with_mm_only
> - *	is set and the task has no mm of its own (ie. it is a kernel thread),
> - *	its TIF_FREEZE flag should not be set.
> - *
> - *	The task_lock() is necessary to prevent races with exit_mm() or
> - *	use_mm()/unuse_mm() from occuring.
> + *	or not it has PF_FREEZER_NOSIG set.  If @sig_only is set and the task
> + *	has PF_FREEZER_NOSIG set (ie. it is a typical kernel thread), its
> + *	TIF_FREEZE flag will not be set.
>   */
> -static int freeze_task(struct task_struct *p, int with_mm_only)
> +static bool freeze_task(struct task_struct *p, bool sig_only)
>  {
> -	int ret = 1;
> +	/*
> +	 * We first check if the task is freezing and next if it has already
> +	 * been frozen to avoid the race with frozen_process() which first marks
> +	 * the task as frozen and next clears its TIF_FREEZE.
> +	 */
> +	if (!freezing(p)) {
> +		rmb();
> +		if (frozen(p))
> +			return false;
> 
> -	task_lock(p);
> -	if (freezing(p)) {
> -		if (has_mm(p)) {
> -			if (!signal_pending(p))
> -				fake_signal_wake_up(p);
> -		} else {
> -			if (with_mm_only)
> -				ret = 0;
> -			else
> -				wake_up_state(p, TASK_INTERRUPTIBLE);
> -		}
> +		if (!sig_only || should_send_signal(p))
> +			set_freeze_flag(p);
> +		else
> +			return false;
> +	}
> +
> +	if (should_send_signal(p)) {
> +		if (!signal_pending(p))
> +			fake_signal_wake_up(p);
> +	} else if (sig_only) {
> +		return false;
>  	} else {
> -		rmb();
> -		if (frozen(p)) {
> -			ret = 0;
> -		} else {
> -			if (has_mm(p)) {
> -				set_freeze_flag(p);
> -				fake_signal_wake_up(p);
> -			} else {
> -				if (with_mm_only) {
> -					ret = 0;
> -				} else {
> -					set_freeze_flag(p);
> -					wake_up_state(p, TASK_INTERRUPTIBLE);
> -				}
> -			}
> -		}
> +		wake_up_state(p, TASK_INTERRUPTIBLE);
>  	}
> -	task_unlock(p);
> -	return ret;
> +
> +	return true;
>  }
> 
>  static void cancel_freezing(struct task_struct *p)
> @@ -156,7 +143,7 @@ static void cancel_freezing(struct task_
>  	}
>  }
> 
> -static int try_to_freeze_tasks(int freeze_user_space)
> +static int try_to_freeze_tasks(bool sig_only)
>  {
>  	struct task_struct *g, *p;
>  	unsigned long end_time;
> @@ -175,7 +162,7 @@ static int try_to_freeze_tasks(int freez
>  			if (frozen(p) || !freezeable(p))
>  				continue;
> 
> -			if (!freeze_task(p, freeze_user_space))
> +			if (!freeze_task(p, sig_only))
>  				continue;
> 
>  			/*
> @@ -235,13 +222,13 @@ int freeze_processes(void)
>  	int error;
> 
>  	printk("Freezing user space processes ... ");
> -	error = try_to_freeze_tasks(FREEZER_USER_SPACE);
> +	error = try_to_freeze_tasks(true);
>  	if (error)
>  		goto Exit;
>  	printk("done.\n");
> 
>  	printk("Freezing remaining freezable tasks ... ");
> -	error = try_to_freeze_tasks(FREEZER_KERNEL_THREADS);
> +	error = try_to_freeze_tasks(false);
>  	if (error)
>  		goto Exit;
>  	printk("done.");
> @@ -251,7 +238,7 @@ int freeze_processes(void)
>  	return error;
>  }
> 
> -static void thaw_tasks(int thaw_user_space)
> +static void thaw_tasks(bool sig_only)
>  {
>  	struct task_struct *g, *p;
> 
> @@ -260,7 +247,7 @@ static void thaw_tasks(int thaw_user_spa
>  		if (!freezeable(p))
>  			continue;
> 
> -		if (!p->mm == thaw_user_space)
> +		if (sig_only && !should_send_signal(p))
>  			continue;
> 
>  		thaw_process(p);
> @@ -271,8 +258,8 @@ static void thaw_tasks(int thaw_user_spa
>  void thaw_processes(void)
>  {
>  	printk("Restarting tasks ... ");
> -	thaw_tasks(FREEZER_KERNEL_THREADS);
> -	thaw_tasks(FREEZER_USER_SPACE);
> +	thaw_tasks(true);
> +	thaw_tasks(false);

Shouldn't the order be 
	thaw_tasks(false);
	thaw_tasks(true);


>  	schedule();
>  	printk("done.\n");
>  }
> Index: linux-2.6/kernel/kthread.c
> ===================================================================
> --- linux-2.6.orig/kernel/kthread.c
> +++ linux-2.6/kernel/kthread.c
> @@ -234,7 +234,7 @@ int kthreadd(void *unused)
>  	set_user_nice(tsk, KTHREAD_NICE_LEVEL);
>  	set_cpus_allowed(tsk, CPU_MASK_ALL);
> 
> -	current->flags |= PF_NOFREEZE;
> +	current->flags |= PF_NOFREEZE | PF_FREEZER_NOSIG;
> 
>  	for (;;) {
>  		set_current_state(TASK_INTERRUPTIBLE);
> _______________________________________________
> linux-pm mailing list
> linux-pm@lists.linux-foundation.org
> https://lists.linux-foundation.org/mailman/listinfo/linux-pm

-- 
Thanks and Regards
gautham

  reply	other threads:[~2008-05-07  0:36 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-05-06 22:03 [RFC][PATCH 0/2] Freezer face lifting Rafael J. Wysocki
2008-05-06 22:05 ` [RFC][PATCH 1/2] Freezer: Introduce PF_FREEZER_NOSIG Rafael J. Wysocki
2008-05-07  0:38   ` Gautham R Shenoy [this message]
2008-05-07 12:11     ` [linux-pm] " Rafael J. Wysocki
2008-05-07  9:36   ` Pavel Machek
2008-05-07 12:16     ` Rafael J. Wysocki
2008-05-06 22:07 ` [RFC][PATCH 2/2] Freezer: Try to handle killable tasks Rafael J. Wysocki
2008-05-07  9:41   ` Pavel Machek
2008-05-07 13:57     ` Matthew Wilcox
2008-05-07 18:35       ` Rafael J. Wysocki
2008-05-07 13:53   ` Matthew Wilcox
2008-05-07 18:41     ` Rafael J. Wysocki
2008-05-19 22:59       ` Pavel Machek

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=20080507003829.GA13608@in.ibm.com \
    --to=ego@in.ibm.com \
    --cc=akpm@linux-foundation.org \
    --cc=clg@fr.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@lists.linux-foundation.org \
    --cc=menage@google.com \
    --cc=mingo@elte.hu \
    --cc=rjw@sisk.pl \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox