mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
[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>
This commit is contained in:
parent
35fa2048ab
commit
c18258c6f0
3 changed files with 15 additions and 7 deletions
11
fs/exec.c
11
fs/exec.c
|
@ -696,23 +696,20 @@ static int de_thread(struct task_struct *tsk)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Become a process group leader with the old leader's pid.
|
/* Become a process group leader with the old leader's pid.
|
||||||
* Note: The old leader also uses thispid until release_task
|
* 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.
|
* is called. Odd but simple and correct.
|
||||||
*/
|
*/
|
||||||
detach_pid(current, PIDTYPE_PID);
|
detach_pid(current, PIDTYPE_PID);
|
||||||
current->pid = leader->pid;
|
current->pid = leader->pid;
|
||||||
attach_pid(current, PIDTYPE_PID, current->pid);
|
attach_pid(current, PIDTYPE_PID, current->pid);
|
||||||
attach_pid(current, PIDTYPE_PGID, current->signal->pgrp);
|
transfer_pid(leader, current, PIDTYPE_PGID);
|
||||||
attach_pid(current, PIDTYPE_SID, current->signal->session);
|
transfer_pid(leader, current, PIDTYPE_SID);
|
||||||
list_replace_rcu(&leader->tasks, ¤t->tasks);
|
list_replace_rcu(&leader->tasks, ¤t->tasks);
|
||||||
|
|
||||||
current->group_leader = current;
|
current->group_leader = current;
|
||||||
leader->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;
|
current->exit_signal = SIGCHLD;
|
||||||
|
|
||||||
BUG_ON(leader->exit_state != EXIT_ZOMBIE);
|
BUG_ON(leader->exit_state != EXIT_ZOMBIE);
|
||||||
|
|
|
@ -76,6 +76,8 @@ extern int FASTCALL(attach_pid(struct task_struct *task,
|
||||||
enum pid_type type, int nr));
|
enum pid_type type, int nr));
|
||||||
|
|
||||||
extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type));
|
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
|
* look up a PID in the hash table. Must be called with the tasklist_lock
|
||||||
|
|
|
@ -252,6 +252,15 @@ void fastcall detach_pid(struct task_struct *task, enum pid_type type)
|
||||||
free_pid(pid);
|
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 * fastcall pid_task(struct pid *pid, enum pid_type type)
|
||||||
{
|
{
|
||||||
struct task_struct *result = NULL;
|
struct task_struct *result = NULL;
|
||||||
|
|
Loading…
Reference in a new issue