Commit 27925dfb authored by Patrick Mochel's avatar Patrick Mochel

[power] Move process suspension functions to their own file.

- Now in drivers/power/process.c
- Make those functions only dependent on CONFIG_PM, not CONFIG_SOFTWARE_SUSPEND.
parent e239395d
obj-y := process.o
obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
/*
* 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);
......@@ -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);
......@@ -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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment