aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/exit.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/exit.c')
-rw-r--r--kernel/exit.c66
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)