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 a0b0852414c..819f17ac796 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 | { |
