Commit 18c830df authored by Oleg Nesterov's avatar Oleg Nesterov Committed by Linus Torvalds

kernel/fork.c:copy_process(): consolidate the lockless CLONE_THREAD checks

copy_process() does a lot of "chaotic" initializations and checks
CLONE_THREAD twice before it takes tasklist.  In particular it sets
"p->group_leader = p" and then changes it again under tasklist if
!thread_group_leader(p).

This looks a bit confusing, lets create a single "if (CLONE_THREAD)" block
which initializes ->exit_signal, ->group_leader, and ->tgid.
Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Pavel Emelyanov <xemul@parallels.com>
Cc: Sergey Dyasly <dserrg@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 81907739
...@@ -1360,11 +1360,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, ...@@ -1360,11 +1360,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
goto bad_fork_cleanup_io; goto bad_fork_cleanup_io;
} }
p->pid = pid_nr(pid);
p->tgid = p->pid;
if (clone_flags & CLONE_THREAD)
p->tgid = current->tgid;
p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
/* /*
* Clear TID on mm_release()? * Clear TID on mm_release()?
...@@ -1400,12 +1395,19 @@ static struct task_struct *copy_process(unsigned long clone_flags, ...@@ -1400,12 +1395,19 @@ static struct task_struct *copy_process(unsigned long clone_flags,
clear_all_latency_tracing(p); clear_all_latency_tracing(p);
/* ok, now we should be set up.. */ /* ok, now we should be set up.. */
if (clone_flags & CLONE_THREAD) p->pid = pid_nr(pid);
if (clone_flags & CLONE_THREAD) {
p->exit_signal = -1; p->exit_signal = -1;
else if (clone_flags & CLONE_PARENT) p->group_leader = current->group_leader;
p->tgid = current->tgid;
} else {
if (clone_flags & CLONE_PARENT)
p->exit_signal = current->group_leader->exit_signal; p->exit_signal = current->group_leader->exit_signal;
else else
p->exit_signal = (clone_flags & CSIGNAL); p->exit_signal = (clone_flags & CSIGNAL);
p->group_leader = p;
p->tgid = p->pid;
}
p->pdeath_signal = 0; p->pdeath_signal = 0;
p->exit_state = 0; p->exit_state = 0;
...@@ -1414,15 +1416,13 @@ static struct task_struct *copy_process(unsigned long clone_flags, ...@@ -1414,15 +1416,13 @@ static struct task_struct *copy_process(unsigned long clone_flags,
p->nr_dirtied_pause = 128 >> (PAGE_SHIFT - 10); p->nr_dirtied_pause = 128 >> (PAGE_SHIFT - 10);
p->dirty_paused_when = 0; p->dirty_paused_when = 0;
/*
* Ok, make it visible to the rest of the system.
* We dont wake it up yet.
*/
p->group_leader = p;
INIT_LIST_HEAD(&p->thread_group); INIT_LIST_HEAD(&p->thread_group);
p->task_works = NULL; p->task_works = NULL;
/* Need tasklist lock for parent etc handling! */ /*
* Make it visible to the rest of the system, but dont wake it up yet.
* Need tasklist lock for parent etc handling!
*/
write_lock_irq(&tasklist_lock); write_lock_irq(&tasklist_lock);
/* CLONE_PARENT re-uses the old parent */ /* CLONE_PARENT re-uses the old parent */
...@@ -1476,7 +1476,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, ...@@ -1476,7 +1476,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
current->signal->nr_threads++; current->signal->nr_threads++;
atomic_inc(&current->signal->live); atomic_inc(&current->signal->live);
atomic_inc(&current->signal->sigcnt); atomic_inc(&current->signal->sigcnt);
p->group_leader = current->group_leader;
list_add_tail_rcu(&p->thread_group, list_add_tail_rcu(&p->thread_group,
&p->group_leader->thread_group); &p->group_leader->thread_group);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment