sched: Add a generic notifier when a task struct is about to be freed

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>
This commit is contained in:
San Mehat 2010-05-06 15:37:55 -07:00 committed by Colin Cross
parent ff3ab81c21
commit 897672e9ff
2 changed files with 19 additions and 0 deletions

View file

@ -1801,6 +1801,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
*/

View file

@ -157,6 +157,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));
@ -187,6 +190,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);
@ -198,6 +213,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);
}