aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/hw_breakpoint.c
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2010-02-27 10:18:46 -0500
committerFrederic Weisbecker <fweisbec@gmail.com>2010-02-27 10:18:46 -0500
commit018cbffe6819f6f8db20a0a3acd9bab9bfd667e4 (patch)
treefadde2521591998dc653fa094c636e8a547e620d /kernel/hw_breakpoint.c
parent1dd2980d990068e20045b90c424518cc7f3657ff (diff)
parent60b341b778cc2929df16c0a504c91621b3c6a4ad (diff)
Merge commit 'v2.6.33' into perf/core
Merge reason: __percpu annotations need the corresponding sparse address space definition upstream. Conflicts: tools/perf/util/probe-event.c (trivial)
Diffstat (limited to 'kernel/hw_breakpoint.c')
-rw-r--r--kernel/hw_breakpoint.c54
1 files changed, 43 insertions, 11 deletions
diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c
index c030ae657f20..967e66143e11 100644
--- a/kernel/hw_breakpoint.c
+++ b/kernel/hw_breakpoint.c
@@ -243,38 +243,70 @@ static void toggle_bp_slot(struct perf_event *bp, bool enable)
243 * ((per_cpu(nr_bp_flexible, *) > 1) + max(per_cpu(nr_cpu_bp_pinned, *)) 243 * ((per_cpu(nr_bp_flexible, *) > 1) + max(per_cpu(nr_cpu_bp_pinned, *))
244 * + max(per_cpu(nr_task_bp_pinned, *))) < HBP_NUM 244 * + max(per_cpu(nr_task_bp_pinned, *))) < HBP_NUM
245 */ 245 */
246int reserve_bp_slot(struct perf_event *bp) 246static int __reserve_bp_slot(struct perf_event *bp)
247{ 247{
248 struct bp_busy_slots slots = {0}; 248 struct bp_busy_slots slots = {0};
249 int ret = 0;
250
251 mutex_lock(&nr_bp_mutex);
252 249
253 fetch_bp_busy_slots(&slots, bp); 250 fetch_bp_busy_slots(&slots, bp);
254 251
255 /* Flexible counters need to keep at least one slot */ 252 /* Flexible counters need to keep at least one slot */
256 if (slots.pinned + (!!slots.flexible) == HBP_NUM) { 253 if (slots.pinned + (!!slots.flexible) == HBP_NUM)
257 ret = -ENOSPC; 254 return -ENOSPC;
258 goto end;
259 }
260 255
261 toggle_bp_slot(bp, true); 256 toggle_bp_slot(bp, true);
262 257
263end: 258 return 0;
259}
260
261int reserve_bp_slot(struct perf_event *bp)
262{
263 int ret;
264
265 mutex_lock(&nr_bp_mutex);
266
267 ret = __reserve_bp_slot(bp);
268
264 mutex_unlock(&nr_bp_mutex); 269 mutex_unlock(&nr_bp_mutex);
265 270
266 return ret; 271 return ret;
267} 272}
268 273
274static void __release_bp_slot(struct perf_event *bp)
275{
276 toggle_bp_slot(bp, false);
277}
278
269void release_bp_slot(struct perf_event *bp) 279void release_bp_slot(struct perf_event *bp)
270{ 280{
271 mutex_lock(&nr_bp_mutex); 281 mutex_lock(&nr_bp_mutex);
272 282
273 toggle_bp_slot(bp, false); 283 __release_bp_slot(bp);
274 284
275 mutex_unlock(&nr_bp_mutex); 285 mutex_unlock(&nr_bp_mutex);
276} 286}
277 287
288/*
289 * Allow the kernel debugger to reserve breakpoint slots without
290 * taking a lock using the dbg_* variant of for the reserve and
291 * release breakpoint slots.
292 */
293int dbg_reserve_bp_slot(struct perf_event *bp)
294{
295 if (mutex_is_locked(&nr_bp_mutex))
296 return -1;
297
298 return __reserve_bp_slot(bp);
299}
300
301int dbg_release_bp_slot(struct perf_event *bp)
302{
303 if (mutex_is_locked(&nr_bp_mutex))
304 return -1;
305
306 __release_bp_slot(bp);
307
308 return 0;
309}
278 310
279int register_perf_hw_breakpoint(struct perf_event *bp) 311int register_perf_hw_breakpoint(struct perf_event *bp)
280{ 312{
@@ -328,8 +360,8 @@ EXPORT_SYMBOL_GPL(register_user_hw_breakpoint);
328int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr) 360int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr)
329{ 361{
330 u64 old_addr = bp->attr.bp_addr; 362 u64 old_addr = bp->attr.bp_addr;
363 u64 old_len = bp->attr.bp_len;
331 int old_type = bp->attr.bp_type; 364 int old_type = bp->attr.bp_type;
332 int old_len = bp->attr.bp_len;
333 int err = 0; 365 int err = 0;
334 366
335 perf_event_disable(bp); 367 perf_event_disable(bp);