mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
perf: Fix race between event install and jump_labels
perf_install_in_context() relies upon the context switch hooks to have scheduled in events when the IPI misses its target -- after all, if the task has moved from the CPU (or wasn't running at all), it will have to context switch to run elsewhere. This however doesn't appear to be happening. It is possible for the IPI to not happen (task wasn't running) only to later observe the task running with an inactive context. The only possible explanation is that the context switch hooks are not called. Therefore put in a sync_sched() after toggling the jump_label to guarantee all CPUs will have them enabled before we install an event. A simple if (0->1) sync_sched() will not in fact work, because any further increment can race and complete before the sync_sched(). Therefore we must jump through some hoops. Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Arnaldo Carvalho de Melo <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
This commit is contained in:
parent
a69b0ca4ac
commit
9107c89e26
2 changed files with 44 additions and 11 deletions
|
|
@ -906,7 +906,7 @@ perf_sw_event_sched(u32 event_id, u64 nr, u64 addr)
|
|||
}
|
||||
}
|
||||
|
||||
extern struct static_key_deferred perf_sched_events;
|
||||
extern struct static_key_false perf_sched_events;
|
||||
|
||||
static __always_inline bool
|
||||
perf_sw_migrate_enabled(void)
|
||||
|
|
@ -925,7 +925,7 @@ static inline void perf_event_task_migrate(struct task_struct *task)
|
|||
static inline void perf_event_task_sched_in(struct task_struct *prev,
|
||||
struct task_struct *task)
|
||||
{
|
||||
if (static_key_false(&perf_sched_events.key))
|
||||
if (static_branch_unlikely(&perf_sched_events))
|
||||
__perf_event_task_sched_in(prev, task);
|
||||
|
||||
if (perf_sw_migrate_enabled() && task->sched_migrated) {
|
||||
|
|
@ -942,7 +942,7 @@ static inline void perf_event_task_sched_out(struct task_struct *prev,
|
|||
{
|
||||
perf_sw_event_sched(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 0);
|
||||
|
||||
if (static_key_false(&perf_sched_events.key))
|
||||
if (static_branch_unlikely(&perf_sched_events))
|
||||
__perf_event_task_sched_out(prev, next);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue