|
@@ -549,6 +549,7 @@ struct signal_struct {
|
|
|
atomic_t sigcnt;
|
|
|
atomic_t live;
|
|
|
int nr_threads;
|
|
|
+ struct list_head thread_head;
|
|
|
|
|
|
wait_queue_head_t wait_chldexit; /* for wait4() */
|
|
|
|
|
@@ -1271,6 +1272,7 @@ struct task_struct {
|
|
|
/* PID/PID hash table linkage. */
|
|
|
struct pid_link pids[PIDTYPE_MAX];
|
|
|
struct list_head thread_group;
|
|
|
+ struct list_head thread_node;
|
|
|
|
|
|
struct completion *vfork_done; /* for vfork() */
|
|
|
int __user *set_child_tid; /* CLONE_CHILD_SETTID */
|
|
@@ -2341,6 +2343,16 @@ extern bool current_is_single_threaded(void);
|
|
|
#define while_each_thread(g, t) \
|
|
|
while ((t = next_thread(t)) != g)
|
|
|
|
|
|
+#define __for_each_thread(signal, t) \
|
|
|
+ list_for_each_entry_rcu(t, &(signal)->thread_head, thread_node)
|
|
|
+
|
|
|
+#define for_each_thread(p, t) \
|
|
|
+ __for_each_thread((p)->signal, t)
|
|
|
+
|
|
|
+/* Careful: this is a double loop, 'break' won't work as expected. */
|
|
|
+#define for_each_process_thread(p, t) \
|
|
|
+ for_each_process(p) for_each_thread(p, t)
|
|
|
+
|
|
|
static inline int get_nr_threads(struct task_struct *tsk)
|
|
|
{
|
|
|
return tsk->signal->nr_threads;
|