diff options
author | Matt Helsley <matthltc@us.ibm.com> | 2008-10-18 23:27:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-20 11:52:33 -0400 |
commit | 8174f1503f4bf7e9a14b3fbbfdb30c6be6e29f77 (patch) | |
tree | a8df1ebd62255dd231452b3f72782604e8919991 /kernel/power | |
parent | 83224b08372be48d5fcefedc4886457da29130c8 (diff) |
container freezer: make refrigerator always available
Now that the TIF_FREEZE flag is available in all architectures, extract
the refrigerator() and freeze_task() from kernel/power/process.c and make
it available to all.
The refrigerator() can now be used in a control group subsystem
implementing a control group freezer.
Signed-off-by: Cedric Le Goater <clg@fr.ibm.com>
Signed-off-by: Matt Helsley <matthltc@us.ibm.com>
Acked-by: Serge E. Hallyn <serue@us.ibm.com>
Tested-by: Matt Helsley <matthltc@us.ibm.com>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/power')
-rw-r--r-- | kernel/power/Kconfig | 3 | ||||
-rw-r--r-- | kernel/power/process.c | 116 |
2 files changed, 3 insertions, 116 deletions
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index dcd165f92a88..ebdd7f55273d 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig | |||
@@ -85,6 +85,9 @@ config PM_SLEEP | |||
85 | depends on SUSPEND || HIBERNATION || XEN_SAVE_RESTORE | 85 | depends on SUSPEND || HIBERNATION || XEN_SAVE_RESTORE |
86 | default y | 86 | default y |
87 | 87 | ||
88 | config FREEZER | ||
89 | def_bool PM_SLEEP | ||
90 | |||
88 | config SUSPEND | 91 | config SUSPEND |
89 | bool "Suspend to RAM and standby" | 92 | bool "Suspend to RAM and standby" |
90 | depends on PM && ARCH_SUSPEND_POSSIBLE | 93 | depends on PM && ARCH_SUSPEND_POSSIBLE |
diff --git a/kernel/power/process.c b/kernel/power/process.c index 278946aecaf0..444cea80fde8 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c | |||
@@ -28,121 +28,6 @@ static inline int freezeable(struct task_struct * p) | |||
28 | return 1; | 28 | return 1; |
29 | } | 29 | } |
30 | 30 | ||
31 | /* | ||
32 | * freezing is complete, mark current process as frozen | ||
33 | */ | ||
34 | static inline void frozen_process(void) | ||
35 | { | ||
36 | if (!unlikely(current->flags & PF_NOFREEZE)) { | ||
37 | current->flags |= PF_FROZEN; | ||
38 | wmb(); | ||
39 | } | ||
40 | clear_freeze_flag(current); | ||
41 | } | ||
42 | |||
43 | /* Refrigerator is place where frozen processes are stored :-). */ | ||
44 | void refrigerator(void) | ||
45 | { | ||
46 | /* Hmm, should we be allowed to suspend when there are realtime | ||
47 | processes around? */ | ||
48 | long save; | ||
49 | |||
50 | task_lock(current); | ||
51 | if (freezing(current)) { | ||
52 | frozen_process(); | ||
53 | task_unlock(current); | ||
54 | } else { | ||
55 | task_unlock(current); | ||
56 | return; | ||
57 | } | ||
58 | save = current->state; | ||
59 | pr_debug("%s entered refrigerator\n", current->comm); | ||
60 | |||
61 | spin_lock_irq(¤t->sighand->siglock); | ||
62 | recalc_sigpending(); /* We sent fake signal, clean it up */ | ||
63 | spin_unlock_irq(¤t->sighand->siglock); | ||
64 | |||
65 | for (;;) { | ||
66 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
67 | if (!frozen(current)) | ||
68 | break; | ||
69 | schedule(); | ||
70 | } | ||
71 | pr_debug("%s left refrigerator\n", current->comm); | ||
72 | __set_current_state(save); | ||
73 | } | ||
74 | |||
75 | static void fake_signal_wake_up(struct task_struct *p) | ||
76 | { | ||
77 | unsigned long flags; | ||
78 | |||
79 | spin_lock_irqsave(&p->sighand->siglock, flags); | ||
80 | signal_wake_up(p, 0); | ||
81 | spin_unlock_irqrestore(&p->sighand->siglock, flags); | ||
82 | } | ||
83 | |||
84 | static inline bool should_send_signal(struct task_struct *p) | ||
85 | { | ||
86 | return !(p->flags & PF_FREEZER_NOSIG); | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * freeze_task - send a freeze request to given task | ||
91 | * @p: task to send the request to | ||
92 | * @sig_only: if set, the request will only be sent if the task has the | ||
93 | * PF_FREEZER_NOSIG flag unset | ||
94 | * Return value: 'false', if @sig_only is set and the task has | ||
95 | * PF_FREEZER_NOSIG set or the task is frozen, 'true', otherwise | ||
96 | * | ||
97 | * The freeze request is sent by setting the tasks's TIF_FREEZE flag and | ||
98 | * either sending a fake signal to it or waking it up, depending on whether | ||
99 | * or not it has PF_FREEZER_NOSIG set. If @sig_only is set and the task | ||
100 | * has PF_FREEZER_NOSIG set (ie. it is a typical kernel thread), its | ||
101 | * TIF_FREEZE flag will not be set. | ||
102 | */ | ||
103 | static bool freeze_task(struct task_struct *p, bool sig_only) | ||
104 | { | ||
105 | /* | ||
106 | * We first check if the task is freezing and next if it has already | ||
107 | * been frozen to avoid the race with frozen_process() which first marks | ||
108 | * the task as frozen and next clears its TIF_FREEZE. | ||
109 | */ | ||
110 | if (!freezing(p)) { | ||
111 | rmb(); | ||
112 | if (frozen(p)) | ||
113 | return false; | ||
114 | |||
115 | if (!sig_only || should_send_signal(p)) | ||
116 | set_freeze_flag(p); | ||
117 | else | ||
118 | return false; | ||
119 | } | ||
120 | |||
121 | if (should_send_signal(p)) { | ||
122 | if (!signal_pending(p)) | ||
123 | fake_signal_wake_up(p); | ||
124 | } else if (sig_only) { | ||
125 | return false; | ||
126 | } else { | ||
127 | wake_up_state(p, TASK_INTERRUPTIBLE); | ||
128 | } | ||
129 | |||
130 | return true; | ||
131 | } | ||
132 | |||
133 | static void cancel_freezing(struct task_struct *p) | ||
134 | { | ||
135 | unsigned long flags; | ||
136 | |||
137 | if (freezing(p)) { | ||
138 | pr_debug(" clean up: %s\n", p->comm); | ||
139 | clear_freeze_flag(p); | ||
140 | spin_lock_irqsave(&p->sighand->siglock, flags); | ||
141 | recalc_sigpending_and_wake(p); | ||
142 | spin_unlock_irqrestore(&p->sighand->siglock, flags); | ||
143 | } | ||
144 | } | ||
145 | |||
146 | static int try_to_freeze_tasks(bool sig_only) | 31 | static int try_to_freeze_tasks(bool sig_only) |
147 | { | 32 | { |
148 | struct task_struct *g, *p; | 33 | struct task_struct *g, *p; |
@@ -264,4 +149,3 @@ void thaw_processes(void) | |||
264 | printk("done.\n"); | 149 | printk("done.\n"); |
265 | } | 150 | } |
266 | 151 | ||
267 | EXPORT_SYMBOL(refrigerator); | ||