Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0+
2 : : /*
3 : : * This file contains the jiffies based clocksource.
4 : : *
5 : : * Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com)
6 : : */
7 : : #include <linux/clocksource.h>
8 : : #include <linux/jiffies.h>
9 : : #include <linux/module.h>
10 : : #include <linux/init.h>
11 : :
12 : : #include "timekeeping.h"
13 : :
14 : :
15 : : /* Since jiffies uses a simple TICK_NSEC multiplier
16 : : * conversion, the .shift value could be zero. However
17 : : * this would make NTP adjustments impossible as they are
18 : : * in units of 1/2^.shift. Thus we use JIFFIES_SHIFT to
19 : : * shift both the nominator and denominator the same
20 : : * amount, and give ntp adjustments in units of 1/2^8
21 : : *
22 : : * The value 8 is somewhat carefully chosen, as anything
23 : : * larger can result in overflows. TICK_NSEC grows as HZ
24 : : * shrinks, so values greater than 8 overflow 32bits when
25 : : * HZ=100.
26 : : */
27 : : #if HZ < 34
28 : : #define JIFFIES_SHIFT 6
29 : : #elif HZ < 67
30 : : #define JIFFIES_SHIFT 7
31 : : #else
32 : : #define JIFFIES_SHIFT 8
33 : : #endif
34 : :
35 : 440288 : static u64 jiffies_read(struct clocksource *cs)
36 : : {
37 : 440288 : return (u64) jiffies;
38 : : }
39 : :
40 : : /*
41 : : * The Jiffies based clocksource is the lowest common
42 : : * denominator clock source which should function on
43 : : * all systems. It has the same coarse resolution as
44 : : * the timer interrupt frequency HZ and it suffers
45 : : * inaccuracies caused by missed or lost timer
46 : : * interrupts and the inability for the timer
47 : : * interrupt hardware to accuratly tick at the
48 : : * requested HZ value. It is also not recommended
49 : : * for "tick-less" systems.
50 : : */
51 : : static struct clocksource clocksource_jiffies = {
52 : : .name = "jiffies",
53 : : .rating = 1, /* lowest valid rating*/
54 : : .read = jiffies_read,
55 : : .mask = CLOCKSOURCE_MASK(32),
56 : : .mult = TICK_NSEC << JIFFIES_SHIFT, /* details above */
57 : : .shift = JIFFIES_SHIFT,
58 : : .max_cycles = 10,
59 : : };
60 : :
61 : : __cacheline_aligned_in_smp DEFINE_SEQLOCK(jiffies_lock);
62 : :
63 : : #if (BITS_PER_LONG < 64)
64 : 808 : u64 get_jiffies_64(void)
65 : : {
66 : : unsigned int seq;
67 : : u64 ret;
68 : :
69 : : do {
70 : : seq = read_seqbegin(&jiffies_lock);
71 : 812 : ret = jiffies_64;
72 [ + + ]: 812 : } while (read_seqretry(&jiffies_lock, seq));
73 : 808 : return ret;
74 : : }
75 : : EXPORT_SYMBOL(get_jiffies_64);
76 : : #endif
77 : :
78 : : EXPORT_SYMBOL(jiffies);
79 : :
80 : 404 : static int __init init_jiffies_clocksource(void)
81 : : {
82 : 404 : return __clocksource_register(&clocksource_jiffies);
83 : : }
84 : :
85 : : core_initcall(init_jiffies_clocksource);
86 : :
87 : 808 : struct clocksource * __init __weak clocksource_default_clock(void)
88 : : {
89 : 808 : return &clocksource_jiffies;
90 : : }
91 : :
92 : : static struct clocksource refined_jiffies;
93 : :
94 : 0 : int register_refined_jiffies(long cycles_per_second)
95 : : {
96 : : u64 nsec_per_tick, shift_hz;
97 : : long cycles_per_tick;
98 : :
99 : :
100 : :
101 : 0 : refined_jiffies = clocksource_jiffies;
102 : 0 : refined_jiffies.name = "refined-jiffies";
103 : 0 : refined_jiffies.rating++;
104 : :
105 : : /* Calc cycles per tick */
106 : 0 : cycles_per_tick = (cycles_per_second + HZ/2)/HZ;
107 : : /* shift_hz stores hz<<8 for extra accuracy */
108 : 0 : shift_hz = (u64)cycles_per_second << 8;
109 : 0 : shift_hz += cycles_per_tick/2;
110 [ # # # # : 0 : do_div(shift_hz, cycles_per_tick);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
111 : : /* Calculate nsec_per_tick using shift_hz */
112 : 0 : nsec_per_tick = (u64)NSEC_PER_SEC << 8;
113 : 0 : nsec_per_tick += (u32)shift_hz/2;
114 [ # # # # : 0 : do_div(nsec_per_tick, (u32)shift_hz);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
115 : :
116 : 0 : refined_jiffies.mult = ((u32)nsec_per_tick) << JIFFIES_SHIFT;
117 : :
118 : : __clocksource_register(&refined_jiffies);
119 : 0 : return 0;
120 : : }
|