diff options
| author | David Howells <dhowells@redhat.com> | 2002-03-14 21:20:04 -0800 |
|---|---|---|
| committer | Kai Germaschewski <kai@tp1.ruhr-uni-bochum.de> | 2002-03-14 21:20:04 -0800 |
| commit | 3154d91ded003170229670313ff6ded47bcf640e (patch) | |
| tree | 6a9dfa1f8715895b00dadf63110a2dc49ef46fcd /kernel | |
| parent | 5d043fece463db6fcd69dfe1ec2a094d352af15c (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.c | 39 | ||||
| -rw-r--r-- | kernel/fork.c | 11 | ||||
| -rw-r--r-- | kernel/ptrace.c | 8 | ||||
| -rw-r--r-- | kernel/sched.c | 15 | ||||
| -rw-r--r-- | kernel/signal.c | 4 | ||||
| -rw-r--r-- | kernel/sys.c | 2 | ||||
| -rw-r--r-- | kernel/timer.c | 4 |
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; } |
