This source file includes following definitions.
- sched_clock
- this_scd
- cpu_sdc
- sched_clock_stable
- __scd_stamp
- __set_sched_clock_stable
- __sched_clock_work
- __clear_sched_clock_stable
- clear_sched_clock_stable
- __sched_clock_gtod_offset
- sched_clock_init
- sched_clock_init_late
- wrap_min
- wrap_max
- sched_clock_local
- sched_clock_remote
- sched_clock_cpu
- sched_clock_tick
- sched_clock_tick_stable
- sched_clock_idle_sleep_event
- sched_clock_idle_wakeup_event
- sched_clock_init
- sched_clock_cpu
- running_clock
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 #include "sched.h"
57 #include <linux/sched_clock.h>
58
59
60
61
62
63
64 unsigned long long __weak sched_clock(void)
65 {
66 return (unsigned long long)(jiffies - INITIAL_JIFFIES)
67 * (NSEC_PER_SEC / HZ);
68 }
69 EXPORT_SYMBOL_GPL(sched_clock);
70
71 static DEFINE_STATIC_KEY_FALSE(sched_clock_running);
72
73 #ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK
74
75
76
77
78
79
80
81 static DEFINE_STATIC_KEY_FALSE(__sched_clock_stable);
82 static int __sched_clock_stable_early = 1;
83
84
85
86
87 __read_mostly u64 __sched_clock_offset;
88 static __read_mostly u64 __gtod_offset;
89
90 struct sched_clock_data {
91 u64 tick_raw;
92 u64 tick_gtod;
93 u64 clock;
94 };
95
96 static DEFINE_PER_CPU_SHARED_ALIGNED(struct sched_clock_data, sched_clock_data);
97
98 static inline struct sched_clock_data *this_scd(void)
99 {
100 return this_cpu_ptr(&sched_clock_data);
101 }
102
103 static inline struct sched_clock_data *cpu_sdc(int cpu)
104 {
105 return &per_cpu(sched_clock_data, cpu);
106 }
107
108 int sched_clock_stable(void)
109 {
110 return static_branch_likely(&__sched_clock_stable);
111 }
112
113 static void __scd_stamp(struct sched_clock_data *scd)
114 {
115 scd->tick_gtod = ktime_get_ns();
116 scd->tick_raw = sched_clock();
117 }
118
119 static void __set_sched_clock_stable(void)
120 {
121 struct sched_clock_data *scd;
122
123
124
125
126
127 local_irq_disable();
128 scd = this_scd();
129
130
131
132 __sched_clock_offset = (scd->tick_gtod + __gtod_offset) - (scd->tick_raw);
133 local_irq_enable();
134
135 printk(KERN_INFO "sched_clock: Marking stable (%lld, %lld)->(%lld, %lld)\n",
136 scd->tick_gtod, __gtod_offset,
137 scd->tick_raw, __sched_clock_offset);
138
139 static_branch_enable(&__sched_clock_stable);
140 tick_dep_clear(TICK_DEP_BIT_CLOCK_UNSTABLE);
141 }
142
143
144
145
146
147
148
149
150
151
152
153
154 static void __sched_clock_work(struct work_struct *work)
155 {
156 struct sched_clock_data *scd;
157 int cpu;
158
159
160 preempt_disable();
161 scd = this_scd();
162 __scd_stamp(scd);
163 scd->clock = scd->tick_gtod + __gtod_offset;
164 preempt_enable();
165
166
167 for_each_possible_cpu(cpu)
168 per_cpu(sched_clock_data, cpu) = *scd;
169
170 printk(KERN_WARNING "TSC found unstable after boot, most likely due to broken BIOS. Use 'tsc=unstable'.\n");
171 printk(KERN_INFO "sched_clock: Marking unstable (%lld, %lld)<-(%lld, %lld)\n",
172 scd->tick_gtod, __gtod_offset,
173 scd->tick_raw, __sched_clock_offset);
174
175 static_branch_disable(&__sched_clock_stable);
176 }
177
178 static DECLARE_WORK(sched_clock_work, __sched_clock_work);
179
180 static void __clear_sched_clock_stable(void)
181 {
182 if (!sched_clock_stable())
183 return;
184
185 tick_dep_set(TICK_DEP_BIT_CLOCK_UNSTABLE);
186 schedule_work(&sched_clock_work);
187 }
188
189 void clear_sched_clock_stable(void)
190 {
191 __sched_clock_stable_early = 0;
192
193 smp_mb();
194
195 if (static_key_count(&sched_clock_running.key) == 2)
196 __clear_sched_clock_stable();
197 }
198
199 static void __sched_clock_gtod_offset(void)
200 {
201 struct sched_clock_data *scd = this_scd();
202
203 __scd_stamp(scd);
204 __gtod_offset = (scd->tick_raw + __sched_clock_offset) - scd->tick_gtod;
205 }
206
207 void __init sched_clock_init(void)
208 {
209
210
211
212
213
214
215
216 local_irq_disable();
217 __sched_clock_gtod_offset();
218 local_irq_enable();
219
220 static_branch_inc(&sched_clock_running);
221 }
222
223
224
225
226 static int __init sched_clock_init_late(void)
227 {
228 static_branch_inc(&sched_clock_running);
229
230
231
232
233
234
235
236 smp_mb();
237
238 if (__sched_clock_stable_early)
239 __set_sched_clock_stable();
240
241 return 0;
242 }
243 late_initcall(sched_clock_init_late);
244
245
246
247
248
249 static inline u64 wrap_min(u64 x, u64 y)
250 {
251 return (s64)(x - y) < 0 ? x : y;
252 }
253
254 static inline u64 wrap_max(u64 x, u64 y)
255 {
256 return (s64)(x - y) > 0 ? x : y;
257 }
258
259
260
261
262
263
264
265 static u64 sched_clock_local(struct sched_clock_data *scd)
266 {
267 u64 now, clock, old_clock, min_clock, max_clock, gtod;
268 s64 delta;
269
270 again:
271 now = sched_clock();
272 delta = now - scd->tick_raw;
273 if (unlikely(delta < 0))
274 delta = 0;
275
276 old_clock = scd->clock;
277
278
279
280
281
282
283
284 gtod = scd->tick_gtod + __gtod_offset;
285 clock = gtod + delta;
286 min_clock = wrap_max(gtod, old_clock);
287 max_clock = wrap_max(old_clock, gtod + TICK_NSEC);
288
289 clock = wrap_max(clock, min_clock);
290 clock = wrap_min(clock, max_clock);
291
292 if (cmpxchg64(&scd->clock, old_clock, clock) != old_clock)
293 goto again;
294
295 return clock;
296 }
297
298 static u64 sched_clock_remote(struct sched_clock_data *scd)
299 {
300 struct sched_clock_data *my_scd = this_scd();
301 u64 this_clock, remote_clock;
302 u64 *ptr, old_val, val;
303
304 #if BITS_PER_LONG != 64
305 again:
306
307
308
309
310
311
312
313
314
315
316
317 this_clock = sched_clock_local(my_scd);
318
319
320
321
322
323 remote_clock = cmpxchg64(&scd->clock, 0, 0);
324 #else
325
326
327
328
329 sched_clock_local(my_scd);
330 again:
331 this_clock = my_scd->clock;
332 remote_clock = scd->clock;
333 #endif
334
335
336
337
338
339
340
341 if (likely((s64)(remote_clock - this_clock) < 0)) {
342 ptr = &scd->clock;
343 old_val = remote_clock;
344 val = this_clock;
345 } else {
346
347
348
349 ptr = &my_scd->clock;
350 old_val = this_clock;
351 val = remote_clock;
352 }
353
354 if (cmpxchg64(ptr, old_val, val) != old_val)
355 goto again;
356
357 return val;
358 }
359
360
361
362
363
364
365 u64 sched_clock_cpu(int cpu)
366 {
367 struct sched_clock_data *scd;
368 u64 clock;
369
370 if (sched_clock_stable())
371 return sched_clock() + __sched_clock_offset;
372
373 if (!static_branch_unlikely(&sched_clock_running))
374 return sched_clock();
375
376 preempt_disable_notrace();
377 scd = cpu_sdc(cpu);
378
379 if (cpu != smp_processor_id())
380 clock = sched_clock_remote(scd);
381 else
382 clock = sched_clock_local(scd);
383 preempt_enable_notrace();
384
385 return clock;
386 }
387 EXPORT_SYMBOL_GPL(sched_clock_cpu);
388
389 void sched_clock_tick(void)
390 {
391 struct sched_clock_data *scd;
392
393 if (sched_clock_stable())
394 return;
395
396 if (!static_branch_unlikely(&sched_clock_running))
397 return;
398
399 lockdep_assert_irqs_disabled();
400
401 scd = this_scd();
402 __scd_stamp(scd);
403 sched_clock_local(scd);
404 }
405
406 void sched_clock_tick_stable(void)
407 {
408 if (!sched_clock_stable())
409 return;
410
411
412
413
414
415
416
417
418 local_irq_disable();
419 __sched_clock_gtod_offset();
420 local_irq_enable();
421 }
422
423
424
425
426 void sched_clock_idle_sleep_event(void)
427 {
428 sched_clock_cpu(smp_processor_id());
429 }
430 EXPORT_SYMBOL_GPL(sched_clock_idle_sleep_event);
431
432
433
434
435 void sched_clock_idle_wakeup_event(void)
436 {
437 unsigned long flags;
438
439 if (sched_clock_stable())
440 return;
441
442 if (unlikely(timekeeping_suspended))
443 return;
444
445 local_irq_save(flags);
446 sched_clock_tick();
447 local_irq_restore(flags);
448 }
449 EXPORT_SYMBOL_GPL(sched_clock_idle_wakeup_event);
450
451 #else
452
453 void __init sched_clock_init(void)
454 {
455 static_branch_inc(&sched_clock_running);
456 local_irq_disable();
457 generic_sched_clock_init();
458 local_irq_enable();
459 }
460
461 u64 sched_clock_cpu(int cpu)
462 {
463 if (!static_branch_unlikely(&sched_clock_running))
464 return 0;
465
466 return sched_clock();
467 }
468
469 #endif
470
471
472
473
474
475
476
477
478
479 u64 __weak running_clock(void)
480 {
481 return local_clock();
482 }