diff options
| -rw-r--r-- | include/linux/perf_event.h | 6 | ||||
| -rw-r--r-- | kernel/events/core.c | 49 |
2 files changed, 44 insertions, 11 deletions
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 39156619e108..f5c5a3fa2c81 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h | |||
| @@ -906,7 +906,7 @@ perf_sw_event_sched(u32 event_id, u64 nr, u64 addr) | |||
| 906 | } | 906 | } |
| 907 | } | 907 | } |
| 908 | 908 | ||
| 909 | extern struct static_key_deferred perf_sched_events; | 909 | extern struct static_key_false perf_sched_events; |
| 910 | 910 | ||
| 911 | static __always_inline bool | 911 | static __always_inline bool |
| 912 | perf_sw_migrate_enabled(void) | 912 | perf_sw_migrate_enabled(void) |
| @@ -925,7 +925,7 @@ static inline void perf_event_task_migrate(struct task_struct *task) | |||
| 925 | static inline void perf_event_task_sched_in(struct task_struct *prev, | 925 | static inline void perf_event_task_sched_in(struct task_struct *prev, |
| 926 | struct task_struct *task) | 926 | struct task_struct *task) |
| 927 | { | 927 | { |
| 928 | if (static_key_false(&perf_sched_events.key)) | 928 | if (static_branch_unlikely(&perf_sched_events)) |
| 929 | __perf_event_task_sched_in(prev, task); | 929 | __perf_event_task_sched_in(prev, task); |
| 930 | 930 | ||
| 931 | if (perf_sw_migrate_enabled() && task->sched_migrated) { | 931 | if (perf_sw_migrate_enabled() && task->sched_migrated) { |
| @@ -942,7 +942,7 @@ static inline void perf_event_task_sched_out(struct task_struct *prev, | |||
| 942 | { | 942 | { |
| 943 | perf_sw_event_sched(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 0); | 943 | perf_sw_event_sched(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 0); |
| 944 | 944 | ||
| 945 | if (static_key_false(&perf_sched_events.key)) | 945 | if (static_branch_unlikely(&perf_sched_events)) |
| 946 | __perf_event_task_sched_out(prev, next); | 946 | __perf_event_task_sched_out(prev, next); |
| 947 | } | 947 | } |
| 948 | 948 | ||
diff --git a/kernel/events/core.c b/kernel/events/core.c index 92d6999a4f2f..ea064ca8dd3c 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
| @@ -321,7 +321,13 @@ enum event_type_t { | |||
| 321 | * perf_sched_events : >0 events exist | 321 | * perf_sched_events : >0 events exist |
| 322 | * perf_cgroup_events: >0 per-cpu cgroup events exist on this cpu | 322 | * perf_cgroup_events: >0 per-cpu cgroup events exist on this cpu |
| 323 | */ | 323 | */ |
| 324 | struct static_key_deferred perf_sched_events __read_mostly; | 324 | |
| 325 | static void perf_sched_delayed(struct work_struct *work); | ||
| 326 | DEFINE_STATIC_KEY_FALSE(perf_sched_events); | ||
| 327 | static DECLARE_DELAYED_WORK(perf_sched_work, perf_sched_delayed); | ||
| 328 | static DEFINE_MUTEX(perf_sched_mutex); | ||
| 329 | static atomic_t perf_sched_count; | ||
| 330 | |||
| 325 | static DEFINE_PER_CPU(atomic_t, perf_cgroup_events); | 331 | static DEFINE_PER_CPU(atomic_t, perf_cgroup_events); |
| 326 | static DEFINE_PER_CPU(int, perf_sched_cb_usages); | 332 | static DEFINE_PER_CPU(int, perf_sched_cb_usages); |
| 327 | 333 | ||
| @@ -3536,12 +3542,22 @@ static void unaccount_event(struct perf_event *event) | |||
| 3536 | if (has_branch_stack(event)) | 3542 | if (has_branch_stack(event)) |
| 3537 | dec = true; | 3543 | dec = true; |
| 3538 | 3544 | ||
| 3539 | if (dec) | 3545 | if (dec) { |
| 3540 | static_key_slow_dec_deferred(&perf_sched_events); | 3546 | if (!atomic_add_unless(&perf_sched_count, -1, 1)) |
| 3547 | schedule_delayed_work(&perf_sched_work, HZ); | ||
| 3548 | } | ||
| 3541 | 3549 | ||
| 3542 | unaccount_event_cpu(event, event->cpu); | 3550 | unaccount_event_cpu(event, event->cpu); |
| 3543 | } | 3551 | } |
| 3544 | 3552 | ||
| 3553 | static void perf_sched_delayed(struct work_struct *work) | ||
| 3554 | { | ||
| 3555 | mutex_lock(&perf_sched_mutex); | ||
| 3556 | if (atomic_dec_and_test(&perf_sched_count)) | ||
| 3557 | static_branch_disable(&perf_sched_events); | ||
| 3558 | mutex_unlock(&perf_sched_mutex); | ||
| 3559 | } | ||
| 3560 | |||
| 3545 | /* | 3561 | /* |
| 3546 | * The following implement mutual exclusion of events on "exclusive" pmus | 3562 | * The following implement mutual exclusion of events on "exclusive" pmus |
| 3547 | * (PERF_PMU_CAP_EXCLUSIVE). Such pmus can only have one event scheduled | 3563 | * (PERF_PMU_CAP_EXCLUSIVE). Such pmus can only have one event scheduled |
| @@ -7780,8 +7796,28 @@ static void account_event(struct perf_event *event) | |||
| 7780 | if (is_cgroup_event(event)) | 7796 | if (is_cgroup_event(event)) |
| 7781 | inc = true; | 7797 | inc = true; |
| 7782 | 7798 | ||
| 7783 | if (inc) | 7799 | if (inc) { |
| 7784 | static_key_slow_inc(&perf_sched_events.key); | 7800 | if (atomic_inc_not_zero(&perf_sched_count)) |
| 7801 | goto enabled; | ||
| 7802 | |||
| 7803 | mutex_lock(&perf_sched_mutex); | ||
| 7804 | if (!atomic_read(&perf_sched_count)) { | ||
| 7805 | static_branch_enable(&perf_sched_events); | ||
| 7806 | /* | ||
| 7807 | * Guarantee that all CPUs observe they key change and | ||
| 7808 | * call the perf scheduling hooks before proceeding to | ||
| 7809 | * install events that need them. | ||
| 7810 | */ | ||
| 7811 | synchronize_sched(); | ||
| 7812 | } | ||
| 7813 | /* | ||
| 7814 | * Now that we have waited for the sync_sched(), allow further | ||
| 7815 | * increments to by-pass the mutex. | ||
| 7816 | */ | ||
| 7817 | atomic_inc(&perf_sched_count); | ||
| 7818 | mutex_unlock(&perf_sched_mutex); | ||
| 7819 | } | ||
| 7820 | enabled: | ||
| 7785 | 7821 | ||
| 7786 | account_event_cpu(event, event->cpu); | 7822 | account_event_cpu(event, event->cpu); |
| 7787 | } | 7823 | } |
| @@ -9344,9 +9380,6 @@ void __init perf_event_init(void) | |||
| 9344 | ret = init_hw_breakpoint(); | 9380 | ret = init_hw_breakpoint(); |
| 9345 | WARN(ret, "hw_breakpoint initialization failed with: %d", ret); | 9381 | WARN(ret, "hw_breakpoint initialization failed with: %d", ret); |
| 9346 | 9382 | ||
| 9347 | /* do not patch jump label more than once per second */ | ||
| 9348 | jump_label_rate_limit(&perf_sched_events, HZ); | ||
| 9349 | |||
| 9350 | /* | 9383 | /* |
| 9351 | * Build time assertion that we keep the data_head at the intended | 9384 | * Build time assertion that we keep the data_head at the intended |
| 9352 | * location. IOW, validation we got the __reserved[] size right. | 9385 | * location. IOW, validation we got the __reserved[] size right. |
