here's a (tested) patch i did that should simplify changes done to
p->children and p->sibling handling.
Ingo
---------------------->
Subject: [patch] uninline remove/add_parent() APIs
From: Ingo Molnar <[email protected]>
uninline/simplify remove/add_parent() APIs.
Signed-off-by: Ingo Molnar <[email protected]>
---
include/linux/sched.h | 5 +++--
kernel/exit.c | 31 +++++++++++++++++++++----------
kernel/fork.c | 2 +-
kernel/ptrace.c | 11 ++++-------
4 files changed, 29 insertions(+), 20 deletions(-)
Index: linux/include/linux/sched.h
===================================================================
--- linux.orig/include/linux/sched.h
+++ linux/include/linux/sched.h
@@ -1418,8 +1418,9 @@ extern void wait_task_inactive(struct ta
#define wait_task_inactive(p) do { } while (0)
#endif
-#define remove_parent(p) list_del_init(&(p)->sibling)
-#define add_parent(p) list_add_tail(&(p)->sibling,&(p)->parent->children)
+extern void
+task_relink_parent(struct task_struct *p, struct task_struct *new_real_parent,
+ struct task_struct *new_parent);
#define next_task(p) list_entry(rcu_dereference((p)->tasks.next), struct task_struct, tasks)
Index: linux/kernel/exit.c
===================================================================
--- linux.orig/kernel/exit.c
+++ linux/kernel/exit.c
@@ -52,6 +52,20 @@ extern void sem_exit (void);
static void exit_mm(struct task_struct * tsk);
+void
+task_relink_parent(struct task_struct *p,
+ struct task_struct *new_real_parent,
+ struct task_struct *new_parent)
+{
+ /*
+ * Move this task to a new parent's children list.
+ * (if p->parent == new->parent this this requeues from head to tail)
+ */
+ list_move_tail(&p->sibling, &new_parent->children);
+ p->real_parent = new_real_parent;
+ p->parent = new_parent;
+}
+
static void __unhash_process(struct task_struct *p)
{
nr_threads--;
@@ -64,7 +78,7 @@ static void __unhash_process(struct task
__get_cpu_var(process_counts)--;
}
list_del_rcu(&p->thread_group);
- remove_parent(p);
+ list_del_init(&p->sibling);
}
/*
@@ -268,14 +282,14 @@ static int has_stopped_jobs(struct pid *
*/
static void reparent_to_init(void)
{
+ struct task_struct *reaper;
+
write_lock_irq(&tasklist_lock);
ptrace_unlink(current);
/* Reparent to init */
- remove_parent(current);
- current->parent = child_reaper(current);
- current->real_parent = child_reaper(current);
- add_parent(current);
+ reaper = child_reaper(current);
+ task_relink_parent(current, reaper, reaper);
/* Set the exit signal to SIGCHLD so we signal init on exit */
current->exit_signal = SIGCHLD;
@@ -611,9 +625,7 @@ reparent_thread(struct task_struct *p, s
* anyway, so let go of it.
*/
p->ptrace = 0;
- remove_parent(p);
- p->parent = p->real_parent;
- add_parent(p);
+ task_relink_parent(p, p->real_parent, p->real_parent);
if (p->state == TASK_TRACED) {
/*
@@ -1344,8 +1356,7 @@ bail_ref:
}
/* move to end of parent's list to avoid starvation */
- remove_parent(p);
- add_parent(p);
+ task_relink_parent(p, p->real_parent, p->parent);
write_unlock_irq(&tasklist_lock);
Index: linux/kernel/fork.c
===================================================================
--- linux.orig/kernel/fork.c
+++ linux/kernel/fork.c
@@ -1242,7 +1242,7 @@ static struct task_struct *copy_process(
}
if (likely(p->pid)) {
- add_parent(p);
+ list_add_tail(&p->sibling, &p->parent->children);
if (unlikely(p->ptrace & PT_PTRACED))
__ptrace_link(p, current->parent);
Index: linux/kernel/ptrace.c
===================================================================
--- linux.orig/kernel/ptrace.c
+++ linux/kernel/ptrace.c
@@ -34,11 +34,9 @@ void __ptrace_link(struct task_struct *c
if (child->parent == new_parent)
return;
list_add(&child->ptrace_list, &child->parent->ptrace_children);
- remove_parent(child);
- child->parent = new_parent;
- add_parent(child);
+ task_relink_parent(child, new_parent, child->real_parent);
}
-
+
/*
* Turn a tracing stop into a normal stop now, since with no tracer there
* would be no way to wake it up with SIGCONT or SIGKILL. If there was a
@@ -72,9 +70,8 @@ void __ptrace_unlink(struct task_struct
child->ptrace = 0;
if (!list_empty(&child->ptrace_list)) {
list_del_init(&child->ptrace_list);
- remove_parent(child);
- child->parent = child->real_parent;
- add_parent(child);
+ task_relink_parent(child, child->real_parent,
+ child->real_parent);
}
if (child->state == TASK_TRACED)
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]