Messages in this thread Patch in this message | | | Date | Tue, 6 Dec 2011 01:45:49 -0800 | From | tip-bot for Peter Zijlstra <> | Subject | [tip:perf/core] perf, x86: Prefer fixed-purpose counters when scheduling |
| |
Commit-ID: 4defea8559bc0f97a899d94c8d19d3b8bb802bc4 Gitweb: http://git.kernel.org/tip/4defea8559bc0f97a899d94c8d19d3b8bb802bc4 Author: Peter Zijlstra <a.p.zijlstra@chello.nl> AuthorDate: Thu, 10 Nov 2011 15:15:42 +0100 Committer: Ingo Molnar <mingo@elte.hu> CommitDate: Tue, 6 Dec 2011 08:33:58 +0100
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> --- 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 fa6fdec..66f8ba9 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) c = sched->constraints[sched->state.event]; + /* Prefer fixed purpose counters */ + if (x86_pmu.num_counters_fixed) { + idx = X86_PMC_IDX_FIXED; + for_each_set_bit_cont(idx, c->idxmsk, X86_PMC_IDX_MAX) { + if (!__test_and_set_bit(idx, sched->state.used)) + goto done; + } + } /* Grab the first unused counter starting with idx */ idx = sched->state.counter; - for_each_set_bit_cont(idx, c->idxmsk, X86_PMC_IDX_MAX) { + for_each_set_bit_cont(idx, c->idxmsk, X86_PMC_IDX_FIXED) { if (!__test_and_set_bit(idx, sched->state.used)) - break; + goto done; } - sched->state.counter = idx; - if (idx >= X86_PMC_IDX_MAX) - return false; + return false; + +done: + sched->state.counter = idx; if (c->overlap) perf_sched_save_state(sched);
| |