diff --git a/include/linux/profile.h b/include/linux/profile.h index bad18ca43150..2b0561f450d6 100644 --- a/include/linux/profile.h +++ b/include/linux/profile.h @@ -67,9 +67,6 @@ static inline void profile_hit(int type, void *ip) struct task_struct; struct mm_struct; -/* task is in do_exit() */ -void profile_task_exit(struct task_struct * task); - /* task is dead, free task struct ? Returns 1 if * the task was taken, 0 if the task should be freed. */ @@ -81,9 +78,6 @@ void profile_munmap(unsigned long addr); int task_handoff_register(struct notifier_block * n); int task_handoff_unregister(struct notifier_block * n); -int profile_event_register(enum profile_type, struct notifier_block * n); -int profile_event_unregister(enum profile_type, struct notifier_block * n); - struct pt_regs; #else @@ -120,20 +114,15 @@ static inline int task_handoff_unregister(struct notifier_block * n) return -ENOSYS; } -static inline int profile_event_register(enum profile_type t, struct notifier_block * n) -{ - return -ENOSYS; -} - -static inline int profile_event_unregister(enum profile_type t, struct notifier_block * n) -{ - return -ENOSYS; -} - -#define profile_task_exit(a) do { } while (0) #define profile_handoff_task(a) (0) #define profile_munmap(a) do { } while (0) #endif /* CONFIG_PROFILING */ +/* task is in do_exit() */ +void profile_task_exit(struct task_struct * task); + +int profile_event_register(enum profile_type, struct notifier_block * n); +int profile_event_unregister(enum profile_type, struct notifier_block * n); + #endif /* _LINUX_PROFILE_H */ diff --git a/kernel/exit.c b/kernel/exit.c index 87b26d8dddd9..e0a866cc77ce 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -776,6 +776,32 @@ static void check_stack_usage(void) static inline void check_stack_usage(void) {} #endif +#ifndef CONFIG_PROFILING +static BLOCKING_NOTIFIER_HEAD(task_exit_notifier); + +int profile_event_register(enum profile_type t, struct notifier_block *n) +{ + if (t == PROFILE_TASK_EXIT) + return blocking_notifier_chain_register(&task_exit_notifier, n); + + return -ENOSYS; +} + +int profile_event_unregister(enum profile_type t, struct notifier_block *n) +{ + if (t == PROFILE_TASK_EXIT) + return blocking_notifier_chain_unregister(&task_exit_notifier, + n); + + return -ENOSYS; +} + +void profile_task_exit(struct task_struct *tsk) +{ + blocking_notifier_call_chain(&task_exit_notifier, 0, tsk); +} +#endif + void __noreturn do_exit(long code) { struct task_struct *tsk = current;