aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/perf_counter.h3
-rw-r--r--kernel/perf_counter.c32
2 files changed, 28 insertions, 7 deletions
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h
index 6bc250039738..4f9d39ecdc05 100644
--- a/include/linux/perf_counter.h
+++ b/include/linux/perf_counter.h
@@ -373,6 +373,9 @@ struct hw_perf_counter {
373 u64 sample_period; 373 u64 sample_period;
374 atomic64_t period_left; 374 atomic64_t period_left;
375 u64 interrupts; 375 u64 interrupts;
376
377 u64 freq_count;
378 u64 freq_interrupts;
376#endif 379#endif
377}; 380};
378 381
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}