add task handling notifier: base definitions
Subsystems (3)
PATCH 1/4 add task handling notifier: base definitions
This is the base patch, adding notification for task creation and deletion.
--- include/linux/sched.h | 8 +++++++- kernel/fork.c | 11 +++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-)
include/linux/sched.h +7 -1
@@ -80,7 +80,7 @@ struct sched_param {#include <linux/rcupdate.h> #include <linux/futex.h> #include <linux/rtmutex.h> - +#include <linux/notifier.h> #include <linux/time.h> #include <linux/param.h> #include <linux/resource.h>
@@ -1700,6 +1700,12 @@ extern int do_execve(char *, char __userextern long do_fork (unsigned long ,unsigned long ,struct pt_regs *,unsigned long ,int __user *,int __user *);struct task_struct *fork_idle (int ); +#define TASK_NEW 1 +#define TASK_DELETE 2 + +extern struct blocking_notifier_head task_notifier_list; +extern struct atomic_notifier_head atomic_task_notifier_list; +extern void set_task_comm (struct task_struct *tsk,char *from);extern void get_task_comm (char *to,struct task_struct *tsk);
kernel/fork.c +11 -0
@@ -46,6 +46,7 @@#include <linux/tsacct_kern.h> #include <linux/cn_proc.h> #include <linux/freezer.h> +#include <linux/notifier.h> #include <linux/delayacct.h> #include <linux/taskstats_kern.h> #include <linux/random.h>
@@ -71,6 +72,11 @@ DEFINE_PER_CPU(unsigned long, process_co__cacheline_aligned DEFINE_RWLOCK (tasklist_lock );/* outer */ +BLOCKING_NOTIFIER_HEAD (task_notifier_list); +EXPORT_SYMBOL_GPL (task_notifier_list); +ATOMIC_NOTIFIER_HEAD (atomic_task_notifier_list); +EXPORT_SYMBOL_GPL (atomic_task_notifier_list); +int nr_processes (void ) {int cpu;
@@ -121,6 +127,9 @@ void __put_task_struct(struct task_strucWARN_ON (atomic_read (&tsk->usage));WARN_ON (tsk == current); +atomic_notifier_call_chain (&atomic_task_notifier_list, +TASK_DELETE , tsk); +security_task_free (tsk);free_uid (tsk->user);put_group_info (tsk->group_info);
@@ -1450,6 +1459,8 @@ long do_fork(unsigned long clone_flags,set_tsk_thread_flag (p,TIF_SIGPENDING ); } +blocking_notifier_call_chain (&task_notifier_list,TASK_NEW , p); +if (!(clone_flags &CLONE_STOPPED ))wake_up_new_task (p, clone_flags);else
Quoted 2 lines · Jan Beulich
This is the base patch, adding notification for task creation and deletion.
I like the basic concept. At some point I suspect we'll even need a per task dynamic data allocator, that would remove even more cruft.
Could you change the block notifier calls first to not take their lock when there is nothing in the list (the common case)? It is weird that they don't already do this, but they should definitely here.
I think the use of the blocking/atomic notifiers needs some comment. I think I understand why you did it -- exit atomic because sleeping in exit can be illegal and blocking for fork to allow GFP_KERNEL allocations -- but that should be documented somewhere.
-Andi
Quoted 44 lines · Jan Beulich
This is the base patch, adding notification for task creation and deletion.
Signed-off-by Jan Beulich <[email protected]>--- include/linux/sched.h | 8 +++++++- kernel/fork.c | 11 +++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-)include/linux/sched.h +7
-1@@ -80,7 +80,7 @@ struct sched_param {#include <linux/rcupdate.h> #include <linux/futex.h> #include <linux/rtmutex.h> - +#include <linux/notifier.h> #include <linux/time.h> #include <linux/param.h> #include <linux/resource.h> @@ -1700,6 +1700,12 @@ extern int do_execve(char *, char __userextern long do_fork (unsigned long ,unsigned long ,struct pt_regs *,unsigned long ,int __user *,int __user *);struct task_struct *fork_idle (int ); +#define TASK_NEW 1 +#define TASK_DELETE 2 + +extern struct blocking_notifier_head task_notifier_list; +extern struct atomic_notifier_head atomic_task_notifier_list; +extern void set_task_comm (struct task_struct *tsk,char *from);extern void get_task_comm (char *to,struct task_struct *tsk);kernel/fork.c +1
-0@@ -46,6 +46,7 @@#include <linux/tsacct_kern.h> #include <linux/cn_proc.h> #include <linux/freezer.h> +#include <linux/notifier.h> #include <linux/delayacct.h> #include <linux/taskstats_kern.h> #include <linux/random.h>
kernel/fork.c DEFINE_PER_CPU(unsigned long, process_co · line 79
Quoted 8 lines
kernel/fork.c +5
-0@@ -71,6 +72,11 @@ DEFINE_PER_CPU(unsigned long, process_co__cacheline_aligned DEFINE_RWLOCK (tasklist_lock );/* outer */ +BLOCKING_NOTIFIER_HEAD (task_notifier_list); +EXPORT_SYMBOL_GPL (task_notifier_list); +ATOMIC_NOTIFIER_HEAD (atomic_task_notifier_list); +EXPORT_SYMBOL_GPL (atomic_task_notifier_list); +
When these global notifier lists were proposed years ago folks at SGI loudly objected with concerns over anticipated cache line bouncing on 512+ cpu machines. Is that no longer a concern?
kernel/fork.c void __put_task_struct(struct task_struc · line 135
Quoted 13 lines
kernel/fork.c +3
-0int nr_processes (void ) {int cpu;@@ -121,6 +127,9 @@ void __put_task_struct(struct task_strucWARN_ON (atomic_read (&tsk->usage));WARN_ON (tsk == current); +atomic_notifier_call_chain (&atomic_task_notifier_list, +TASK_DELETE , tsk); +security_task_free (tsk);free_uid (tsk->user);put_group_info (tsk->group_info);
Would the atomic notifier call chain be necessary if you hooked into an earlier section of do_exit() instead?
Cheers,
-Matt Helsley
Quoted 9 lines
kernel/fork.c DEFINE_PER_CPU(unsigned long, process_co · line 79
Quoted 5 lines
kernel/fork.c +5
-0+BLOCKING_NOTIFIER_HEAD (task_notifier_list); +EXPORT_SYMBOL_GPL (task_notifier_list); +ATOMIC_NOTIFIER_HEAD (atomic_task_notifier_list); +EXPORT_SYMBOL_GPL (atomic_task_notifier_list); +When these global notifier lists were proposed years ago folks at SGI loudly objected with concerns over anticipated cache line bouncing on 512+ cpu machines. Is that no longer a concern?
I can't see an alternative, since the serialization is unavoidable.
Quoted 4 lines
Quoted 4 lines
kernel/fork.c +0
-0@@ -121,6 +127,9 @@ void __put_task_struct(struct task_strucWARN_ON (atomic_read (&tsk->usage));WARN_ON (tsk == current);
Quoted 9 lines
kernel/fork.c void __put_task_struct(struct task_struc · line 135
Quoted 6 lines
kernel/fork.c +3
-0+atomic_notifier_call_chain (&atomic_task_notifier_list, +TASK_DELETE , tsk); +security_task_free (tsk);free_uid (tsk->user);put_group_info (tsk->group_info);Would the atomic notifier call chain be necessary if you hooked into an earlier section of
do_exit()instead?
I'm afraid it is, as I was told that sleeping in the do_exit() path is not generally possible.
Jan
Quoted 11 lines · Jan Beulich
Quoted 9 lines
kernel/fork.c DEFINE_PER_CPU(unsigned long, process_co · line 79
Quoted 5 lines
kernel/fork.c +5
-0+BLOCKING_NOTIFIER_HEAD (task_notifier_list); +EXPORT_SYMBOL_GPL (task_notifier_list); +ATOMIC_NOTIFIER_HEAD (atomic_task_notifier_list); +EXPORT_SYMBOL_GPL (atomic_task_notifier_list); +When these global notifier lists were proposed years ago folks at SGI loudly objected with concerns over anticipated cache line bouncing on 512+ cpu machines. Is that no longer a concern?
I can't see an alternative, since the serialization is unavoidable.
There are definitely alternatives. Naturally they are all much more complex than using a single notifier chain. You could do per-cpu chains for example (ugly, I know..).
Quoted 14 lines
Quoted 4 lines
Quoted 4 lines
kernel/fork.c +0
-0@@ -121,6 +127,9 @@ void __put_task_struct(struct task_strucWARN_ON (atomic_read (&tsk->usage));WARN_ON (tsk == current);Quoted 9 lines
kernel/fork.c void __put_task_struct(struct task_struc · line 135
Quoted 6 lines
kernel/fork.c +3
-0+atomic_notifier_call_chain (&atomic_task_notifier_list, +TASK_DELETE , tsk); +security_task_free (tsk);free_uid (tsk->user);put_group_info (tsk->group_info);Would the atomic notifier call chain be necessary if you hooked into an earlier section of
do_exit()instead?
Quoted 4 lines
I'm afraid it is, as I was told that sleeping in the
do_exit()path is not generally possible.Jan
Odd. Last I checked I thought I saw a bunch of calls in do_exit() that could sleep. Only in certain sections and at the end did it appear to prevent sleeping.
Sorry for the late reply.
Cheers,
-Matt Helsley