diff options
author | Oleg Nesterov <oleg@redhat.com> | 2013-07-03 18:08:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-03 19:08:03 -0400 |
commit | 18c830df771f2ba8b4699fea9af1492275ae627b (patch) | |
tree | 01b1dc470a1a30102a3f94e539bdbf74faa548be /kernel/fork.c | |
parent | 8190773985141f063e1d6dc10200527c655abfb5 (diff) |
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: Oleg 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: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 33 |
1 files changed, 16 insertions, 17 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 7d6962fb6156..6e6a1c11b3e5 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -1360,11 +1360,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1360 | goto bad_fork_cleanup_io; | 1360 | goto bad_fork_cleanup_io; |
1361 | } | 1361 | } |
1362 | 1362 | ||
1363 | p->pid = pid_nr(pid); | ||
1364 | p->tgid = p->pid; | ||
1365 | if (clone_flags & CLONE_THREAD) | ||
1366 | p->tgid = current->tgid; | ||
1367 | |||
1368 | p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; | 1363 | p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; |
1369 | /* | 1364 | /* |
1370 | * Clear TID on mm_release()? | 1365 | * Clear TID on mm_release()? |
@@ -1400,12 +1395,19 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1400 | clear_all_latency_tracing(p); | 1395 | clear_all_latency_tracing(p); |
1401 | 1396 | ||
1402 | /* ok, now we should be set up.. */ | 1397 | /* ok, now we should be set up.. */ |
1403 | if (clone_flags & CLONE_THREAD) | 1398 | p->pid = pid_nr(pid); |
1399 | if (clone_flags & CLONE_THREAD) { | ||
1404 | p->exit_signal = -1; | 1400 | p->exit_signal = -1; |
1405 | else if (clone_flags & CLONE_PARENT) | 1401 | p->group_leader = current->group_leader; |
1406 | p->exit_signal = current->group_leader->exit_signal; | 1402 | p->tgid = current->tgid; |
1407 | else | 1403 | } else { |
1408 | p->exit_signal = (clone_flags & CSIGNAL); | 1404 | if (clone_flags & CLONE_PARENT) |
1405 | p->exit_signal = current->group_leader->exit_signal; | ||
1406 | else | ||
1407 | p->exit_signal = (clone_flags & CSIGNAL); | ||
1408 | p->group_leader = p; | ||
1409 | p->tgid = p->pid; | ||
1410 | } | ||
1409 | 1411 | ||
1410 | p->pdeath_signal = 0; | 1412 | p->pdeath_signal = 0; |
1411 | p->exit_state = 0; | 1413 | p->exit_state = 0; |
@@ -1414,15 +1416,13 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1414 | p->nr_dirtied_pause = 128 >> (PAGE_SHIFT - 10); | 1416 | p->nr_dirtied_pause = 128 >> (PAGE_SHIFT - 10); |
1415 | p->dirty_paused_when = 0; | 1417 | p->dirty_paused_when = 0; |
1416 | 1418 | ||
1417 | /* | ||
1418 | * Ok, make it visible to the rest of the system. | ||
1419 | * We dont wake it up yet. | ||
1420 | */ | ||
1421 | p->group_leader = p; | ||
1422 | INIT_LIST_HEAD(&p->thread_group); | 1419 | INIT_LIST_HEAD(&p->thread_group); |
1423 | p->task_works = NULL; | 1420 | p->task_works = NULL; |
1424 | 1421 | ||
1425 | /* Need tasklist lock for parent etc handling! */ | 1422 | /* |
1423 | * Make it visible to the rest of the system, but dont wake it up yet. | ||
1424 | * Need tasklist lock for parent etc handling! | ||
1425 | */ | ||
1426 | write_lock_irq(&tasklist_lock); | 1426 | write_lock_irq(&tasklist_lock); |
1427 | 1427 | ||
1428 | /* CLONE_PARENT re-uses the old parent */ | 1428 | /* CLONE_PARENT re-uses the old parent */ |
@@ -1476,7 +1476,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1476 | current->signal->nr_threads++; | 1476 | current->signal->nr_threads++; |
1477 | atomic_inc(¤t->signal->live); | 1477 | atomic_inc(¤t->signal->live); |
1478 | atomic_inc(¤t->signal->sigcnt); | 1478 | atomic_inc(¤t->signal->sigcnt); |
1479 | p->group_leader = current->group_leader; | ||
1480 | list_add_tail_rcu(&p->thread_group, | 1479 | list_add_tail_rcu(&p->thread_group, |
1481 | &p->group_leader->thread_group); | 1480 | &p->group_leader->thread_group); |
1482 | } | 1481 | } |