diff options
-rw-r--r-- | include/linux/perf_counter.h | 15 | ||||
-rw-r--r-- | kernel/perf_counter.c | 92 | ||||
-rw-r--r-- | tools/perf/builtin-annotate.c | 24 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 24 |
4 files changed, 35 insertions, 120 deletions
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h index 5e970c7d3fd5..bd15d7a5f5ce 100644 --- a/include/linux/perf_counter.h +++ b/include/linux/perf_counter.h | |||
@@ -120,8 +120,9 @@ enum perf_counter_sample_format { | |||
120 | PERF_SAMPLE_ID = 1U << 6, | 120 | PERF_SAMPLE_ID = 1U << 6, |
121 | PERF_SAMPLE_CPU = 1U << 7, | 121 | PERF_SAMPLE_CPU = 1U << 7, |
122 | PERF_SAMPLE_PERIOD = 1U << 8, | 122 | PERF_SAMPLE_PERIOD = 1U << 8, |
123 | PERF_SAMPLE_STREAM_ID = 1U << 9, | ||
123 | 124 | ||
124 | PERF_SAMPLE_MAX = 1U << 9, /* non-ABI */ | 125 | PERF_SAMPLE_MAX = 1U << 10, /* non-ABI */ |
125 | }; | 126 | }; |
126 | 127 | ||
127 | /* | 128 | /* |
@@ -312,16 +313,7 @@ enum perf_event_type { | |||
312 | * struct perf_event_header header; | 313 | * struct perf_event_header header; |
313 | * u64 time; | 314 | * u64 time; |
314 | * u64 id; | 315 | * u64 id; |
315 | * u64 sample_period; | 316 | * u64 stream_id; |
316 | * }; | ||
317 | */ | ||
318 | PERF_EVENT_PERIOD = 4, | ||
319 | |||
320 | /* | ||
321 | * struct { | ||
322 | * struct perf_event_header header; | ||
323 | * u64 time; | ||
324 | * u64 id; | ||
325 | * }; | 317 | * }; |
326 | */ | 318 | */ |
327 | PERF_EVENT_THROTTLE = 5, | 319 | PERF_EVENT_THROTTLE = 5, |
@@ -356,6 +348,7 @@ enum perf_event_type { | |||
356 | * { u64 time; } && PERF_SAMPLE_TIME | 348 | * { u64 time; } && PERF_SAMPLE_TIME |
357 | * { u64 addr; } && PERF_SAMPLE_ADDR | 349 | * { u64 addr; } && PERF_SAMPLE_ADDR |
358 | * { u64 id; } && PERF_SAMPLE_ID | 350 | * { u64 id; } && PERF_SAMPLE_ID |
351 | * { u64 stream_id;} && PERF_SAMPLE_STREAM_ID | ||
359 | * { u32 cpu, res; } && PERF_SAMPLE_CPU | 352 | * { u32 cpu, res; } && PERF_SAMPLE_CPU |
360 | * { u64 period; } && PERF_SAMPLE_PERIOD | 353 | * { u64 period; } && PERF_SAMPLE_PERIOD |
361 | * | 354 | * |
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index e1d6a3aa1333..7530588fa5c5 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c | |||
@@ -155,6 +155,20 @@ static void unclone_ctx(struct perf_counter_context *ctx) | |||
155 | } | 155 | } |
156 | 156 | ||
157 | /* | 157 | /* |
158 | * If we inherit counters we want to return the parent counter id | ||
159 | * to userspace. | ||
160 | */ | ||
161 | static u64 primary_counter_id(struct perf_counter *counter) | ||
162 | { | ||
163 | u64 id = counter->id; | ||
164 | |||
165 | if (counter->parent) | ||
166 | id = counter->parent->id; | ||
167 | |||
168 | return id; | ||
169 | } | ||
170 | |||
171 | /* | ||
158 | * Get the perf_counter_context for a task and lock it. | 172 | * Get the perf_counter_context for a task and lock it. |
159 | * This has to cope with with the fact that until it is locked, | 173 | * This has to cope with with the fact that until it is locked, |
160 | * the context could get moved to another task. | 174 | * the context could get moved to another task. |
@@ -1296,7 +1310,6 @@ static void perf_counter_cpu_sched_in(struct perf_cpu_context *cpuctx, int cpu) | |||
1296 | #define MAX_INTERRUPTS (~0ULL) | 1310 | #define MAX_INTERRUPTS (~0ULL) |
1297 | 1311 | ||
1298 | static void perf_log_throttle(struct perf_counter *counter, int enable); | 1312 | static void perf_log_throttle(struct perf_counter *counter, int enable); |
1299 | static void perf_log_period(struct perf_counter *counter, u64 period); | ||
1300 | 1313 | ||
1301 | static void perf_adjust_period(struct perf_counter *counter, u64 events) | 1314 | static void perf_adjust_period(struct perf_counter *counter, u64 events) |
1302 | { | 1315 | { |
@@ -1315,8 +1328,6 @@ static void perf_adjust_period(struct perf_counter *counter, u64 events) | |||
1315 | if (!sample_period) | 1328 | if (!sample_period) |
1316 | sample_period = 1; | 1329 | sample_period = 1; |
1317 | 1330 | ||
1318 | perf_log_period(counter, sample_period); | ||
1319 | |||
1320 | hwc->sample_period = sample_period; | 1331 | hwc->sample_period = sample_period; |
1321 | } | 1332 | } |
1322 | 1333 | ||
@@ -1705,7 +1716,7 @@ perf_read_hw(struct perf_counter *counter, char __user *buf, size_t count) | |||
1705 | values[n++] = counter->total_time_running + | 1716 | values[n++] = counter->total_time_running + |
1706 | atomic64_read(&counter->child_total_time_running); | 1717 | atomic64_read(&counter->child_total_time_running); |
1707 | if (counter->attr.read_format & PERF_FORMAT_ID) | 1718 | if (counter->attr.read_format & PERF_FORMAT_ID) |
1708 | values[n++] = counter->id; | 1719 | values[n++] = primary_counter_id(counter); |
1709 | mutex_unlock(&counter->child_mutex); | 1720 | mutex_unlock(&counter->child_mutex); |
1710 | 1721 | ||
1711 | if (count < n * sizeof(u64)) | 1722 | if (count < n * sizeof(u64)) |
@@ -1812,8 +1823,6 @@ static int perf_counter_period(struct perf_counter *counter, u64 __user *arg) | |||
1812 | 1823 | ||
1813 | counter->attr.sample_freq = value; | 1824 | counter->attr.sample_freq = value; |
1814 | } else { | 1825 | } else { |
1815 | perf_log_period(counter, value); | ||
1816 | |||
1817 | counter->attr.sample_period = value; | 1826 | counter->attr.sample_period = value; |
1818 | counter->hw.sample_period = value; | 1827 | counter->hw.sample_period = value; |
1819 | } | 1828 | } |
@@ -2662,6 +2671,9 @@ static void perf_counter_output(struct perf_counter *counter, int nmi, | |||
2662 | if (sample_type & PERF_SAMPLE_ID) | 2671 | if (sample_type & PERF_SAMPLE_ID) |
2663 | header.size += sizeof(u64); | 2672 | header.size += sizeof(u64); |
2664 | 2673 | ||
2674 | if (sample_type & PERF_SAMPLE_STREAM_ID) | ||
2675 | header.size += sizeof(u64); | ||
2676 | |||
2665 | if (sample_type & PERF_SAMPLE_CPU) { | 2677 | if (sample_type & PERF_SAMPLE_CPU) { |
2666 | header.size += sizeof(cpu_entry); | 2678 | header.size += sizeof(cpu_entry); |
2667 | 2679 | ||
@@ -2705,7 +2717,13 @@ static void perf_counter_output(struct perf_counter *counter, int nmi, | |||
2705 | if (sample_type & PERF_SAMPLE_ADDR) | 2717 | if (sample_type & PERF_SAMPLE_ADDR) |
2706 | perf_output_put(&handle, data->addr); | 2718 | perf_output_put(&handle, data->addr); |
2707 | 2719 | ||
2708 | if (sample_type & PERF_SAMPLE_ID) | 2720 | if (sample_type & PERF_SAMPLE_ID) { |
2721 | u64 id = primary_counter_id(counter); | ||
2722 | |||
2723 | perf_output_put(&handle, id); | ||
2724 | } | ||
2725 | |||
2726 | if (sample_type & PERF_SAMPLE_STREAM_ID) | ||
2709 | perf_output_put(&handle, counter->id); | 2727 | perf_output_put(&handle, counter->id); |
2710 | 2728 | ||
2711 | if (sample_type & PERF_SAMPLE_CPU) | 2729 | if (sample_type & PERF_SAMPLE_CPU) |
@@ -2728,7 +2746,7 @@ static void perf_counter_output(struct perf_counter *counter, int nmi, | |||
2728 | if (sub != counter) | 2746 | if (sub != counter) |
2729 | sub->pmu->read(sub); | 2747 | sub->pmu->read(sub); |
2730 | 2748 | ||
2731 | group_entry.id = sub->id; | 2749 | group_entry.id = primary_counter_id(sub); |
2732 | group_entry.counter = atomic64_read(&sub->count); | 2750 | group_entry.counter = atomic64_read(&sub->count); |
2733 | 2751 | ||
2734 | perf_output_put(&handle, group_entry); | 2752 | perf_output_put(&handle, group_entry); |
@@ -2788,15 +2806,8 @@ perf_counter_read_event(struct perf_counter *counter, | |||
2788 | } | 2806 | } |
2789 | 2807 | ||
2790 | if (counter->attr.read_format & PERF_FORMAT_ID) { | 2808 | if (counter->attr.read_format & PERF_FORMAT_ID) { |
2791 | u64 id; | ||
2792 | |||
2793 | event.header.size += sizeof(u64); | 2809 | event.header.size += sizeof(u64); |
2794 | if (counter->parent) | 2810 | event.format[i++] = primary_counter_id(counter); |
2795 | id = counter->parent->id; | ||
2796 | else | ||
2797 | id = counter->id; | ||
2798 | |||
2799 | event.format[i++] = id; | ||
2800 | } | 2811 | } |
2801 | 2812 | ||
2802 | ret = perf_output_begin(&handle, counter, event.header.size, 0, 0); | 2813 | ret = perf_output_begin(&handle, counter, event.header.size, 0, 0); |
@@ -3191,49 +3202,6 @@ void __perf_counter_mmap(struct vm_area_struct *vma) | |||
3191 | } | 3202 | } |
3192 | 3203 | ||
3193 | /* | 3204 | /* |
3194 | * Log sample_period changes so that analyzing tools can re-normalize the | ||
3195 | * event flow. | ||
3196 | */ | ||
3197 | |||
3198 | struct freq_event { | ||
3199 | struct perf_event_header header; | ||
3200 | u64 time; | ||
3201 | u64 id; | ||
3202 | u64 period; | ||
3203 | }; | ||
3204 | |||
3205 | static void perf_log_period(struct perf_counter *counter, u64 period) | ||
3206 | { | ||
3207 | struct perf_output_handle handle; | ||
3208 | struct freq_event event; | ||
3209 | int ret; | ||
3210 | |||
3211 | if (counter->hw.sample_period == period) | ||
3212 | return; | ||
3213 | |||
3214 | if (counter->attr.sample_type & PERF_SAMPLE_PERIOD) | ||
3215 | return; | ||
3216 | |||
3217 | event = (struct freq_event) { | ||
3218 | .header = { | ||
3219 | .type = PERF_EVENT_PERIOD, | ||
3220 | .misc = 0, | ||
3221 | .size = sizeof(event), | ||
3222 | }, | ||
3223 | .time = sched_clock(), | ||
3224 | .id = counter->id, | ||
3225 | .period = period, | ||
3226 | }; | ||
3227 | |||
3228 | ret = perf_output_begin(&handle, counter, sizeof(event), 1, 0); | ||
3229 | if (ret) | ||
3230 | return; | ||
3231 | |||
3232 | perf_output_put(&handle, event); | ||
3233 | perf_output_end(&handle); | ||
3234 | } | ||
3235 | |||
3236 | /* | ||
3237 | * IRQ throttle logging | 3205 | * IRQ throttle logging |
3238 | */ | 3206 | */ |
3239 | 3207 | ||
@@ -3246,14 +3214,16 @@ static void perf_log_throttle(struct perf_counter *counter, int enable) | |||
3246 | struct perf_event_header header; | 3214 | struct perf_event_header header; |
3247 | u64 time; | 3215 | u64 time; |
3248 | u64 id; | 3216 | u64 id; |
3217 | u64 stream_id; | ||
3249 | } throttle_event = { | 3218 | } throttle_event = { |
3250 | .header = { | 3219 | .header = { |
3251 | .type = PERF_EVENT_THROTTLE + 1, | 3220 | .type = PERF_EVENT_THROTTLE + 1, |
3252 | .misc = 0, | 3221 | .misc = 0, |
3253 | .size = sizeof(throttle_event), | 3222 | .size = sizeof(throttle_event), |
3254 | }, | 3223 | }, |
3255 | .time = sched_clock(), | 3224 | .time = sched_clock(), |
3256 | .id = counter->id, | 3225 | .id = primary_counter_id(counter), |
3226 | .stream_id = counter->id, | ||
3257 | }; | 3227 | }; |
3258 | 3228 | ||
3259 | ret = perf_output_begin(&handle, counter, sizeof(throttle_event), 1, 0); | 3229 | ret = perf_output_begin(&handle, counter, sizeof(throttle_event), 1, 0); |
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 5f9eefecc574..1dba568e1941 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -74,20 +74,12 @@ struct fork_event { | |||
74 | u32 pid, ppid; | 74 | u32 pid, ppid; |
75 | }; | 75 | }; |
76 | 76 | ||
77 | struct period_event { | ||
78 | struct perf_event_header header; | ||
79 | u64 time; | ||
80 | u64 id; | ||
81 | u64 sample_period; | ||
82 | }; | ||
83 | |||
84 | typedef union event_union { | 77 | typedef union event_union { |
85 | struct perf_event_header header; | 78 | struct perf_event_header header; |
86 | struct ip_event ip; | 79 | struct ip_event ip; |
87 | struct mmap_event mmap; | 80 | struct mmap_event mmap; |
88 | struct comm_event comm; | 81 | struct comm_event comm; |
89 | struct fork_event fork; | 82 | struct fork_event fork; |
90 | struct period_event period; | ||
91 | } event_t; | 83 | } event_t; |
92 | 84 | ||
93 | 85 | ||
@@ -998,19 +990,6 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head) | |||
998 | } | 990 | } |
999 | 991 | ||
1000 | static int | 992 | static int |
1001 | process_period_event(event_t *event, unsigned long offset, unsigned long head) | ||
1002 | { | ||
1003 | dprintf("%p [%p]: PERF_EVENT_PERIOD: time:%Ld, id:%Ld: period:%Ld\n", | ||
1004 | (void *)(offset + head), | ||
1005 | (void *)(long)(event->header.size), | ||
1006 | event->period.time, | ||
1007 | event->period.id, | ||
1008 | event->period.sample_period); | ||
1009 | |||
1010 | return 0; | ||
1011 | } | ||
1012 | |||
1013 | static int | ||
1014 | process_event(event_t *event, unsigned long offset, unsigned long head) | 993 | process_event(event_t *event, unsigned long offset, unsigned long head) |
1015 | { | 994 | { |
1016 | switch (event->header.type) { | 995 | switch (event->header.type) { |
@@ -1025,9 +1004,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head) | |||
1025 | 1004 | ||
1026 | case PERF_EVENT_FORK: | 1005 | case PERF_EVENT_FORK: |
1027 | return process_fork_event(event, offset, head); | 1006 | return process_fork_event(event, offset, head); |
1028 | |||
1029 | case PERF_EVENT_PERIOD: | ||
1030 | return process_period_event(event, offset, head); | ||
1031 | /* | 1007 | /* |
1032 | * We dont process them right now but they are fine: | 1008 | * We dont process them right now but they are fine: |
1033 | */ | 1009 | */ |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index a118bc77286d..b20a4b6e31b7 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -101,13 +101,6 @@ struct fork_event { | |||
101 | u32 pid, ppid; | 101 | u32 pid, ppid; |
102 | }; | 102 | }; |
103 | 103 | ||
104 | struct period_event { | ||
105 | struct perf_event_header header; | ||
106 | u64 time; | ||
107 | u64 id; | ||
108 | u64 sample_period; | ||
109 | }; | ||
110 | |||
111 | struct lost_event { | 104 | struct lost_event { |
112 | struct perf_event_header header; | 105 | struct perf_event_header header; |
113 | u64 id; | 106 | u64 id; |
@@ -127,7 +120,6 @@ typedef union event_union { | |||
127 | struct mmap_event mmap; | 120 | struct mmap_event mmap; |
128 | struct comm_event comm; | 121 | struct comm_event comm; |
129 | struct fork_event fork; | 122 | struct fork_event fork; |
130 | struct period_event period; | ||
131 | struct lost_event lost; | 123 | struct lost_event lost; |
132 | struct read_event read; | 124 | struct read_event read; |
133 | } event_t; | 125 | } event_t; |
@@ -1636,19 +1628,6 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head) | |||
1636 | } | 1628 | } |
1637 | 1629 | ||
1638 | static int | 1630 | static int |
1639 | process_period_event(event_t *event, unsigned long offset, unsigned long head) | ||
1640 | { | ||
1641 | dprintf("%p [%p]: PERF_EVENT_PERIOD: time:%Ld, id:%Ld: period:%Ld\n", | ||
1642 | (void *)(offset + head), | ||
1643 | (void *)(long)(event->header.size), | ||
1644 | event->period.time, | ||
1645 | event->period.id, | ||
1646 | event->period.sample_period); | ||
1647 | |||
1648 | return 0; | ||
1649 | } | ||
1650 | |||
1651 | static int | ||
1652 | process_lost_event(event_t *event, unsigned long offset, unsigned long head) | 1631 | process_lost_event(event_t *event, unsigned long offset, unsigned long head) |
1653 | { | 1632 | { |
1654 | dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n", | 1633 | dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n", |
@@ -1729,9 +1708,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head) | |||
1729 | case PERF_EVENT_FORK: | 1708 | case PERF_EVENT_FORK: |
1730 | return process_fork_event(event, offset, head); | 1709 | return process_fork_event(event, offset, head); |
1731 | 1710 | ||
1732 | case PERF_EVENT_PERIOD: | ||
1733 | return process_period_event(event, offset, head); | ||
1734 | |||
1735 | case PERF_EVENT_LOST: | 1711 | case PERF_EVENT_LOST: |
1736 | return process_lost_event(event, offset, head); | 1712 | return process_lost_event(event, offset, head); |
1737 | 1713 | ||