--- linux-3.10.16/kernel/profile.c 2013-10-13 16:08:56.000000000 -0700 +++ linux-3.10.16-patched/kernel/profile.c 2013-10-31 13:33:45.913457494 -0700 @@ -37,6 +37,9 @@ struct profile_hit { #define NR_PROFILE_HIT (PAGE_SIZE/sizeof(struct profile_hit)) #define NR_PROFILE_GRP (NR_PROFILE_HIT/PROFILE_GRPSZ) +/* Oprofile timer tick hook */ +static int (*timer_hook)(struct pt_regs *) __read_mostly; + static atomic_t *prof_buffer; static unsigned long prof_len, prof_shift; @@ -205,6 +208,24 @@ int profile_event_unregister(enum profil } EXPORT_SYMBOL_GPL(profile_event_unregister); +int register_timer_hook(int (*hook)(struct pt_regs *)) +{ + if (timer_hook) + return -EBUSY; + timer_hook = hook; + return 0; +} +EXPORT_SYMBOL_GPL(register_timer_hook); + +void unregister_timer_hook(int (*hook)(struct pt_regs *)) +{ + WARN_ON(hook != timer_hook); + timer_hook = NULL; + /* make sure all CPUs see the NULL hook */ + synchronize_sched(); /* Allow ongoing interrupts to complete. */ +} +EXPORT_SYMBOL_GPL(unregister_timer_hook); + #ifdef CONFIG_SMP /* * Each cpu has a pair of open-addressed hashtables for pending @@ -414,6 +435,9 @@ void profile_tick(int type) { struct pt_regs *regs = get_irq_regs(); + if (type == CPU_PROFILING && timer_hook) + timer_hook(regs); + if (!user_mode(regs) && prof_cpu_mask != NULL && cpumask_test_cpu(smp_processor_id(), prof_cpu_mask)) profile_hit(type, (void *)profile_pc(regs)); --- linux-3.10.16/include/linux/profile.h 2013-10-13 16:08:56.000000000 -0700 +++ linux-3.10.16-patched/include/linux/profile.h 2013-10-31 12:39:44.558759374 -0700 @@ -82,6 +82,9 @@ int task_handoff_unregister(struct notif int profile_event_register(enum profile_type, struct notifier_block * n); int profile_event_unregister(enum profile_type, struct notifier_block * n); +int register_timer_hook(int (*hook)(struct pt_regs *)); +void unregister_timer_hook(int (*hook)(struct pt_regs *)); + struct pt_regs; #else @@ -132,6 +135,16 @@ static inline int profile_event_unregist #define profile_handoff_task(a) (0) #define profile_munmap(a) do { } while (0) +static inline int register_timer_hook(int (*hook)(struct pt_regs *)) +{ + return -ENOSYS; +} + +static inline void unregister_timer_hook(int (*hook)(struct pt_regs *)) +{ + return; +} + #endif /* CONFIG_PROFILING */ #endif /* _LINUX_PROFILE_H */