]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] wait4() WIFSTOPPED starvation fix #1/2
authorDavid Howells <dhowells@redhat.com>
Fri, 15 Mar 2002 05:20:04 +0000 (21:20 -0800)
committerKai Germaschewski <kai@tp1.ruhr-uni-bochum.de>
Fri, 15 Mar 2002 05:20:04 +0000 (21:20 -0800)
This patch (#1) just converts the task_struct to use struct list_head rather
than direct pointers for maintaining the children list.

13 files changed:
arch/i386/kernel/signal.c
fs/binfmt_elf.c
fs/proc/array.c
fs/proc/base.c
include/linux/init_task.h
include/linux/sched.h
kernel/exit.c
kernel/fork.c
kernel/ptrace.c
kernel/sched.c
kernel/signal.c
kernel/sys.c
kernel/timer.c

index a45838e288054158f755b8c3dad52e3d5ceddcb3..f1a412ec83705c96aa69c1d9d8b89aee2fd6580f 100644 (file)
@@ -630,8 +630,8 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
                                info.si_signo = signr;
                                info.si_errno = 0;
                                info.si_code = SI_USER;
-                               info.si_pid = current->p_pptr->pid;
-                               info.si_uid = current->p_pptr->uid;
+                               info.si_pid = current->parent->pid;
+                               info.si_uid = current->parent->uid;
                        }
 
                        /* If the (new) signal is now blocked, requeue it.  */
@@ -670,7 +670,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
                        case SIGSTOP: {
                                struct signal_struct *sig;
                                current->exit_code = signr;
-                               sig = current->p_pptr->sig;
+                               sig = current->parent->sig;
                                preempt_disable();
                                current->state = TASK_STOPPED;
                                if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
index 3ca4e62e435698a352e0c42069d48117dbbf487a..a4a35fcf7f812eee38ffd9e3991aa3a693e22f5c 100644 (file)
@@ -1094,7 +1094,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
        prstatus.pr_sigpend = current->pending.signal.sig[0];
        prstatus.pr_sighold = current->blocked.sig[0];
        psinfo.pr_pid = prstatus.pr_pid = current->pid;
-       psinfo.pr_ppid = prstatus.pr_ppid = current->p_pptr->pid;
+       psinfo.pr_ppid = prstatus.pr_ppid = current->parent->pid;
        psinfo.pr_pgrp = prstatus.pr_pgrp = current->pgrp;
        psinfo.pr_sid = prstatus.pr_sid = current->session;
        prstatus.pr_utime.tv_sec = CT_TO_SECS(current->times.tms_utime);
index 7186199d5e4bf9f7b251aa91906a2366ce845e01..d216d47ddcdc547e9d6b51f26c06f5fe7ad0863a 100644 (file)
@@ -159,7 +159,7 @@ static inline char * task_state(struct task_struct *p, char *buffer)
                "Uid:\t%d\t%d\t%d\t%d\n"
                "Gid:\t%d\t%d\t%d\t%d\n",
                get_task_state(p), p->tgid,
-               p->pid, p->pid ? p->p_opptr->pid : 0, 0,
+               p->pid, p->pid ? p->real_parent->pid : 0, 0,
                p->uid, p->euid, p->suid, p->fsuid,
                p->gid, p->egid, p->sgid, p->fsgid);
        read_unlock(&tasklist_lock);    
@@ -340,7 +340,7 @@ int proc_pid_stat(struct task_struct *task, char * buffer)
        nice = task_nice(task);
 
        read_lock(&tasklist_lock);
-       ppid = task->pid ? task->p_opptr->pid : 0;
+       ppid = task->pid ? task->real_parent->pid : 0;
        read_unlock(&tasklist_lock);
        res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
 %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu \
index c8ba919af768456b7e8f19d7f683c7af38832138..fb250b29fbd5190051cd371af97980aa1125e7bc 100644 (file)
@@ -336,7 +336,7 @@ static struct file_operations proc_info_file_operations = {
 };
 
 #define MAY_PTRACE(p) \
-(p==current||(p->p_pptr==current&&(p->ptrace & PT_PTRACED)&&p->state==TASK_STOPPED))
+(p==current||(p->parent==current&&(p->ptrace & PT_PTRACED)&&p->state==TASK_STOPPED))
 
 
 static int mem_open(struct inode* inode, struct file* file)
index 9f34e057079af4d145c678f75fbcd93c98bf12f8..5f0f74653fdaf36d39a190b4c529e508918be0cd 100644 (file)
     time_slice:                HZ,                                             \
     next_task:         &tsk,                                           \
     prev_task:         &tsk,                                           \
-    p_opptr:           &tsk,                                           \
-    p_pptr:            &tsk,                                           \
+    real_parent:       &tsk,                                           \
+    parent:            &tsk,                                           \
+    children:          LIST_HEAD_INIT(tsk.children),                   \
+    sibling:           LIST_HEAD_INIT(tsk.sibling),                    \
     thread_group:      LIST_HEAD_INIT(tsk.thread_group),               \
     wait_chldexit:     __WAIT_QUEUE_HEAD_INITIALIZER(tsk.wait_chldexit),\
     real_timer:                {                                               \
index c71390735df2ca115d587561270fd20a96092188..009436ba5de6d24a73440f2e25fdc9dd0cebc74e 100644 (file)
@@ -274,9 +274,12 @@ struct task_struct {
        /* 
         * pointers to (original) parent process, youngest child, younger sibling,
         * older sibling, respectively.  (p->father can be replaced with 
-        * p->p_pptr->pid)
+        * p->parent->pid)
         */
-       struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
+       struct task_struct *real_parent; /* real parent process (when being debugged) */
+       struct task_struct *parent;     /* parent process */
+       struct list_head children;      /* list of my children */
+       struct list_head sibling;       /* linkage in my parent's children list */
        struct list_head thread_group;
 
        /* PID hash table linkage. */
@@ -715,28 +718,44 @@ do {                                                                      \
        __ret;                                                          \
 })
 
-#define REMOVE_LINKS(p) do { \
-       (p)->next_task->prev_task = (p)->prev_task; \
-       (p)->prev_task->next_task = (p)->next_task; \
-       if ((p)->p_osptr) \
-               (p)->p_osptr->p_ysptr = (p)->p_ysptr; \
-       if ((p)->p_ysptr) \
-               (p)->p_ysptr->p_osptr = (p)->p_osptr; \
-       else \
-               (p)->p_pptr->p_cptr = (p)->p_osptr; \
+#define REMOVE_LINKS(p) do {                           \
+       (p)->next_task->prev_task = (p)->prev_task;     \
+       (p)->prev_task->next_task = (p)->next_task;     \
+       list_del_init(&(p)->sibling);                   \
        } while (0)
 
-#define SET_LINKS(p) do { \
-       (p)->next_task = &init_task; \
-       (p)->prev_task = init_task.prev_task; \
-       init_task.prev_task->next_task = (p); \
-       init_task.prev_task = (p); \
-       (p)->p_ysptr = NULL; \
-       if (((p)->p_osptr = (p)->p_pptr->p_cptr) != NULL) \
-               (p)->p_osptr->p_ysptr = p; \
-       (p)->p_pptr->p_cptr = p; \
+#define SET_LINKS(p) do {                                      \
+       (p)->next_task = &init_task;                            \
+       (p)->prev_task = init_task.prev_task;                   \
+       init_task.prev_task->next_task = (p);                   \
+       init_task.prev_task = (p);                              \
+       list_add_tail(&(p)->sibling,&(p)->parent->children);    \
        } while (0)
 
+static inline struct task_struct *eldest_child(struct task_struct *p)
+{
+       if (list_empty(&p->children)) return NULL;
+       return list_entry(p->children.next,struct task_struct,sibling);
+}
+
+static inline struct task_struct *youngest_child(struct task_struct *p)
+{
+       if (list_empty(&p->children)) return NULL;
+       return list_entry(p->children.prev,struct task_struct,sibling);
+}
+
+static inline struct task_struct *older_sibling(struct task_struct *p)
+{
+       if (p->sibling.prev==&p->parent->children) return NULL;
+       return list_entry(p->sibling.prev,struct task_struct,sibling);
+}
+
+static inline struct task_struct *younger_sibling(struct task_struct *p)
+{
+       if (p->sibling.next==&p->parent->children) return NULL;
+       return list_entry(p->sibling.next,struct task_struct,sibling);
+}
+
 #define for_each_task(p) \
        for (p = &init_task ; (p = p->next_task) != &init_task ; )
 
index 45214fffb162124487b3a556af4e35eee8bb241b..4410c1405ea5f636e5e1bc2249f9efd22dd491cf 100644 (file)
@@ -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);
index 2f3f7301236f2f76490b507fe5a0ca67640d06b2..a05f52776e358d1c36ac75518eddb210dfb57da5 100644 (file)
@@ -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) {
index a5db3a5c57935a6eff1c43cf1e24a5470c04a9f5..bade71e2c0f0f51b651279e1949dcb9ce7ea0b37 100644 (file)
@@ -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);
 
index 73110e6a8abc2b7c527eb720bc8e688016583eb2..49aa10fe905c34dc9e6a0935bdb95ef226daba41 100644 (file)
@@ -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)
index 25846598407a2d45a3bad4eb8cb8090518b60a01..440ffbdf1e9cdd68b4bec08b181444492a34dbe1 100644 (file)
@@ -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);
 }
 
 
index 56d483f984fd4c2536fbe59f75e86e469030abc2..fc8e5e4060a01e298e70871e5f46f19c5a97a525 100644 (file)
@@ -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;
index 6b79d204588297ae8a2e94b5ae2403a93793d179..504af956c037576d180a1e29ab8d537319e250d9 100644 (file)
@@ -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;
 }