diff options
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index a75b6a7f458a..235cf6825593 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -772,6 +772,68 @@ static void check_stack_usage(void) static inline void check_stack_usage(void) {} #endif +#ifdef CONFIG_MRVL_OCTEONTX_EL0_INTR +struct task_cleanup_handler { + void (*handler)(struct task_struct *); + struct list_head list; +}; + +static DEFINE_MUTEX(task_cleanup_handlers_mutex); +static LIST_HEAD(task_cleanup_handlers); + +int task_cleanup_handler_add(void (*handler)(struct task_struct *)) +{ + struct task_cleanup_handler *newhandler; + + newhandler = (struct task_cleanup_handler *) + kmalloc(sizeof(struct task_cleanup_handler), GFP_KERNEL); + if (newhandler == NULL) + return -1; + newhandler->handler = handler; + mutex_lock(&task_cleanup_handlers_mutex); + list_add(&newhandler->list, &task_cleanup_handlers); + mutex_unlock(&task_cleanup_handlers_mutex); + return 0; +} +EXPORT_SYMBOL(task_cleanup_handler_add); + +int task_cleanup_handler_remove(void (*handler)(struct task_struct *)) +{ + struct list_head *pos, *tmppos; + struct task_cleanup_handler *curr_task_cleanup_handler; + int retval = -1; + + mutex_lock(&task_cleanup_handlers_mutex); + list_for_each_safe(pos, tmppos, &task_cleanup_handlers) { + curr_task_cleanup_handler + = list_entry(pos, struct task_cleanup_handler, list); + if (curr_task_cleanup_handler->handler == handler) { + list_del(pos); + kfree(curr_task_cleanup_handler); + retval = 0; + } + } + mutex_unlock(&task_cleanup_handlers_mutex); + return retval; +} +EXPORT_SYMBOL(task_cleanup_handler_remove); + +static void task_cleanup_handlers_call(struct task_struct *task) +{ + struct list_head *pos; + struct task_cleanup_handler *curr_task_cleanup_handler; + + mutex_lock(&task_cleanup_handlers_mutex); + list_for_each(pos, &task_cleanup_handlers) { + curr_task_cleanup_handler = + list_entry(pos, struct task_cleanup_handler, list); + if (curr_task_cleanup_handler->handler != NULL) + curr_task_cleanup_handler->handler(task); + } + mutex_unlock(&task_cleanup_handlers_mutex); +} +#endif + void __noreturn do_exit(long code) { struct task_struct *tsk = current; @@ -861,6 +923,10 @@ void __noreturn do_exit(long code) tsk->exit_code = code; taskstats_exit(tsk, group_dead); +#ifdef CONFIG_MRVL_OCTEONTX_EL0_INTR + task_cleanup_handlers_call(tsk); +#endif + exit_mm(); if (group_dead) |