aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/init_task.h2
-rw-r--r--include/linux/sched.h12
-rw-r--r--kernel/exit.c1
-rw-r--r--kernel/fork.c7
4 files changed, 22 insertions, 0 deletions
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index f0e52383a001..1516a8ff8f92 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -41,6 +41,7 @@ extern struct fs_struct init_fs;
41 41
42#define INIT_SIGNALS(sig) { \ 42#define INIT_SIGNALS(sig) { \
43 .nr_threads = 1, \ 43 .nr_threads = 1, \
44 .thread_head = LIST_HEAD_INIT(init_task.thread_node), \
44 .wait_chldexit = __WAIT_QUEUE_HEAD_INITIALIZER(sig.wait_chldexit),\ 45 .wait_chldexit = __WAIT_QUEUE_HEAD_INITIALIZER(sig.wait_chldexit),\
45 .shared_pending = { \ 46 .shared_pending = { \
46 .list = LIST_HEAD_INIT(sig.shared_pending.list), \ 47 .list = LIST_HEAD_INIT(sig.shared_pending.list), \
@@ -222,6 +223,7 @@ extern struct task_group root_task_group;
222 [PIDTYPE_SID] = INIT_PID_LINK(PIDTYPE_SID), \ 223 [PIDTYPE_SID] = INIT_PID_LINK(PIDTYPE_SID), \
223 }, \ 224 }, \
224 .thread_group = LIST_HEAD_INIT(tsk.thread_group), \ 225 .thread_group = LIST_HEAD_INIT(tsk.thread_group), \
226 .thread_node = LIST_HEAD_INIT(init_signals.thread_head), \
225 INIT_IDS \ 227 INIT_IDS \
226 INIT_PERF_EVENTS(tsk) \ 228 INIT_PERF_EVENTS(tsk) \
227 INIT_TRACE_IRQFLAGS \ 229 INIT_TRACE_IRQFLAGS \
diff --git a/include/linux/sched.h b/include/linux/sched.h
index ffccdad050b5..485234d2fd42 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -549,6 +549,7 @@ struct signal_struct {
549 atomic_t sigcnt; 549 atomic_t sigcnt;
550 atomic_t live; 550 atomic_t live;
551 int nr_threads; 551 int nr_threads;
552 struct list_head thread_head;
552 553
553 wait_queue_head_t wait_chldexit; /* for wait4() */ 554 wait_queue_head_t wait_chldexit; /* for wait4() */
554 555
@@ -1271,6 +1272,7 @@ struct task_struct {
1271 /* PID/PID hash table linkage. */ 1272 /* PID/PID hash table linkage. */
1272 struct pid_link pids[PIDTYPE_MAX]; 1273 struct pid_link pids[PIDTYPE_MAX];
1273 struct list_head thread_group; 1274 struct list_head thread_group;
1275 struct list_head thread_node;
1274 1276
1275 struct completion *vfork_done; /* for vfork() */ 1277 struct completion *vfork_done; /* for vfork() */
1276 int __user *set_child_tid; /* CLONE_CHILD_SETTID */ 1278 int __user *set_child_tid; /* CLONE_CHILD_SETTID */
@@ -2341,6 +2343,16 @@ extern bool current_is_single_threaded(void);
2341#define while_each_thread(g, t) \ 2343#define while_each_thread(g, t) \
2342 while ((t = next_thread(t)) != g) 2344 while ((t = next_thread(t)) != g)
2343 2345
2346#define __for_each_thread(signal, t) \
2347 list_for_each_entry_rcu(t, &(signal)->thread_head, thread_node)
2348
2349#define for_each_thread(p, t) \
2350 __for_each_thread((p)->signal, t)
2351
2352/* Careful: this is a double loop, 'break' won't work as expected. */
2353#define for_each_process_thread(p, t) \
2354 for_each_process(p) for_each_thread(p, t)
2355
2344static inline int get_nr_threads(struct task_struct *tsk) 2356static inline int get_nr_threads(struct task_struct *tsk)
2345{ 2357{
2346 return tsk->signal->nr_threads; 2358 return tsk->signal->nr_threads;
diff --git a/kernel/exit.c b/kernel/exit.c
index a949819055d5..1e77fc645317 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -74,6 +74,7 @@ static void __unhash_process(struct task_struct *p, bool group_dead)
74 __this_cpu_dec(process_counts); 74 __this_cpu_dec(process_counts);
75 } 75 }
76 list_del_rcu(&p->thread_group); 76 list_del_rcu(&p->thread_group);
77 list_del_rcu(&p->thread_node);
77} 78}
78 79
79/* 80/*
diff --git a/kernel/fork.c b/kernel/fork.c
index 294189fc7ac8..2f11bbe376b0 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1035,6 +1035,11 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
1035 sig->nr_threads = 1; 1035 sig->nr_threads = 1;
1036 atomic_set(&sig->live, 1); 1036 atomic_set(&sig->live, 1);
1037 atomic_set(&sig->sigcnt, 1); 1037 atomic_set(&sig->sigcnt, 1);
1038
1039 /* list_add(thread_node, thread_head) without INIT_LIST_HEAD() */
1040 sig->thread_head = (struct list_head)LIST_HEAD_INIT(tsk->thread_node);
1041 tsk->thread_node = (struct list_head)LIST_HEAD_INIT(sig->thread_head);
1042
1038 init_waitqueue_head(&sig->wait_chldexit); 1043 init_waitqueue_head(&sig->wait_chldexit);
1039 sig->curr_target = tsk; 1044 sig->curr_target = tsk;
1040 init_sigpending(&sig->shared_pending); 1045 init_sigpending(&sig->shared_pending);
@@ -1474,6 +1479,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1474 atomic_inc(&current->signal->sigcnt); 1479 atomic_inc(&current->signal->sigcnt);
1475 list_add_tail_rcu(&p->thread_group, 1480 list_add_tail_rcu(&p->thread_group,
1476 &p->group_leader->thread_group); 1481 &p->group_leader->thread_group);
1482 list_add_tail_rcu(&p->thread_node,
1483 &p->signal->thread_head);
1477 } 1484 }
1478 attach_pid(p, PIDTYPE_PID); 1485 attach_pid(p, PIDTYPE_PID);
1479 nr_threads++; 1486 nr_threads++;