aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/freezer.h33
-rw-r--r--kernel/cgroup_freezer.c10
-rw-r--r--kernel/fork.c1
-rw-r--r--kernel/freezer.c62
-rw-r--r--kernel/power/process.c15
5 files changed, 72 insertions, 49 deletions
diff --git a/include/linux/freezer.h b/include/linux/freezer.h
index b2b4abc5a739..8e29f2b7ce11 100644
--- a/include/linux/freezer.h
+++ b/include/linux/freezer.h
@@ -5,8 +5,13 @@
5 5
6#include <linux/sched.h> 6#include <linux/sched.h>
7#include <linux/wait.h> 7#include <linux/wait.h>
8#include <linux/atomic.h>
8 9
9#ifdef CONFIG_FREEZER 10#ifdef CONFIG_FREEZER
11extern atomic_t system_freezing_cnt; /* nr of freezing conds in effect */
12extern bool pm_freezing; /* PM freezing in effect */
13extern bool pm_nosig_freezing; /* PM nosig freezing in effect */
14
10/* 15/*
11 * Check if a process has been frozen 16 * Check if a process has been frozen
12 */ 17 */
@@ -15,28 +20,16 @@ static inline int frozen(struct task_struct *p)
15 return p->flags & PF_FROZEN; 20 return p->flags & PF_FROZEN;
16} 21}
17 22
18/* 23extern bool freezing_slow_path(struct task_struct *p);
19 * Check if there is a request to freeze a process
20 */
21static inline int freezing(struct task_struct *p)
22{
23 return test_tsk_thread_flag(p, TIF_FREEZE);
24}
25 24
26/* 25/*
27 * Request that a process be frozen 26 * Check if there is a request to freeze a process
28 */
29static inline void set_freeze_flag(struct task_struct *p)
30{
31 set_tsk_thread_flag(p, TIF_FREEZE);
32}
33
34/*
35 * Sometimes we may need to cancel the previous 'freeze' request
36 */ 27 */
37static inline void clear_freeze_flag(struct task_struct *p) 28static inline bool freezing(struct task_struct *p)
38{ 29{
39 clear_tsk_thread_flag(p, TIF_FREEZE); 30 if (likely(!atomic_read(&system_freezing_cnt)))
31 return false;
32 return freezing_slow_path(p);
40} 33}
41 34
42static inline bool should_send_signal(struct task_struct *p) 35static inline bool should_send_signal(struct task_struct *p)
@@ -174,9 +167,7 @@ static inline void set_freezable_with_signal(void)
174}) 167})
175#else /* !CONFIG_FREEZER */ 168#else /* !CONFIG_FREEZER */
176static inline int frozen(struct task_struct *p) { return 0; } 169static inline int frozen(struct task_struct *p) { return 0; }
177static inline int freezing(struct task_struct *p) { return 0; } 170static inline bool freezing(struct task_struct *p) { return false; }
178static inline void set_freeze_flag(struct task_struct *p) {}
179static inline void clear_freeze_flag(struct task_struct *p) {}
180 171
181static inline bool __refrigerator(bool check_kthr_stop) { return false; } 172static inline bool __refrigerator(bool check_kthr_stop) { return false; }
182static inline int freeze_processes(void) { return -ENOSYS; } 173static inline int freeze_processes(void) { return -ENOSYS; }
diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c
index e6a1b8d1b8bc..2327ad11725f 100644
--- a/kernel/cgroup_freezer.c
+++ b/kernel/cgroup_freezer.c
@@ -145,7 +145,11 @@ static struct cgroup_subsys_state *freezer_create(struct cgroup_subsys *ss,
145static void freezer_destroy(struct cgroup_subsys *ss, 145static void freezer_destroy(struct cgroup_subsys *ss,
146 struct cgroup *cgroup) 146 struct cgroup *cgroup)
147{ 147{
148 kfree(cgroup_freezer(cgroup)); 148 struct freezer *freezer = cgroup_freezer(cgroup);
149
150 if (freezer->state != CGROUP_THAWED)
151 atomic_dec(&system_freezing_cnt);
152 kfree(freezer);
149} 153}
150 154
151/* 155/*
@@ -307,10 +311,14 @@ static int freezer_change_state(struct cgroup *cgroup,
307 311
308 switch (goal_state) { 312 switch (goal_state) {
309 case CGROUP_THAWED: 313 case CGROUP_THAWED:
314 if (freezer->state != CGROUP_THAWED)
315 atomic_dec(&system_freezing_cnt);
310 freezer->state = CGROUP_THAWED; 316 freezer->state = CGROUP_THAWED;
311 unfreeze_cgroup(cgroup, freezer); 317 unfreeze_cgroup(cgroup, freezer);
312 break; 318 break;
313 case CGROUP_FROZEN: 319 case CGROUP_FROZEN:
320 if (freezer->state == CGROUP_THAWED)
321 atomic_inc(&system_freezing_cnt);
314 freezer->state = CGROUP_FREEZING; 322 freezer->state = CGROUP_FREEZING;
315 retval = try_to_freeze_cgroup(cgroup, freezer); 323 retval = try_to_freeze_cgroup(cgroup, freezer);
316 break; 324 break;
diff --git a/kernel/fork.c b/kernel/fork.c
index ba0d17261329..d53316e88d9d 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -997,7 +997,6 @@ static void copy_flags(unsigned long clone_flags, struct task_struct *p)
997 new_flags |= PF_FORKNOEXEC; 997 new_flags |= PF_FORKNOEXEC;
998 new_flags |= PF_STARTING; 998 new_flags |= PF_STARTING;
999 p->flags = new_flags; 999 p->flags = new_flags;
1000 clear_freeze_flag(p);
1001} 1000}
1002 1001
1003SYSCALL_DEFINE1(set_tid_address, int __user *, tidptr) 1002SYSCALL_DEFINE1(set_tid_address, int __user *, tidptr)
diff --git a/kernel/freezer.c b/kernel/freezer.c
index 11e32d419dec..f53cd5aa5b2e 100644
--- a/kernel/freezer.c
+++ b/kernel/freezer.c
@@ -11,9 +11,41 @@
11#include <linux/freezer.h> 11#include <linux/freezer.h>
12#include <linux/kthread.h> 12#include <linux/kthread.h>
13 13
14/* total number of freezing conditions in effect */
15atomic_t system_freezing_cnt = ATOMIC_INIT(0);
16EXPORT_SYMBOL(system_freezing_cnt);
17
18/* indicate whether PM freezing is in effect, protected by pm_mutex */
19bool pm_freezing;
20bool pm_nosig_freezing;
21
14/* protects freezing and frozen transitions */ 22/* protects freezing and frozen transitions */
15static DEFINE_SPINLOCK(freezer_lock); 23static DEFINE_SPINLOCK(freezer_lock);
16 24
25/**
26 * freezing_slow_path - slow path for testing whether a task needs to be frozen
27 * @p: task to be tested
28 *
29 * This function is called by freezing() if system_freezing_cnt isn't zero
30 * and tests whether @p needs to enter and stay in frozen state. Can be
31 * called under any context. The freezers are responsible for ensuring the
32 * target tasks see the updated state.
33 */
34bool freezing_slow_path(struct task_struct *p)
35{
36 if (p->flags & PF_NOFREEZE)
37 return false;
38
39 if (pm_nosig_freezing || cgroup_freezing(p))
40 return true;
41
42 if (pm_freezing && !(p->flags & PF_FREEZER_NOSIG))
43 return true;
44
45 return false;
46}
47EXPORT_SYMBOL(freezing_slow_path);
48
17/* Refrigerator is place where frozen processes are stored :-). */ 49/* Refrigerator is place where frozen processes are stored :-). */
18bool __refrigerator(bool check_kthr_stop) 50bool __refrigerator(bool check_kthr_stop)
19{ 51{
@@ -23,17 +55,11 @@ bool __refrigerator(bool check_kthr_stop)
23 long save; 55 long save;
24 56
25 /* 57 /*
26 * Enter FROZEN. If NOFREEZE, schedule immediate thawing by 58 * No point in checking freezing() again - the caller already did.
27 * clearing freezing. 59 * Proceed to enter FROZEN.
28 */ 60 */
29 spin_lock_irq(&freezer_lock); 61 spin_lock_irq(&freezer_lock);
30repeat: 62repeat:
31 if (!freezing(current)) {
32 spin_unlock_irq(&freezer_lock);
33 return was_frozen;
34 }
35 if (current->flags & PF_NOFREEZE)
36 clear_freeze_flag(current);
37 current->flags |= PF_FROZEN; 63 current->flags |= PF_FROZEN;
38 spin_unlock_irq(&freezer_lock); 64 spin_unlock_irq(&freezer_lock);
39 65
@@ -99,18 +125,12 @@ static void fake_signal_wake_up(struct task_struct *p)
99bool freeze_task(struct task_struct *p, bool sig_only) 125bool freeze_task(struct task_struct *p, bool sig_only)
100{ 126{
101 unsigned long flags; 127 unsigned long flags;
102 bool ret = false;
103 128
104 spin_lock_irqsave(&freezer_lock, flags); 129 spin_lock_irqsave(&freezer_lock, flags);
105 130 if (!freezing(p) || frozen(p)) {
106 if ((p->flags & PF_NOFREEZE) || 131 spin_unlock_irqrestore(&freezer_lock, flags);
107 (sig_only && !should_send_signal(p))) 132 return false;
108 goto out_unlock; 133 }
109
110 if (frozen(p))
111 goto out_unlock;
112
113 set_freeze_flag(p);
114 134
115 if (should_send_signal(p)) { 135 if (should_send_signal(p)) {
116 fake_signal_wake_up(p); 136 fake_signal_wake_up(p);
@@ -123,10 +143,9 @@ bool freeze_task(struct task_struct *p, bool sig_only)
123 } else { 143 } else {
124 wake_up_state(p, TASK_INTERRUPTIBLE); 144 wake_up_state(p, TASK_INTERRUPTIBLE);
125 } 145 }
126 ret = true; 146
127out_unlock:
128 spin_unlock_irqrestore(&freezer_lock, flags); 147 spin_unlock_irqrestore(&freezer_lock, flags);
129 return ret; 148 return true;
130} 149}
131 150
132void __thaw_task(struct task_struct *p) 151void __thaw_task(struct task_struct *p)
@@ -143,7 +162,6 @@ void __thaw_task(struct task_struct *p)
143 * avoid leaving dangling TIF_SIGPENDING behind. 162 * avoid leaving dangling TIF_SIGPENDING behind.
144 */ 163 */
145 spin_lock_irqsave(&freezer_lock, flags); 164 spin_lock_irqsave(&freezer_lock, flags);
146 clear_freeze_flag(p);
147 if (frozen(p)) { 165 if (frozen(p)) {
148 wake_up_process(p); 166 wake_up_process(p);
149 } else { 167 } else {
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 9f6f5c755cfa..0beb51e1dec9 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -101,7 +101,7 @@ static int try_to_freeze_tasks(bool sig_only)
101 read_lock(&tasklist_lock); 101 read_lock(&tasklist_lock);
102 do_each_thread(g, p) { 102 do_each_thread(g, p) {
103 if (!wakeup && !freezer_should_skip(p) && 103 if (!wakeup && !freezer_should_skip(p) &&
104 freezing(p) && !frozen(p)) 104 p != current && freezing(p) && !frozen(p))
105 sched_show_task(p); 105 sched_show_task(p);
106 } while_each_thread(g, p); 106 } while_each_thread(g, p);
107 read_unlock(&tasklist_lock); 107 read_unlock(&tasklist_lock);
@@ -122,7 +122,11 @@ int freeze_processes(void)
122{ 122{
123 int error; 123 int error;
124 124
125 if (!pm_freezing)
126 atomic_inc(&system_freezing_cnt);
127
125 printk("Freezing user space processes ... "); 128 printk("Freezing user space processes ... ");
129 pm_freezing = true;
126 error = try_to_freeze_tasks(true); 130 error = try_to_freeze_tasks(true);
127 if (!error) { 131 if (!error) {
128 printk("done."); 132 printk("done.");
@@ -146,6 +150,7 @@ int freeze_kernel_threads(void)
146 int error; 150 int error;
147 151
148 printk("Freezing remaining freezable tasks ... "); 152 printk("Freezing remaining freezable tasks ... ");
153 pm_nosig_freezing = true;
149 error = try_to_freeze_tasks(false); 154 error = try_to_freeze_tasks(false);
150 if (!error) 155 if (!error)
151 printk("done."); 156 printk("done.");
@@ -162,6 +167,11 @@ void thaw_processes(void)
162{ 167{
163 struct task_struct *g, *p; 168 struct task_struct *g, *p;
164 169
170 if (pm_freezing)
171 atomic_dec(&system_freezing_cnt);
172 pm_freezing = false;
173 pm_nosig_freezing = false;
174
165 oom_killer_enable(); 175 oom_killer_enable();
166 176
167 printk("Restarting tasks ... "); 177 printk("Restarting tasks ... ");
@@ -170,9 +180,6 @@ void thaw_processes(void)
170 180
171 read_lock(&tasklist_lock); 181 read_lock(&tasklist_lock);
172 do_each_thread(g, p) { 182 do_each_thread(g, p) {
173 if (cgroup_freezing(p))
174 continue;
175
176 __thaw_task(p); 183 __thaw_task(p);
177 } while_each_thread(g, p); 184 } while_each_thread(g, p);
178 read_unlock(&tasklist_lock); 185 read_unlock(&tasklist_lock);