2 * linux/kernel/profile.c
5 #include <linux/config.h>
6 #include <linux/module.h>
7 #include <linux/profile.h>
8 #include <linux/bootmem.h>
9 #include <linux/notifier.h>
12 extern char _stext
, _etext
;
14 unsigned int * prof_buffer
;
15 unsigned long prof_len
;
16 unsigned long prof_shift
;
19 int __init
profile_setup(char * str
)
22 if (get_option(&str
,&par
)) {
25 printk(KERN_INFO
"kernel profiling enabled\n");
31 void __init
profile_init(void)
38 /* only text is profiled */
39 prof_len
= (unsigned long) &_etext
- (unsigned long) &_stext
;
40 prof_len
>>= prof_shift
;
42 size
= prof_len
* sizeof(unsigned int) + PAGE_SIZE
- 1;
43 prof_buffer
= (unsigned int *) alloc_bootmem(size
);
46 /* Profile event notifications */
48 #ifdef CONFIG_PROFILING
50 static DECLARE_RWSEM(profile_rwsem
);
51 static struct notifier_block
* exit_task_notifier
;
52 static struct notifier_block
* exit_mmap_notifier
;
53 static struct notifier_block
* exec_unmap_notifier
;
55 void profile_exit_task(struct task_struct
* task
)
57 down_read(&profile_rwsem
);
58 notifier_call_chain(&exit_task_notifier
, 0, task
);
59 up_read(&profile_rwsem
);
62 void profile_exit_mmap(struct mm_struct
* mm
)
64 down_read(&profile_rwsem
);
65 notifier_call_chain(&exit_mmap_notifier
, 0, mm
);
66 up_read(&profile_rwsem
);
69 void profile_exec_unmap(struct mm_struct
* mm
)
71 down_read(&profile_rwsem
);
72 notifier_call_chain(&exec_unmap_notifier
, 0, mm
);
73 up_read(&profile_rwsem
);
76 int profile_event_register(enum profile_type type
, struct notifier_block
* n
)
80 down_write(&profile_rwsem
);
84 err
= notifier_chain_register(&exit_task_notifier
, n
);
87 err
= notifier_chain_register(&exit_mmap_notifier
, n
);
90 err
= notifier_chain_register(&exec_unmap_notifier
, n
);
94 up_write(&profile_rwsem
);
100 int profile_event_unregister(enum profile_type type
, struct notifier_block
* n
)
104 down_write(&profile_rwsem
);
108 err
= notifier_chain_unregister(&exit_task_notifier
, n
);
111 err
= notifier_chain_unregister(&exit_mmap_notifier
, n
);
114 err
= notifier_chain_unregister(&exec_unmap_notifier
, n
);
118 up_write(&profile_rwsem
);
122 static struct notifier_block
* profile_listeners
;
123 static rwlock_t profile_lock
= RW_LOCK_UNLOCKED
;
125 int register_profile_notifier(struct notifier_block
* nb
)
128 write_lock_irq(&profile_lock
);
129 err
= notifier_chain_register(&profile_listeners
, nb
);
130 write_unlock_irq(&profile_lock
);
135 int unregister_profile_notifier(struct notifier_block
* nb
)
138 write_lock_irq(&profile_lock
);
139 err
= notifier_chain_unregister(&profile_listeners
, nb
);
140 write_unlock_irq(&profile_lock
);
145 void profile_hook(struct pt_regs
* regs
)
147 read_lock(&profile_lock
);
148 notifier_call_chain(&profile_listeners
, 0, regs
);
149 read_unlock(&profile_lock
);
152 EXPORT_SYMBOL_GPL(register_profile_notifier
);
153 EXPORT_SYMBOL_GPL(unregister_profile_notifier
);
155 #endif /* CONFIG_PROFILING */
157 EXPORT_SYMBOL_GPL(profile_event_register
);
158 EXPORT_SYMBOL_GPL(profile_event_unregister
);