diff options
-rw-r--r-- | kernel/power/process.c | 29 | ||||
-rw-r--r-- | kernel/signal.c | 16 |
2 files changed, 26 insertions, 19 deletions
diff --git a/kernel/power/process.c b/kernel/power/process.c index 7c2118f9597f..f1d0b345c9ba 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c | |||
@@ -75,22 +75,15 @@ void refrigerator(void) | |||
75 | __set_current_state(save); | 75 | __set_current_state(save); |
76 | } | 76 | } |
77 | 77 | ||
78 | static void fake_signal_wake_up(struct task_struct *p, int resume) | 78 | static void fake_signal_wake_up(struct task_struct *p) |
79 | { | 79 | { |
80 | unsigned long flags; | 80 | unsigned long flags; |
81 | 81 | ||
82 | spin_lock_irqsave(&p->sighand->siglock, flags); | 82 | spin_lock_irqsave(&p->sighand->siglock, flags); |
83 | signal_wake_up(p, resume); | 83 | signal_wake_up(p, 0); |
84 | spin_unlock_irqrestore(&p->sighand->siglock, flags); | 84 | spin_unlock_irqrestore(&p->sighand->siglock, flags); |
85 | } | 85 | } |
86 | 86 | ||
87 | static void send_fake_signal(struct task_struct *p) | ||
88 | { | ||
89 | if (task_is_stopped(p)) | ||
90 | force_sig_specific(SIGSTOP, p); | ||
91 | fake_signal_wake_up(p, task_is_stopped(p)); | ||
92 | } | ||
93 | |||
94 | static int has_mm(struct task_struct *p) | 87 | static int has_mm(struct task_struct *p) |
95 | { | 88 | { |
96 | return (p->mm && !(p->flags & PF_BORROWED_MM)); | 89 | return (p->mm && !(p->flags & PF_BORROWED_MM)); |
@@ -121,7 +114,7 @@ static int freeze_task(struct task_struct *p, int with_mm_only) | |||
121 | if (freezing(p)) { | 114 | if (freezing(p)) { |
122 | if (has_mm(p)) { | 115 | if (has_mm(p)) { |
123 | if (!signal_pending(p)) | 116 | if (!signal_pending(p)) |
124 | fake_signal_wake_up(p, 0); | 117 | fake_signal_wake_up(p); |
125 | } else { | 118 | } else { |
126 | if (with_mm_only) | 119 | if (with_mm_only) |
127 | ret = 0; | 120 | ret = 0; |
@@ -135,7 +128,7 @@ static int freeze_task(struct task_struct *p, int with_mm_only) | |||
135 | } else { | 128 | } else { |
136 | if (has_mm(p)) { | 129 | if (has_mm(p)) { |
137 | set_freeze_flag(p); | 130 | set_freeze_flag(p); |
138 | send_fake_signal(p); | 131 | fake_signal_wake_up(p); |
139 | } else { | 132 | } else { |
140 | if (with_mm_only) { | 133 | if (with_mm_only) { |
141 | ret = 0; | 134 | ret = 0; |
@@ -182,15 +175,17 @@ static int try_to_freeze_tasks(int freeze_user_space) | |||
182 | if (frozen(p) || !freezeable(p)) | 175 | if (frozen(p) || !freezeable(p)) |
183 | continue; | 176 | continue; |
184 | 177 | ||
185 | if (task_is_traced(p) && frozen(p->parent)) { | ||
186 | cancel_freezing(p); | ||
187 | continue; | ||
188 | } | ||
189 | |||
190 | if (!freeze_task(p, freeze_user_space)) | 178 | if (!freeze_task(p, freeze_user_space)) |
191 | continue; | 179 | continue; |
192 | 180 | ||
193 | if (!freezer_should_skip(p)) | 181 | /* |
182 | * Now that we've done set_freeze_flag, don't | ||
183 | * perturb a task in TASK_STOPPED or TASK_TRACED. | ||
184 | * It is "frozen enough". If the task does wake | ||
185 | * up, it will immediately call try_to_freeze. | ||
186 | */ | ||
187 | if (!task_is_stopped_or_traced(p) && | ||
188 | !freezer_should_skip(p)) | ||
194 | todo++; | 189 | todo++; |
195 | } while_each_thread(g, p); | 190 | } while_each_thread(g, p); |
196 | read_unlock(&tasklist_lock); | 191 | read_unlock(&tasklist_lock); |
diff --git a/kernel/signal.c b/kernel/signal.c index 84917fe507f7..6af1210092c3 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -1623,7 +1623,6 @@ static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info) | |||
1623 | /* Let the debugger run. */ | 1623 | /* Let the debugger run. */ |
1624 | __set_current_state(TASK_TRACED); | 1624 | __set_current_state(TASK_TRACED); |
1625 | spin_unlock_irq(¤t->sighand->siglock); | 1625 | spin_unlock_irq(¤t->sighand->siglock); |
1626 | try_to_freeze(); | ||
1627 | read_lock(&tasklist_lock); | 1626 | read_lock(&tasklist_lock); |
1628 | if (!unlikely(killed) && may_ptrace_stop()) { | 1627 | if (!unlikely(killed) && may_ptrace_stop()) { |
1629 | do_notify_parent_cldstop(current, CLD_TRAPPED); | 1628 | do_notify_parent_cldstop(current, CLD_TRAPPED); |
@@ -1641,6 +1640,13 @@ static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info) | |||
1641 | } | 1640 | } |
1642 | 1641 | ||
1643 | /* | 1642 | /* |
1643 | * While in TASK_TRACED, we were considered "frozen enough". | ||
1644 | * Now that we woke up, it's crucial if we're supposed to be | ||
1645 | * frozen that we freeze now before running anything substantial. | ||
1646 | */ | ||
1647 | try_to_freeze(); | ||
1648 | |||
1649 | /* | ||
1644 | * We are back. Now reacquire the siglock before touching | 1650 | * We are back. Now reacquire the siglock before touching |
1645 | * last_siginfo, so that we are sure to have synchronized with | 1651 | * last_siginfo, so that we are sure to have synchronized with |
1646 | * any signal-sending on another CPU that wants to examine it. | 1652 | * any signal-sending on another CPU that wants to examine it. |
@@ -1757,9 +1763,15 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, | |||
1757 | sigset_t *mask = ¤t->blocked; | 1763 | sigset_t *mask = ¤t->blocked; |
1758 | int signr = 0; | 1764 | int signr = 0; |
1759 | 1765 | ||
1766 | relock: | ||
1767 | /* | ||
1768 | * We'll jump back here after any time we were stopped in TASK_STOPPED. | ||
1769 | * While in TASK_STOPPED, we were considered "frozen enough". | ||
1770 | * Now that we woke up, it's crucial if we're supposed to be | ||
1771 | * frozen that we freeze now before running anything substantial. | ||
1772 | */ | ||
1760 | try_to_freeze(); | 1773 | try_to_freeze(); |
1761 | 1774 | ||
1762 | relock: | ||
1763 | spin_lock_irq(¤t->sighand->siglock); | 1775 | spin_lock_irq(¤t->sighand->siglock); |
1764 | for (;;) { | 1776 | for (;;) { |
1765 | struct k_sigaction *ka; | 1777 | struct k_sigaction *ka; |