diff options
-rw-r--r-- | include/linux/init_task.h | 2 | ||||
-rw-r--r-- | include/linux/sched.h | 12 | ||||
-rw-r--r-- | kernel/exit.c | 1 | ||||
-rw-r--r-- | kernel/fork.c | 7 |
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 | |||
2344 | static inline int get_nr_threads(struct task_struct *tsk) | 2356 | static 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(¤t->signal->sigcnt); | 1479 | atomic_inc(¤t->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++; |