diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/sched/clock.c | 57 | ||||
| -rw-r--r-- | kernel/sched/core.c | 1 | ||||
| -rw-r--r-- | kernel/sched/debug.c | 2 | ||||
| -rw-r--r-- | kernel/time/sched_clock.c | 2 | ||||
| -rw-r--r-- | kernel/time/timekeeping.c | 62 |
5 files changed, 74 insertions, 50 deletions
diff --git a/kernel/sched/clock.c b/kernel/sched/clock.c index 10c83e73837a..e3e3b979f9bd 100644 --- a/kernel/sched/clock.c +++ b/kernel/sched/clock.c | |||
| @@ -53,6 +53,7 @@ | |||
| 53 | * | 53 | * |
| 54 | */ | 54 | */ |
| 55 | #include "sched.h" | 55 | #include "sched.h" |
| 56 | #include <linux/sched_clock.h> | ||
| 56 | 57 | ||
| 57 | /* | 58 | /* |
| 58 | * Scheduler clock - returns current time in nanosec units. | 59 | * Scheduler clock - returns current time in nanosec units. |
| @@ -66,12 +67,7 @@ unsigned long long __weak sched_clock(void) | |||
| 66 | } | 67 | } |
| 67 | EXPORT_SYMBOL_GPL(sched_clock); | 68 | EXPORT_SYMBOL_GPL(sched_clock); |
| 68 | 69 | ||
| 69 | __read_mostly int sched_clock_running; | 70 | static DEFINE_STATIC_KEY_FALSE(sched_clock_running); |
| 70 | |||
| 71 | void sched_clock_init(void) | ||
| 72 | { | ||
| 73 | sched_clock_running = 1; | ||
| 74 | } | ||
| 75 | 71 | ||
| 76 | #ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK | 72 | #ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK |
| 77 | /* | 73 | /* |
| @@ -195,17 +191,40 @@ void clear_sched_clock_stable(void) | |||
| 195 | 191 | ||
| 196 | smp_mb(); /* matches sched_clock_init_late() */ | 192 | smp_mb(); /* matches sched_clock_init_late() */ |
| 197 | 193 | ||
| 198 | if (sched_clock_running == 2) | 194 | if (static_key_count(&sched_clock_running.key) == 2) |
| 199 | __clear_sched_clock_stable(); | 195 | __clear_sched_clock_stable(); |
| 200 | } | 196 | } |
| 201 | 197 | ||
| 198 | static void __sched_clock_gtod_offset(void) | ||
| 199 | { | ||
| 200 | struct sched_clock_data *scd = this_scd(); | ||
| 201 | |||
| 202 | __scd_stamp(scd); | ||
| 203 | __gtod_offset = (scd->tick_raw + __sched_clock_offset) - scd->tick_gtod; | ||
| 204 | } | ||
| 205 | |||
| 206 | void __init sched_clock_init(void) | ||
| 207 | { | ||
| 208 | /* | ||
| 209 | * Set __gtod_offset such that once we mark sched_clock_running, | ||
| 210 | * sched_clock_tick() continues where sched_clock() left off. | ||
| 211 | * | ||
| 212 | * Even if TSC is buggered, we're still UP at this point so it | ||
| 213 | * can't really be out of sync. | ||
| 214 | */ | ||
| 215 | local_irq_disable(); | ||
| 216 | __sched_clock_gtod_offset(); | ||
| 217 | local_irq_enable(); | ||
| 218 | |||
| 219 | static_branch_inc(&sched_clock_running); | ||
| 220 | } | ||
| 202 | /* | 221 | /* |
| 203 | * We run this as late_initcall() such that it runs after all built-in drivers, | 222 | * We run this as late_initcall() such that it runs after all built-in drivers, |
| 204 | * notably: acpi_processor and intel_idle, which can mark the TSC as unstable. | 223 | * notably: acpi_processor and intel_idle, which can mark the TSC as unstable. |
| 205 | */ | 224 | */ |
| 206 | static int __init sched_clock_init_late(void) | 225 | static int __init sched_clock_init_late(void) |
| 207 | { | 226 | { |
| 208 | sched_clock_running = 2; | 227 | static_branch_inc(&sched_clock_running); |
| 209 | /* | 228 | /* |
| 210 | * Ensure that it is impossible to not do a static_key update. | 229 | * Ensure that it is impossible to not do a static_key update. |
| 211 | * | 230 | * |
| @@ -350,8 +369,8 @@ u64 sched_clock_cpu(int cpu) | |||
| 350 | if (sched_clock_stable()) | 369 | if (sched_clock_stable()) |
| 351 | return sched_clock() + __sched_clock_offset; | 370 | return sched_clock() + __sched_clock_offset; |
| 352 | 371 | ||
| 353 | if (unlikely(!sched_clock_running)) | 372 | if (!static_branch_unlikely(&sched_clock_running)) |
| 354 | return 0ull; | 373 | return sched_clock(); |
| 355 | 374 | ||
| 356 | preempt_disable_notrace(); | 375 | preempt_disable_notrace(); |
| 357 | scd = cpu_sdc(cpu); | 376 | scd = cpu_sdc(cpu); |
| @@ -373,7 +392,7 @@ void sched_clock_tick(void) | |||
| 373 | if (sched_clock_stable()) | 392 | if (sched_clock_stable()) |
| 374 | return; | 393 | return; |
| 375 | 394 | ||
| 376 | if (unlikely(!sched_clock_running)) | 395 | if (!static_branch_unlikely(&sched_clock_running)) |
| 377 | return; | 396 | return; |
| 378 | 397 | ||
| 379 | lockdep_assert_irqs_disabled(); | 398 | lockdep_assert_irqs_disabled(); |
| @@ -385,8 +404,6 @@ void sched_clock_tick(void) | |||
| 385 | 404 | ||
| 386 | void sched_clock_tick_stable(void) | 405 | void sched_clock_tick_stable(void) |
| 387 | { | 406 | { |
| 388 | u64 gtod, clock; | ||
| 389 | |||
| 390 | if (!sched_clock_stable()) | 407 | if (!sched_clock_stable()) |
| 391 | return; | 408 | return; |
| 392 | 409 | ||
| @@ -398,9 +415,7 @@ void sched_clock_tick_stable(void) | |||
| 398 | * TSC to be unstable, any computation will be computing crap. | 415 | * TSC to be unstable, any computation will be computing crap. |
| 399 | */ | 416 | */ |
| 400 | local_irq_disable(); | 417 | local_irq_disable(); |
| 401 | gtod = ktime_get_ns(); | 418 | __sched_clock_gtod_offset(); |
| 402 | clock = sched_clock(); | ||
| 403 | __gtod_offset = (clock + __sched_clock_offset) - gtod; | ||
| 404 | local_irq_enable(); | 419 | local_irq_enable(); |
| 405 | } | 420 | } |
| 406 | 421 | ||
| @@ -434,9 +449,17 @@ EXPORT_SYMBOL_GPL(sched_clock_idle_wakeup_event); | |||
| 434 | 449 | ||
| 435 | #else /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */ | 450 | #else /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */ |
| 436 | 451 | ||
| 452 | void __init sched_clock_init(void) | ||
| 453 | { | ||
| 454 | static_branch_inc(&sched_clock_running); | ||
| 455 | local_irq_disable(); | ||
| 456 | generic_sched_clock_init(); | ||
| 457 | local_irq_enable(); | ||
| 458 | } | ||
| 459 | |||
| 437 | u64 sched_clock_cpu(int cpu) | 460 | u64 sched_clock_cpu(int cpu) |
| 438 | { | 461 | { |
| 439 | if (unlikely(!sched_clock_running)) | 462 | if (!static_branch_unlikely(&sched_clock_running)) |
| 440 | return 0; | 463 | return 0; |
| 441 | 464 | ||
| 442 | return sched_clock(); | 465 | return sched_clock(); |
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index d17d99778356..c45de46fdf10 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
| @@ -5916,7 +5916,6 @@ void __init sched_init(void) | |||
| 5916 | int i, j; | 5916 | int i, j; |
| 5917 | unsigned long alloc_size = 0, ptr; | 5917 | unsigned long alloc_size = 0, ptr; |
| 5918 | 5918 | ||
| 5919 | sched_clock_init(); | ||
| 5920 | wait_bit_init(); | 5919 | wait_bit_init(); |
| 5921 | 5920 | ||
| 5922 | #ifdef CONFIG_FAIR_GROUP_SCHED | 5921 | #ifdef CONFIG_FAIR_GROUP_SCHED |
diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c index 870d4f3da285..60caf1fb94e0 100644 --- a/kernel/sched/debug.c +++ b/kernel/sched/debug.c | |||
| @@ -622,8 +622,6 @@ void print_dl_rq(struct seq_file *m, int cpu, struct dl_rq *dl_rq) | |||
| 622 | #undef PU | 622 | #undef PU |
| 623 | } | 623 | } |
| 624 | 624 | ||
| 625 | extern __read_mostly int sched_clock_running; | ||
| 626 | |||
| 627 | static void print_cpu(struct seq_file *m, int cpu) | 625 | static void print_cpu(struct seq_file *m, int cpu) |
| 628 | { | 626 | { |
| 629 | struct rq *rq = cpu_rq(cpu); | 627 | struct rq *rq = cpu_rq(cpu); |
diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c index 2d8f05aad442..cbc72c2c1fca 100644 --- a/kernel/time/sched_clock.c +++ b/kernel/time/sched_clock.c | |||
| @@ -237,7 +237,7 @@ sched_clock_register(u64 (*read)(void), int bits, unsigned long rate) | |||
| 237 | pr_debug("Registered %pF as sched_clock source\n", read); | 237 | pr_debug("Registered %pF as sched_clock source\n", read); |
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | void __init sched_clock_postinit(void) | 240 | void __init generic_sched_clock_init(void) |
| 241 | { | 241 | { |
| 242 | /* | 242 | /* |
| 243 | * If no sched_clock() function has been provided at that point, | 243 | * If no sched_clock() function has been provided at that point, |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index d9e659a12c76..f3b22f456fac 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/nmi.h> | 17 | #include <linux/nmi.h> |
| 18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
| 19 | #include <linux/sched/loadavg.h> | 19 | #include <linux/sched/loadavg.h> |
| 20 | #include <linux/sched/clock.h> | ||
| 20 | #include <linux/syscore_ops.h> | 21 | #include <linux/syscore_ops.h> |
| 21 | #include <linux/clocksource.h> | 22 | #include <linux/clocksource.h> |
| 22 | #include <linux/jiffies.h> | 23 | #include <linux/jiffies.h> |
| @@ -1505,18 +1506,23 @@ void __weak read_persistent_clock64(struct timespec64 *ts64) | |||
| 1505 | } | 1506 | } |
| 1506 | 1507 | ||
| 1507 | /** | 1508 | /** |
| 1508 | * read_boot_clock64 - Return time of the system start. | 1509 | * read_persistent_wall_and_boot_offset - Read persistent clock, and also offset |
| 1510 | * from the boot. | ||
| 1509 | * | 1511 | * |
| 1510 | * Weak dummy function for arches that do not yet support it. | 1512 | * Weak dummy function for arches that do not yet support it. |
| 1511 | * Function to read the exact time the system has been started. | 1513 | * wall_time - current time as returned by persistent clock |
| 1512 | * Returns a timespec64 with tv_sec=0 and tv_nsec=0 if unsupported. | 1514 | * boot_offset - offset that is defined as wall_time - boot_time |
| 1513 | * | ||
