aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sched.h6
-rw-r--r--kernel/signal.c62
2 files changed, 60 insertions, 8 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 4b601be3dace..85f51042c2b8 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1260,6 +1260,7 @@ struct task_struct {
1260 int exit_state; 1260 int exit_state;
1261 int exit_code, exit_signal; 1261 int exit_code, exit_signal;
1262 int pdeath_signal; /* The signal sent when the parent dies */ 1262 int pdeath_signal; /* The signal sent when the parent dies */
1263 unsigned int group_stop; /* GROUP_STOP_*, siglock protected */
1263 /* ??? */ 1264 /* ??? */
1264 unsigned int personality; 1265 unsigned int personality;
1265 unsigned did_exec:1; 1266 unsigned did_exec:1;
@@ -1771,6 +1772,11 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *
1771#define tsk_used_math(p) ((p)->flags & PF_USED_MATH) 1772#define tsk_used_math(p) ((p)->flags & PF_USED_MATH)
1772#define used_math() tsk_used_math(current) 1773#define used_math() tsk_used_math(current)
1773 1774
1775/*
1776 * task->group_stop flags
1777 */
1778#define GROUP_STOP_CONSUME (1 << 17) /* consume group stop count */
1779
1774#ifdef CONFIG_PREEMPT_RCU 1780#ifdef CONFIG_PREEMPT_RCU
1775 1781
1776#define RCU_READ_UNLOCK_BLOCKED (1 << 0) /* blocked while in RCU read-side. */ 1782#define RCU_READ_UNLOCK_BLOCKED (1 << 0) /* blocked while in RCU read-side. */
diff --git a/kernel/signal.c b/kernel/signal.c
index 95ac42dc3bcb..ecb20089eaff 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -223,6 +223,52 @@ static inline void print_dropped_signal(int sig)
223 current->comm, current->pid, sig); 223 current->comm, current->pid, sig);
224} 224}
225 225
226/**
227 * task_clear_group_stop_pending - clear pending group stop
228 * @task: target task
229 *
230 * Clear group stop states for @task.
231 *
232 * CONTEXT:
233 * Must be called with @task->sighand->siglock held.
234 */
235static void task_clear_group_stop_pending(struct task_struct *task)
236{
237 task->group_stop &= ~GROUP_STOP_CONSUME;
238}
239
240/**
241 * task_participate_group_stop - participate in a group stop
242 * @task: task participating in a group stop
243 *
244 * @task is participating in a group stop. Group stop states are cleared
245 * and the group stop count is consumed if %GROUP_STOP_CONSUME was set. If
246 * the consumption completes the group stop, the appropriate %SIGNAL_*
247 * flags are set.
248 *
249 * CONTEXT:
250 * Must be called with @task->sighand->siglock held.
251 */
252static bool task_participate_group_stop(struct task_struct *task)
253{
254 struct signal_struct *sig = task->signal;
255 bool consume = task->group_stop & GROUP_STOP_CONSUME;
256
257 task_clear_group_stop_pending(task);
258
259 if (!consume)
260 return false;
261
262 if (!WARN_ON_ONCE(sig->group_stop_count == 0))
263 sig->group_stop_count--;
264
265 if (!sig->group_stop_count) {
266 sig->flags = SIGNAL_STOP_STOPPED;
267 return true;
268 }
269 return false;
270}
271
226/* 272/*
227 * allocate a new signal queue record 273 * allocate a new signal queue record
228 * - this may be called without locks if and only if t == current, otherwise an 274 * - this may be called without locks if and only if t == current, otherwise an
@@ -1645,7 +1691,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
1645 * we must participate in the bookkeeping. 1691 * we must participate in the bookkeeping.
1646 */ 1692 */
1647 if (current->signal->group_stop_count > 0) 1693 if (current->signal->group_stop_count > 0)
1648 --current->signal->group_stop_count; 1694 task_participate_group_stop(current);
1649 1695
1650 current->last_siginfo = info; 1696 current->last_siginfo = info;
1651 current->exit_code = exit_code; 1697 current->exit_code = exit_code;
@@ -1730,6 +1776,7 @@ static int do_signal_stop(int signr)
1730 int notify = 0; 1776 int notify = 0;
1731 1777
1732 if (!sig->group_stop_count) { 1778 if (!sig->group_stop_count) {
1779 unsigned int gstop = GROUP_STOP_CONSUME;
1733 struct task_struct *t; 1780 struct task_struct *t;
1734 1781
1735 if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) || 1782 if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) ||
@@ -1741,6 +1788,7 @@ static int do_signal_stop(int signr)
1741 */ 1788 */
1742 sig->group_exit_code = signr; 1789 sig->group_exit_code = signr;
1743 1790
1791 current->group_stop = gstop;
1744 sig->group_stop_count = 1; 1792 sig->group_stop_count = 1;
1745 for (t = next_thread(current); t != current; t = next_thread(t)) 1793 for (t = next_thread(current); t != current; t = next_thread(t))
1746 /* 1794 /*
@@ -1750,19 +1798,19 @@ static int do_signal_stop(int signr)
1750 */ 1798 */
1751 if (!(t->flags & PF_EXITING) && 1799 if (!(t->flags & PF_EXITING) &&
1752 !task_is_stopped_or_traced(t)) { 1800 !task_is_stopped_or_traced(t)) {
1801 t->group_stop = gstop;
1753 sig->group_stop_count++; 1802 sig->group_stop_count++;
1754 signal_wake_up(t, 0); 1803 signal_wake_up(t, 0);
1755 } 1804 } else
1805 task_clear_group_stop_pending(t);
1756 } 1806 }
1757 /* 1807 /*
1758 * If there are no other threads in the group, or if there is 1808 * If there are no other threads in the group, or if there is
1759 * a group stop in progress and we are the last to stop, report 1809 * a group stop in progress and we are the last to stop, report
1760 * to the parent. When ptraced, every thread reports itself. 1810 * to the parent. When ptraced, every thread reports itself.
1761 */ 1811 */
1762 if (!--sig->group_stop_count) { 1812 if (task_participate_group_stop(current))
1763 sig->flags = SIGNAL_STOP_STOPPED;
1764 notify = CLD_STOPPED; 1813 notify = CLD_STOPPED;
1765 }
1766 if (task_ptrace(current)) 1814 if (task_ptrace(current))
1767 notify = CLD_STOPPED; 1815 notify = CLD_STOPPED;
1768 1816
@@ -2026,10 +2074,8 @@ void exit_signals(struct task_struct *tsk)
2026 recalc_sigpending_and_wake(t); 2074 recalc_sigpending_and_wake(t);
2027 2075
2028 if (unlikely(tsk->signal->group_stop_count) && 2076 if (unlikely(tsk->signal->group_stop_count) &&
2029 !--tsk->signal->group_stop_count) { 2077 task_participate_group_stop(tsk))
2030 tsk->signal->flags = SIGNAL_STOP_STOPPED;
2031 group_stop = CLD_STOPPED; 2078 group_stop = CLD_STOPPED;
2032 }
2033out: 2079out:
2034 spin_unlock_irq(&tsk->sighand->siglock); 2080 spin_unlock_irq(&tsk->sighand->siglock);
2035 2081