oprofile - timer hook
Subsystems (2)
PATCH 3/7 oprofile - timer hook
This patch implements a simple hook into the profiling timer for x86 so that non-perfctr machines can still use oprofile. This has proven useful for laptops and the like.
It also reduces header dependencies a bit by centralising readprofile code
arch/i386/kernel/Makefile +1 -0
@@ -27,6 +27,7 @@ obj-$(CONFIG_X86_IO_APIC) += io_apic.o obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o obj-$(CONFIG_X86_NUMAQ) += numaq.o +obj-$(CONFIG_PROFILING) += profile.o EXTRA_AFLAGS := -traditional
arch/i386/kernel/apic.c +2 -10
@@ -1008,17 +1008,9 @@inline void smp_local_timer_interrupt (struct pt_regs * regs) { -int user =user_mode (regs);int cpu =smp_processor_id (); -/* -* The profiling function is SMP safe. (nothing can mess -* around with "current", and the profiling counters are -* updated with atomic operations). This is especially -* useful with a profiling multiplier != 1 -*/ -if (!user) -x86_do_profile (regs->eip); +x86_do_profile (regs);if (--prof_counter[cpu] <=0 ) {/*
@@ -1036,7 +1028,7 @@ }#ifdef CONFIG_SMP -update_process_times (user); +update_process_times (user_mode (regs));#endif }
arch/i386/kernel/i386_ksyms.c +3 -0
@@ -167,6 +167,9 @@EXPORT_SYMBOL (rtc_lock); +EXPORT_SYMBOL_GPL (register_profile_notifier); +EXPORT_SYMBOL_GPL (unregister_profile_notifier); +#undef memcpy#undef memsetextern void *memset (void *,int ,__kernel_size_t );
arch/i386/kernel/profile.c +45 -0
45 lines not on this page · raw message
arch/i386/kernel/time.c +0 -5
@@ -64,11 +64,6 @@#include "do_timer.h" -/* -* for x86_do_profile() -*/ -#include <linux/irq.h> -u64 jiffies_64;unsigned long cpu_khz;/* Detected as we calibrate the TSC */
arch/i386/mach-generic/do_timer.h +1 -2
@@ -20,8 +20,7 @@* system, in that case we have to call the local interrupt handler. */ #ifndef CONFIG_X86_LOCAL_APIC -if (!user_mode (regs)) -x86_do_profile (regs->eip); +x86_do_profile (regs);#else if (!using_apic_timer)smp_local_timer_interrupt (regs);
arch/i386/mach-visws/do_timer.h +1 -2
@@ -15,8 +15,7 @@* system, in that case we have to call the local interrupt handler. */ #ifndef CONFIG_X86_LOCAL_APIC -if (!user_mode (regs)) -x86_do_profile (regs->eip); +x86_do_profile (regs);#else if (!using_apic_timer)smp_local_timer_interrupt (regs);
fs/proc/proc_misc.c +1 -0
@@ -38,6 +38,7 @@#include <linux/smp_lock.h> #include <linux/seq_file.h> #include <linux/times.h> +#include <linux/profile.h> #include <asm/uaccess.h> #include <asm/pgtable.h>
include/asm-i386/hw_irq.h +41 -8
74 lines not on this page · raw message
include/linux/profile.h +11 -0
@@ -8,6 +8,17 @@#include <linux/init.h> #include <asm/errno.h> +/* parse command line */ +int __init profile_setup (char * str); + +/* init basic kernel profiler */ +void __init profile_init (void ); + +extern unsigned int * prof_buffer; +extern unsigned long prof_len; +extern unsigned long prof_shift; + +enum profile_type {EXIT_TASK ,EXIT_MMAP ,
include/linux/sched.h +0 -4
@@ -492,10 +492,6 @@extern unsigned long itimer_next;extern void do_timer (struct pt_regs *); -extern unsigned int * prof_buffer; -extern unsigned long prof_len; -extern unsigned long prof_shift; -extern void FASTCALL (__wake_up (wait_queue_head_t *q,unsigned int mode,int nr));extern void FASTCALL (__wake_up_locked (wait_queue_head_t *q,unsigned int mode));extern void FASTCALL (__wake_up_sync (wait_queue_head_t *q,unsigned int mode,int nr));
init/main.c +2 -18
@@ -30,6 +30,7 @@#include <linux/kernel_stat.h> #include <linux/security.h> #include <linux/workqueue.h> +#include <linux/profile.h> #include <asm/io.h> #include <asm/bugs.h>
@@ -52,7 +53,6 @@#error Sorry, your GCC is too old. It builds incorrect kernels.#endif -extern char _stext, _etext;extern char *linux_banner;static int init (void *);
@@ -130,13 +130,6 @@static char * argv_init[MAX_INIT_ARGS +2 ] = {"init" ,NULL , };char * envp_init[MAX_INIT_ENVS +2 ] = {"HOME=/" ,"TERM=linux" ,NULL , }; -static int __init profile_setup (char *str) -{ -int par; -if (get_option (&str,&par)) prof_shift = par; -return 1 ; -} -__setup ("profile=" , profile_setup);static int __init checksetup (char *line)
@@ -411,16 +404,7 @@#ifdef CONFIG_MODULES init_modules ();#endif -if (prof_shift) { -unsigned int size; -/* only text is profiled */ - prof_len = (unsigned long ) &_etext - (unsigned long ) &_stext; - prof_len >>= prof_shift; - - size = prof_len *sizeof (unsigned int ) +PAGE_SIZE -1 ; - prof_buffer = (unsigned int *)alloc_bootmem (size); - } - +profile_init ();kmem_cache_init ();local_irq_enable ();calibrate_delay ();
kernel/profile.c +30 -0
@@ -9,6 +9,36 @@#include <linux/notifier.h> #include <linux/mm.h> +extern char _stext, _etext; + +unsigned int * prof_buffer; +unsigned long prof_len; +unsigned long prof_shift; + +int __init profile_setup (char * str) +{ +int par; +if (get_option (&str,&par)) + prof_shift = par; +return 1 ; +} + + +void __init profile_init (void ) +{ +unsigned int size; + +if (!prof_shift) +return ; + +/* only text is profiled */ + prof_len = (unsigned long ) &_etext - (unsigned long ) &_stext; + prof_len >>= prof_shift; + + size = prof_len *sizeof (unsigned int ) +PAGE_SIZE -1 ; + prof_buffer = (unsigned int *)alloc_bootmem (size); +} +/* Profile event notifications */ #ifdef CONFIG_PROFILING
kernel/timer.c +0 -4
@@ -406,10 +406,6 @@long time_reftime;/* time at last adjustment (s) */ long time_adjust; -unsigned int * prof_buffer; -unsigned long prof_len; -unsigned long prof_shift; -/* * this routine handles the overflow of the microsecond field *