summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSan Mehat <san@google.com>2011-12-13 01:08:18 +0800
committerAndy Green <andy.green@linaro.org>2012-01-09 10:26:39 +0800
commit5b196f64ebe07624d44eadb5e0ea72f8dd2e22cc (patch)
tree163bd57f12b8ecee9f5de09a5622c81e9410ea5c
parentc97c51cfafe6ba958dff7417e6e880cd48863928 (diff)
sched: Add a generic notifier when a task struct is about to be freedlinaro-androidization-topic-sched
This patch adds a notifier which can be used by subsystems that may be interested in when a task has completely died and is about to have it's last resource freed. The Android lowmemory killer uses this to determine when a task it has killed has finally given up its goods. Signed-off-by: San Mehat <san@google.com>
-rw-r--r--include/linux/sched.h3
-rw-r--r--kernel/fork.c16
2 files changed, 19 insertions, 0 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 1c4f3e9b9bc..653c9c3799b 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1756,6 +1756,9 @@ static inline void put_task_struct(struct task_struct *t)
extern void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st);
extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st);
+extern int task_free_register(struct notifier_block *n);
+extern int task_free_unregister(struct notifier_block *n);
+
/*
* Per process flags
*/
diff --git a/kernel/fork.c b/kernel/fork.c
index da4a6a10d08..69c2e4ce3a3 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -153,6 +153,9 @@ struct kmem_cache *vm_area_cachep;
/* SLAB cache for mm_struct structures (tsk->mm) */
static struct kmem_cache *mm_cachep;
+/* Notifier list called when a task struct is freed */
+static ATOMIC_NOTIFIER_HEAD(task_free_notifier);
+
static void account_kernel_stack(struct thread_info *ti, int account)
{
struct zone *zone = page_zone(virt_to_page(ti));
@@ -183,6 +186,18 @@ static inline void put_signal_struct(struct signal_struct *sig)
free_signal_struct(sig);
}
+int task_free_register(struct notifier_block *n)
+{
+ return atomic_notifier_chain_register(&task_free_notifier, n);
+}
+EXPORT_SYMBOL(task_free_register);
+
+int task_free_unregister(struct notifier_block *n)
+{
+ return atomic_notifier_chain_unregister(&task_free_notifier, n);
+}
+EXPORT_SYMBOL(task_free_unregister);
+
void __put_task_struct(struct task_struct *tsk)
{
WARN_ON(!tsk->exit_state);
@@ -193,6 +208,7 @@ void __put_task_struct(struct task_struct *tsk)
delayacct_tsk_free(tsk);
put_signal_struct(tsk->signal);
+ atomic_notifier_call_chain(&task_free_notifier, 0, tsk);
if (!profile_handoff_task(tsk))
free_task(tsk);
}