diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2011-11-10 09:15:42 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-12-06 02:33:58 -0500 |
commit | 4defea8559bc0f97a899d94c8d19d3b8bb802bc4 (patch) | |
tree | a9f0e5352d199542128e538ce77ff0d271ac23db | |
parent | bc1738f6ee83015f090867813dcca4d690e7917c (diff) |
perf, x86: Prefer fixed-purpose counters when scheduling
This avoids a scheduling failure for cases like:
cycles, cycles, instructions, instructions (on Core2)
Which would end up being programmed like:
PMC0, PMC1, FP-instructions, fail
Because all events will have the same weight.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/n/tip-8tnwb92asqj7xajqqoty4gel@git.kernel.org
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index fa6fdec5afb..66f8ba9a67f 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -574,16 +574,25 @@ static bool __perf_sched_find_counter(struct perf_sched *sched) | |||
574 | 574 | ||
575 | c = sched->constraints[sched->state.event]; | 575 | c = sched->constraints[sched->state.event]; |
576 | 576 | ||
577 | /* Prefer fixed purpose counters */ | ||
578 | if (x86_pmu.num_counters_fixed) { | ||
579 | idx = X86_PMC_IDX_FIXED; | ||
580 | for_each_set_bit_cont(idx, c->idxmsk, X86_PMC_IDX_MAX) { | ||
581 | if (!__test_and_set_bit(idx, sched->state.used)) | ||
582 | goto done; | ||
583 | } | ||
584 | } | ||
577 | /* Grab the first unused counter starting with idx */ | 585 | /* Grab the first unused counter starting with idx */ |
578 | idx = sched->state.counter; | 586 | idx = sched->state.counter; |
579 | for_each_set_bit_cont(idx, c->idxmsk, X86_PMC_IDX_MAX) { | 587 | for_each_set_bit_cont(idx, c->idxmsk, X86_PMC_IDX_FIXED) { |
580 | if (!__test_and_set_bit(idx, sched->state.used)) | 588 | if (!__test_and_set_bit(idx, sched->state.used)) |
581 | break; | 589 | goto done; |
582 | } | 590 | } |
583 | sched->state.counter = idx; | ||
584 | 591 | ||
585 | if (idx >= X86_PMC_IDX_MAX) | 592 | return false; |
586 | return false; | 593 | |
594 | done: | ||
595 | sched->state.counter = idx; | ||
587 | 596 | ||
588 | if (c->overlap) | 597 | if (c->overlap) |
589 | perf_sched_save_state(sched); | 598 | perf_sched_save_state(sched); |