Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c18258c6 authored by Eric W. Biederman's avatar Eric W. Biederman Committed by Linus Torvalds
Browse files

[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: default avatarEric W. Biederman <ebiederm@xmission.com>
Cc: Oleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 35fa2048
Loading
Loading
Loading
Loading
+4 −7
Original line number Diff line number Diff line
@@ -696,23 +696,20 @@ static int de_thread(struct task_struct *tsk)
		 */

		/* Become a process group leader with the old leader's pid.
		 * The old leader becomes a thread of the this thread group.
		 * Note: The old leader also uses this pid until release_task
		 *       is called.  Odd but simple and correct.
		 */
		detach_pid(current, PIDTYPE_PID);
		current->pid = leader->pid;
		attach_pid(current, PIDTYPE_PID,  current->pid);
		attach_pid(current, PIDTYPE_PGID, current->signal->pgrp);
		attach_pid(current, PIDTYPE_SID,  current->signal->session);
		transfer_pid(leader, current, PIDTYPE_PGID);
		transfer_pid(leader, current, PIDTYPE_SID);
		list_replace_rcu(&leader->tasks, &current->tasks);

		current->group_leader = current;
		leader->group_leader = current;

		/* Reduce leader to a thread */
		detach_pid(leader, PIDTYPE_PGID);
		detach_pid(leader, PIDTYPE_SID);

		current->exit_signal = SIGCHLD;

		BUG_ON(leader->exit_state != EXIT_ZOMBIE);
+2 −0
Original line number Diff line number Diff line
@@ -76,6 +76,8 @@ extern int FASTCALL(attach_pid(struct task_struct *task,
				enum pid_type type, int nr));

extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type));
extern void FASTCALL(transfer_pid(struct task_struct *old,
				  struct task_struct *new, enum pid_type));

/*
 * look up a PID in the hash table. Must be called with the tasklist_lock
+9 −0
Original line number Diff line number Diff line
@@ -252,6 +252,15 @@ void fastcall detach_pid(struct task_struct *task, enum pid_type type)
	free_pid(pid);
}

/* transfer_pid is an optimization of attach_pid(new), detach_pid(old) */
void fastcall transfer_pid(struct task_struct *old, struct task_struct *new,
			   enum pid_type type)
{
	new->pids[type].pid = old->pids[type].pid;
	hlist_replace_rcu(&old->pids[type].node, &new->pids[type].node);
	old->pids[type].pid = NULL;
}

struct task_struct * fastcall pid_task(struct pid *pid, enum pid_type type)
{
	struct task_struct *result = NULL;