Commit 19bb2ab9 authored by John Levon's avatar John Levon Committed by Linus Torvalds

[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.
parent dec3735e
......@@ -1048,6 +1048,11 @@ CONFIG_DEBUG_OBSOLETE
Say Y here if you want to reduce the chances of the tree compiling,
and are prepared to dig into driver internals to fix compile errors.
Profiling support
CONFIG_PROFILING
Say Y here to enable the extended profiling support mechanisms used
by profilers such as OProfile.
Software Suspend
CONFIG_SOFTWARE_SUSPEND
Enable the possibilty of suspendig machine. It doesn't need APM.
......
......@@ -442,6 +442,13 @@ source drivers/usb/Config.in
source net/bluetooth/Config.in
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
mainmenu_option next_comment
comment 'Profiling support'
bool 'Profiling support (EXPERIMENTAL)' CONFIG_PROFILING
endmenu
fi
mainmenu_option next_comment
comment 'Kernel hacking'
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
......
#ifndef _LINUX_PROFILE_H
#define _LINUX_PROFILE_H
#ifdef __KERNEL__
#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/init.h>
#include <asm/errno.h>
enum profile_type {
EXIT_TASK,
EXIT_MMAP,
EXEC_UNMAP
};
#ifdef CONFIG_PROFILING
struct notifier_block;
struct task_struct;
struct mm_struct;
/* task is in do_exit() */
void profile_exit_task(struct task_struct * task);
/* change of vma mappings */
void profile_exec_unmap(struct mm_struct * mm);
/* exit of all vmas for a task */
void profile_exit_mmap(struct mm_struct * mm);
int profile_event_register(enum profile_type, struct notifier_block * n);
int profile_event_unregister(enum profile_type, struct notifier_block * n);
#else
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_exit_task(a) do { } while (0)
#define profile_exec_unmap(a) do { } while (0)
#define profile_exit_mmap(a) do { } while (0)
#endif /* CONFIG_PROFILING */
#endif /* __KERNEL__ */
#endif /* _LINUX_PROFILE_H */
......@@ -3,9 +3,10 @@
#
export-objs = signal.o sys.o kmod.o workqueue.o ksyms.o pm.o exec_domain.o \
printk.o platform.o suspend.o dma.o module.o cpufreq.o
printk.o platform.o suspend.o dma.o module.o cpufreq.o \
profile.o
obj-y = sched.o fork.o exec_domain.o panic.o printk.o \
obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
module.o exit.o itimer.o time.o softirq.o resource.o \
sysctl.o capability.o ptrace.o timer.o user.o \
signal.o sys.o kmod.o workqueue.o futex.o platform.o pid.o
......
......@@ -19,6 +19,7 @@
#include <linux/file.h>
#include <linux/binfmts.h>
#include <linux/ptrace.h>
#include <linux/profile.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
......@@ -60,10 +61,11 @@ void release_task(struct task_struct * p)
struct dentry *proc_dentry;
task_t *leader;
if (p->state < TASK_ZOMBIE)
BUG();
BUG_ON(p->state < TASK_ZOMBIE);
if (p != current)
wait_task_inactive(p);
atomic_dec(&p->user->processes);
security_ops->task_free_security(p);
free_uid(p->user);
......@@ -635,6 +637,8 @@ NORET_TYPE void do_exit(long code)
current->comm, current->pid,
preempt_count());
profile_exit_task(tsk);
fake_volatile:
acct_process(code);
__exit_mm(tsk);
......
/*
* 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);
......@@ -16,6 +16,7 @@
#include <linux/fs.h>
#include <linux/personality.h>
#include <linux/security.h>
#include <linux/profile.h>
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
......@@ -1104,6 +1105,10 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
if (mpnt->vm_start >= end)
return 0;
/* Something will probably happen, so notify. */
if (mpnt->vm_file && (mpnt->vm_flags & VM_EXEC))
profile_exec_unmap(mm);
/*
* If we need to split any vma, do it now to save pain later.
*/
......@@ -1253,7 +1258,10 @@ void exit_mmap(struct mm_struct * mm)
mmu_gather_t *tlb;
struct vm_area_struct * mpnt;
profile_exit_mmap(mm);
release_segments(mm);
spin_lock(&mm->page_table_lock);
tlb = tlb_gather_mmu(mm, 1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment