diff options
Diffstat (limited to 'kernel/sched_clock.c')
-rw-r--r-- | kernel/sched_clock.c | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/kernel/sched_clock.c b/kernel/sched_clock.c index a0b0852414cc..819f17ac796e 100644 --- a/kernel/sched_clock.c +++ b/kernel/sched_clock.c | |||
@@ -24,11 +24,12 @@ | |||
24 | * The clock: sched_clock_cpu() is monotonic per cpu, and should be somewhat | 24 | * The clock: sched_clock_cpu() is monotonic per cpu, and should be somewhat |
25 | * consistent between cpus (never more than 2 jiffies difference). | 25 | * consistent between cpus (never more than 2 jiffies difference). |
26 | */ | 26 | */ |
27 | #include <linux/sched.h> | ||
28 | #include <linux/percpu.h> | ||
29 | #include <linux/spinlock.h> | 27 | #include <linux/spinlock.h> |
30 | #include <linux/ktime.h> | 28 | #include <linux/hardirq.h> |
31 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/percpu.h> | ||
31 | #include <linux/ktime.h> | ||
32 | #include <linux/sched.h> | ||
32 | 33 | ||
33 | /* | 34 | /* |
34 | * Scheduler clock - returns current time in nanosec units. | 35 | * Scheduler clock - returns current time in nanosec units. |
@@ -43,6 +44,7 @@ unsigned long long __attribute__((weak)) sched_clock(void) | |||
43 | static __read_mostly int sched_clock_running; | 44 | static __read_mostly int sched_clock_running; |
44 | 45 | ||
45 | #ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK | 46 | #ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK |
47 | __read_mostly int sched_clock_stable; | ||
46 | 48 | ||
47 | struct sched_clock_data { | 49 | struct sched_clock_data { |
48 | /* | 50 | /* |
@@ -87,7 +89,7 @@ void sched_clock_init(void) | |||
87 | } | 89 | } |
88 | 90 | ||
89 | /* | 91 | /* |
90 | * min,max except they take wrapping into account | 92 | * min, max except they take wrapping into account |
91 | */ | 93 | */ |
92 | 94 | ||
93 | static inline u64 wrap_min(u64 x, u64 y) | 95 | static inline u64 wrap_min(u64 x, u64 y) |
@@ -111,15 +113,13 @@ static u64 __update_sched_clock(struct sched_clock_data *scd, u64 now) | |||
111 | s64 delta = now - scd->tick_raw; | 113 | s64 delta = now - scd->tick_raw; |
112 | u64 clock, min_clock, max_clock; | 114 | u64 clock, min_clock, max_clock; |
113 | 115 | ||
114 | WARN_ON_ONCE(!irqs_disabled()); | ||
115 | |||
116 | if (unlikely(delta < 0)) | 116 | if (unlikely(delta < 0)) |
117 | delta = 0; | 117 | delta = 0; |
118 | 118 | ||
119 | /* | 119 | /* |
120 | * scd->clock = clamp(scd->tick_gtod + delta, | 120 | * scd->clock = clamp(scd->tick_gtod + delta, |
121 | * max(scd->tick_gtod, scd->clock), | 121 | * max(scd->tick_gtod, scd->clock), |
122 | * scd->tick_gtod + TICK_NSEC); | 122 | * scd->tick_gtod + TICK_NSEC); |
123 | */ | 123 | */ |
124 | 124 | ||
125 | clock = scd->tick_gtod + delta; | 125 | clock = scd->tick_gtod + delta; |
@@ -148,8 +148,20 @@ static void lock_double_clock(struct sched_clock_data *data1, | |||
148 | 148 | ||
149 | u64 sched_clock_cpu(int cpu) | 149 | u64 sched_clock_cpu(int cpu) |
150 | { | 150 | { |
151 | struct sched_clock_data *scd = cpu_sdc(cpu); | ||
152 | u64 now, clock, this_clock, remote_clock; | 151 | u64 now, clock, this_clock, remote_clock; |
152 | struct sched_clock_data *scd; | ||
153 | |||
154 | if (sched_clock_stable) | ||
155 | return sched_clock(); | ||
156 | |||
157 | scd = cpu_sdc(cpu); | ||
158 | |||
159 | /* | ||
160 | * Normally this is not called in NMI context - but if it is, | ||
161 | * trying to do any locking here is totally lethal. | ||
162 | */ | ||
163 | if (unlikely(in_nmi())) | ||
164 | return scd->clock; | ||
153 | 165 | ||
154 | if (unlikely(!sched_clock_running)) | 166 | if (unlikely(!sched_clock_running)) |
155 | return 0ull; | 167 | return 0ull; |
@@ -195,14 +207,18 @@ u64 sched_clock_cpu(int cpu) | |||
195 | 207 | ||
196 | void sched_clock_tick(void) | 208 | void sched_clock_tick(void) |
197 | { | 209 | { |
198 | struct sched_clock_data *scd = this_scd(); | 210 | struct sched_clock_data *scd; |
199 | u64 now, now_gtod; | 211 | u64 now, now_gtod; |
200 | 212 | ||
213 | if (sched_clock_stable) | ||
214 | return; | ||
215 | |||
201 | if (unlikely(!sched_clock_running)) | 216 | if (unlikely(!sched_clock_running)) |
202 | return; | 217 | return; |
203 | 218 | ||
204 | WARN_ON_ONCE(!irqs_disabled()); | 219 | WARN_ON_ONCE(!irqs_disabled()); |
205 | 220 | ||
221 | scd = this_scd(); | ||
206 | now_gtod = ktime_to_ns(ktime_get()); | 222 | now_gtod = ktime_to_ns(ktime_get()); |
207 | now = sched_clock(); | 223 | now = sched_clock(); |
208 | 224 | ||
@@ -250,7 +266,7 @@ u64 sched_clock_cpu(int cpu) | |||
250 | return sched_clock(); | 266 | return sched_clock(); |
251 | } | 267 | } |
252 | 268 | ||
253 | #endif | 269 | #endif /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */ |
254 | 270 | ||
255 | unsigned long long cpu_clock(int cpu) | 271 | unsigned long long cpu_clock(int cpu) |
256 | { | 272 | { |