diff options
Diffstat (limited to 'kernel/events')
-rw-r--r-- | kernel/events/core.c | 81 |
1 files changed, 29 insertions, 52 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c index 37cc20e8aa3b..7f2fbb8b5069 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
@@ -872,22 +872,32 @@ void perf_pmu_enable(struct pmu *pmu) | |||
872 | pmu->pmu_enable(pmu); | 872 | pmu->pmu_enable(pmu); |
873 | } | 873 | } |
874 | 874 | ||
875 | static DEFINE_PER_CPU(struct list_head, rotation_list); | 875 | static DEFINE_PER_CPU(struct list_head, active_ctx_list); |
876 | 876 | ||
877 | /* | 877 | /* |
878 | * perf_pmu_rotate_start() and perf_rotate_context() are fully serialized | 878 | * perf_event_ctx_activate(), perf_event_ctx_deactivate(), and |
879 | * because they're strictly cpu affine and rotate_start is called with IRQs | 879 | * perf_event_task_tick() are fully serialized because they're strictly cpu |
880 | * disabled, while rotate_context is called from IRQ context. | 880 | * affine and perf_event_ctx{activate,deactivate} are called with IRQs |
881 | * disabled, while perf_event_task_tick is called from IRQ context. | ||
881 | */ | 882 | */ |
882 | static void perf_pmu_rotate_start(struct pmu *pmu) | 883 | static void perf_event_ctx_activate(struct perf_event_context *ctx) |
883 | { | 884 | { |
884 | struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); | 885 | struct list_head *head = this_cpu_ptr(&active_ctx_list); |
885 | struct list_head *head = this_cpu_ptr(&rotation_list); | ||
886 | 886 | ||
887 | WARN_ON(!irqs_disabled()); | 887 | WARN_ON(!irqs_disabled()); |
888 | 888 | ||
889 | if (list_empty(&cpuctx->rotation_list)) | 889 | WARN_ON(!list_empty(&ctx->active_ctx_list)); |
890 | list_add(&cpuctx->rotation_list, head); | 890 | |
891 | list_add(&ctx->active_ctx_list, head); | ||
892 | } | ||
893 | |||
894 | static void perf_event_ctx_deactivate(struct perf_event_context *ctx) | ||
895 | { | ||
896 | WARN_ON(!irqs_disabled()); | ||
897 | |||
898 | WARN_ON(list_empty(&ctx->active_ctx_list)); | ||
899 | |||
900 | list_del_init(&ctx->active_ctx_list); | ||
891 | } | 901 | } |
892 | 902 | ||
893 | static void get_ctx(struct perf_event_context *ctx) | 903 | static void get_ctx(struct perf_event_context *ctx) |
@@ -1233,8 +1243,6 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx) | |||
1233 | ctx->nr_branch_stack++; | 1243 | ctx->nr_branch_stack++; |
1234 | 1244 | ||
1235 | list_add_rcu(&event->event_entry, &ctx->event_list); | 1245 | list_add_rcu(&event->event_entry, &ctx->event_list); |
1236 | if (!ctx->nr_events) | ||
1237 | perf_pmu_rotate_start(ctx->pmu); | ||
1238 | ctx->nr_events++; | 1246 | ctx->nr_events++; |
1239 | if (event->attr.inherit_stat) | 1247 | if (event->attr.inherit_stat) |
1240 | ctx->nr_stat++; | 1248 | ctx->nr_stat++; |
@@ -1561,7 +1569,8 @@ event_sched_out(struct perf_event *event, | |||
1561 | 1569 | ||
1562 | if (!is_software_event(event)) | 1570 | if (!is_software_event(event)) |
1563 | cpuctx->active_oncpu--; | 1571 | cpuctx->active_oncpu--; |
1564 | ctx->nr_active--; | 1572 | if (!--ctx->nr_active) |
1573 | perf_event_ctx_deactivate(ctx); | ||
1565 | if (event->attr.freq && event->attr.sample_freq) | 1574 | if (event->attr.freq && event->attr.sample_freq) |
1566 | ctx->nr_freq--; | 1575 | ctx->nr_freq--; |
1567 | if (event->attr.exclusive || !cpuctx->active_oncpu) | 1576 | if (event->attr.exclusive || !cpuctx->active_oncpu) |
@@ -1885,7 +1894,8 @@ event_sched_in(struct perf_event *event, | |||
1885 | 1894 | ||
1886 | if (!is_software_event(event)) | 1895 | if (!is_software_event(event)) |
1887 | cpuctx->active_oncpu++; | 1896 | cpuctx->active_oncpu++; |
1888 | ctx->nr_active++; | 1897 | if (!ctx->nr_active++) |
1898 | perf_event_ctx_activate(ctx); | ||
1889 | if (event->attr.freq && event->attr.sample_freq) | 1899 | if (event->attr.freq && event->attr.sample_freq) |
1890 | ctx->nr_freq++; | 1900 | ctx->nr_freq++; |
1891 | 1901 | ||
@@ -2742,12 +2752,6 @@ static void perf_event_context_sched_in(struct perf_event_context *ctx, | |||
2742 | 2752 | ||
2743 | perf_pmu_enable(ctx->pmu); | 2753 | perf_pmu_enable(ctx->pmu); |
2744 | perf_ctx_unlock(cpuctx, ctx); | 2754 | perf_ctx_unlock(cpuctx, ctx); |
2745 | |||
2746 | /* | ||
2747 | * Since these rotations are per-cpu, we need to ensure the | ||
2748 | * cpu-context we got scheduled on is actually rotating. | ||
2749 | */ | ||
2750 | perf_pmu_rotate_start(ctx->pmu); | ||
2751 | } | 2755 | } |
2752 | 2756 | ||
2753 | /* | 2757 | /* |
@@ -3035,25 +3039,18 @@ static void rotate_ctx(struct perf_event_context *ctx) | |||
3035 | list_rotate_left(&ctx->flexible_groups); | 3039 | list_rotate_left(&ctx->flexible_groups); |
3036 | } | 3040 | } |
3037 | 3041 | ||
3038 | /* | ||
3039 | * perf_pmu_rotate_start() and perf_rotate_context() are fully serialized | ||
3040 | * because they're strictly cpu affine and rotate_start is called with IRQs | ||
3041 | * disabled, while rotate_context is called from IRQ context. | ||
3042 | */ | ||
3043 | static int perf_rotate_context(struct perf_cpu_context *cpuctx) | 3042 | static int perf_rotate_context(struct perf_cpu_context *cpuctx) |
3044 | { | 3043 | { |
3045 | struct perf_event_context *ctx = NULL; | 3044 | struct perf_event_context *ctx = NULL; |
3046 | int rotate = 0, remove = 1; | 3045 | int rotate = 0; |
3047 | 3046 | ||
3048 | if (cpuctx->ctx.nr_events) { | 3047 | if (cpuctx->ctx.nr_events) { |
3049 | remove = 0; | ||
3050 | if (cpuctx->ctx.nr_events != cpuctx->ctx.nr_active) | 3048 | if (cpuctx->ctx.nr_events != cpuctx->ctx.nr_active) |
3051 | rotate = 1; | 3049 | rotate = 1; |
3052 | } | 3050 | } |
3053 | 3051 | ||
3054 | ctx = cpuctx->task_ctx; | 3052 | ctx = cpuctx->task_ctx; |
3055 | if (ctx && ctx->nr_events) { | 3053 | if (ctx && ctx->nr_events) { |
3056 | remove = 0; | ||
3057 | if (ctx->nr_events != ctx->nr_active) | 3054 | if (ctx->nr_events != ctx->nr_active) |
3058 | rotate = 1; | 3055 | rotate = 1; |
3059 | } | 3056 | } |
@@ -3077,8 +3074,6 @@ static int perf_rotate_context(struct perf_cpu_context *cpuctx) | |||
3077 | perf_pmu_enable(cpuctx->ctx.pmu); | 3074 | perf_pmu_enable(cpuctx->ctx.pmu); |
3078 | perf_ctx_unlock(cpuctx, cpuctx->task_ctx); | 3075 | perf_ctx_unlock(cpuctx, cpuctx->task_ctx); |
3079 | done: | 3076 | done: |
3080 | if (remove) | ||
3081 | list_del_init(&cpuctx->rotation_list); | ||
3082 | 3077 | ||
3083 | return rotate; | 3078 | return rotate; |
3084 | } | 3079 | } |
@@ -3096,9 +3091,8 @@ bool perf_event_can_stop_tick(void) | |||
3096 | 3091 | ||
3097 | void perf_event_task_tick(void) | 3092 | void perf_event_task_tick(void) |
3098 | { | 3093 | { |
3099 | struct list_head *head = this_cpu_ptr(&rotation_list); | 3094 | struct list_head *head = this_cpu_ptr(&active_ctx_list); |
3100 | struct perf_cpu_context *cpuctx, *tmp; | 3095 | struct perf_event_context *ctx, *tmp; |
3101 | struct perf_event_context *ctx; | ||
3102 | int throttled; | 3096 | int throttled; |
3103 | 3097 | ||
3104 | WARN_ON(!irqs_disabled()); | 3098 | WARN_ON(!irqs_disabled()); |
@@ -3106,14 +3100,8 @@ void perf_event_task_tick(void) | |||
3106 | __this_cpu_inc(perf_throttled_seq); | 3100 | __this_cpu_inc(perf_throttled_seq); |
3107 | throttled = __this_cpu_xchg(perf_throttled_count, 0); | 3101 | throttled = __this_cpu_xchg(perf_throttled_count, 0); |
3108 | 3102 | ||
3109 | list_for_each_entry_safe(cpuctx, tmp, head, rotation_list) { | 3103 | list_for_each_entry_safe(ctx, tmp, head, active_ctx_list) |
3110 | ctx = &cpuctx->ctx; | ||
3111 | perf_adjust_freq_unthr_context(ctx, throttled); | 3104 | perf_adjust_freq_unthr_context(ctx, throttled); |
3112 | |||
3113 | ctx = cpuctx->task_ctx; | ||
3114 | if (ctx) | ||
3115 | perf_adjust_freq_unthr_context(ctx, throttled); | ||
3116 | } | ||
3117 | } | 3105 | } |
3118 | 3106 | ||
3119 | static int event_enable_on_exec(struct perf_event *event, | 3107 | static int event_enable_on_exec(struct perf_event *event, |
@@ -3272,6 +3260,7 @@ static void __perf_event_init_context(struct perf_event_context *ctx) | |||
3272 | { | 3260 | { |
3273 | raw_spin_lock_init(&ctx->lock); | 3261 | raw_spin_lock_init(&ctx->lock); |
3274 | mutex_init(&ctx->mutex); | 3262 | mutex_init(&ctx->mutex); |
3263 | INIT_LIST_HEAD(&ctx->active_ctx_list); | ||
3275 | INIT_LIST_HEAD(&ctx->pinned_groups); | 3264 | INIT_LIST_HEAD(&ctx->pinned_groups); |
3276 | INIT_LIST_HEAD(&ctx->flexible_groups); | 3265 | INIT_LIST_HEAD(&ctx->flexible_groups); |
3277 | INIT_LIST_HEAD(&ctx->event_list); | 3266 | INIT_LIST_HEAD(&ctx->event_list); |
@@ -6954,7 +6943,6 @@ skip_type: | |||
6954 | 6943 | ||
6955 | __perf_cpu_hrtimer_init(cpuctx, cpu); | 6944 | __perf_cpu_hrtimer_init(cpuctx, cpu); |
6956 | 6945 | ||
6957 | INIT_LIST_HEAD(&cpuctx->rotation_list); | ||
6958 | cpuctx->unique_pmu = pmu; | 6946 | cpuctx->unique_pmu = pmu; |
6959 | } | 6947 | } |
6960 | 6948 | ||
@@ -8384,7 +8372,7 @@ static void __init perf_event_init_all_cpus(void) | |||
8384 | for_each_possible_cpu(cpu) { | 8372 | for_each_possible_cpu(cpu) { |
8385 | swhash = &per_cpu(swevent_htable, cpu); | 8373 | swhash = &per_cpu(swevent_htable, cpu); |
8386 | mutex_init(&swhash->hlist_mutex); | 8374 | mutex_init(&swhash->hlist_mutex); |
8387 | INIT_LIST_HEAD(&per_cpu(rotation_list, cpu)); | 8375 | INIT_LIST_HEAD(&per_cpu(active_ctx_list, cpu)); |
8388 | } | 8376 | } |
8389 | } | 8377 | } |
8390 | 8378 | ||
@@ -8405,22 +8393,11 @@ static void perf_event_init_cpu(int cpu) | |||
8405 | } | 8393 | } |
8406 | 8394 | ||
8407 | #if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC | 8395 | #if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC |
8408 | static void perf_pmu_rotate_stop(struct pmu *pmu) | ||
8409 | { | ||
8410 | struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); | ||
8411 | |||
8412 | WARN_ON(!irqs_disabled()); | ||
8413 | |||
8414 | list_del_init(&cpuctx->rotation_list); | ||
8415 | } | ||
8416 | |||
8417 | static void __perf_event_exit_context(void *__info) | 8396 | static void __perf_event_exit_context(void *__info) |
8418 | { | 8397 | { |
8419 | struct remove_event re = { .detach_group = true }; | 8398 | struct remove_event re = { .detach_group = true }; |
8420 | struct perf_event_context *ctx = __info; | 8399 | struct perf_event_context *ctx = __info; |
8421 | 8400 | ||
8422 | perf_pmu_rotate_stop(ctx->pmu); | ||
8423 | |||
8424 | rcu_read_lock(); | 8401 | rcu_read_lock(); |
8425 | list_for_each_entry_rcu(re.event, &ctx->event_list, event_entry) | 8402 | list_for_each_entry_rcu(re.event, &ctx->event_list, event_entry) |
8426 | __perf_remove_from_context(&re); | 8403 | __perf_remove_from_context(&re); |