aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu/perf_event.c
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2010-01-22 10:32:17 -0500
committerIngo Molnar <mingo@elte.hu>2010-01-29 03:01:40 -0500
commit63b146490befc027a7e0923e333269e68b20d380 (patch)
tree11e485149324134a6e4e6164eba728fe10256e59 /arch/x86/kernel/cpu/perf_event.c
parent9f41699ed067fa695faff8e2e9981b2550abec62 (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.c75
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
145static struct x86_pmu x86_pmu __read_mostly; 147static 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
2158static struct event_constraint unconstrained;
2159
2158static struct event_constraint bts_constraint = 2160static 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
2161static int intel_special_constraints(struct perf_event *event, 2163static struct event_constraint *
2162 unsigned long *idxmsk) 2164intel_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
2180static void intel_get_event_constraints(struct cpu_hw_events *cpuc, 2179static struct event_constraint *
2181 struct perf_event *event, 2180intel_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
2206static void amd_get_event_constraints(struct cpu_hw_events *cpuc, 2198static struct event_constraint *
2207 struct perf_event *event, 2199amd_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
2214static int x86_event_sched_in(struct perf_event *event, 2204static 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);