aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-12-13 03:00:03 -0500
committerIngo Molnar <mingo@elte.hu>2008-12-14 14:30:48 -0500
commitee06094f8279e1312fc0a31591320cc7b6f0ab1e (patch)
treeaecf8f2177b2398e4db8df68a9705009b31a8ef7 /kernel
parent9b194e831fb2c322ed81a373e49620f34edc2778 (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')
-rw-r--r--kernel/perf_counter.c68
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
46u64 __weak hw_perf_save_disable(void) { return 0; } 46u64 __weak hw_perf_save_disable(void) { return 0; }
47void __weak hw_perf_restore(u64 ctrl) { } 47void __weak hw_perf_restore(u64 ctrl) { }
48void __weak hw_perf_counter_setup(void) { } 48void __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 */
56static inline u64 perf_counter_read_safe(struct perf_counter *counter)
57{
58 return (u64) atomic64_read(&counter->count);
59}
60
61void atomic64_counter_set(struct perf_counter *counter, u64 val)
62{
63 atomic64_set(&counter->count, val);
64}
65
66u64 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 */
77static 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
92void 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
100u64 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
108static void 50static void
109list_add_counter(struct perf_counter *counter, struct perf_counter_context *ctx) 51list_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
927static const struct hw_perf_counter_ops perf_ops_cpu_clock = { 869static 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
941static void task_clock_perf_counter_read(struct perf_counter *counter) 883static 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
946static const struct hw_perf_counter_ops perf_ops_task_clock = { 888static const struct hw_perf_counter_ops perf_ops_task_clock = {