Re: [PATCH -mm 1/2] Separate freezer from PM code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Apr 27, 2007 at 11:29:34PM +0200, Rafael J. Wysocki wrote:
> On Friday, 27 April 2007 22:20, Jeremy Fitzhardinge wrote:
> > Rafael J. Wysocki wrote:
> > > Makes sense.  Please have a look at the updated patch below.
> > >
> > > Sam, does this one look better to you?
> > >   
> > 
> > If freezer.c is in kernel/, then shouldn't the corresponding config var
> > be in a non-arch Kconfig file?
> 
> Well, I though it would look strange.  Still, I can do that, of course:

It would have been much better to have a single kernel/Kconfig
so you avoided all the arch specific source lines.
But thats not this patch and can come later.

So I'm OK with this one.

	Sam

> 
> ---
> From: Rafael J. Wysocki <[email protected]>
> 
> Now that the freezer is used by kprobes, it is no longer a PM-specific piece of
> code.  Move the freezer code out of kernel/power and introduce the
> CONFIG_FREEZER option that will be chosen automatically if PM or KPROBES is set.
> 
> Signed-off-by: Rafael J. Wysocki <[email protected]>
> ---
>  arch/arm/Kconfig         |    2 
>  arch/avr32/Kconfig       |    2 
>  arch/avr32/Kconfig.debug |    1 
>  arch/blackfin/Kconfig    |    2 
>  arch/frv/Kconfig         |    2 
>  arch/i386/Kconfig        |    3 
>  arch/ia64/Kconfig        |    3 
>  arch/mips/Kconfig        |    2 
>  arch/powerpc/Kconfig     |    3 
>  arch/ppc/Kconfig         |    2 
>  arch/s390/Kconfig        |    3 
>  arch/sh/Kconfig          |    2 
>  arch/sparc64/Kconfig     |    3 
>  arch/x86_64/Kconfig      |    3 
>  include/linux/freezer.h  |    2 
>  kernel/Kconfig.freezer   |    5 
>  kernel/Makefile          |    1 
>  kernel/freezer.c         |  236 +++++++++++++++++++++++++++++++++++++++++++++++
>  kernel/kprobes.c         |    2 
>  kernel/power/Kconfig     |    1 
>  kernel/power/Makefile    |    2 
>  kernel/power/process.c   |  236 -----------------------------------------------
>  22 files changed, 279 insertions(+), 239 deletions(-)
> 
> Index: linux-2.6.21-rc7-mm2/arch/x86_64/Kconfig
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/arch/x86_64/Kconfig	2007-04-27 21:41:05.000000000 +0200
> +++ linux-2.6.21-rc7-mm2/arch/x86_64/Kconfig	2007-04-27 23:20:43.000000000 +0200
> @@ -703,6 +703,8 @@ config GENERIC_PENDING_IRQ
>  	depends on GENERIC_HARDIRQS && SMP
>  	default y
>  
> +source "kernel/Kconfig.freezer"
> +
>  menu "Power management options"
>  
>  source kernel/power/Kconfig
> @@ -791,6 +793,7 @@ source "arch/x86_64/oprofile/Kconfig"
>  config KPROBES
>  	bool "Kprobes (EXPERIMENTAL)"
>  	depends on KALLSYMS && EXPERIMENTAL && MODULES
> +	select FREEZER
>  	help
>  	  Kprobes allows you to trap at almost any kernel address and
>  	  execute a callback function.  register_kprobe() establishes
> Index: linux-2.6.21-rc7-mm2/arch/avr32/Kconfig.debug
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/arch/avr32/Kconfig.debug	2007-04-27 21:41:05.000000000 +0200
> +++ linux-2.6.21-rc7-mm2/arch/avr32/Kconfig.debug	2007-04-27 21:54:19.000000000 +0200
> @@ -12,6 +12,7 @@ menu "Instrumentation Support"
>  config KPROBES
>  	bool "Kprobes"
>  	depends on DEBUG_KERNEL
> +	select FREEZER
>  	help
>  	  Kprobes allows you to trap at almost any kernel address and
>            execute a callback function.  register_kprobe() establishes
> Index: linux-2.6.21-rc7-mm2/arch/frv/Kconfig
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/arch/frv/Kconfig	2007-04-27 21:41:05.000000000 +0200
> +++ linux-2.6.21-rc7-mm2/arch/frv/Kconfig	2007-04-27 23:13:27.000000000 +0200
> @@ -364,6 +364,8 @@ source "drivers/pcmcia/Kconfig"
>  #	  sleep-deprived psychotic hacker types can say Y now, everyone else
>  #	  should probably wait a while.
>  
> +source "kernel/Kconfig.freezer"
> +
>  menu "Power management options"
>  source kernel/power/Kconfig
>  endmenu
> Index: linux-2.6.21-rc7-mm2/arch/i386/Kconfig
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/arch/i386/Kconfig	2007-04-27 21:41:05.000000000 +0200
> +++ linux-2.6.21-rc7-mm2/arch/i386/Kconfig	2007-04-27 23:17:36.000000000 +0200
> @@ -912,6 +912,8 @@ config ARCH_ENABLE_MEMORY_HOTPLUG
>  	def_bool y
>  	depends on HIGHMEM
>  
> +source "kernel/Kconfig.freezer"
> +
>  menu "Power management options (ACPI, APM)"
>  	depends on !X86_VOYAGER
>  
> @@ -1218,6 +1220,7 @@ source "arch/i386/oprofile/Kconfig"
>  config KPROBES
>  	bool "Kprobes (EXPERIMENTAL)"
>  	depends on KALLSYMS && EXPERIMENTAL && MODULES
> +	select FREEZER
>  	help
>  	  Kprobes allows you to trap at almost any kernel address and
>  	  execute a callback function.  register_kprobe() establishes
> Index: linux-2.6.21-rc7-mm2/arch/ia64/Kconfig
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/arch/ia64/Kconfig	2007-04-27 21:41:05.000000000 +0200
> +++ linux-2.6.21-rc7-mm2/arch/ia64/Kconfig	2007-04-27 23:21:40.000000000 +0200
> @@ -495,6 +495,8 @@ source "fs/Kconfig.binfmt"
>  
>  endmenu
>  
> +source "kernel/Kconfig.freezer"
> +
>  menu "Power management and ACPI"
>  
>  source "kernel/power/Kconfig"
> @@ -582,6 +584,7 @@ source "arch/ia64/oprofile/Kconfig"
>  config KPROBES
>  	bool "Kprobes (EXPERIMENTAL)"
>  	depends on KALLSYMS && EXPERIMENTAL && MODULES
> +	select FREEZER
>  	help
>  	  Kprobes allows you to trap at almost any kernel address and
>  	  execute a callback function.  register_kprobe() establishes
> Index: linux-2.6.21-rc7-mm2/arch/powerpc/Kconfig
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/arch/powerpc/Kconfig	2007-04-27 21:41:05.000000000 +0200
> +++ linux-2.6.21-rc7-mm2/arch/powerpc/Kconfig	2007-04-27 23:15:12.000000000 +0200
> @@ -552,6 +552,8 @@ config CMDLINE
>  	  some command-line options at build time by entering them here.  In
>  	  most cases you will need to specify the root device here.
>  
> +source kernel/Kconfig.freezer
> +
>  if !44x || BROKEN
>  source kernel/power/Kconfig
>  endif
> @@ -865,6 +867,7 @@ source "arch/powerpc/oprofile/Kconfig"
>  config KPROBES
>  	bool "Kprobes (EXPERIMENTAL)"
>  	depends on !BOOKE && !4xx && KALLSYMS && EXPERIMENTAL && MODULES
> +	select FREEZER
>  	help
>  	  Kprobes allows you to trap at almost any kernel address and
>  	  execute a callback function.  register_kprobe() establishes
> Index: linux-2.6.21-rc7-mm2/arch/ppc/Kconfig
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/arch/ppc/Kconfig	2007-04-27 21:41:05.000000000 +0200
> +++ linux-2.6.21-rc7-mm2/arch/ppc/Kconfig	2007-04-27 23:15:25.000000000 +0200
> @@ -1153,6 +1153,8 @@ config PROC_HARDWARE
>  
>  source "drivers/zorro/Kconfig"
>  
> +source "kernel/Kconfig.freezer"
> +
>  if !44x || BROKEN
>  source kernel/power/Kconfig
>  endif
> Index: linux-2.6.21-rc7-mm2/arch/s390/Kconfig
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/arch/s390/Kconfig	2007-04-27 21:41:05.000000000 +0200
> +++ linux-2.6.21-rc7-mm2/arch/s390/Kconfig	2007-04-27 23:23:19.000000000 +0200
> @@ -550,6 +550,8 @@ source "drivers/net/Kconfig"
>  
>  source "fs/Kconfig"
>  
> +source "kernel/Kconfig.freezer"
> +
>  menu "Instrumentation Support"
>  
>  source "arch/s390/oprofile/Kconfig"
> @@ -557,6 +559,7 @@ source "arch/s390/oprofile/Kconfig"
>  config KPROBES
>  	bool "Kprobes (EXPERIMENTAL)"
>  	depends on EXPERIMENTAL && MODULES
> +	select FREEZER
>  	help
>  	  Kprobes allows you to trap at almost any kernel address and
>  	  execute a callback function.	register_kprobe() establishes
> Index: linux-2.6.21-rc7-mm2/arch/sh/Kconfig
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/arch/sh/Kconfig	2007-04-27 21:41:05.000000000 +0200
> +++ linux-2.6.21-rc7-mm2/arch/sh/Kconfig	2007-04-27 23:23:33.000000000 +0200
> @@ -699,6 +699,8 @@ source "fs/Kconfig.binfmt"
>  
>  endmenu
>  
> +source "kernel/Kconfig.freezer"
> +
>  menu "Power management options (EXPERIMENTAL)"
>  depends on EXPERIMENTAL
>  
> Index: linux-2.6.21-rc7-mm2/arch/sparc64/Kconfig
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/arch/sparc64/Kconfig	2007-04-27 21:41:05.000000000 +0200
> +++ linux-2.6.21-rc7-mm2/arch/sparc64/Kconfig	2007-04-27 23:23:44.000000000 +0200
> @@ -420,6 +420,8 @@ source "drivers/fc4/Kconfig"
>  
>  source "fs/Kconfig"
>  
> +source "kernel/Kconfig.freezer"
> +
>  menu "Instrumentation Support"
>          depends on EXPERIMENTAL
>  
> @@ -428,6 +430,7 @@ source "arch/sparc64/oprofile/Kconfig"
>  config KPROBES
>  	bool "Kprobes (EXPERIMENTAL)"
>  	depends on KALLSYMS && EXPERIMENTAL && MODULES
> +	select FREEZER
>  	help
>  	  Kprobes allows you to trap at almost any kernel address and
>  	  execute a callback function.  register_kprobe() establishes
> Index: linux-2.6.21-rc7-mm2/kernel/Makefile
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/kernel/Makefile	2007-04-27 21:41:05.000000000 +0200
> +++ linux-2.6.21-rc7-mm2/kernel/Makefile	2007-04-27 21:41:28.000000000 +0200
> @@ -33,6 +33,7 @@ obj-$(CONFIG_MODULES) += module.o
>  obj-$(CONFIG_KALLSYMS) += kallsyms.o
>  obj-$(CONFIG_STACK_UNWIND) += unwind.o
>  obj-$(CONFIG_PM) += power/
> +obj-$(CONFIG_FREEZER) += freezer.o
>  obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
>  obj-$(CONFIG_KEXEC) += kexec.o
>  obj-$(CONFIG_COMPAT) += compat.o
> Index: linux-2.6.21-rc7-mm2/kernel/power/Makefile
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/kernel/power/Makefile	2007-04-27 21:41:05.000000000 +0200
> +++ linux-2.6.21-rc7-mm2/kernel/power/Makefile	2007-04-27 21:41:28.000000000 +0200
> @@ -3,7 +3,7 @@ ifeq ($(CONFIG_PM_DEBUG),y)
>  EXTRA_CFLAGS	+=	-DDEBUG
>  endif
>  
> -obj-y				:= main.o process.o console.o notify.o
> +obj-y				:= main.o console.o notify.o
>  obj-$(CONFIG_PM_LEGACY)		+= pm.o
>  obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o disk.o snapshot.o swap.o user.o
>  
> Index: linux-2.6.21-rc7-mm2/kernel/kprobes.c
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/kernel/kprobes.c	2007-04-27 21:41:05.000000000 +0200
> +++ linux-2.6.21-rc7-mm2/kernel/kprobes.c	2007-04-27 21:41:28.000000000 +0200
> @@ -108,7 +108,7 @@ static int collect_garbage_slots(void);
>  static int __kprobes check_safety(void)
>  {
>  	int ret = 0;
> -#if defined(CONFIG_PREEMPT) && defined(CONFIG_PM)
> +#ifdef CONFIG_PREEMPT
>  	ret = freeze_processes();
>  	if (ret == 0) {
>  		struct task_struct *p, *q;
> Index: linux-2.6.21-rc7-mm2/include/linux/freezer.h
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/include/linux/freezer.h	2007-04-27 21:41:27.000000000 +0200
> +++ linux-2.6.21-rc7-mm2/include/linux/freezer.h	2007-04-27 23:20:23.000000000 +0200
> @@ -2,7 +2,7 @@
>  
>  #include <linux/sched.h>
>  
> -#ifdef CONFIG_PM
> +#ifdef CONFIG_FREEZER
>  /*
>   * Check if a process has been frozen
>   */
> Index: linux-2.6.21-rc7-mm2/arch/arm/Kconfig
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/arch/arm/Kconfig	2007-04-27 21:41:05.000000000 +0200
> +++ linux-2.6.21-rc7-mm2/arch/arm/Kconfig	2007-04-27 23:11:10.000000000 +0200
> @@ -925,6 +925,8 @@ config ARTHUR
>  
>  endmenu
>  
> +source "kernel/Kconfig.freezer"
> +
>  menu "Power management options"
>  
>  source "kernel/power/Kconfig"
> Index: linux-2.6.21-rc7-mm2/arch/blackfin/Kconfig
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/arch/blackfin/Kconfig	2007-04-27 21:41:05.000000000 +0200
> +++ linux-2.6.21-rc7-mm2/arch/blackfin/Kconfig	2007-04-27 23:13:09.000000000 +0200
> @@ -816,6 +816,8 @@ source "fs/Kconfig.binfmt"
>  
>  endmenu
>  
> +source "kernel/Kconfig.freezer"
> +
>  menu "Power management options"
>  source "kernel/power/Kconfig"
>  
> Index: linux-2.6.21-rc7-mm2/arch/mips/Kconfig
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/arch/mips/Kconfig	2007-04-27 21:41:05.000000000 +0200
> +++ linux-2.6.21-rc7-mm2/arch/mips/Kconfig	2007-04-27 23:22:37.000000000 +0200
> @@ -2067,6 +2067,8 @@ source "drivers/pci/hotplug/Kconfig"
>  
>  endmenu
>  
> +source "kernel/Kconfig.freezer"
> +
>  menu "Executable file formats"
>  
>  source "fs/Kconfig.binfmt"
> Index: linux-2.6.21-rc7-mm2/kernel/freezer.c
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ linux-2.6.21-rc7-mm2/kernel/freezer.c	2007-04-27 23:20:23.000000000 +0200
> @@ -0,0 +1,236 @@
> +/*
> + * linux/kernel/freezer.c
> + *
> + * Generic mechanism for freezing and thawing tasks, originally from swsusp.
> + *
> + * Distributed under the GPLv2
> + */
> +
> +
> +#undef DEBUG
> +
> +#include <linux/sched.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/syscalls.h>
> +#include <linux/freezer.h>
> +
> +/*
> + * Timeout for stopping processes
> + */
> +#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) ||
> +	    (p->flags & PF_NOFREEZE) ||
> +	    (p->exit_state != 0))
> +		return 0;
> +	return 1;
> +}
> +
> +/*
> + * freezing is complete, mark current process as frozen
> + */
> +static inline void frozen_process(void)
> +{
> +	if (!unlikely(current->flags & PF_NOFREEZE)) {
> +		current->flags |= PF_FROZEN;
> +		wmb();
> +	}
> +	clear_tsk_thread_flag(current, TIF_FREEZE);
> +}
> +
> +/* Refrigerator is place where frozen processes are stored :-). */
> +void refrigerator(void)
> +{
> +	/* Hmm, should we be allowed to suspend when there are realtime
> +	   processes around? */
> +	long save;
> +
> +	task_lock(current);
> +	if (freezing(current)) {
> +		frozen_process();
> +		task_unlock(current);
> +	} else {
> +		task_unlock(current);
> +		return;
> +	}
> +	save = current->state;
> +	pr_debug("%s entered refrigerator\n", current->comm);
> +
> +	spin_lock_irq(&current->sighand->siglock);
> +	recalc_sigpending(); /* We sent fake signal, clean it up */
> +	spin_unlock_irq(&current->sighand->siglock);
> +
> +	for (;;) {
> +		set_current_state(TASK_UNINTERRUPTIBLE);
> +		if (!frozen(current))
> +			break;
> +		schedule();
> +	}
> +	pr_debug("%s left refrigerator\n", current->comm);
> +	current->state = save;
> +}
> +
> +static inline void freeze_process(struct task_struct *p)
> +{
> +	unsigned long flags;
> +
> +	if (!freezing(p)) {
> +		rmb();
> +		if (!frozen(p)) {
> +			if (p->state == TASK_STOPPED)
> +				force_sig_specific(SIGSTOP, p);
> +
> +			freeze(p);
> +			spin_lock_irqsave(&p->sighand->siglock, flags);
> +			signal_wake_up(p, p->state == TASK_STOPPED);
> +			spin_unlock_irqrestore(&p->sighand->siglock, flags);
> +		}
> +	}
> +}
> +
> +static void cancel_freezing(struct task_struct *p)
> +{
> +	unsigned long flags;
> +
> +	if (freezing(p)) {
> +		pr_debug("  clean up: %s\n", p->comm);
> +		do_not_freeze(p);
> +		spin_lock_irqsave(&p->sighand->siglock, flags);
> +		recalc_sigpending_tsk(p);
> +		spin_unlock_irqrestore(&p->sighand->siglock, flags);
> +	}
> +}
> +
> +static inline int is_user_space(struct task_struct *p)
> +{
> +	int ret;
> +
> +	task_lock(p);
> +	ret = p->mm && !(p->flags & PF_BORROWED_MM);
> +	task_unlock(p);
> +	return ret;
> +}
> +
> +static unsigned int try_to_freeze_tasks(int freeze_user_space)
> +{
> +	struct task_struct *g, *p;
> +	unsigned long end_time;
> +	unsigned int todo;
> +
> +	end_time = jiffies + TIMEOUT;
> +	do {
> +		todo = 0;
> +		read_lock(&tasklist_lock);
> +		do_each_thread(g, p) {
> +			if (!freezeable(p))
> +				continue;
> +
> +			if (frozen(p))
> +				continue;
> +
> +			if (p->state == TASK_TRACED && frozen(p->parent)) {
> +				cancel_freezing(p);
> +				continue;
> +			}
> +			if (freeze_user_space && !is_user_space(p))
> +				continue;
> +
> +			freeze_process(p);
> +			if (!freezer_should_skip(p))
> +				todo++;
> +		} while_each_thread(g, p);
> +		read_unlock(&tasklist_lock);
> +		yield();			/* Yield is okay here */
> +		if (todo && time_after(jiffies, end_time))
> +			break;
> +	} while (todo);
> +
> +	if (todo) {
> +		/* This does not unfreeze processes that are already frozen
> +		 * (we have slightly ugly calling convention in that respect,
> +		 * and caller must call thaw_processes() if something fails),
> +		 * but it cleans up leftover PF_FREEZE requests.
> +		 */
> +		printk("\n");
> +		printk(KERN_ERR "Stopping %s timed out after %d seconds "
> +				"(%d tasks refusing to freeze):\n",
> +				freeze_user_space ? "user space processes" :
> +					"kernel threads",
> +				TIMEOUT / HZ, todo);
> +		read_lock(&tasklist_lock);
> +		do_each_thread(g, p) {
> +			if (freeze_user_space && !is_user_space(p))
> +				continue;
> +
> +			task_lock(p);
> +			if (freezeable(p) && !frozen(p) &&
> +			    !freezer_should_skip(p))
> +				printk(KERN_ERR " %s\n", p->comm);
> +
> +			cancel_freezing(p);
> +			task_unlock(p);
> +		} while_each_thread(g, p);
> +		read_unlock(&tasklist_lock);
> +	}
> +
> +	return todo;
> +}
> +
> +/**
> + *	freeze_processes - tell processes to enter the refrigerator
> + *
> + *	Returns 0 on success, or the number of processes that didn't freeze,
> + *	although they were told to.
> + */
> +int freeze_processes(void)
> +{
> +	unsigned int nr_unfrozen;
> +
> +	printk("Stopping tasks ... ");
> +	nr_unfrozen = try_to_freeze_tasks(FREEZER_USER_SPACE);
> +	if (nr_unfrozen)
> +		return nr_unfrozen;
> +
> +	sys_sync();
> +	nr_unfrozen = try_to_freeze_tasks(FREEZER_KERNEL_THREADS);
> +	if (nr_unfrozen)
> +		return nr_unfrozen;
> +
> +	printk("done.\n");
> +	BUG_ON(in_atomic());
> +	return 0;
> +}
> +
> +static void thaw_tasks(int thaw_user_space)
> +{
> +	struct task_struct *g, *p;
> +
> +	read_lock(&tasklist_lock);
> +	do_each_thread(g, p) {
> +		if (!freezeable(p))
> +			continue;
> +
> +		if (is_user_space(p) == !thaw_user_space)
> +			continue;
> +
> +		thaw_process(p);
> +	} while_each_thread(g, p);
> +	read_unlock(&tasklist_lock);
> +}
> +
> +void thaw_processes(void)
> +{
> +	printk("Restarting tasks ... ");
> +	thaw_tasks(FREEZER_KERNEL_THREADS);
> +	thaw_tasks(FREEZER_USER_SPACE);
> +	schedule();
> +	printk("done.\n");
> +}
> +
> +EXPORT_SYMBOL(refrigerator);
> Index: linux-2.6.21-rc7-mm2/kernel/power/process.c
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/kernel/power/process.c	2007-04-27 21:41:27.000000000 +0200
> +++ /dev/null	1970-01-01 00:00:00.000000000 +0000
> @@ -1,236 +0,0 @@
> -/*
> - * drivers/power/process.c - Functions for starting/stopping processes on 
> - *                           suspend transitions.
> - *
> - * Originally from swsusp.
> - */
> -
> -
> -#undef DEBUG
> -
> -#include <linux/sched.h>
> -#include <linux/interrupt.h>
> -#include <linux/suspend.h>
> -#include <linux/module.h>
> -#include <linux/syscalls.h>
> -#include <linux/freezer.h>
> -
> -/* 
> - * Timeout for stopping processes
> - */
> -#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) ||
> -	    (p->flags & PF_NOFREEZE) ||
> -	    (p->exit_state != 0))
> -		return 0;
> -	return 1;
> -}
> -
> -/*
> - * freezing is complete, mark current process as frozen
> - */
> -static inline void frozen_process(void)
> -{
> -	if (!unlikely(current->flags & PF_NOFREEZE)) {
> -		current->flags |= PF_FROZEN;
> -		wmb();
> -	}
> -	clear_tsk_thread_flag(current, TIF_FREEZE);
> -}
> -
> -/* Refrigerator is place where frozen processes are stored :-). */
> -void refrigerator(void)
> -{
> -	/* Hmm, should we be allowed to suspend when there are realtime
> -	   processes around? */
> -	long save;
> -
> -	task_lock(current);
> -	if (freezing(current)) {
> -		frozen_process();
> -		task_unlock(current);
> -	} else {
> -		task_unlock(current);
> -		return;
> -	}
> -	save = current->state;
> -	pr_debug("%s entered refrigerator\n", current->comm);
> -
> -	spin_lock_irq(&current->sighand->siglock);
> -	recalc_sigpending(); /* We sent fake signal, clean it up */
> -	spin_unlock_irq(&current->sighand->siglock);
> -
> -	for (;;) {
> -		set_current_state(TASK_UNINTERRUPTIBLE);
> -		if (!frozen(current))
> -			break;
> -		schedule();
> -	}
> -	pr_debug("%s left refrigerator\n", current->comm);
> -	current->state = save;
> -}
> -
> -static inline void freeze_process(struct task_struct *p)
> -{
> -	unsigned long flags;
> -
> -	if (!freezing(p)) {
> -		rmb();
> -		if (!frozen(p)) {
> -			if (p->state == TASK_STOPPED)
> -				force_sig_specific(SIGSTOP, p);
> -
> -			freeze(p);
> -			spin_lock_irqsave(&p->sighand->siglock, flags);
> -			signal_wake_up(p, p->state == TASK_STOPPED);
> -			spin_unlock_irqrestore(&p->sighand->siglock, flags);
> -		}
> -	}
> -}
> -
> -static void cancel_freezing(struct task_struct *p)
> -{
> -	unsigned long flags;
> -
> -	if (freezing(p)) {
> -		pr_debug("  clean up: %s\n", p->comm);
> -		do_not_freeze(p);
> -		spin_lock_irqsave(&p->sighand->siglock, flags);
> -		recalc_sigpending_tsk(p);
> -		spin_unlock_irqrestore(&p->sighand->siglock, flags);
> -	}
> -}
> -
> -static inline int is_user_space(struct task_struct *p)
> -{
> -	int ret;
> -
> -	task_lock(p);
> -	ret = p->mm && !(p->flags & PF_BORROWED_MM);
> -	task_unlock(p);
> -	return ret;
> -}
> -
> -static unsigned int try_to_freeze_tasks(int freeze_user_space)
> -{
> -	struct task_struct *g, *p;
> -	unsigned long end_time;
> -	unsigned int todo;
> -
> -	end_time = jiffies + TIMEOUT;
> -	do {
> -		todo = 0;
> -		read_lock(&tasklist_lock);
> -		do_each_thread(g, p) {
> -			if (!freezeable(p))
> -				continue;
> -
> -			if (frozen(p))
> -				continue;
> -
> -			if (p->state == TASK_TRACED && frozen(p->parent)) {
> -				cancel_freezing(p);
> -				continue;
> -			}
> -			if (freeze_user_space && !is_user_space(p))
> -				continue;
> -
> -			freeze_process(p);
> -			if (!freezer_should_skip(p))
> -				todo++;
> -		} while_each_thread(g, p);
> -		read_unlock(&tasklist_lock);
> -		yield();			/* Yield is okay here */
> -		if (todo && time_after(jiffies, end_time))
> -			break;
> -	} while (todo);
> -
> -	if (todo) {
> -		/* This does not unfreeze processes that are already frozen
> -		 * (we have slightly ugly calling convention in that respect,
> -		 * and caller must call thaw_processes() if something fails),
> -		 * but it cleans up leftover PF_FREEZE requests.
> -		 */
> -		printk("\n");
> -		printk(KERN_ERR "Stopping %s timed out after %d seconds "
> -				"(%d tasks refusing to freeze):\n",
> -				freeze_user_space ? "user space processes" :
> -					"kernel threads",
> -				TIMEOUT / HZ, todo);
> -		read_lock(&tasklist_lock);
> -		do_each_thread(g, p) {
> -			if (freeze_user_space && !is_user_space(p))
> -				continue;
> -
> -			task_lock(p);
> -			if (freezeable(p) && !frozen(p) &&
> -			    !freezer_should_skip(p))
> -				printk(KERN_ERR " %s\n", p->comm);
> -
> -			cancel_freezing(p);
> -			task_unlock(p);
> -		} while_each_thread(g, p);
> -		read_unlock(&tasklist_lock);
> -	}
> -
> -	return todo;
> -}
> -
> -/**
> - *	freeze_processes - tell processes to enter the refrigerator
> - *
> - *	Returns 0 on success, or the number of processes that didn't freeze,
> - *	although they were told to.
> - */
> -int freeze_processes(void)
> -{
> -	unsigned int nr_unfrozen;
> -
> -	printk("Stopping tasks ... ");
> -	nr_unfrozen = try_to_freeze_tasks(FREEZER_USER_SPACE);
> -	if (nr_unfrozen)
> -		return nr_unfrozen;
> -
> -	sys_sync();
> -	nr_unfrozen = try_to_freeze_tasks(FREEZER_KERNEL_THREADS);
> -	if (nr_unfrozen)
> -		return nr_unfrozen;
> -
> -	printk("done.\n");
> -	BUG_ON(in_atomic());
> -	return 0;
> -}
> -
> -static void thaw_tasks(int thaw_user_space)
> -{
> -	struct task_struct *g, *p;
> -
> -	read_lock(&tasklist_lock);
> -	do_each_thread(g, p) {
> -		if (!freezeable(p))
> -			continue;
> -
> -		if (is_user_space(p) == !thaw_user_space)
> -			continue;
> -
> -		thaw_process(p);
> -	} while_each_thread(g, p);
> -	read_unlock(&tasklist_lock);
> -}
> -
> -void thaw_processes(void)
> -{
> -	printk("Restarting tasks ... ");
> -	thaw_tasks(FREEZER_KERNEL_THREADS);
> -	thaw_tasks(FREEZER_USER_SPACE);
> -	schedule();
> -	printk("done.\n");
> -}
> -
> -EXPORT_SYMBOL(refrigerator);
> Index: linux-2.6.21-rc7-mm2/arch/avr32/Kconfig
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/arch/avr32/Kconfig	2007-04-27 01:00:50.000000000 +0200
> +++ linux-2.6.21-rc7-mm2/arch/avr32/Kconfig	2007-04-27 23:12:42.000000000 +0200
> @@ -209,6 +209,8 @@ source "drivers/Kconfig"
>  
>  source "fs/Kconfig"
>  
> +source "kernel/Kconfig.freezer"
> +
>  source "arch/avr32/Kconfig.debug"
>  
>  source "security/Kconfig"
> Index: linux-2.6.21-rc7-mm2/kernel/power/Kconfig
> ===================================================================
> --- linux-2.6.21-rc7-mm2.orig/kernel/power/Kconfig	2007-04-27 21:41:05.000000000 +0200
> +++ linux-2.6.21-rc7-mm2/kernel/power/Kconfig	2007-04-27 21:42:52.000000000 +0200
> @@ -1,6 +1,7 @@
>  config PM
>  	bool "Power Management support"
>  	depends on !IA64_HP_SIM
> +	select FREEZER
>  	---help---
>  	  "Power Management" means that parts of your computer are shut
>  	  off or put into a power conserving "sleep" mode if they are not
> Index: linux-2.6.21-rc7-mm2/kernel/Kconfig.freezer
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ linux-2.6.21-rc7-mm2/kernel/Kconfig.freezer	2007-04-27 23:06:52.000000000 +0200
> @@ -0,0 +1,5 @@
> +# Tasks freezer configuration
> +
> +config FREEZER
> +	bool
> +	default n
> 
> 
> -
> 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/
-
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/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux