diff options
Diffstat (limited to 'drivers/oprofile/timer_int.c')
| -rw-r--r-- | drivers/oprofile/timer_int.c | 78 |
1 files changed, 69 insertions, 9 deletions
diff --git a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c index 333f915568c7..dc0ae4d14dff 100644 --- a/drivers/oprofile/timer_int.c +++ b/drivers/oprofile/timer_int.c | |||
| @@ -13,34 +13,94 @@ | |||
| 13 | #include <linux/oprofile.h> | 13 | #include <linux/oprofile.h> |
| 14 | #include <linux/profile.h> | 14 | #include <linux/profile.h> |
| 15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| 16 | #include <linux/cpu.h> | ||
| 17 | #include <linux/hrtimer.h> | ||
| 18 | #include <asm/irq_regs.h> | ||
| 16 | #include <asm/ptrace.h> | 19 | #include <asm/ptrace.h> |
| 17 | 20 | ||
| 18 | #include "oprof.h" | 21 | #include "oprof.h" |
| 19 | 22 | ||
| 20 | static int timer_notify(struct pt_regs *regs) | 23 | static DEFINE_PER_CPU(struct hrtimer, oprofile_hrtimer); |
| 24 | |||
| 25 | static enum hrtimer_restart oprofile_hrtimer_notify(struct hrtimer *hrtimer) | ||
| 26 | { | ||
| 27 | oprofile_add_sample(get_irq_regs(), 0); | ||
| 28 | hrtimer_forward_now(hrtimer, ns_to_ktime(TICK_NSEC)); | ||
| 29 | return HRTIMER_RESTART; | ||
| 30 | } | ||
| 31 | |||
| 32 | static void __oprofile_hrtimer_start(void *unused) | ||
| 33 | { | ||
| 34 | struct hrtimer *hrtimer = &__get_cpu_var(oprofile_hrtimer); | ||
| 35 | |||
| 36 | hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | ||
| 37 | hrtimer->function = oprofile_hrtimer_notify; | ||
| 38 | |||
| 39 | hrtimer_start(hrtimer, ns_to_ktime(TICK_NSEC), | ||
| 40 | HRTIMER_MODE_REL_PINNED); | ||
| 41 | } | ||
| 42 | |||
| 43 | static int oprofile_hrtimer_start(void) | ||
| 21 | { | 44 | { |
| 22 | oprofile_add_sample(regs, 0); | 45 | on_each_cpu(__oprofile_hrtimer_start, NULL, 1); |
| 23 | return 0; | 46 | return 0; |
| 24 | } | 47 | } |
| 25 | 48 | ||
| 26 | static int timer_start(void) | 49 | static void __oprofile_hrtimer_stop(int cpu) |
| 27 | { | 50 | { |
| 28 | return register_timer_hook(timer_notify); | 51 | struct hrtimer *hrtimer = &per_cpu(oprofile_hrtimer, cpu); |
| 52 | |||
| 53 | hrtimer_cancel(hrtimer); | ||
| 29 | } | 54 | } |
| 30 | 55 | ||
| 56 | static void oprofile_hrtimer_stop(void) | ||
| 57 | { | ||
| 58 | int cpu; | ||
| 59 | |||
| 60 | for_each_online_cpu(cpu) | ||
| 61 | __oprofile_hrtimer_stop(cpu); | ||
| 62 | } | ||
| 31 | 63 | ||
| 32 | static void timer_stop(void) | 64 | static int __cpuinit oprofile_cpu_notify(struct notifier_block *self, |
| 65 | unsigned long action, void *hcpu) | ||
| 33 | { | 66 | { |
| 34 | unregister_timer_hook(timer_notify); | 67 | long cpu = (long) hcpu; |
| 68 | |||
| 69 | switch (action) { | ||
| 70 | case CPU_ONLINE: | ||
| 71 | case CPU_ONLINE_FROZEN: | ||
| 72 | smp_call_function_single(cpu, __oprofile_hrtimer_start, | ||
| 73 | NULL, 1); | ||
| 74 | break; | ||
| 75 | case CPU_DEAD: | ||
| 76 | case CPU_DEAD_FROZEN: | ||
| 77 | __oprofile_hrtimer_stop(cpu); | ||
| 78 | break; | ||
| 79 | } | ||
| 80 | return NOTIFY_OK; | ||
| 35 | } | 81 | } |
| 36 | 82 | ||
| 83 | static struct notifier_block __refdata oprofile_cpu_notifier = { | ||
| 84 | .notifier_call = oprofile_cpu_notify, | ||
| 85 | }; | ||
| 37 | 86 | ||
| 38 | void __init oprofile_timer_init(struct oprofile_operations *ops) | 87 | int __init oprofile_timer_init(struct oprofile_operations *ops) |
| 39 | { | 88 | { |
| 89 | int rc; | ||
| 90 | |||
| 91 | rc = register_hotcpu_notifier(&oprofile_cpu_notifier); | ||
| 92 | if (rc) | ||
| 93 | return rc; | ||
| 40 | ops->create_files = NULL; | 94 | ops->create_files = NULL; |
| 41 | ops->setup = NULL; | 95 | ops->setup = NULL; |
| 42 | ops->shutdown = NULL; | 96 | ops->shutdown = NULL; |
| 43 | ops->start = timer_start; | 97 | ops->start = oprofile_hrtimer_start; |
| 44 | ops->stop = timer_stop; | 98 | ops->stop = oprofile_hrtimer_stop; |
| 45 | ops->cpu_type = "timer"; | 99 | ops->cpu_type = "timer"; |
| 100 | return 0; | ||
| 101 | } | ||
| 102 | |||
| 103 | void __exit oprofile_timer_exit(void) | ||
| 104 | { | ||
| 105 | unregister_hotcpu_notifier(&oprofile_cpu_notifier); | ||
| 46 | } | 106 | } |
