diff options
| author | Ingo Molnar <mingo@kernel.org> | 2014-06-06 01:55:06 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2014-06-06 01:55:06 -0400 |
| commit | ec00010972a0971b2c1da4fbe4e5c7d8ed1ecb05 (patch) | |
| tree | c28975d7daf6d8a3aa23afe8f42837b71105b269 /kernel/events | |
| parent | 8c6e549a447c51f4f8c0ba7f1e444469f75a354a (diff) | |
| parent | e041e328c4b41e1db79bfe5ba9992c2ed771ad19 (diff) | |
Merge branch 'perf/urgent' into perf/core, to resolve conflict and to prepare for new patches
Conflicts:
arch/x86/kernel/traps.c
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/events')
| -rw-r--r-- | kernel/events/core.c | 153 |
1 files changed, 80 insertions, 73 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c index e9ef0c6646af..8fac2056d51e 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
| @@ -2973,6 +2973,22 @@ out: | |||
| 2973 | local_irq_restore(flags); | 2973 | local_irq_restore(flags); |
| 2974 | } | 2974 | } |
| 2975 | 2975 | ||
| 2976 | void perf_event_exec(void) | ||
| 2977 | { | ||
| 2978 | struct perf_event_context *ctx; | ||
| 2979 | int ctxn; | ||
| 2980 | |||
| 2981 | rcu_read_lock(); | ||
| 2982 | for_each_task_context_nr(ctxn) { | ||
| 2983 | ctx = current->perf_event_ctxp[ctxn]; | ||
| 2984 | if (!ctx) | ||
| 2985 | continue; | ||
| 2986 | |||
| 2987 | perf_event_enable_on_exec(ctx); | ||
| 2988 | } | ||
| 2989 | rcu_read_unlock(); | ||
| 2990 | } | ||
| 2991 | |||
| 2976 | /* | 2992 | /* |
| 2977 | * Cross CPU call to read the hardware event | 2993 | * Cross CPU call to read the hardware event |
| 2978 | */ | 2994 | */ |
| @@ -3195,7 +3211,8 @@ static void free_event_rcu(struct rcu_head *head) | |||
| 3195 | } | 3211 | } |
| 3196 | 3212 | ||
| 3197 | static void ring_buffer_put(struct ring_buffer *rb); | 3213 | static void ring_buffer_put(struct ring_buffer *rb); |
| 3198 | static void ring_buffer_detach(struct perf_event *event, struct ring_buffer *rb); | 3214 | static void ring_buffer_attach(struct perf_event *event, |
| 3215 | struct ring_buffer *rb); | ||
| 3199 | 3216 | ||
| 3200 | static void unaccount_event_cpu(struct perf_event *event, int cpu) | 3217 | static void unaccount_event_cpu(struct perf_event *event, int cpu) |
| 3201 | { | 3218 | { |
| @@ -3259,8 +3276,6 @@ static void _free_event(struct perf_event *event) | |||
| 3259 | unaccount_event(event); | 3276 | unaccount_event(event); |
| 3260 | 3277 | ||
| 3261 | if (event->rb) { | 3278 | if (event->rb) { |
| 3262 | struct ring_buffer *rb; | ||
| 3263 | |||
| 3264 | /* | 3279 | /* |
| 3265 | * Can happen when we close an event with re-directed output. | 3280 | * Can happen when we close an event with re-directed output. |
| 3266 | * | 3281 | * |
| @@ -3268,12 +3283,7 @@ static void _free_event(struct perf_event *event) | |||
| 3268 | * over us; possibly making our ring_buffer_put() the last. | 3283 | * over us; possibly making our ring_buffer_put() the last. |
| 3269 | */ | 3284 | */ |
| 3270 | mutex_lock(&event->mmap_mutex); | 3285 | mutex_lock(&event->mmap_mutex); |
| 3271 | rb = event->rb; | 3286 | ring_buffer_attach(event, NULL); |
| 3272 | if (rb) { | ||
| 3273 | rcu_assign_pointer(event->rb, NULL); | ||
| 3274 | ring_buffer_detach(event, rb); | ||
| 3275 | ring_buffer_put(rb); /* could be last */ | ||
| 3276 | } | ||
| 3277 | mutex_unlock(&event->mmap_mutex); | 3287 | mutex_unlock(&event->mmap_mutex); |
| 3278 | } | 3288 | } |
| 3279 | 3289 | ||
| @@ -3870,28 +3880,47 @@ unlock: | |||
| 3870 | static void ring_buffer_attach(struct perf_event *event, | 3880 | static void ring_buffer_attach(struct perf_event *event, |
| 3871 | struct ring_buffer *rb) | 3881 | struct ring_buffer *rb) |
| 3872 | { | 3882 | { |
| 3883 | struct ring_buffer *old_rb = NULL; | ||
| 3873 | unsigned long flags; | 3884 | unsigned long flags; |
| 3874 | 3885 | ||
| 3875 | if (!list_empty(&event->rb_entry)) | 3886 | if (event->rb) { |
| 3876 | return; | 3887 | /* |
| 3888 | * Should be impossible, we set this when removing | ||
| 3889 | * event->rb_entry and wait/clear when adding event->rb_entry. | ||
| 3890 | */ | ||
| 3891 | WARN_ON_ONCE(event->rcu_pending); | ||
| 3877 | 3892 | ||
| 3878 | spin_lock_irqsave(&rb->event_lock, flags); | 3893 | old_rb = event->rb; |
| 3879 | if (list_empty(&event->rb_entry)) | 3894 | event->rcu_batches = get_state_synchronize_rcu(); |
| 3880 | list_add(&event->rb_entry, &rb->event_list); | 3895 | event->rcu_pending = 1; |
| 3881 | spin_unlock_irqrestore(&rb->event_lock, flags); | ||
| 3882 | } | ||
| 3883 | 3896 | ||
| 3884 | static void ring_buffer_detach(struct perf_event *event, struct ring_buffer *rb) | 3897 | spin_lock_irqsave(&old_rb->event_lock, flags); |
| 3885 | { | 3898 | list_del_rcu(&event->rb_entry); |
| 3886 | unsigned long flags; | 3899 | spin_unlock_irqrestore(&old_rb->event_lock, flags); |
| 3900 | } | ||
| 3887 | 3901 | ||
| 3888 | if (list_empty(&event->rb_entry)) | 3902 | if (event->rcu_pending && rb) { |
| 3889 | return; | 3903 | cond_synchronize_rcu(event->rcu_batches); |
| 3904 | event->rcu_pending = 0; | ||
| 3905 | } | ||
| 3906 | |||
| 3907 | if (rb) { | ||
| 3908 | spin_lock_irqsave(&rb->event_lock, flags); | ||
| 3909 | list_add_rcu(&event->rb_entry, &rb->event_list); | ||
| 3910 | spin_unlock_irqrestore(&rb->event_lock, flags); | ||
| 3911 | } | ||
| 3912 | |||
| 3913 | rcu_assign_pointer(event->rb, rb); | ||
| 3890 | 3914 | ||
| 3891 | spin_lock_irqsave(&rb->event_lock, flags); | 3915 | if (old_rb) { |
| 3892 | list_del_init(&event->rb_entry); | 3916 | ring_buffer_put(old_rb); |
| 3893 | wake_up_all(&event->waitq); | 3917 | /* |
| 3894 | spin_unlock_irqrestore(&rb->event_lock, flags); | 3918 | * Since we detached before setting the new rb, so that we |
| 3919 | * could attach the new rb, we could have missed a wakeup. | ||
| 3920 | * Provide it now. | ||
| 3921 | */ | ||
| 3922 | wake_up_all(&event->waitq); | ||
| 3923 | } | ||
| 3895 | } | 3924 | } |
| 3896 | 3925 | ||
| 3897 | static void ring_buffer_wakeup(struct perf_event *event) | 3926 | static void ring_buffer_wakeup(struct perf_event *event) |
| @@ -3960,7 +3989,7 @@ static void perf_mmap_close(struct vm_area_struct *vma) | |||
| 3960 | { | 3989 | { |
| 3961 | struct perf_event *event = vma->vm_file->private_data; | 3990 | struct perf_event *event = vma->vm_file->private_data; |
| 3962 | 3991 | ||
| 3963 | struct ring_buffer *rb = event->rb; | 3992 | struct ring_buffer *rb = ring_buffer_get(event); |
| 3964 | struct user_struct *mmap_user = rb->mmap_user; | 3993 | struct user_struct *mmap_user = rb->mmap_user; |
| 3965 | int mmap_locked = rb->mmap_locked; | 3994 | int mmap_locked = rb->mmap_locked; |
| 3966 | unsigned long size = perf_data_size(rb); | 3995 | unsigned long size = perf_data_size(rb); |
| @@ -3968,18 +3997,14 @@ static void perf_mmap_close(struct vm_area_struct *vma) | |||
| 3968 | atomic_dec(&rb->mmap_count); | 3997 | atomic_dec(&rb->mmap_count); |
| 3969 | 3998 | ||
| 3970 | if (!atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) | 3999 | if (!atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) |
| 3971 | return; | 4000 | goto out_put; |
| 3972 | 4001 | ||
| 3973 | /* Detach current event from the buffer. */ | 4002 | ring_buffer_attach(event, NULL); |
| 3974 | rcu_assign_pointer(event->rb, NULL); | ||
| 3975 | ring_buffer_detach(event, rb); | ||
| 3976 | mutex_unlock(&event->mmap_mutex); | 4003 | mutex_unlock(&event->mmap_mutex); |
| 3977 | 4004 | ||
| 3978 | /* If there's still other mmap()s of this buffer, we're done. */ | 4005 | /* If there's still other mmap()s of this buffer, we're done. */ |
| 3979 | if (atomic_read(&rb->mmap_count)) { | 4006 | if (atomic_read(&rb->mmap_count)) |
| 3980 | ring_buffer_put(rb); /* can't be last */ | 4007 | goto out_put; |
| 3981 | return; | ||
| 3982 | } | ||
| 3983 | 4008 | ||
| 3984 | /* | 4009 | /* |
| 3985 | * No other mmap()s, detach from all other events that might redirect | 4010 | * No other mmap()s, detach from all other events that might redirect |
| @@ -4009,11 +4034,9 @@ again: | |||
| 4009 | * still restart the iteration to make sure we're not now | 4034 | * still restart the iteration to make sure we're not now |
| 4010 | * iterating the wrong list. | 4035 | * iterating the wrong list. |
| 4011 | */ | 4036 | */ |
| 4012 | if (event->rb == rb) { | 4037 | if (event->rb == rb) |
| 4013 | rcu_assign_pointer(event->rb, NULL); | 4038 | ring_buffer_attach(event, NULL); |
| 4014 | ring_buffer_detach(event, rb); | 4039 | |
| 4015 | ring_buffer_put(rb); /* can't be last, we still have one */ | ||
| 4016 | } | ||
| 4017 | mutex_unlock(&event->mmap_mutex); | 4040 | mutex_unlock(&event->mmap_mutex); |
| 4018 | put_event(event); | 4041 | put_event(event); |
| 4019 | 4042 | ||
| @@ -4038,6 +4061,7 @@ again: | |||
| 4038 | vma->vm_mm->pinned_vm -= mmap_locked; | 4061 | vma->vm_mm->pinned_vm -= mmap_locked; |
| 4039 | free_uid(mmap_user); | 4062 | free_uid(mmap_user); |
| 4040 | 4063 | ||
| 4064 | out_put: | ||
| 4041 | ring_buffer_put(rb); /* could be last */ | 4065 | ring_buffer_put(rb); /* could be last */ |
| 4042 | } | 4066 | } |
| 4043 | 4067 | ||
| @@ -4155,7 +4179,6 @@ again: | |||
| 4155 | vma->vm_mm->pinned_vm += extra; | 4179 | vma->vm_mm->pinned_vm += extra; |
| 4156 | 4180 | ||
| 4157 | ring_buffer_attach(event, rb); | 4181 | ring_buffer_attach(event, rb); |
| 4158 | rcu_assign_pointer(event->rb, rb); | ||
| 4159 | 4182 | ||
| 4160 | perf_event_init_userpage(event); | 4183 | perf_event_init_userpage(event); |
| 4161 | perf_event_update_userpage(event); | 4184 | perf_event_update_userpage(event); |
| @@ -5070,18 +5093,6 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event) | |||
| 5070 | void perf_event_comm(struct task_struct *task) | 5093 | void perf_event_comm(struct task_struct *task) |
| 5071 | { | 5094 | { |
| 5072 | struct perf_comm_event comm_event; | 5095 | struct perf_comm_event comm_event; |
| 5073 | struct perf_event_context *ctx; | ||
| 5074 | int ctxn; | ||
| 5075 | |||
| 5076 | rcu_read_lock(); | ||
| 5077 | for_each_task_context_nr(ctxn) { | ||
| 5078 | ctx = task->perf_event_ctxp[ctxn]; | ||
| 5079 | if (!ctx) | ||
| 5080 | continue; | ||
| 5081 | |||
| 5082 | perf_event_enable_on_exec(ctx); | ||
| 5083 | } | ||
| 5084 | rcu_read_unlock(); | ||
| 5085 | 5096 | ||
| 5086 | if (!atomic_read(&nr_comm_events)) | 5097 | if (!atomic_read(&nr_comm_events)) |
| 5087 | return; | 5098 | return; |
| @@ -5439,6 +5450,9 @@ struct swevent_htable { | |||
| 5439 | 5450 | ||
| 5440 | /* Recursion avoidance in each contexts */ | 5451 | /* Recursion avoidance in each contexts */ |
| 5441 | int recursion[PERF_NR_CONTEXTS]; | 5452 | int recursion[PERF_NR_CONTEXTS]; |
| 5453 | |||
| 5454 | /* Keeps track of cpu being initialized/exited */ | ||
| 5455 | bool online; | ||
| 5442 | }; | 5456 | }; |
| 5443 | 5457 | ||
| 5444 | static DEFINE_PER_CPU(struct swevent_htable, swevent_htable); | 5458 | static DEFINE_PER_CPU(struct swevent_htable, swevent_htable); |
| @@ -5685,8 +5699,14 @@ static int perf_swevent_add(struct perf_event *event, int flags) | |||
| 5685 | hwc->state = !(flags & PERF_EF_START); | 5699 | hwc->state = !(flags & PERF_EF_START); |
| 5686 | 5700 | ||
| 5687 | head = find_swevent_head(swhash, event); | 5701 | head = find_swevent_head(swhash, event); |
| 5688 | if (WARN_ON_ONCE(!head)) | 5702 | if (!head) { |
| 5703 | /* | ||
| 5704 | * We can race with cpu hotplug code. Do not | ||
| 5705 | * WARN if the cpu just got unplugged. | ||
| 5706 | */ | ||
| 5707 | WARN_ON_ONCE(swhash->online); | ||
| 5689 | return -EINVAL; | 5708 | return -EINVAL; |
| 5709 | } | ||
| 5690 | 5710 | ||
| 5691 | hlist_add_head_rcu(&event->hlist_entry, head); | 5711 | hlist_add_head_rcu(&event->hlist_entry, head); |
| 5692 | 5712 | ||
| @@ -6956,7 +6976,7 @@ err_size: | |||
| 6956 | static int | 6976 | static int |
| 6957 | perf_event_set_output(struct perf_event *event, struct perf_event *output_event) | 6977 | perf_event_set_output(struct perf_event *event, struct perf_event *output_event) |
| 6958 | { | 6978 | { |
| 6959 | struct ring_buffer *rb = NULL, *old_rb = NULL; | 6979 | struct ring_buffer *rb = NULL; |
| 6960 | int ret = -EINVAL; | 6980 | int ret = -EINVAL; |
| 6961 | 6981 | ||
| 6962 | if (!output_event) | 6982 | if (!output_event) |
| @@ -6984,8 +7004,6 @@ set: | |||
| 6984 | if (atomic_read(&event->mmap_count)) | 7004 | if (atomic_read(&event->mmap_count)) |
| 6985 | goto unlock; | 7005 | goto unlock; |
| 6986 | 7006 | ||
| 6987 | old_rb = event->rb; | ||
| 6988 | |||
| 6989 | if (output_event) { | 7007 | if (output_event) { |
| 6990 | /* get the rb we want to redirect to */ | 7008 | /* get the rb we want to redirect to */ |
| 6991 | rb = ring_buffer_get(output_event); | 7009 | rb = ring_buffer_get(output_event); |
| @@ -6993,23 +7011,7 @@ set: | |||
| 6993 | goto unlock; | 7011 | goto unlock; |
| 6994 | } | 7012 | } |
| 6995 | 7013 | ||
| 6996 | if (old_rb) | 7014 | ring_buffer_attach(event, rb); |
| 6997 | ring_buffer_detach(event, old_rb); | ||
| 6998 | |||
| 6999 | if (rb) | ||
| 7000 | ring_buffer_attach(event, rb); | ||
| 7001 | |||
| 7002 | rcu_assign_pointer(event->rb, rb); | ||
| 7003 | |||
| 7004 | if (old_rb) { | ||
| 7005 | ring_buffer_put(old_rb); | ||
| 7006 | /* | ||
| 7007 | * Since we detached before setting the new rb, so that we | ||
| 7008 | * could attach the new rb, we could have missed a wakeup. | ||
| 7009 | * Provide it now. | ||
| 7010 | */ | ||
| 7011 | wake_up_all(&event->waitq); | ||
| 7012 | } | ||
| 7013 | 7015 | ||
| 7014 | ret = 0; | 7016 | ret = 0; |
| 7015 | unlock: | 7017 | unlock: |
| @@ -7060,6 +7062,9 @@ SYSCALL_DEFINE5(perf_event_open, | |||
| 7060 | if (attr.freq) { | 7062 | if (attr.freq) { |
| 7061 | if (attr.sample_freq > sysctl_perf_event_sample_rate) | 7063 | if (attr.sample_freq > sysctl_perf_event_sample_rate) |
| 7062 | return -EINVAL; | 7064 | return -EINVAL; |
| 7065 | } else { | ||
| 7066 | if (attr.sample_period & (1ULL << 63)) | ||
| 7067 | return -EINVAL; | ||
| 7063 | } | 7068 | } |
| 7064 | 7069 | ||
| 7065 | /* | 7070 | /* |
| @@ -7872,6 +7877,7 @@ static void perf_event_init_cpu(int cpu) | |||
| 7872 | struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); | 7877 | struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); |
| 7873 | 7878 | ||
| 7874 | mutex_lock(&swhash->hlist_mutex); | 7879 | mutex_lock(&swhash->hlist_mutex); |
| 7880 | swhash->online = true; | ||
| 7875 | if (swhash->hlist_refcount > 0) { | 7881 | if (swhash->hlist_refcount > 0) { |
| 7876 | struct swevent_hlist *hlist; | 7882 | struct swevent_hlist *hlist; |
| 7877 | 7883 | ||
| @@ -7929,6 +7935,7 @@ static void perf_event_exit_cpu(int cpu) | |||
| 7929 | perf_event_exit_cpu_context(cpu); | 7935 | perf_event_exit_cpu_context(cpu); |
| 7930 | 7936 | ||
| 7931 | mutex_lock(&swhash->hlist_mutex); | 7937 | mutex_lock(&swhash->hlist_mutex); |
| 7938 | swhash->online = false; | ||
| 7932 | swevent_hlist_release(swhash); | 7939 | swevent_hlist_release(swhash); |
| 7933 | mutex_unlock(&swhash->hlist_mutex); | 7940 | mutex_unlock(&swhash->hlist_mutex); |
| 7934 | } | 7941 | } |
