aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/freezer.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-11-23 12:28:17 -0500
committerTejun Heo <tj@kernel.org>2011-11-23 12:28:17 -0500
commit34b087e48367c252e343c2f8de65676a78af1e4a (patch)
treefbe94bad0a3073c6f4231752fba99c6bc8702277 /kernel/freezer.c
parentadfa543e7314b36ac55a40019977de6e47946dd7 (diff)
freezer: kill unused set_freezable_with_signal()
There's no in-kernel user of set_freezable_with_signal() left. Mixing TIF_SIGPENDING with kernel threads can lead to nasty corner cases as kernel threads never travel signal delivery path on their own. e.g. the current implementation is buggy in the cancelation path of __thaw_task(). It calls recalc_sigpending_and_wake() in an attempt to clear TIF_SIGPENDING but the function never clears it regardless of sigpending state. This means that signallable freezable kthreads may continue executing with !freezing() && stuck TIF_SIGPENDING, which can be troublesome. This patch removes set_freezable_with_signal() along with PF_FREEZER_NOSIG and recalc_sigpending*() calls in freezer. User tasks get TIF_SIGPENDING, kernel tasks get woken up and the spurious sigpending is dealt with in the usual signal delivery path. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Oleg Nesterov <oleg@redhat.com>
Diffstat (limited to 'kernel/freezer.c')
-rw-r--r--kernel/freezer.c27
1 files changed, 6 insertions, 21 deletions
diff --git a/kernel/freezer.c b/kernel/freezer.c
index 2589a61de44c..9815b8d1eed5 100644
--- a/kernel/freezer.c
+++ b/kernel/freezer.c
@@ -39,7 +39,7 @@ bool freezing_slow_path(struct task_struct *p)
39 if (pm_nosig_freezing || cgroup_freezing(p)) 39 if (pm_nosig_freezing || cgroup_freezing(p))
40 return true; 40 return true;
41 41
42 if (pm_freezing && !(p->flags & PF_FREEZER_NOSIG)) 42 if (pm_freezing && !(p->flags & PF_KTHREAD))
43 return true; 43 return true;
44 44
45 return false; 45 return false;
@@ -72,10 +72,6 @@ bool __refrigerator(bool check_kthr_stop)
72 schedule(); 72 schedule();
73 } 73 }
74 74
75 spin_lock_irq(&current->sighand->siglock);
76 recalc_sigpending(); /* We sent fake signal, clean it up */
77 spin_unlock_irq(&current->sighand->siglock);
78
79 pr_debug("%s left refrigerator\n", current->comm); 75 pr_debug("%s left refrigerator\n", current->comm);
80 76
81 /* 77 /*
@@ -120,7 +116,7 @@ bool freeze_task(struct task_struct *p)
120 return false; 116 return false;
121 } 117 }
122 118
123 if (!(p->flags & PF_FREEZER_NOSIG)) { 119 if (!(p->flags & PF_KTHREAD)) {
124 fake_signal_wake_up(p); 120 fake_signal_wake_up(p);
125 /* 121 /*
126 * fake_signal_wake_up() goes through p's scheduler 122 * fake_signal_wake_up() goes through p's scheduler
@@ -145,28 +141,19 @@ void __thaw_task(struct task_struct *p)
145 * be visible to @p as waking up implies wmb. Waking up inside 141 * be visible to @p as waking up implies wmb. Waking up inside
146 * freezer_lock also prevents wakeups from leaking outside 142 * freezer_lock also prevents wakeups from leaking outside
147 * refrigerator. 143 * refrigerator.
148 *
149 * If !FROZEN, @p hasn't reached refrigerator, recalc sigpending to
150 * avoid leaving dangling TIF_SIGPENDING behind.
151 */ 144 */
152 spin_lock_irqsave(&freezer_lock, flags); 145 spin_lock_irqsave(&freezer_lock, flags);
153 if (frozen(p)) { 146 if (frozen(p))
154 wake_up_process(p); 147 wake_up_process(p);
155 } else {
156 spin_lock(&p->sighand->siglock);
157 recalc_sigpending_and_wake(p);
158 spin_unlock(&p->sighand->siglock);
159 }
160 spin_unlock_irqrestore(&freezer_lock, flags); 148 spin_unlock_irqrestore(&freezer_lock, flags);
161} 149}
162 150
163/** 151/**
164 * __set_freezable - make %current freezable 152 * set_freezable - make %current freezable
165 * @with_signal: do we want %TIF_SIGPENDING for notification too?
166 * 153 *
167 * Mark %current freezable and enter refrigerator if necessary. 154 * Mark %current freezable and enter refrigerator if necessary.
168 */ 155 */
169bool __set_freezable(bool with_signal) 156bool set_freezable(void)
170{ 157{
171 might_sleep(); 158 might_sleep();
172 159
@@ -177,10 +164,8 @@ bool __set_freezable(bool with_signal)
177 */ 164 */
178 spin_lock_irq(&freezer_lock); 165 spin_lock_irq(&freezer_lock);
179 current->flags &= ~PF_NOFREEZE; 166 current->flags &= ~PF_NOFREEZE;
180 if (with_signal)
181 current->flags &= ~PF_FREEZER_NOSIG;
182 spin_unlock_irq(&freezer_lock); 167 spin_unlock_irq(&freezer_lock);
183 168
184 return try_to_freeze(); 169 return try_to_freeze();
185} 170}
186EXPORT_SYMBOL(__set_freezable); 171EXPORT_SYMBOL(set_freezable);