diff options
| author | John Levon <levon@movementarian.org> | 2002-10-15 04:30:26 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2002-10-15 04:30:26 -0700 |
| commit | 19bb2ab92d37ae85fc6d4cb6ae1fea6a8de027b1 (patch) | |
| tree | 5ad54f2904c7c1debc965c1b201d5005d1436733 /kernel/profile.c | |
| parent | dec3735ebf58a4691a0fb2df38a7f1a7c63fdb7d (diff) | |
[PATCH] oprofile - hooks
This implements the simple hooks we need to catch unmappings, and to
make sure no stale task_struct*'s are ever used by the main oprofile
core mechanism. If disabled, it compiles to nothing.
Diffstat (limited to 'kernel/profile.c')
| -rw-r--r-- | kernel/profile.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/kernel/profile.c b/kernel/profile.c new file mode 100644 index 000000000000..7ebffe971ca8 --- /dev/null +++ b/kernel/profile.c @@ -0,0 +1,91 @@ +/* + * linux/kernel/profile.c + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/profile.h> +#include <linux/bootmem.h> +#include <linux/notifier.h> +#include <linux/mm.h> + +/* Profile event notifications */ + +#ifdef CONFIG_PROFILING + +static DECLARE_RWSEM(profile_rwsem); +static struct notifier_block * exit_task_notifier; +static struct notifier_block * exit_mmap_notifier; +static struct notifier_block * exec_unmap_notifier; + +void profile_exit_task(struct task_struct * task) +{ + down_read(&profile_rwsem); + notifier_call_chain(&exit_task_notifier, 0, task); + up_read(&profile_rwsem); +} + +void profile_exit_mmap(struct mm_struct * mm) +{ + down_read(&profile_rwsem); + notifier_call_chain(&exit_mmap_notifier, 0, mm); + up_read(&profile_rwsem); +} + +void profile_exec_unmap(struct mm_struct * mm) +{ + down_read(&profile_rwsem); + notifier_call_chain(&exec_unmap_notifier, 0, mm); + up_read(&profile_rwsem); +} + +int profile_event_register(enum profile_type type, struct notifier_block * n) +{ + int err = -EINVAL; + + down_write(&profile_rwsem); + + switch (type) { + case EXIT_TASK: + err = notifier_chain_register(&exit_task_notifier, n); + break; + case EXIT_MMAP: + err = notifier_chain_register(&exit_mmap_notifier, n); + break; + case EXEC_UNMAP: + err = notifier_chain_register(&exec_unmap_notifier, n); + break; + } + + up_write(&profile_rwsem); + + return err; +} + + +int profile_event_unregister(enum profile_type type, struct notifier_block * n) +{ + int err = -EINVAL; + + down_write(&profile_rwsem); + + switch (type) { + case EXIT_TASK: + err = notifier_chain_unregister(&exit_task_notifier, n); + break; + case EXIT_MMAP: + err = notifier_chain_unregister(&exit_mmap_notifier, n); + break; + case EXEC_UNMAP: + err = notifier_chain_unregister(&exec_unmap_notifier, n); + break; + } + + up_write(&profile_rwsem); + return err; +} + +#endif /* CONFIG_PROFILING */ + +EXPORT_SYMBOL_GPL(profile_event_register); +EXPORT_SYMBOL_GPL(profile_event_unregister); |
