at v2.6.36 106 lines 2.3 kB view raw
1/** 2 * @file timer_int.c 3 * 4 * @remark Copyright 2002 OProfile authors 5 * @remark Read the file COPYING 6 * 7 * @author John Levon <levon@movementarian.org> 8 */ 9 10#include <linux/kernel.h> 11#include <linux/notifier.h> 12#include <linux/smp.h> 13#include <linux/oprofile.h> 14#include <linux/profile.h> 15#include <linux/init.h> 16#include <linux/cpu.h> 17#include <linux/hrtimer.h> 18#include <asm/irq_regs.h> 19#include <asm/ptrace.h> 20 21#include "oprof.h" 22 23static DEFINE_PER_CPU(struct hrtimer, oprofile_hrtimer); 24 25static 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 32static 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 43static int oprofile_hrtimer_start(void) 44{ 45 on_each_cpu(__oprofile_hrtimer_start, NULL, 1); 46 return 0; 47} 48 49static void __oprofile_hrtimer_stop(int cpu) 50{ 51 struct hrtimer *hrtimer = &per_cpu(oprofile_hrtimer, cpu); 52 53 hrtimer_cancel(hrtimer); 54} 55 56static void oprofile_hrtimer_stop(void) 57{ 58 int cpu; 59 60 for_each_online_cpu(cpu) 61 __oprofile_hrtimer_stop(cpu); 62} 63 64static int __cpuinit oprofile_cpu_notify(struct notifier_block *self, 65 unsigned long action, void *hcpu) 66{ 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; 81} 82 83static struct notifier_block __refdata oprofile_cpu_notifier = { 84 .notifier_call = oprofile_cpu_notify, 85}; 86 87int __init oprofile_timer_init(struct oprofile_operations *ops) 88{ 89 int rc; 90 91 rc = register_hotcpu_notifier(&oprofile_cpu_notifier); 92 if (rc) 93 return rc; 94 ops->create_files = NULL; 95 ops->setup = NULL; 96 ops->shutdown = NULL; 97 ops->start = oprofile_hrtimer_start; 98 ops->stop = oprofile_hrtimer_stop; 99 ops->cpu_type = "timer"; 100 return 0; 101} 102 103void __exit oprofile_timer_exit(void) 104{ 105 unregister_hotcpu_notifier(&oprofile_cpu_notifier); 106}