diff options
-rw-r--r-- | fs/exec.c | 11 | ||||
-rw-r--r-- | include/linux/pid.h | 2 | ||||
-rw-r--r-- | kernel/pid.c | 9 |
3 files changed, 15 insertions, 7 deletions
@@ -696,23 +696,20 @@ static int de_thread(struct task_struct *tsk) | |||
696 | */ | 696 | */ |
697 | 697 | ||
698 | /* Become a process group leader with the old leader's pid. | 698 | /* Become a process group leader with the old leader's pid. |
699 | * Note: The old leader also uses thispid until release_task | 699 | * The old leader becomes a thread of the this thread group. |
700 | * Note: The old leader also uses this pid until release_task | ||
700 | * is called. Odd but simple and correct. | 701 | * is called. Odd but simple and correct. |
701 | */ | 702 | */ |
702 | detach_pid(current, PIDTYPE_PID); | 703 | detach_pid(current, PIDTYPE_PID); |
703 | current->pid = leader->pid; | 704 | current->pid = leader->pid; |
704 | attach_pid(current, PIDTYPE_PID, current->pid); | 705 | attach_pid(current, PIDTYPE_PID, current->pid); |
705 | attach_pid(current, PIDTYPE_PGID, current->signal->pgrp); | 706 | transfer_pid(leader, current, PIDTYPE_PGID); |
706 | attach_pid(current, PIDTYPE_SID, current->signal->session); | 707 | transfer_pid(leader, current, PIDTYPE_SID); |
707 | list_replace_rcu(&leader->tasks, ¤t->tasks); | 708 | list_replace_rcu(&leader->tasks, ¤t->tasks); |
708 | 709 | ||
709 | current->group_leader = current; | 710 | current->group_leader = current; |
710 | leader->group_leader = current; | 711 | leader->group_leader = current; |
711 | 712 | ||
712 | /* Reduce leader to a thread */ | ||
713 | detach_pid(leader, PIDTYPE_PGID); | ||
714 | detach_pid(leader, PIDTYPE_SID); | ||
715 | |||
716 | current->exit_signal = SIGCHLD; | 713 | current->exit_signal = SIGCHLD; |
717 | 714 | ||
718 | BUG_ON(leader->exit_state != EXIT_ZOMBIE); | 715 | BUG_ON(leader->exit_state != EXIT_ZOMBIE); |
diff --git a/include/linux/pid.h b/include/linux/pid.h index 29960b03bef7..93da7e2d9f30 100644 --- a/include/linux/pid.h +++ b/include/linux/pid.h | |||
@@ -76,6 +76,8 @@ extern int FASTCALL(attach_pid(struct task_struct *task, | |||
76 | enum pid_type type, int nr)); | 76 | enum pid_type type, int nr)); |
77 | 77 | ||
78 | extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type)); | 78 | extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type)); |
79 | extern void FASTCALL(transfer_pid(struct task_struct *old, | ||
80 | struct task_struct *new, enum pid_type)); | ||
79 | 81 | ||
80 | /* | 82 | /* |
81 | * look up a PID in the hash table. Must be called with the tasklist_lock | 83 | * look up a PID in the hash table. Must be called with the tasklist_lock |
diff --git a/kernel/pid.c b/kernel/pid.c index 93e212f20671..6db82b68e2f8 100644 --- a/kernel/pid.c +++ b/kernel/pid.c | |||
@@ -252,6 +252,15 @@ void fastcall detach_pid(struct task_struct *task, enum pid_type type) | |||
252 | free_pid(pid); | 252 | free_pid(pid); |
253 | } | 253 | } |
254 | 254 | ||
255 | /* transfer_pid is an optimization of attach_pid(new), detach_pid(old) */ | ||
256 | void fastcall transfer_pid(struct task_struct *old, struct task_struct *new, | ||
257 | enum pid_type type) | ||
258 | { | ||
259 | new->pids[type].pid = old->pids[type].pid; | ||
260 | hlist_replace_rcu(&old->pids[type].node, &new->pids[type].node); | ||
261 | old->pids[type].pid = NULL; | ||
262 | } | ||
263 | |||
255 | struct task_struct * fastcall pid_task(struct pid *pid, enum pid_type type) | 264 | struct task_struct * fastcall pid_task(struct pid *pid, enum pid_type type) |
256 | { | 265 | { |
257 | struct task_struct *result = NULL; | 266 | struct task_struct *result = NULL; |