diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-12-13 03:00:03 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-12-14 14:30:48 -0500 |
commit | ee06094f8279e1312fc0a31591320cc7b6f0ab1e (patch) | |
tree | aecf8f2177b2398e4db8df68a9705009b31a8ef7 /kernel/perf_counter.c | |
parent | 9b194e831fb2c322ed81a373e49620f34edc2778 (diff) |
perfcounters: restructure x86 counter math
Impact: restructure code
Change counter math from absolute values to clear delta logic.
We try to extract elapsed deltas from the raw hw counter - and put
that into the generic counter.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/perf_counter.c')
-rw-r--r-- | kernel/perf_counter.c | 68 |
1 files changed, 5 insertions, 63 deletions
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index 559130b8774d..416861ce8b27 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c | |||
@@ -44,67 +44,9 @@ hw_perf_counter_init(struct perf_counter *counter) | |||
44 | } | 44 | } |
45 | 45 | ||
46 | u64 __weak hw_perf_save_disable(void) { return 0; } | 46 | u64 __weak hw_perf_save_disable(void) { return 0; } |
47 | void __weak hw_perf_restore(u64 ctrl) { } | 47 | void __weak hw_perf_restore(u64 ctrl) { } |
48 | void __weak hw_perf_counter_setup(void) { } | 48 | void __weak hw_perf_counter_setup(void) { } |
49 | 49 | ||
50 | #if BITS_PER_LONG == 64 | ||
51 | |||
52 | /* | ||
53 | * Read the cached counter in counter safe against cross CPU / NMI | ||
54 | * modifications. 64 bit version - no complications. | ||
55 | */ | ||
56 | static inline u64 perf_counter_read_safe(struct perf_counter *counter) | ||
57 | { | ||
58 | return (u64) atomic64_read(&counter->count); | ||
59 | } | ||
60 | |||
61 | void atomic64_counter_set(struct perf_counter *counter, u64 val) | ||
62 | { | ||
63 | atomic64_set(&counter->count, val); | ||
64 | } | ||
65 | |||
66 | u64 atomic64_counter_read(struct perf_counter *counter) | ||
67 | { | ||
68 | return atomic64_read(&counter->count); | ||
69 | } | ||
70 | |||
71 | #else | ||
72 | |||
73 | /* | ||
74 | * Read the cached counter in counter safe against cross CPU / NMI | ||
75 | * modifications. 32 bit version. | ||
76 | */ | ||
77 | static u64 perf_counter_read_safe(struct perf_counter *counter) | ||
78 | { | ||
79 | u32 cntl, cnth; | ||
80 | |||
81 | local_irq_disable(); | ||
82 | do { | ||
83 | cnth = atomic_read(&counter->count32[1]); | ||
84 | cntl = atomic_read(&counter->count32[0]); | ||
85 | } while (cnth != atomic_read(&counter->count32[1])); | ||
86 | |||
87 | local_irq_enable(); | ||
88 | |||
89 | return cntl | ((u64) cnth) << 32; | ||
90 | } | ||
91 | |||
92 | void atomic64_counter_set(struct perf_counter *counter, u64 val64) | ||
93 | { | ||
94 | u32 *val32 = (void *)&val64; | ||
95 | |||
96 | atomic_set(counter->count32 + 0, *(val32 + 0)); | ||
97 | atomic_set(counter->count32 + 1, *(val32 + 1)); | ||
98 | } | ||
99 | |||
100 | u64 atomic64_counter_read(struct perf_counter *counter) | ||
101 | { | ||
102 | return atomic_read(counter->count32 + 0) | | ||
103 | (u64) atomic_read(counter->count32 + 1) << 32; | ||
104 | } | ||
105 | |||
106 | #endif | ||
107 | |||
108 | static void | 50 | static void |
109 | list_add_counter(struct perf_counter *counter, struct perf_counter_context *ctx) | 51 | list_add_counter(struct perf_counter *counter, struct perf_counter_context *ctx) |
110 | { | 52 | { |
@@ -280,11 +222,11 @@ static void __perf_install_in_context(void *info) | |||
280 | ctx->nr_counters++; | 222 | ctx->nr_counters++; |
281 | 223 | ||
282 | if (cpuctx->active_oncpu < perf_max_counters) { | 224 | if (cpuctx->active_oncpu < perf_max_counters) { |
283 | counter->hw_ops->hw_perf_counter_enable(counter); | ||
284 | counter->state = PERF_COUNTER_STATE_ACTIVE; | 225 | counter->state = PERF_COUNTER_STATE_ACTIVE; |
285 | counter->oncpu = cpu; | 226 | counter->oncpu = cpu; |
286 | ctx->nr_active++; | 227 | ctx->nr_active++; |
287 | cpuctx->active_oncpu++; | 228 | cpuctx->active_oncpu++; |
229 | counter->hw_ops->hw_perf_counter_enable(counter); | ||
288 | } | 230 | } |
289 | 231 | ||
290 | if (!ctx->task && cpuctx->max_pertask) | 232 | if (!ctx->task && cpuctx->max_pertask) |
@@ -624,7 +566,7 @@ static u64 perf_counter_read(struct perf_counter *counter) | |||
624 | __hw_perf_counter_read, counter, 1); | 566 | __hw_perf_counter_read, counter, 1); |
625 | } | 567 | } |
626 | 568 | ||
627 | return perf_counter_read_safe(counter); | 569 | return atomic64_read(&counter->count); |
628 | } | 570 | } |
629 | 571 | ||
630 | /* | 572 | /* |
@@ -921,7 +863,7 @@ static void cpu_clock_perf_counter_read(struct perf_counter *counter) | |||
921 | { | 863 | { |
922 | int cpu = raw_smp_processor_id(); | 864 | int cpu = raw_smp_processor_id(); |
923 | 865 | ||
924 | atomic64_counter_set(counter, cpu_clock(cpu)); | 866 | atomic64_set(&counter->count, cpu_clock(cpu)); |
925 | } | 867 | } |
926 | 868 | ||
927 | static const struct hw_perf_counter_ops perf_ops_cpu_clock = { | 869 | static const struct hw_perf_counter_ops perf_ops_cpu_clock = { |
@@ -940,7 +882,7 @@ static void task_clock_perf_counter_disable(struct perf_counter *counter) | |||
940 | 882 | ||
941 | static void task_clock_perf_counter_read(struct perf_counter *counter) | 883 | static void task_clock_perf_counter_read(struct perf_counter *counter) |
942 | { | 884 | { |
943 | atomic64_counter_set(counter, current->se.sum_exec_runtime); | 885 | atomic64_set(&counter->count, current->se.sum_exec_runtime); |
944 | } | 886 | } |
945 | 887 | ||
946 | static const struct hw_perf_counter_ops perf_ops_task_clock = { | 888 | static const struct hw_perf_counter_ops perf_ops_task_clock = { |