aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2010-12-14 22:37:07 -0500
committerJohn Stultz <john.stultz@linaro.org>2011-02-21 15:53:04 -0500
commite06383db9ec591696a06654257474b85bac1f8cb (patch)
treeee541661450da71e204370c84a15bae64847c368
parentdb1c1cce4a653dcbe6949c72ae7b9f42cab1b929 (diff)
hrtimers: extend hrtimer base code to handle more then 2 clockids
The hrtimer code is written mainly with CLOCK_REALTIME and CLOCK_MONOTONIC in mind. These are clockids 0 and 1 resepctively. However, if we are to introduce any new hrtimer bases, using new clockids, we have to skip the cputimers (clockids 2,3) as well as other clockids that may not impelement timers. This patch adds a little bit of indirection between the clockid and the base, so that we can extend the base by one when we add a new clockid at number 7 or so. CC: Jamie Lokier <jamie@shareable.org> CC: Thomas Gleixner <tglx@linutronix.de> CC: Alexander Shishkin <virtuoso@slind.org> CC: Arve Hjønnevåg <arve@android.com> Signed-off-by: John Stultz <john.stultz@linaro.org>
-rw-r--r--include/linux/hrtimer.h6
-rw-r--r--kernel/hrtimer.c40
2 files changed, 32 insertions, 14 deletions
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index f376ddc64c4d..20b8e6601a04 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -148,7 +148,11 @@ struct hrtimer_clock_base {
148#endif 148#endif
149}; 149};
150 150
151#define HRTIMER_MAX_CLOCK_BASES 2 151enum hrtimer_base_type {
152 HRTIMER_BASE_REALTIME,
153 HRTIMER_BASE_MONOTONIC,
154 HRTIMER_MAX_CLOCK_BASES,
155};
152 156
153/* 157/*
154 * struct hrtimer_cpu_base - the per cpu clock bases 158 * struct hrtimer_cpu_base - the per cpu clock bases
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 57c4d33c9a9d..ca99e2454600 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -53,11 +53,10 @@
53/* 53/*
54 * The timer bases: 54 * The timer bases:
55 * 55 *
56 * Note: If we want to add new timer bases, we have to skip the two 56 * There are more clockids then hrtimer bases. Thus, we index
57 * clock ids captured by the cpu-timers. We do this by holding empty 57 * into the timer bases by the hrtimer_base_type enum. When trying
58 * entries rather than doing math adjustment of the clock ids. 58 * to reach a base using a clockid, hrtimer_clockid_to_base()
59 * This ensures that we capture erroneous accesses to these clock ids 59 * is used to convert from clockid to the proper hrtimer_base_type.
60 * rather than moving them into the range of valid clock id's.
61 */ 60 */
62DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) = 61DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
63{ 62{
@@ -77,6 +76,14 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
77 } 76 }
78}; 77};
79 78
79static int hrtimer_clock_to_base_table[MAX_CLOCKS];
80
81static inline int hrtimer_clockid_to_base(clockid_t clock_id)
82{
83 return hrtimer_clock_to_base_table[clock_id];
84}
85
86
80/* 87/*
81 * Get the coarse grained time at the softirq based on xtime and 88 * Get the coarse grained time at the softirq based on xtime and
82 * wall_to_monotonic. 89 * wall_to_monotonic.
@@ -90,8 +97,8 @@ static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base)
90 97
91 xtim = timespec_to_ktime(xts); 98 xtim = timespec_to_ktime(xts);
92 tomono = timespec_to_ktime(tom); 99 tomono = timespec_to_ktime(tom);
93 base->clock_base[CLOCK_REALTIME].softirq_time = xtim; 100 base->clock_base[HRTIMER_BASE_REALTIME].softirq_time = xtim;
94 base->clock_base[CLOCK_MONOTONIC].softirq_time = 101 base->clock_base[HRTIMER_BASE_MONOTONIC].softirq_time =
95 ktime_add(xtim, tomono); 102 ktime_add(xtim, tomono);
96} 103}
97 104
@@ -179,10 +186,11 @@ switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base,
179 struct hrtimer_cpu_base *new_cpu_base; 186 struct hrtimer_cpu_base *new_cpu_base;
180 int this_cpu = smp_processor_id(); 187 int this_cpu = smp_processor_id();
181 int cpu = hrtimer_get_target(this_cpu, pinned); 188 int cpu = hrtimer_get_target(this_cpu, pinned);
189 int basenum = hrtimer_clockid_to_base(base->index);
182 190
183again: 191again:
184 new_cpu_base = &per_cpu(hrtimer_bases, cpu); 192 new_cpu_base = &per_cpu(hrtimer_bases, cpu);
185 new_base = &new_cpu_base->clock_base[base->index]; 193 new_base = &new_cpu_base->clock_base[basenum];
186 194
187 if (base != new_base) { 195 if (base != new_base) {
188 /* 196 /*
@@ -618,7 +626,7 @@ static void retrigger_next_event(void *arg)
618 626
619 /* Adjust CLOCK_REALTIME offset */ 627 /* Adjust CLOCK_REALTIME offset */
620 raw_spin_lock(&base->lock); 628 raw_spin_lock(&base->lock);
621 base->clock_base[CLOCK_REALTIME].offset = 629 base->clock_base[HRTIMER_BASE_REALTIME].offset =
622 timespec_to_ktime(realtime_offset); 630 timespec_to_ktime(realtime_offset);
623 631
624 hrtimer_force_reprogram(base, 0); 632 hrtimer_force_reprogram(base, 0);
@@ -716,8 +724,8 @@ static int hrtimer_switch_to_hres(void)
716 return 0; 724 return 0;
717 } 725 }
718 base->hres_active = 1; 726 base->hres_active = 1;
719 base->clock_base[CLOCK_REALTIME].resolution = KTIME_HIGH_RES; 727 base->clock_base[HRTIMER_BASE_REALTIME].resolution = KTIME_HIGH_RES;
720 base->clock_base[CLOCK_MONOTONIC].resolution = KTIME_HIGH_RES; 728 base->clock_base[HRTIMER_BASE_MONOTONIC].resolution = KTIME_HIGH_RES;
721 729
722 tick_setup_sched_timer(); 730 tick_setup_sched_timer();
723 731
@@ -1112,6 +1120,7 @@ static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
1112 enum hrtimer_mode mode) 1120 enum hrtimer_mode mode)
1113{ 1121{
1114 struct hrtimer_cpu_base *cpu_base; 1122 struct hrtimer_cpu_base *cpu_base;
1123 int base;
1115 1124
1116 memset(timer, 0, sizeof(struct hrtimer)); 1125 memset(timer, 0, sizeof(struct hrtimer));
1117 1126
@@ -1120,7 +1129,8 @@ static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
1120 if (clock_id == CLOCK_REALTIME && mode != HRTIMER_MODE_ABS) 1129 if (clock_id == CLOCK_REALTIME && mode != HRTIMER_MODE_ABS)
1121 clock_id = CLOCK_MONOTONIC; 1130 clock_id = CLOCK_MONOTONIC;
1122 1131
1123 timer->base = &cpu_base->clock_base[clock_id]; 1132 base = hrtimer_clockid_to_base(clock_id);
1133 timer->base = &cpu_base->clock_base[base];
1124 hrtimer_init_timer_hres(timer); 1134 hrtimer_init_timer_hres(timer);
1125 timerqueue_init(&timer->node); 1135 timerqueue_init(&timer->node);
1126 1136
@@ -1156,9 +1166,10 @@ EXPORT_SYMBOL_GPL(hrtimer_init);
1156int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp) 1166int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
1157{ 1167{
1158 struct hrtimer_cpu_base *cpu_base; 1168 struct hrtimer_cpu_base *cpu_base;
1169 int base = hrtimer_clockid_to_base(which_clock);
1159 1170
1160 cpu_base = &__raw_get_cpu_var(hrtimer_bases); 1171 cpu_base = &__raw_get_cpu_var(hrtimer_bases);
1161 *tp = ktime_to_timespec(cpu_base->clock_base[which_clock].resolution); 1172 *tp = ktime_to_timespec(cpu_base->clock_base[base].resolution);
1162 1173
1163 return 0; 1174 return 0;
1164} 1175}
@@ -1705,6 +1716,9 @@ static struct notifier_block __cpuinitdata hrtimers_nb = {
1705 1716
1706void __init hrtimers_init(void) 1717void __init hrtimers_init(void)
1707{ 1718{
1719 hrtimer_clock_to_base_table[CLOCK_REALTIME] = HRTIMER_BASE_REALTIME;
1720 hrtimer_clock_to_base_table[CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC;
1721
1708 hrtimer_cpu_notify(&hrtimers_nb, (unsigned long)CPU_UP_PREPARE, 1722 hrtimer_cpu_notify(&hrtimers_nb, (unsigned long)CPU_UP_PREPARE,
1709 (void *)(long)smp_processor_id()); 1723 (void *)(long)smp_processor_id());
1710 register_cpu_notifier(&hrtimers_nb); 1724 register_cpu_notifier(&hrtimers_nb);