summaryrefslogtreecommitdiff
path: root/kernel/pid.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/pid.c')
-rw-r--r--kernel/pid.c88
1 files changed, 41 insertions, 47 deletions
diff --git a/kernel/pid.c b/kernel/pid.c
index 8c9b7510174a..57527f0cda5e 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -146,74 +146,66 @@ failure:
return -1;
}
-fastcall struct pid *find_pid(enum pid_type type, int nr)
+struct pid * fastcall find_pid(enum pid_type type, int nr)
{
struct hlist_node *elem;
struct pid *pid;
hlist_for_each_entry(pid, elem,
- &pid_hash[type][pid_hashfn(nr)], hash_chain) {
+ &pid_hash[type][pid_hashfn(nr)], pid_chain) {
if (pid->nr == nr)
return pid;
}
return NULL;
}
-void fastcall link_pid(task_t *task, struct pid_link *link, struct pid *pid)
-{
- atomic_inc(&pid->count);
- list_add_tail(&link->pid_chain, &pid->task_list);
- link->pidptr = pid;
-}
-
int fastcall attach_pid(task_t *task, enum pid_type type, int nr)
{
- struct pid *pid = find_pid(type, nr);
-
- if (pid)
- atomic_inc(&pid->count);
- else {
- pid = &task->pids[type].pid;
- pid->nr = nr;
- atomic_set(&pid->count, 1);
- INIT_LIST_HEAD(&pid->task_list);
- pid->task = task;
- get_task_struct(task);
- hlist_add_head(&pid->hash_chain,
+ struct pid *pid, *task_pid;
+
+ task_pid = &task->pids[type];
+ pid = find_pid(type, nr);
+ if (pid == NULL) {
+ hlist_add_head(&task_pid->pid_chain,
&pid_hash[type][pid_hashfn(nr)]);
+ INIT_LIST_HEAD(&task_pid->pid_list);
+ } else {
+ INIT_HLIST_NODE(&task_pid->pid_chain);
+ list_add_tail(&task_pid->pid_list, &pid->pid_list);
}
- list_add_tail(&task->pids[type].pid_chain, &pid->task_list);
- task->pids[type].pidptr = pid;
+ task_pid->nr = nr;
return 0;
}
static inline int __detach_pid(task_t *task, enum pid_type type)
{
- struct pid_link *link = task->pids + type;
- struct pid *pid = link->pidptr;
+ struct pid *pid, *pid_next;
int nr;
- list_del(&link->pid_chain);
- if (!atomic_dec_and_test(&pid->count))
- return 0;
-
+ pid = &task->pids[type];
+ if (!hlist_unhashed(&pid->pid_chain)) {
+ hlist_del(&pid->pid_chain);
+ if (!list_empty(&pid->pid_list)) {
+ pid_next = list_entry(pid->pid_list.next,
+ struct pid, pid_list);
+ /* insert next pid from pid_list to hash */
+ hlist_add_head(&pid_next->pid_chain,
+ &pid_hash[type][pid_hashfn(pid_next->nr)]);
+ }
+ }
+ list_del(&pid->pid_list);
nr = pid->nr;
- hlist_del(&pid->hash_chain);
- put_task_struct(pid->task);
+ pid->nr = 0;
return nr;
}
-static void _detach_pid(task_t *task, enum pid_type type)
-{
- __detach_pid(task, type);
-}
-
void fastcall detach_pid(task_t *task, enum pid_type type)
{
- int nr = __detach_pid(task, type);
+ int nr;
+ nr = __detach_pid(task, type);
if (!nr)
return;
@@ -223,16 +215,18 @@ void fastcall detach_pid(task_t *task, enum pid_type type)
free_pidmap(nr);
}
-task_t *find_task_by_pid(int nr)
+task_t *find_task_by_pid_type(int type, int nr)
{
- struct pid *pid = find_pid(PIDTYPE_PID, nr);
+ struct pid *pid;
+ pid = find_pid(type, nr);
if (!pid)
return NULL;
- return pid_task(pid->task_list.next, PIDTYPE_PID);
+
+ return pid_task(&pid->pid_list, type);
}
-EXPORT_SYMBOL(find_task_by_pid);
+EXPORT_SYMBOL(find_task_by_pid_type);
/*
* This function switches the PIDs if a non-leader thread calls
@@ -241,13 +235,13 @@ EXPORT_SYMBOL(find_task_by_pid);
*/
void switch_exec_pids(task_t *leader, task_t *thread)
{
- _detach_pid(leader, PIDTYPE_PID);
- _detach_pid(leader, PIDTYPE_TGID);
- _detach_pid(leader, PIDTYPE_PGID);
- _detach_pid(leader, PIDTYPE_SID);
+ __detach_pid(leader, PIDTYPE_PID);
+ __detach_pid(leader, PIDTYPE_TGID);
+ __detach_pid(leader, PIDTYPE_PGID);
+ __detach_pid(leader, PIDTYPE_SID);
- _detach_pid(thread, PIDTYPE_PID);
- _detach_pid(thread, PIDTYPE_TGID);
+ __detach_pid(thread, PIDTYPE_PID);
+ __detach_pid(thread, PIDTYPE_TGID);
leader->pid = leader->tgid = thread->pid;
thread->pid = thread->tgid;