aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/perf_counter.c
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2009-06-05 12:01:29 -0400
committerIngo Molnar <mingo@elte.hu>2009-06-05 12:07:48 -0400
commit6a24ed6c6082ec65d19331a4bfa30c0512a1a822 (patch)
tree0d8beed316cf34cd8e986eb2f9b230a29caa6c88 /kernel/perf_counter.c
parent689802b2d0536e72281dc959ab9cb34fb3c304cf (diff)
perf_counter: Fix frequency adjustment for < HZ
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/perf_counter.c')
-rw-r--r--kernel/perf_counter.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index f8390668c391..47c92fb927f2 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -1187,8 +1187,9 @@ static void perf_log_period(struct perf_counter *counter, u64 period);
1187static void perf_adjust_freq(struct perf_counter_context *ctx) 1187static void perf_adjust_freq(struct perf_counter_context *ctx)
1188{ 1188{
1189 struct perf_counter *counter; 1189 struct perf_counter *counter;
1190 struct hw_perf_counter *hwc;
1190 u64 interrupts, sample_period; 1191 u64 interrupts, sample_period;
1191 u64 events, period; 1192 u64 events, period, freq;
1192 s64 delta; 1193 s64 delta;
1193 1194
1194 spin_lock(&ctx->lock); 1195 spin_lock(&ctx->lock);
@@ -1196,8 +1197,10 @@ static void perf_adjust_freq(struct perf_counter_context *ctx)
1196 if (counter->state != PERF_COUNTER_STATE_ACTIVE) 1197 if (counter->state != PERF_COUNTER_STATE_ACTIVE)
1197 continue; 1198 continue;
1198 1199
1199 interrupts = counter->hw.interrupts; 1200 hwc = &counter->hw;
1200 counter->hw.interrupts = 0; 1201
1202 interrupts = hwc->interrupts;
1203 hwc->interrupts = 0;
1201 1204
1202 if (interrupts == MAX_INTERRUPTS) { 1205 if (interrupts == MAX_INTERRUPTS) {
1203 perf_log_throttle(counter, 1); 1206 perf_log_throttle(counter, 1);
@@ -1208,20 +1211,35 @@ static void perf_adjust_freq(struct perf_counter_context *ctx)
1208 if (!counter->attr.freq || !counter->attr.sample_freq) 1211 if (!counter->attr.freq || !counter->attr.sample_freq)
1209 continue; 1212 continue;
1210 1213
1211 events = HZ * interrupts * counter->hw.sample_period; 1214 if (counter->attr.sample_freq < HZ) {
1215 freq = counter->attr.sample_freq;
1216
1217 hwc->freq_count += freq;
1218 hwc->freq_interrupts += interrupts;
1219
1220 if (hwc->freq_count < HZ)
1221 continue;
1222
1223 interrupts = hwc->freq_interrupts;
1224 hwc->freq_interrupts = 0;
1225 hwc->freq_count -= HZ;
1226 } else
1227 freq = HZ;
1228
1229 events = freq * interrupts * hwc->sample_period;
1212 period = div64_u64(events, counter->attr.sample_freq); 1230 period = div64_u64(events, counter->attr.sample_freq);
1213 1231
1214 delta = (s64)(1 + period - counter->hw.sample_period); 1232 delta = (s64)(1 + period - hwc->sample_period);
1215 delta >>= 1; 1233 delta >>= 1;
1216 1234
1217 sample_period = counter->hw.sample_period + delta; 1235 sample_period = hwc->sample_period + delta;
1218 1236
1219 if (!sample_period) 1237 if (!sample_period)
1220 sample_period = 1; 1238 sample_period = 1;
1221 1239
1222 perf_log_period(counter, sample_period); 1240 perf_log_period(counter, sample_period);
1223 1241
1224 counter->hw.sample_period = sample_period; 1242 hwc->sample_period = sample_period;
1225 } 1243 }
1226 spin_unlock(&ctx->lock); 1244 spin_unlock(&ctx->lock);
1227} 1245}