aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-12-09 03:25:48 -0500
committerIngo Molnar <mingo@elte.hu>2009-12-09 03:48:20 -0500
commit44234adcdce38f83c56e05f808ce656175b4beeb (patch)
treecaff2ca7bbf4bf7c0b12652caf739bcc6db5f4d3 /include
parentc937fe20cb6d9e24c6ad5f9f0c64d64c78411057 (diff)
hw-breakpoints: Modify breakpoints without unregistering them
Currently, when ptrace needs to modify a breakpoint, like disabling it, changing its address, type or len, it calls modify_user_hw_breakpoint(). This latter will perform the heavy and racy task of unregistering the old breakpoint and registering a new one. This is racy as someone else might steal the reserved breakpoint slot under us, which is undesired as the breakpoint is only supposed to be modified, sometimes in the middle of a debugging workflow. We don't want our slot to be stolen in the middle. So instead of unregistering/registering the breakpoint, just disable it while we modify its breakpoint fields and re-enable it after if necessary. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Prasad <prasad@linux.vnet.ibm.com> LKML-Reference: <1260347148-5519-1-git-send-regression-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include')
-rw-r--r--include/linux/hw_breakpoint.h4
-rw-r--r--include/linux/perf_event.h5
2 files changed, 6 insertions, 3 deletions
diff --git a/include/linux/hw_breakpoint.h b/include/linux/hw_breakpoint.h
index 42da1ce19ec0..69f07a9f1277 100644
--- a/include/linux/hw_breakpoint.h
+++ b/include/linux/hw_breakpoint.h
@@ -55,7 +55,7 @@ register_user_hw_breakpoint(struct perf_event_attr *attr,
55 struct task_struct *tsk); 55 struct task_struct *tsk);
56 56
57/* FIXME: only change from the attr, and don't unregister */ 57/* FIXME: only change from the attr, and don't unregister */
58extern struct perf_event * 58extern int
59modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr); 59modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr);
60 60
61/* 61/*
@@ -91,7 +91,7 @@ static inline struct perf_event *
91register_user_hw_breakpoint(struct perf_event_attr *attr, 91register_user_hw_breakpoint(struct perf_event_attr *attr,
92 perf_overflow_handler_t triggered, 92 perf_overflow_handler_t triggered,
93 struct task_struct *tsk) { return NULL; } 93 struct task_struct *tsk) { return NULL; }
94static inline struct perf_event * 94static inline int
95modify_user_hw_breakpoint(struct perf_event *bp, 95modify_user_hw_breakpoint(struct perf_event *bp,
96 struct perf_event_attr *attr) { return NULL; } 96 struct perf_event_attr *attr) { return NULL; }
97static inline struct perf_event * 97static inline struct perf_event *
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index bf3329413e18..64a53f74c9a9 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -872,6 +872,8 @@ extern void perf_output_copy(struct perf_output_handle *handle,
872 const void *buf, unsigned int len); 872 const void *buf, unsigned int len);
873extern int perf_swevent_get_recursion_context(void); 873extern int perf_swevent_get_recursion_context(void);
874extern void perf_swevent_put_recursion_context(int rctx); 874extern void perf_swevent_put_recursion_context(int rctx);
875extern void perf_event_enable(struct perf_event *event);
876extern void perf_event_disable(struct perf_event *event);
875#else 877#else
876static inline void 878static inline void
877perf_event_task_sched_in(struct task_struct *task, int cpu) { } 879perf_event_task_sched_in(struct task_struct *task, int cpu) { }
@@ -902,7 +904,8 @@ static inline void perf_event_fork(struct task_struct *tsk) { }
902static inline void perf_event_init(void) { } 904static inline void perf_event_init(void) { }
903static inline int perf_swevent_get_recursion_context(void) { return -1; } 905static inline int perf_swevent_get_recursion_context(void) { return -1; }
904static inline void perf_swevent_put_recursion_context(int rctx) { } 906static inline void perf_swevent_put_recursion_context(int rctx) { }
905 907static inline void perf_event_enable(struct perf_event *event) { }
908static inline void perf_event_disable(struct perf_event *event) { }
906#endif 909#endif
907 910
908#define perf_output_put(handle, x) \ 911#define perf_output_put(handle, x) \