Makefile | 2 +- include/linux/list.h | 14 ++++++++++++++ include/linux/sched.h | 4 ++-- kernel/exit.c | 28 ++++++++++++++-------------- 4 files changed, 31 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index daeb5c88b50b..cc4b0a266af0 100644 --- a/Makefile +++ b/Makefile @@ -515,7 +515,7 @@ KBUILD_CFLAGS := -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs \ -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE \ -Werror=implicit-function-declaration -Werror=implicit-int \ -Werror=return-type -Wno-format-security \ - -std=gnu89 + -std=gnu11 KBUILD_CPPFLAGS := -D__KERNEL__ KBUILD_AFLAGS_KERNEL := KBUILD_CFLAGS_KERNEL := diff --git a/include/linux/list.h b/include/linux/list.h index dd6c2041d09c..1e8b3e495b51 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -25,6 +25,9 @@ #define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name) +#define list_traversal_head(type,name,target_member) \ + union { struct list_head name; type *name##_traversal_type; } + /** * INIT_LIST_HEAD - Initialize a list_head structure * @list: list_head structure to be initialized. @@ -628,6 +631,17 @@ static inline void list_splice_tail_init(struct list_head *list, #define list_entry_is_head(pos, head, member) \ (&pos->member == (head)) +/** + * list_traverse - iterate over a typed list + * @pos: the name to use for the loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the type. + */ +#define list_traverse(pos, head, member) \ + for (typeof(*head##_traversal_type) pos = list_first_entry(head, typeof(*pos), member); \ + !list_entry_is_head(pos, head, member); \ + pos = list_next_entry(pos, member)) + /** * list_for_each_entry - iterate over list of given type * @pos: the type * to use as a loop cursor. diff --git a/include/linux/sched.h b/include/linux/sched.h index 75ba8aa60248..55e60405da1c 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -965,7 +965,7 @@ struct task_struct { /* * Children/sibling form the list of natural children: */ - struct list_head children; + list_traversal_head(struct task_struct, children, sibling); struct list_head sibling; struct task_struct *group_leader; @@ -975,7 +975,7 @@ struct task_struct { * This includes both natural children and PTRACE_ATTACH targets. * 'ptrace_entry' is this task's link on the p->parent->ptraced list. */ - struct list_head ptraced; + list_traversal_head(struct task_struct, ptraced, ptrace_entry); struct list_head ptrace_entry; /* PID/PID hash table linkage. */ diff --git a/kernel/exit.c b/kernel/exit.c index b00a25bb4ab9..c85cb1a6bec2 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -409,17 +409,21 @@ void mm_update_next_owner(struct mm_struct *mm) /* * Search in the children */ - list_for_each_entry(c, &p->children, sibling) { - if (c->mm == mm) - goto assign_new_owner; + list_traverse(pos, &p->children, sibling) { + if (pos->mm != mm) + continue; + c = pos; + goto assign_new_owner; } /* * Search in the siblings */ - list_for_each_entry(c, &p->real_parent->children, sibling) { - if (c->mm == mm) - goto assign_new_owner; + list_traverse(pos, &p->real_parent->children, sibling) { + if (pos->mm != mm) + continue; + c = pos; + goto assign_new_owner; } /* @@ -628,7 +632,7 @@ static void reparent_leader(struct task_struct *father, struct task_struct *p, static void forget_original_parent(struct task_struct *father, struct list_head *dead) { - struct task_struct *p, *t, *reaper; + struct task_struct *t, *reaper; if (unlikely(!list_empty(&father->ptraced))) exit_ptrace(father, dead); @@ -639,7 +643,7 @@ static void forget_original_parent(struct task_struct *father, return; reaper = find_new_reaper(father, reaper); - list_for_each_entry(p, &father->children, sibling) { + list_traverse(p, &father->children, sibling) { for_each_thread(p, t) { RCU_INIT_POINTER(t->real_parent, reaper); BUG_ON((!t->ptrace) != (rcu_access_pointer(t->parent) == father)); @@ -1405,9 +1409,7 @@ static int wait_consider_task(struct wait_opts *wo, int ptrace, */ static int do_wait_thread(struct wait_opts *wo, struct task_struct *tsk) { - struct task_struct *p; - - list_for_each_entry(p, &tsk->children, sibling) { + list_traverse(p, &tsk->children, sibling) { int ret = wait_consider_task(wo, 0, p); if (ret) @@ -1419,9 +1421,7 @@ static int do_wait_thread(struct wait_opts *wo, struct task_struct *tsk) static int ptrace_do_wait(struct wait_opts *wo, struct task_struct *tsk) { - struct task_struct *p; - - list_for_each_entry(p, &tsk->ptraced, ptrace_entry) { + list_traverse(p, &tsk->ptraced, ptrace_entry) { int ret = wait_consider_task(wo, 1, p); if (ret)