diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 23ff1884052e5d6236306f7ffc6322a3982e7586..01e81e5f5bd7a17fc059177907388078eb17b8b1 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -1 +1,2 @@ +obj-y := process.o obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o diff --git a/drivers/power/process.c b/drivers/power/process.c new file mode 100644 index 0000000000000000000000000000000000000000..bd80a35f5e6abb396e4145c206514dd6b4ceda78 --- /dev/null +++ b/drivers/power/process.c @@ -0,0 +1,120 @@ +/* + * drivers/power/process.c - Functions for starting/stopping processes on + * suspend transitions. + * + * Originally from swsusp. + */ + + +#undef DEBUG + +#include <linux/interrupt.h> +#include <linux/suspend.h> +#include <linux/module.h> + +#ifdef DEBUG_SLOW +#define MDELAY(a) mdelay(a) +#else +#define MDELAY(a) +#endif + +/* + * Timeout for stopping processes + */ +#define TIMEOUT (6 * HZ) + +#define INTERESTING(p) \ + /* We don't want to touch kernel_threads..*/ \ + if (p->flags & PF_IOTHREAD) \ + continue; \ + if (p == current) \ + continue; \ + if (p->state == TASK_ZOMBIE) \ + continue; + +/* Refrigerator is place where frozen processes are stored :-). */ +void refrigerator(unsigned long flag) +{ + /* You need correct to work with real-time processes. + OTOH, this way one process may see (via /proc/) some other + process in stopped state (and thereby discovered we were + suspended. We probably do not care. + */ + long save; + save = current->state; + current->state = TASK_STOPPED; + pr_debug("%s entered refrigerator\n", current->comm); + printk("="); + current->flags &= ~PF_FREEZE; + if (flag) + flush_signals(current); /* We have signaled a kernel thread, which isn't normal behaviour + and that may lead to 100%CPU sucking because those threads + just don't manage signals. */ + current->flags |= PF_FROZEN; + while (current->flags & PF_FROZEN) + schedule(); + pr_debug("%s left refrigerator\n", current->comm); + current->state = save; +} + +/* 0 = success, else # of processes that we failed to stop */ +int freeze_processes(void) +{ + int todo; + unsigned long start_time; + struct task_struct *g, *p; + + printk( "Stopping tasks: " ); + start_time = jiffies; + do { + todo = 0; + read_lock(&tasklist_lock); + do_each_thread(g, p) { + unsigned long flags; + INTERESTING(p); + if (p->flags & PF_FROZEN) + continue; + + /* FIXME: smp problem here: we may not access other process' flags + without locking */ + p->flags |= PF_FREEZE; + spin_lock_irqsave(&p->sighand->siglock, flags); + signal_wake_up(p, 0); + spin_unlock_irqrestore(&p->sighand->siglock, flags); + todo++; + } while_each_thread(g, p); + read_unlock(&tasklist_lock); + yield(); /* Yield is okay here */ + if (time_after(jiffies, start_time + TIMEOUT)) { + printk( "\n" ); + printk(KERN_ERR " stopping tasks failed (%d tasks remaining)\n", todo ); + return todo; + } + } while(todo); + + printk( "|\n" ); + BUG_ON(in_atomic()); + return 0; +} + +void thaw_processes(void) +{ + struct task_struct *g, *p; + + printk( "Restarting tasks..." ); + read_lock(&tasklist_lock); + do_each_thread(g, p) { + INTERESTING(p); + + if (p->flags & PF_FROZEN) p->flags &= ~PF_FROZEN; + else + printk(KERN_INFO " Strange, %s not stopped\n", p->comm ); + wake_up_process(p); + } while_each_thread(g, p); + + read_unlock(&tasklist_lock); + printk( " done\n" ); + MDELAY(500); +} + +EXPORT_SYMBOL(refrigerator); diff --git a/drivers/power/swsusp.c b/drivers/power/swsusp.c index d68eae23c468dea0471566c97bde6ca5cd51b5dd..00ce2720b25dcee437861a167bc120ab8dfbc1b9 100644 --- a/drivers/power/swsusp.c +++ b/drivers/power/swsusp.c @@ -45,7 +45,6 @@ #include <linux/reboot.h> #include <linux/vt_kern.h> #include <linux/bitops.h> -#include <linux/interrupt.h> #include <linux/kbd_kern.h> #include <linux/keyboard.h> #include <linux/spinlock.h> @@ -77,7 +76,6 @@ unsigned char software_suspend_enabled = 0; #undef SUSPEND_CONSOLE #endif -#define TIMEOUT (6 * HZ) /* Timeout for stopping processes */ #define __ADDRESS(x) ((unsigned long) phys_to_virt(x)) #define ADDRESS(x) __ADDRESS((x) << PAGE_SHIFT) #define ADDRESS2(x) __ADDRESS(__pa(x)) /* Needed for x86-64 where some pages are in memory twice */ @@ -159,104 +157,6 @@ static const char name_resume[] = "Resume Machine: "; #define MDELAY(a) #endif -/* - * Refrigerator and related stuff - */ - -#define INTERESTING(p) \ - /* We don't want to touch kernel_threads..*/ \ - if (p->flags & PF_IOTHREAD) \ - continue; \ - if (p == current) \ - continue; \ - if (p->state == TASK_ZOMBIE) \ - continue; - -/* Refrigerator is place where frozen processes are stored :-). */ -void refrigerator(unsigned long flag) -{ - /* You need correct to work with real-time processes. - OTOH, this way one process may see (via /proc/) some other - process in stopped state (and thereby discovered we were - suspended. We probably do not care. - */ - long save; - save = current->state; - current->state = TASK_STOPPED; - PRINTK("%s entered refrigerator\n", current->comm); - printk("="); - current->flags &= ~PF_FREEZE; - if (flag) - flush_signals(current); /* We have signaled a kernel thread, which isn't normal behaviour - and that may lead to 100%CPU sucking because those threads - just don't manage signals. */ - current->flags |= PF_FROZEN; - while (current->flags & PF_FROZEN) - schedule(); - PRINTK("%s left refrigerator\n", current->comm); - current->state = save; -} - -/* 0 = success, else # of processes that we failed to stop */ -int freeze_processes(void) -{ - int todo; - unsigned long start_time; - struct task_struct *g, *p; - - printk( "Stopping tasks: " ); - start_time = jiffies; - do { - todo = 0; - read_lock(&tasklist_lock); - do_each_thread(g, p) { - unsigned long flags; - INTERESTING(p); - if (p->flags & PF_FROZEN) - continue; - - /* FIXME: smp problem here: we may not access other process' flags - without locking */ - p->flags |= PF_FREEZE; - spin_lock_irqsave(&p->sighand->siglock, flags); - signal_wake_up(p, 0); - spin_unlock_irqrestore(&p->sighand->siglock, flags); - todo++; - } while_each_thread(g, p); - read_unlock(&tasklist_lock); - yield(); /* Yield is okay here */ - if (time_after(jiffies, start_time + TIMEOUT)) { - printk( "\n" ); - printk(KERN_ERR " stopping tasks failed (%d tasks remaining)\n", todo ); - return todo; - } - } while(todo); - - printk( "|\n" ); - BUG_ON(in_atomic()); - return 0; -} - -void thaw_processes(void) -{ - struct task_struct *g, *p; - - printk( "Restarting tasks..." ); - read_lock(&tasklist_lock); - do_each_thread(g, p) { - INTERESTING(p); - - if (p->flags & PF_FROZEN) p->flags &= ~PF_FROZEN; - else - printk(KERN_INFO " Strange, %s not stopped\n", p->comm ); - wake_up_process(p); - } while_each_thread(g, p); - - read_unlock(&tasklist_lock); - printk( " done\n" ); - MDELAY(500); -} - /* * Saving part... */ @@ -1278,4 +1178,3 @@ __setup("resume=", resume_setup); EXPORT_SYMBOL(software_suspend); EXPORT_SYMBOL(software_suspend_enabled); -EXPORT_SYMBOL(refrigerator); diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 901d2ac58ba59599c802148f09fff1bf2f68c26e..864067f87aa8fe158b71b61a07d42e53d204f4f6 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -55,10 +55,6 @@ extern void software_resume(void); extern int register_suspend_notifier(struct notifier_block *); extern int unregister_suspend_notifier(struct notifier_block *); -extern void refrigerator(unsigned long); - -extern int freeze_processes(void); -extern void thaw_processes(void); extern unsigned int nr_copy_pages __nosavedata; extern suspend_pagedir_t *pagedir_nosave __nosavedata; @@ -75,16 +71,33 @@ extern void do_magic_suspend_2(void); extern void do_suspend_lowlevel(int resume); extern void do_suspend_lowlevel_s4bios(int resume); -#else +#else /* CONFIG_SOFTWARE_SUSPEND */ static inline void software_suspend(void) { } #define software_resume() do { } while(0) #define register_suspend_notifier(a) do { } while(0) #define unregister_suspend_notifier(a) do { } while(0) -#define refrigerator(a) do { BUG(); } while(0) -#define freeze_processes() do { panic("You need CONFIG_SOFTWARE_SUSPEND to do sleeps."); } while(0) -#define thaw_processes() do { } while(0) -#endif +#endif /* CONFIG_SOFTWARE_SUSPEND */ + + +#ifdef CONFIG_PM +extern void refrigerator(unsigned long); +extern int freeze_processes(void); +extern void thaw_processes(void); +#else +static inline void refrigerator(unsigned long) +{ + +} +static inline int freeze_processes(void) +{ + return 0; +} +static inline void thaw_processes(void) +{ + +} +#endif /* CONFIG_PM */ #endif /* _LINUX_SWSUSP_H */