diff options
author | Pavel Tatashin <pasha.tatashin@oracle.com> | 2017-06-12 16:41:44 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-06-12 18:44:02 -0400 |
commit | 178bf2b9a20e866677bbca5cb521b09a8498c1d7 (patch) | |
tree | c8147817fafe9eafc7ef486375eb77423666f389 | |
parent | b5dd4d807f0fe7da67c5cc67b2ec681b60e4994b (diff) |
sparc64: optimize loads in clock_sched()
In clock sched we now have three loads:
- Function pointer
- quotient for multiplication
- offset
However, it is possible to improve performance substantially, by
guaranteeing that all three loads are from the same cacheline.
By moving these three values first in sparc64_tick_ops, and by having
tick_operations 64-byte aligned we guarantee this.
Signed-off-by: Pavel Tatashin <pasha.tatashin@oracle.com>
Reviewed-by: Shannon Nelson <shannon.nelson@oracle.com>
Reviewed-by: Steven Sistare <steven.sistare@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | arch/sparc/include/asm/timer_64.h | 5 | ||||
-rw-r--r-- | arch/sparc/kernel/time_64.c | 17 |
2 files changed, 12 insertions, 10 deletions
diff --git a/arch/sparc/include/asm/timer_64.h b/arch/sparc/include/asm/timer_64.h index fce415034000..bde2cc40ae02 100644 --- a/arch/sparc/include/asm/timer_64.h +++ b/arch/sparc/include/asm/timer_64.h | |||
@@ -9,7 +9,12 @@ | |||
9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | 11 | ||
12 | /* The most frequently accessed fields should be first, | ||
13 | * to fit into the same cacheline. | ||
14 | */ | ||
12 | struct sparc64_tick_ops { | 15 | struct sparc64_tick_ops { |
16 | unsigned long ticks_per_nsec_quotient; | ||
17 | unsigned long offset; | ||
13 | unsigned long long (*get_tick)(void); | 18 | unsigned long long (*get_tick)(void); |
14 | int (*add_compare)(unsigned long); | 19 | int (*add_compare)(unsigned long); |
15 | unsigned long softint_mask; | 20 | unsigned long softint_mask; |
diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 5f53b74dd493..44e37e9f8428 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c | |||
@@ -164,7 +164,7 @@ static unsigned long tick_add_tick(unsigned long adj) | |||
164 | return new_tick; | 164 | return new_tick; |
165 | } | 165 | } |
166 | 166 | ||
167 | static struct sparc64_tick_ops tick_operations __read_mostly = { | 167 | static struct sparc64_tick_ops tick_operations __cacheline_aligned = { |
168 | .name = "tick", | 168 | .name = "tick", |
169 | .init_tick = tick_init_tick, | 169 | .init_tick = tick_init_tick, |
170 | .disable_irq = tick_disable_irq, | 170 | .disable_irq = tick_disable_irq, |
@@ -391,9 +391,6 @@ static struct sparc64_tick_ops hbtick_operations __read_mostly = { | |||
391 | .softint_mask = 1UL << 0, | 391 | .softint_mask = 1UL << 0, |
392 | }; | 392 | }; |
393 | 393 | ||
394 | static unsigned long timer_ticks_per_nsec_quotient __read_mostly; | ||
395 | static unsigned long timer_offset __read_mostly; | ||
396 | |||
397 | unsigned long cmos_regs; | 394 | unsigned long cmos_regs; |
398 | EXPORT_SYMBOL(cmos_regs); | 395 | EXPORT_SYMBOL(cmos_regs); |
399 | 396 | ||
@@ -784,11 +781,11 @@ void __init time_init(void) | |||
784 | 781 | ||
785 | tb_ticks_per_usec = freq / USEC_PER_SEC; | 782 | tb_ticks_per_usec = freq / USEC_PER_SEC; |
786 | 783 | ||
787 | timer_ticks_per_nsec_quotient = | 784 | tick_operations.ticks_per_nsec_quotient = |
788 | clocksource_hz2mult(freq, SPARC64_NSEC_PER_CYC_SHIFT); | 785 | clocksource_hz2mult(freq, SPARC64_NSEC_PER_CYC_SHIFT); |
789 | 786 | ||
790 | timer_offset = (tick_operations.get_tick() | 787 | tick_operations.offset = (tick_operations.get_tick() |
791 | * timer_ticks_per_nsec_quotient) | 788 | * tick_operations.ticks_per_nsec_quotient) |
792 | >> SPARC64_NSEC_PER_CYC_SHIFT; | 789 | >> SPARC64_NSEC_PER_CYC_SHIFT; |
793 | 790 | ||
794 | clocksource_tick.name = tick_operations.name; | 791 | clocksource_tick.name = tick_operations.name; |
@@ -816,11 +813,11 @@ void __init time_init(void) | |||
816 | 813 | ||
817 | unsigned long long sched_clock(void) | 814 | unsigned long long sched_clock(void) |
818 | { | 815 | { |
816 | unsigned long quotient = tick_operations.ticks_per_nsec_quotient; | ||
817 | unsigned long offset = tick_operations.offset; | ||
819 | unsigned long ticks = tick_operations.get_tick(); | 818 | unsigned long ticks = tick_operations.get_tick(); |
820 | 819 | ||
821 | return ((ticks * timer_ticks_per_nsec_quotient) | 820 | return ((ticks * quotient) >> SPARC64_NSEC_PER_CYC_SHIFT) - offset; |
822 | >> SPARC64_NSEC_PER_CYC_SHIFT) | ||
823 | - timer_offset; | ||
824 | } | 821 | } |
825 | 822 | ||
826 | int read_current_timer(unsigned long *timer_val) | 823 | int read_current_timer(unsigned long *timer_val) |