Branch data Line data Source code
1 : : /*
2 : : * linux/kernel/time/tick-oneshot.c
3 : : *
4 : : * This file contains functions which manage high resolution tick
5 : : * related events.
6 : : *
7 : : * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
8 : : * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
9 : : * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner
10 : : *
11 : : * This code is licenced under the GPL version 2. For details see
12 : : * kernel-base/COPYING.
13 : : */
14 : : #include <linux/cpu.h>
15 : : #include <linux/err.h>
16 : : #include <linux/hrtimer.h>
17 : : #include <linux/interrupt.h>
18 : : #include <linux/percpu.h>
19 : : #include <linux/profile.h>
20 : : #include <linux/sched.h>
21 : :
22 : : #include "tick-internal.h"
23 : :
24 : : /**
25 : : * tick_program_event
26 : : */
27 : 0 : int tick_program_event(ktime_t expires, int force)
28 : : {
29 : 29901578 : struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev);
30 : :
31 : 14950789 : return clockevents_program_event(dev, expires, force);
32 : : }
33 : :
34 : : /**
35 : : * tick_resume_onshot - resume oneshot mode
36 : : */
37 : 0 : void tick_resume_oneshot(void)
38 : : {
39 : 0 : struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev);
40 : :
41 : 0 : clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
42 : 0 : clockevents_program_event(dev, ktime_get(), true);
43 : 0 : }
44 : :
45 : : /**
46 : : * tick_setup_oneshot - setup the event device for oneshot mode (hres or nohz)
47 : : */
48 : 0 : void tick_setup_oneshot(struct clock_event_device *newdev,
49 : : void (*handler)(struct clock_event_device *),
50 : : ktime_t next_event)
51 : : {
52 : 0 : newdev->event_handler = handler;
53 : 0 : clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT);
54 : 0 : clockevents_program_event(newdev, next_event, true);
55 : 0 : }
56 : :
57 : : /**
58 : : * tick_switch_to_oneshot - switch to oneshot mode
59 : : */
60 : 0 : int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *))
61 : : {
62 : 162 : struct tick_device *td = &__get_cpu_var(tick_cpu_device);
63 : 81 : struct clock_event_device *dev = td->evtdev;
64 : :
65 [ + - ][ + - ]: 81 : if (!dev || !(dev->features & CLOCK_EVT_FEAT_ONESHOT) ||
[ - + ]
66 : : !tick_device_is_functional(dev)) {
67 : :
68 : 0 : printk(KERN_INFO "Clockevents: "
69 : : "could not switch to one-shot mode:");
70 [ # # ]: 81 : if (!dev) {
71 : 0 : printk(" no tick device\n");
72 : : } else {
73 [ # # ]: 0 : if (!tick_device_is_functional(dev))
74 : 0 : printk(" %s is not functional.\n", dev->name);
75 : : else
76 : 0 : printk(" %s does not support one-shot mode.\n",
77 : : dev->name);
78 : : }
79 : : return -EINVAL;
80 : : }
81 : :
82 : 81 : td->mode = TICKDEV_MODE_ONESHOT;
83 : 81 : dev->event_handler = handler;
84 : 81 : clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
85 : 81 : tick_broadcast_switch_to_oneshot();
86 : 81 : return 0;
87 : : }
88 : :
89 : : /**
90 : : * tick_check_oneshot_mode - check whether the system is in oneshot mode
91 : : *
92 : : * returns 1 when either nohz or highres are enabled. otherwise 0.
93 : : */
94 : 0 : int tick_oneshot_mode_active(void)
95 : : {
96 : : unsigned long flags;
97 : : int ret;
98 : :
99 : : local_irq_save(flags);
100 : 0 : ret = __this_cpu_read(tick_cpu_device.mode) == TICKDEV_MODE_ONESHOT;
101 [ # # ]: 0 : local_irq_restore(flags);
102 : :
103 : 0 : return ret;
104 : : }
105 : :
106 : : #ifdef CONFIG_HIGH_RES_TIMERS
107 : : /**
108 : : * tick_init_highres - switch to high resolution mode
109 : : *
110 : : * Called with interrupts disabled.
111 : : */
112 : 0 : int tick_init_highres(void)
113 : : {
114 : 81 : return tick_switch_to_oneshot(hrtimer_interrupt);
115 : : }
116 : : #endif
|