Messages in this thread Patch in this message | | | Date | Fri, 30 Mar 2012 20:31:04 +0200 | From | Oleg Nesterov <> | Subject | syscall_regfunc() && TIF_SYSCALL_TRACEPOINT |
| |
Hello.
I've looked at syscall_regfunc/unregfunc by accident, and I am a bit confused...
void syscall_regfunc(void) { unsigned long flags; struct task_struct *g, *t;
if (!sys_tracepoint_refcount) { read_lock_irqsave(&tasklist_lock, flags);
Why _irqsave? write_lock(tasklist) needs to disable irqs, but read_ doesn't. Any subtle reason I missed?
do_each_thread(g, t) { /* Skip kernel threads. */ if (t->mm)
We should check PF_KTHREAD, not ->mm.
set_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT);
But the main question is, can't we race with clone() and miss the new child? The new task is not "visible" to do_each_thread() until copy_process()->list_add_tail_rcu(thread_group/init_task.tasks).
Don't we need something like the patch below?
Oleg.
--- x/kernel/fork.c +++ x/kernel/fork.c @@ -1446,7 +1446,12 @@ static struct task_struct *copy_process( total_forks++; spin_unlock(¤t->sighand->siglock); +#ifdef CONFIG_TRACEPOINTS + if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) + set_tsk_thread_flag(p, TIF_SYSCALL_TRACEPOINT); +#endif write_unlock_irq(&tasklist_lock); + proc_fork_connector(p); cgroup_post_fork(p); if (clone_flags & CLONE_THREAD)
| |