aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/sched_clock.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/arm/kernel/sched_clock.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'arch/arm/kernel/sched_clock.c')
-rw-r--r--arch/arm/kernel/sched_clock.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c
new file mode 100644
index 000000000000..9a46370fe9da
--- /dev/null
+++ b/arch/arm/kernel/sched_clock.c
@@ -0,0 +1,74 @@
1/*
2 * sched_clock.c: support for extending counters to full 64-bit ns counter
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <linux/clocksource.h>
9#include <linux/init.h>
10#include <linux/jiffies.h>
11#include <linux/kernel.h>
12#include <linux/sched.h>
13#include <linux/timer.h>
14
15#include <asm/sched_clock.h>
16
17static void sched_clock_poll(unsigned long wrap_ticks);
18static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0);
19static void (*sched_clock_update_fn)(void);
20
21static void sched_clock_poll(unsigned long wrap_ticks)
22{
23 mod_timer(&sched_clock_timer, round_jiffies(jiffies + wrap_ticks));
24 sched_clock_update_fn();
25}
26
27void __init init_sched_clock(struct clock_data *cd, void (*update)(void),
28 unsigned int clock_bits, unsigned long rate)
29{
30 unsigned long r, w;
31 u64 res, wrap;
32 char r_unit;
33
34 sched_clock_update_fn = update;
35
36 /* calculate the mult/shift to convert counter ticks to ns. */
37 clocks_calc_mult_shift(&cd->mult, &cd->shift, rate, NSEC_PER_SEC, 0);
38
39 r = rate;
40 if (r >= 4000000) {
41 r /= 1000000;
42 r_unit = 'M';
43 } else {
44 r /= 1000;
45 r_unit = 'k';
46 }
47
48 /* calculate how many ns until we wrap */
49 wrap = cyc_to_ns((1ULL << clock_bits) - 1, cd->mult, cd->shift);
50 do_div(wrap, NSEC_PER_MSEC);
51 w = wrap;
52
53 /* calculate the ns resolution of this counter */
54 res = cyc_to_ns(1ULL, cd->mult, cd->shift);
55 pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lums\n",
56 clock_bits, r, r_unit, res, w);
57
58 /*
59 * Start the timer to keep sched_clock() properly updated and
60 * sets the initial epoch.
61 */
62 sched_clock_timer.data = msecs_to_jiffies(w - (w / 10));
63 update();
64
65 /*
66 * Ensure that sched_clock() starts off at 0ns
67 */
68 cd->epoch_ns = 0;
69}
70
71void __init sched_clock_postinit(void)
72{
73 sched_clock_poll(sched_clock_timer.data);
74}