Commit c18258c6f0848f97e85287f6271c511a092bb784

Authored by Eric W. Biederman
Committed by Linus Torvalds
1 parent 35fa2048ab

[PATCH] pid: Implement transfer_pid and use it to simplify de_thread

In de_thread we move pids from one process to another, a rather ugly case.
The function transfer_pid makes it clear what we are doing, and makes the
action atomic.  This is useful we ever want to atomically traverse the
process group and session lists, in a rcu safe manner.

Even if the atomic properties this change should be a win as transfer_pid
should be less code to execute than executing both attach_pid and
detach_pid, and this should make de_thread slightly smaller as only a
single function call needs to be emitted.  The only downside is that the
code might be slower to execute as the odds are against transfer_pid being
in cache.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Cc: Oleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 3 changed files with 15 additions and 7 deletions Side-by-side Diff

... ... @@ -696,22 +696,19 @@
696 696 */
697 697  
698 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 701 * is called. Odd but simple and correct.
701 702 */
702 703 detach_pid(current, PIDTYPE_PID);
703 704 current->pid = leader->pid;
704 705 attach_pid(current, PIDTYPE_PID, current->pid);
705   - attach_pid(current, PIDTYPE_PGID, current->signal->pgrp);
706   - attach_pid(current, PIDTYPE_SID, current->signal->session);
  706 + transfer_pid(leader, current, PIDTYPE_PGID);
  707 + transfer_pid(leader, current, PIDTYPE_SID);
707 708 list_replace_rcu(&leader->tasks, &current->tasks);
708 709  
709 710 current->group_leader = current;
710 711 leader->group_leader = current;
711   -
712   - /* Reduce leader to a thread */
713   - detach_pid(leader, PIDTYPE_PGID);
714   - detach_pid(leader, PIDTYPE_SID);
715 712  
716 713 current->exit_signal = SIGCHLD;
717 714  
... ... @@ -76,6 +76,8 @@
76 76 enum pid_type type, int nr));
77 77  
78 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 83 * look up a PID in the hash table. Must be called with the tasklist_lock
... ... @@ -252,6 +252,15 @@
252 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 264 struct task_struct * fastcall pid_task(struct pid *pid, enum pid_type type)
256 265 {
257 266 struct task_struct *result = NULL;