summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2002-03-14 21:20:04 -0800
committerKai Germaschewski <kai@tp1.ruhr-uni-bochum.de>2002-03-14 21:20:04 -0800
commit3154d91ded003170229670313ff6ded47bcf640e (patch)
tree6a9dfa1f8715895b00dadf63110a2dc49ef46fcd /kernel
parent5d043fece463db6fcd69dfe1ec2a094d352af15c (diff)
[PATCH] wait4() WIFSTOPPED starvation fix #1/2
This patch (#1) just converts the task_struct to use struct list_head rather than direct pointers for maintaining the children list.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/exit.c39
-rw-r--r--kernel/fork.c11
-rw-r--r--kernel/ptrace.c8
-rw-r--r--kernel/sched.c15
-rw-r--r--kernel/signal.c4
-rw-r--r--kernel/sys.c2
-rw-r--r--kernel/timer.c4
7 files changed, 41 insertions, 42 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index 45214fffb162..4410c1405ea5 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -91,10 +91,10 @@ static int will_become_orphaned_pgrp(int pgrp, struct task_struct * ignored_task
for_each_task(p) {
if ((p == ignored_task) || (p->pgrp != pgrp) ||
(p->state == TASK_ZOMBIE) ||
- (p->p_pptr->pid == 1))
+ (p->parent->pid == 1))
continue;
- if ((p->p_pptr->pgrp != pgrp) &&
- (p->p_pptr->session == p->session)) {
+ if ((p->parent->pgrp != pgrp) &&
+ (p->parent->session == p->session)) {
read_unlock(&tasklist_lock);
return 0;
}
@@ -144,8 +144,8 @@ void reparent_to_init(void)
/* Reparent to init */
REMOVE_LINKS(current);
- current->p_pptr = child_reaper;
- current->p_opptr = child_reaper;
+ current->parent = child_reaper;
+ current->real_parent = child_reaper;
SET_LINKS(current);
/* Set the exit signal to SIGCHLD so we signal init on exit */
@@ -217,16 +217,16 @@ static inline void forget_original_parent(struct task_struct * father)
reaper = child_reaper;
for_each_task(p) {
- if (p->p_opptr == father) {
+ if (p->real_parent == father) {
/* We dont want people slaying init */
p->exit_signal = SIGCHLD;
p->self_exec_id++;
/* Make sure we're not reparenting to ourselves */
if (p == reaper)
- p->p_opptr = child_reaper;
+ p->real_parent = child_reaper;
else
- p->p_opptr = reaper;
+ p->real_parent = reaper;
if (p->pdeath_signal) send_sig(p->pdeath_signal, p, 0);
}
@@ -400,7 +400,7 @@ static void exit_notify(void)
* is about to become orphaned.
*/
- t = current->p_pptr;
+ t = current->parent;
if ((t->pgrp != current->pgrp) &&
(t->session == current->session) &&
@@ -445,17 +445,12 @@ static void exit_notify(void)
write_lock_irq(&tasklist_lock);
current->state = TASK_ZOMBIE;
do_notify_parent(current, current->exit_signal);
- while (current->p_cptr != NULL) {
- p = current->p_cptr;
- current->p_cptr = p->p_osptr;
- p->p_ysptr = NULL;
+ while ((p = eldest_child(current))) {
+ list_del_init(&p->sibling);
p->ptrace = 0;
- p->p_pptr = p->p_opptr;
- p->p_osptr = p->p_pptr->p_cptr;
- if (p->p_osptr)
- p->p_osptr->p_ysptr = p;
- p->p_pptr->p_cptr = p;
+ p->parent = p->real_parent;
+ list_add_tail(&p->sibling,&p->parent->children);
if (p->state == TASK_ZOMBIE)
do_notify_parent(p, p->exit_signal);
/*
@@ -568,7 +563,9 @@ repeat:
tsk = current;
do {
struct task_struct *p;
- for (p = tsk->p_cptr ; p ; p = p->p_osptr) {
+ struct list_head *_p;
+ list_for_each(_p,&tsk->children) {
+ p = list_entry(_p,struct task_struct,sibling);
if (pid>0) {
if (p->pid != pid)
continue;
@@ -613,10 +610,10 @@ repeat:
if (retval)
goto end_wait4;
retval = p->pid;
- if (p->p_opptr != p->p_pptr) {
+ if (p->real_parent != p->parent) {
write_lock_irq(&tasklist_lock);
REMOVE_LINKS(p);
- p->p_pptr = p->p_opptr;
+ p->parent = p->real_parent;
SET_LINKS(p);
do_notify_parent(p, SIGCHLD);
write_unlock_irq(&tasklist_lock);
diff --git a/kernel/fork.c b/kernel/fork.c
index 2f3f7301236f..a05f52776e35 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -666,7 +666,8 @@ int do_fork(unsigned long clone_flags, unsigned long stack_start,
INIT_LIST_HEAD(&p->run_list);
- p->p_cptr = NULL;
+ INIT_LIST_HEAD(&p->children);
+ INIT_LIST_HEAD(&p->sibling);
init_waitqueue_head(&p->wait_chldexit);
p->vfork_done = NULL;
if (clone_flags & CLONE_VFORK) {
@@ -766,12 +767,12 @@ int do_fork(unsigned long clone_flags, unsigned long stack_start,
write_lock_irq(&tasklist_lock);
/* CLONE_PARENT re-uses the old parent */
- p->p_opptr = current->p_opptr;
- p->p_pptr = current->p_pptr;
+ p->real_parent = current->real_parent;
+ p->parent = current->parent;
if (!(clone_flags & CLONE_PARENT)) {
- p->p_opptr = current;
+ p->real_parent = current;
if (!(p->ptrace & PT_PTRACED))
- p->p_pptr = current;
+ p->parent = current;
}
if (clone_flags & CLONE_THREAD) {
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index a5db3a5c5793..bade71e2c0f0 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -24,7 +24,7 @@ int ptrace_check_attach(struct task_struct *child, int kill)
if (!(child->ptrace & PT_PTRACED))
return -ESRCH;
- if (child->p_pptr != current)
+ if (child->parent != current)
return -ESRCH;
if (!kill) {
@@ -70,9 +70,9 @@ int ptrace_attach(struct task_struct *task)
task_unlock(task);
write_lock_irq(&tasklist_lock);
- if (task->p_pptr != current) {
+ if (task->parent != current) {
REMOVE_LINKS(task);
- task->p_pptr = current;
+ task->parent = current;
SET_LINKS(task);
}
write_unlock_irq(&tasklist_lock);
@@ -98,7 +98,7 @@ int ptrace_detach(struct task_struct *child, unsigned int data)
child->exit_code = data;
write_lock_irq(&tasklist_lock);
REMOVE_LINKS(child);
- child->p_pptr = child->p_opptr;
+ child->parent = child->real_parent;
SET_LINKS(child);
write_unlock_irq(&tasklist_lock);
diff --git a/kernel/sched.c b/kernel/sched.c
index 73110e6a8abc..49aa10fe905c 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -1320,6 +1320,7 @@ out_nounlock:
static void show_task(task_t * p)
{
unsigned long free = 0;
+ task_t *relative;
int state;
static const char * stat_nam[] = { "R", "S", "D", "Z", "T", "W" };
@@ -1346,17 +1347,17 @@ static void show_task(task_t * p)
n++;
free = (unsigned long) n - (unsigned long)(p+1);
}
- printk("%5lu %5d %6d ", free, p->pid, p->p_pptr->pid);
- if (p->p_cptr)
- printk("%5d ", p->p_cptr->pid);
+ printk("%5lu %5d %6d ", free, p->pid, p->parent->pid);
+ if ((relative = eldest_child(p)))
+ printk("%5d ", relative->pid);
else
printk(" ");
- if (p->p_ysptr)
- printk("%7d", p->p_ysptr->pid);
+ if ((relative = younger_sibling(p)))
+ printk("%7d", relative->pid);
else
printk(" ");
- if (p->p_osptr)
- printk(" %5d", p->p_osptr->pid);
+ if ((relative = older_sibling(p)))
+ printk(" %5d", relative->pid);
else
printk(" ");
if (!p->mm)
diff --git a/kernel/signal.c b/kernel/signal.c
index 25846598407a..440ffbdf1e9c 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -804,8 +804,8 @@ void do_notify_parent(struct task_struct *tsk, int sig)
info.si_code = why;
info.si_status = status;
- send_sig_info(sig, &info, tsk->p_pptr);
- wake_up_parent(tsk->p_pptr);
+ send_sig_info(sig, &info, tsk->parent);
+ wake_up_parent(tsk->parent);
}
diff --git a/kernel/sys.c b/kernel/sys.c
index 56d483f984fd..fc8e5e4060a0 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -839,7 +839,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
if (!p)
goto out;
- if (p->p_pptr == current || p->p_opptr == current) {
+ if (p->parent == current || p->real_parent == current) {
err = -EPERM;
if (p->session != current->session)
goto out;
diff --git a/kernel/timer.c b/kernel/timer.c
index 6b79d2045882..504af956c037 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -742,14 +742,14 @@ asmlinkage long sys_getppid(void)
struct task_struct * me = current;
struct task_struct * parent;
- parent = me->p_opptr;
+ parent = me->real_parent;
for (;;) {
pid = parent->pid;
#if CONFIG_SMP
{
struct task_struct *old = parent;
mb();
- parent = me->p_opptr;
+ parent = me->real_parent;
if (old != parent)
continue;
}