diff options
author | Oleg Nesterov <oleg@redhat.com> | 2012-05-10 20:59:07 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-05-23 22:09:21 -0400 |
commit | e73f8959af0439d114847eab5a8a5ce48f1217c4 (patch) | |
tree | 47f056093590a5e5552e3a75f163e1f798063bda /kernel/fork.c | |
parent | 62366c88b29c5a32e1531142092f98eaf49b1103 (diff) |
task_work_add: generic process-context callbacks
Provide a simple mechanism that allows running code in the (nonatomic)
context of the arbitrary task.
The caller does task_work_add(task, task_work) and this task executes
task_work->func() either from do_notify_resume() or from do_exit(). The
callback can rely on PF_EXITING to detect the latter case.
"struct task_work" can be embedded in another struct, still it has "void
*data" to handle the most common/simple case.
This allows us to kill the ->replacement_session_keyring hack, and
potentially this can have more users.
Performance-wise, this adds 2 "unlikely(!hlist_empty())" checks into
tracehook_notify_resume() and do_exit(). But at the same time we can
remove the "replacement_session_keyring != NULL" checks from
arch/*/signal.c and exit_creds().
Note: task_work_add/task_work_run abuses ->pi_lock. This is only because
this lock is already used by lookup_pi_state() to synchronize with
do_exit() setting PF_EXITING. Fortunately the scope of this lock in
task_work.c is really tiny, and the code is unlikely anyway.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: David Howells <dhowells@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Richard Kuo <rkuo@codeaurora.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Alexander Gordeev <agordeev@redhat.com>
Cc: Chris Zankel <chris@zankel.net>
Cc: David Smith <dsmith@redhat.com>
Cc: "Frank Ch. Eigler" <fche@redhat.com>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Larry Woodman <lwoodman@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Tejun Heo <tj@kernel.org>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 05c813dc9ecc..a46db217a589 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -1411,6 +1411,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1411 | */ | 1411 | */ |
1412 | p->group_leader = p; | 1412 | p->group_leader = p; |
1413 | INIT_LIST_HEAD(&p->thread_group); | 1413 | INIT_LIST_HEAD(&p->thread_group); |
1414 | INIT_HLIST_HEAD(&p->task_works); | ||
1414 | 1415 | ||
1415 | /* Now that the task is set up, run cgroup callbacks if | 1416 | /* Now that the task is set up, run cgroup callbacks if |
1416 | * necessary. We need to run them before the task is visible | 1417 | * necessary. We need to run them before the task is visible |