diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2010-01-22 10:32:17 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-01-29 03:01:40 -0500 |
commit | 63b146490befc027a7e0923e333269e68b20d380 (patch) | |
tree | 11e485149324134a6e4e6164eba728fe10256e59 /arch/x86/kernel/cpu/perf_event.c | |
parent | 9f41699ed067fa695faff8e2e9981b2550abec62 (diff) |
perf_event: x86: Optimize the constraint searching bits
Instead of copying bitmasks around, pass pointers to the constraint
structure.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
LKML-Reference: <20100122155535.887853503@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/cpu/perf_event.c')
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 75 |
1 files changed, 34 insertions, 41 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 4d1ed101c10d..092ad566734c 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -134,12 +134,14 @@ struct x86_pmu { | |||
134 | u64 intel_ctrl; | 134 | u64 intel_ctrl; |
135 | void (*enable_bts)(u64 config); | 135 | void (*enable_bts)(u64 config); |
136 | void (*disable_bts)(void); | 136 | void (*disable_bts)(void); |
137 | void (*get_event_constraints)(struct cpu_hw_events *cpuc, | 137 | |
138 | struct perf_event *event, | 138 | struct event_constraint * |
139 | unsigned long *idxmsk); | 139 | (*get_event_constraints)(struct cpu_hw_events *cpuc, |
140 | struct perf_event *event); | ||
141 | |||
140 | void (*put_event_constraints)(struct cpu_hw_events *cpuc, | 142 | void (*put_event_constraints)(struct cpu_hw_events *cpuc, |
141 | struct perf_event *event); | 143 | struct perf_event *event); |
142 | const struct event_constraint *event_constraints; | 144 | struct event_constraint *event_constraints; |
143 | }; | 145 | }; |
144 | 146 | ||
145 | static struct x86_pmu x86_pmu __read_mostly; | 147 | static struct x86_pmu x86_pmu __read_mostly; |
@@ -1242,17 +1244,15 @@ static int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) | |||
1242 | { | 1244 | { |
1243 | int i, j , w, num; | 1245 | int i, j , w, num; |
1244 | int weight, wmax; | 1246 | int weight, wmax; |
1245 | unsigned long *c; | 1247 | struct event_constraint *c, *constraints[X86_PMC_IDX_MAX]; |
1246 | unsigned long constraints[X86_PMC_IDX_MAX][BITS_TO_LONGS(X86_PMC_IDX_MAX)]; | ||
1247 | unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; | 1248 | unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; |
1248 | struct hw_perf_event *hwc; | 1249 | struct hw_perf_event *hwc; |
1249 | 1250 | ||
1250 | bitmap_zero(used_mask, X86_PMC_IDX_MAX); | 1251 | bitmap_zero(used_mask, X86_PMC_IDX_MAX); |
1251 | 1252 | ||
1252 | for (i = 0; i < n; i++) { | 1253 | for (i = 0; i < n; i++) { |
1253 | x86_pmu.get_event_constraints(cpuc, | 1254 | constraints[i] = |
1254 | cpuc->event_list[i], | 1255 | x86_pmu.get_event_constraints(cpuc, cpuc->event_list[i]); |
1255 | constraints[i]); | ||
1256 | } | 1256 | } |
1257 | 1257 | ||
1258 | /* | 1258 | /* |
@@ -1267,7 +1267,7 @@ static int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) | |||
1267 | break; | 1267 | break; |
1268 | 1268 | ||
1269 | /* constraint still honored */ | 1269 | /* constraint still honored */ |
1270 | if (!test_bit(hwc->idx, c)) | 1270 | if (!test_bit(hwc->idx, c->idxmsk)) |
1271 | break; | 1271 | break; |
1272 | 1272 | ||
1273 | /* not already used */ | 1273 | /* not already used */ |
@@ -1320,11 +1320,11 @@ static int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) | |||
1320 | c = constraints[i]; | 1320 | c = constraints[i]; |
1321 | hwc = &cpuc->event_list[i]->hw; | 1321 | hwc = &cpuc->event_list[i]->hw; |
1322 | 1322 | ||
1323 | weight = bitmap_weight(c, X86_PMC_IDX_MAX); | 1323 | weight = bitmap_weight(c->idxmsk, X86_PMC_IDX_MAX); |
1324 | if (weight != w) | 1324 | if (weight != w) |
1325 | continue; | 1325 | continue; |
1326 | 1326 | ||
1327 | for_each_bit(j, c, X86_PMC_IDX_MAX) { | 1327 | for_each_bit(j, c->idxmsk, X86_PMC_IDX_MAX) { |
1328 | if (!test_bit(j, used_mask)) | 1328 | if (!test_bit(j, used_mask)) |
1329 | break; | 1329 | break; |
1330 | } | 1330 | } |
@@ -2155,11 +2155,13 @@ perf_event_nmi_handler(struct notifier_block *self, | |||
2155 | return NOTIFY_STOP; | 2155 | return NOTIFY_STOP; |
2156 | } | 2156 | } |
2157 | 2157 | ||
2158 | static struct event_constraint unconstrained; | ||
2159 | |||
2158 | static struct event_constraint bts_constraint = | 2160 | static struct event_constraint bts_constraint = |
2159 | EVENT_CONSTRAINT(0, 1ULL << X86_PMC_IDX_FIXED_BTS, 0); | 2161 | EVENT_CONSTRAINT(0, 1ULL << X86_PMC_IDX_FIXED_BTS, 0); |
2160 | 2162 | ||
2161 | static int intel_special_constraints(struct perf_event *event, | 2163 | static struct event_constraint * |
2162 | unsigned long *idxmsk) | 2164 | intel_special_constraints(struct perf_event *event) |
2163 | { | 2165 | { |
2164 | unsigned int hw_event; | 2166 | unsigned int hw_event; |
2165 | 2167 | ||
@@ -2169,46 +2171,34 @@ static int intel_special_constraints(struct perf_event *event, | |||
2169 | x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS)) && | 2171 | x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS)) && |
2170 | (event->hw.sample_period == 1))) { | 2172 | (event->hw.sample_period == 1))) { |
2171 | 2173 | ||
2172 | bitmap_copy((unsigned long *)idxmsk, | 2174 | return &bts_constraint; |
2173 | (unsigned long *)bts_constraint.idxmsk, | ||
2174 | X86_PMC_IDX_MAX); | ||
2175 | return 1; | ||
2176 | } | 2175 | } |
2177 | return 0; | 2176 | return NULL; |
2178 | } | 2177 | } |
2179 | 2178 | ||
2180 | static void intel_get_event_constraints(struct cpu_hw_events *cpuc, | 2179 | static struct event_constraint * |
2181 | struct perf_event *event, | 2180 | intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event) |
2182 | unsigned long *idxmsk) | ||
2183 | { | 2181 | { |
2184 | const struct event_constraint *c; | 2182 | struct event_constraint *c; |
2185 | 2183 | ||
2186 | /* | 2184 | c = intel_special_constraints(event); |
2187 | * cleanup bitmask | 2185 | if (c) |
2188 | */ | 2186 | return c; |
2189 | bitmap_zero(idxmsk, X86_PMC_IDX_MAX); | ||
2190 | |||
2191 | if (intel_special_constraints(event, idxmsk)) | ||
2192 | return; | ||
2193 | 2187 | ||
2194 | if (x86_pmu.event_constraints) { | 2188 | if (x86_pmu.event_constraints) { |
2195 | for_each_event_constraint(c, x86_pmu.event_constraints) { | 2189 | for_each_event_constraint(c, x86_pmu.event_constraints) { |
2196 | if ((event->hw.config & c->cmask) == c->code) { | 2190 | if ((event->hw.config & c->cmask) == c->code) |
2197 | bitmap_copy(idxmsk, c->idxmsk, X86_PMC_IDX_MAX); | 2191 | return c; |
2198 | return; | ||
2199 | } | ||
2200 | } | 2192 | } |
2201 | } | 2193 | } |
2202 | /* no constraints, means supports all generic counters */ | 2194 | |
2203 | bitmap_fill((unsigned long *)idxmsk, x86_pmu.num_events); | 2195 | return &unconstrained; |
2204 | } | 2196 | } |
2205 | 2197 | ||
2206 | static void amd_get_event_constraints(struct cpu_hw_events *cpuc, | 2198 | static struct event_constraint * |
2207 | struct perf_event *event, | 2199 | amd_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event) |
2208 | unsigned long *idxmsk) | ||
2209 | { | 2200 | { |
2210 | /* no constraints, means supports all generic counters */ | 2201 | return &unconstrained; |
2211 | bitmap_fill(idxmsk, x86_pmu.num_events); | ||
2212 | } | 2202 | } |
2213 | 2203 | ||
2214 | static int x86_event_sched_in(struct perf_event *event, | 2204 | static int x86_event_sched_in(struct perf_event *event, |
@@ -2576,6 +2566,9 @@ void __init init_hw_perf_events(void) | |||
2576 | perf_events_lapic_init(); | 2566 | perf_events_lapic_init(); |
2577 | register_die_notifier(&perf_event_nmi_notifier); | 2567 | register_die_notifier(&perf_event_nmi_notifier); |
2578 | 2568 | ||
2569 | unconstrained = (struct event_constraint) | ||
2570 | EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_events) - 1, 0); | ||
2571 | |||
2579 | pr_info("... version: %d\n", x86_pmu.version); | 2572 | pr_info("... version: %d\n", x86_pmu.version); |
2580 | pr_info("... bit width: %d\n", x86_pmu.event_bits); | 2573 | pr_info("... bit width: %d\n", x86_pmu.event_bits); |
2581 | pr_info("... generic registers: %d\n", x86_pmu.num_events); | 2574 | pr_info("... generic registers: %d\n", x86_pmu.num_events); |