aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/perf_event.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/perf_event.c')
-rw-r--r--kernel/perf_event.c89
1 files changed, 57 insertions, 32 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 9ecaa45ab6b2..3256e36ad251 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -2674,20 +2674,21 @@ static void perf_output_wakeup(struct perf_output_handle *handle)
2674static void perf_output_lock(struct perf_output_handle *handle) 2674static void perf_output_lock(struct perf_output_handle *handle)
2675{ 2675{
2676 struct perf_mmap_data *data = handle->data; 2676 struct perf_mmap_data *data = handle->data;
2677 int cpu; 2677 int cur, cpu = get_cpu();
2678 2678
2679 handle->locked = 0; 2679 handle->locked = 0;
2680 2680
2681 local_irq_save(handle->flags); 2681 for (;;) {
2682 cpu = smp_processor_id(); 2682 cur = atomic_cmpxchg(&data->lock, -1, cpu);
2683 2683 if (cur == -1) {
2684 if (in_nmi() && atomic_read(&data->lock) == cpu) 2684 handle->locked = 1;
2685 return; 2685 break;
2686 }
2687 if (cur == cpu)
2688 break;
2686 2689
2687 while (atomic_cmpxchg(&data->lock, -1, cpu) != -1)
2688 cpu_relax(); 2690 cpu_relax();
2689 2691 }
2690 handle->locked = 1;
2691} 2692}
2692 2693
2693static void perf_output_unlock(struct perf_output_handle *handle) 2694static void perf_output_unlock(struct perf_output_handle *handle)
@@ -2733,7 +2734,7 @@ again:
2733 if (atomic_xchg(&data->wakeup, 0)) 2734 if (atomic_xchg(&data->wakeup, 0))
2734 perf_output_wakeup(handle); 2735 perf_output_wakeup(handle);
2735out: 2736out:
2736 local_irq_restore(handle->flags); 2737 put_cpu();
2737} 2738}
2738 2739
2739void perf_output_copy(struct perf_output_handle *handle, 2740void perf_output_copy(struct perf_output_handle *handle,
@@ -3976,8 +3977,9 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
3976 regs = task_pt_regs(current); 3977 regs = task_pt_regs(current);
3977 3978
3978 if (regs) { 3979 if (regs) {
3979 if (perf_event_overflow(event, 0, &data, regs)) 3980 if (!(event->attr.exclude_idle && current->pid == 0))
3980 ret = HRTIMER_NORESTART; 3981 if (perf_event_overflow(event, 0, &data, regs))
3982 ret = HRTIMER_NORESTART;
3981 } 3983 }
3982 3984
3983 period = max_t(u64, 10000, event->hw.sample_period); 3985 period = max_t(u64, 10000, event->hw.sample_period);
@@ -3986,6 +3988,42 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
3986 return ret; 3988 return ret;
3987} 3989}
3988 3990
3991static void perf_swevent_start_hrtimer(struct perf_event *event)
3992{
3993 struct hw_perf_event *hwc = &event->hw;
3994
3995 hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
3996 hwc->hrtimer.function = perf_swevent_hrtimer;
3997 if (hwc->sample_period) {
3998 u64 period;
3999
4000 if (hwc->remaining) {
4001 if (hwc->remaining < 0)
4002 period = 10000;
4003 else
4004 period = hwc->remaining;
4005 hwc->remaining = 0;
4006 } else {
4007 period = max_t(u64, 10000, hwc->sample_period);
4008 }
4009 __hrtimer_start_range_ns(&hwc->hrtimer,
4010 ns_to_ktime(period), 0,
4011 HRTIMER_MODE_REL, 0);
4012 }
4013}
4014
4015static void perf_swevent_cancel_hrtimer(struct perf_event *event)
4016{
4017 struct hw_perf_event *hwc = &event->hw;
4018
4019 if (hwc->sample_period) {
4020 ktime_t remaining = hrtimer_get_remaining(&hwc->hrtimer);
4021 hwc->remaining = ktime_to_ns(remaining);
4022
4023 hrtimer_cancel(&hwc->hrtimer);
4024 }
4025}
4026
3989/* 4027/*
3990 * Software event: cpu wall time clock 4028 * Software event: cpu wall time clock
3991 */ 4029 */
@@ -4008,22 +4046,14 @@ static int cpu_clock_perf_event_enable(struct perf_event *event)
4008 int cpu = raw_smp_processor_id(); 4046 int cpu = raw_smp_processor_id();
4009 4047
4010 atomic64_set(&hwc->prev_count, cpu_clock(cpu)); 4048 atomic64_set(&hwc->prev_count, cpu_clock(cpu));
4011 hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 4049 perf_swevent_start_hrtimer(event);
4012 hwc->hrtimer.function = perf_swevent_hrtimer;
4013 if (hwc->sample_period) {
4014 u64 period = max_t(u64, 10000, hwc->sample_period);
4015 __hrtimer_start_range_ns(&hwc->hrtimer,
4016 ns_to_ktime(period), 0,
4017 HRTIMER_MODE_REL, 0);
4018 }
4019 4050
4020 return 0; 4051 return 0;
4021} 4052}
4022 4053
4023static void cpu_clock_perf_event_disable(struct perf_event *event) 4054static void cpu_clock_perf_event_disable(struct perf_event *event)
4024{ 4055{
4025 if (event->hw.sample_period) 4056 perf_swevent_cancel_hrtimer(event);
4026 hrtimer_cancel(&event->hw.hrtimer);
4027 cpu_clock_perf_event_update(event); 4057 cpu_clock_perf_event_update(event);
4028} 4058}
4029 4059
@@ -4060,22 +4090,15 @@ static int task_clock_perf_event_enable(struct perf_event *event)
4060 now = event->ctx->time; 4090 now = event->ctx->time;
4061 4091
4062 atomic64_set(&hwc->prev_count, now); 4092 atomic64_set(&hwc->prev_count, now);
4063 hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 4093
4064 hwc->hrtimer.function = perf_swevent_hrtimer; 4094 perf_swevent_start_hrtimer(event);
4065 if (hwc->sample_period) {
4066 u64 period = max_t(u64, 10000, hwc->sample_period);
4067 __hrtimer_start_range_ns(&hwc->hrtimer,
4068 ns_to_ktime(period), 0,
4069 HRTIMER_MODE_REL, 0);
4070 }
4071 4095
4072 return 0; 4096 return 0;
4073} 4097}
4074 4098
4075static void task_clock_perf_event_disable(struct perf_event *event) 4099static void task_clock_perf_event_disable(struct perf_event *event)
4076{ 4100{
4077 if (event->hw.sample_period) 4101 perf_swevent_cancel_hrtimer(event);
4078 hrtimer_cancel(&event->hw.hrtimer);
4079 task_clock_perf_event_update(event, event->ctx->time); 4102 task_clock_perf_event_update(event, event->ctx->time);
4080 4103
4081} 4104}
@@ -4252,6 +4275,8 @@ static const struct pmu *sw_perf_event_init(struct perf_event *event)
4252 case PERF_COUNT_SW_PAGE_FAULTS_MAJ: 4275 case PERF_COUNT_SW_PAGE_FAULTS_MAJ:
4253 case PERF_COUNT_SW_CONTEXT_SWITCHES: 4276 case PERF_COUNT_SW_CONTEXT_SWITCHES:
4254 case PERF_COUNT_SW_CPU_MIGRATIONS: 4277 case PERF_COUNT_SW_CPU_MIGRATIONS:
4278 case PERF_COUNT_SW_ALIGNMENT_FAULTS:
4279 case PERF_COUNT_SW_EMULATION_FAULTS:
4255 if (!event->parent) { 4280 if (!event->parent) {
4256 atomic_inc(&perf_swevent_enabled[event_id]); 4281 atomic_inc(&perf_swevent_enabled[event_id]);
4257 event->destroy = sw_perf_event_destroy; 4282 event->destroy = sw_perf_event_destroy;