History

Merge branch 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: perf_counter: Report the cloning task as parent on perf_counter_fork() perf_counter: Fix an ipi-deadlock perf: Rework/fix the whole read vs group stuff perf_counter: Fix swcounter context invariance perf report: Don't show unresolved DSOs and symbols when -S/-d is used perf tools: Add a general option to enable raw sample records perf tools: Add a per tracepoint counter attribute to get raw sample perf_counter: Provide hw_perf_counter_setup_online() APIs perf list: Fix large list output by using the pager perf_counter, x86: Fix/improve apic fallback perf record: Add missing -C option support for specifying profile cpu perf tools: Fix dso__new handle() to handle deleted DSOs perf tools: Fix fallback to cplus_demangle() when bfd_demangle() is not available perf report: Show the tid too in -D perf record: Fix .tid and .pid fill-in when synthesizing events perf_counter, x86: Fix generic cache events on P6-mobile CPUs perf_counter, x86: Fix lapic printk message

Linus Torvalds committed 17 years ago

Commit 3493e842 parents 919aa96 94d5d1b11 files · +429 −190Browse files

Showing the changes to kernel (1 of 11 files). Show all

Unified · Split

kernel/perf_counter.c+236−102
@@ -88,6 +88,7 @@ void __weak hw_perf_disable(void) { barrier(); } · 87 unmodified lines
8888 void __weak hw_perf_enable(void) { barrier(); }
8989
9090 void __weak hw_perf_counter_setup(int cpu) { barrier(); }
91+void __weak hw_perf_counter_setup_online(int cpu) { barrier(); }
9192
9293 int __weak
9394 hw_perf_group_sched_in(struct perf_counter *group_leader,
@@ -306,6 +307,10 @@ counter_sched_out(struct perf_counter *counter, · 212 unmodified lines
306307 return;
307308
308309 counter->state = PERF_COUNTER_STATE_INACTIVE;
310+ if (counter->pending_disable) {
311+ counter->pending_disable = 0;
312+ counter->state = PERF_COUNTER_STATE_OFF;
313+ }
309314 counter->tstamp_stopped = ctx->time;
310315 counter->pmu->disable(counter);
311316 counter->oncpu = -1;
@@ -1691,7 +1696,32 @@ static int perf_release(struct inode *inode, struct file *file) · 1379 unmodified lines
16911696 return 0;
16921697 }
16931698
1694−static u64 perf_counter_read_tree(struct perf_counter *counter)
1699+static int perf_counter_read_size(struct perf_counter *counter)
1700+{
1701+ int entry = sizeof(u64); /* value */
1702+ int size = 0;
1703+ int nr = 1;
1704+
1705+ if (counter->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
1706+ size += sizeof(u64);
1707+
1708+ if (counter->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
1709+ size += sizeof(u64);
1710+
1711+ if (counter->attr.read_format & PERF_FORMAT_ID)
1712+ entry += sizeof(u64);
1713+
1714+ if (counter->attr.read_format & PERF_FORMAT_GROUP) {
1715+ nr += counter->group_leader->nr_siblings;
1716+ size += sizeof(u64);
1717+ }
1718+
1719+ size += entry * nr;
1720+
1721+ return size;
1722+}
1723+
1724+static u64 perf_counter_read_value(struct perf_counter *counter)
16951725 {
16961726 struct perf_counter *child;
16971727 u64 total = 0;
@@ -1703,14 +1733,96 @@ static u64 perf_counter_read_tree(struct perf_counter *counter) · 5 unmodified lines
17031733 return total;
17041734 }
17051735
1736+static int perf_counter_read_entry(struct perf_counter *counter,
1737+ u64 read_format, char __user *buf)
1738+{
1739+ int n = 0, count = 0;
1740+ u64 values[2];
1741+
1742+ values[n++] = perf_counter_read_value(counter);
1743+ if (read_format & PERF_FORMAT_ID)
1744+ values[n++] = primary_counter_id(counter);
1745+
1746+ count = n * sizeof(u64);
1747+
1748+ if (copy_to_user(buf, values, count))
1749+ return -EFAULT;
1750+
1751+ return count;
1752+}
1753+
1754+static int perf_counter_read_group(struct perf_counter *counter,
1755+ u64 read_format, char __user *buf)
1756+{
1757+ struct perf_counter *leader = counter->group_leader, *sub;
1758+ int n = 0, size = 0, err = -EFAULT;
1759+ u64 values[3];
1760+
1761+ values[n++] = 1 + leader->nr_siblings;
1762+ if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
1763+ values[n++] = leader->total_time_enabled +
1764+ atomic64_read(&leader->child_total_time_enabled);
1765+ }
1766+ if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
1767+ values[n++] = leader->total_time_running +
1768+ atomic64_read(&leader->child_total_time_running);
1769+ }
1770+
1771+ size = n * sizeof(u64);
1772+
1773+ if (copy_to_user(buf, values, size))
1774+ return -EFAULT;
1775+
1776+ err = perf_counter_read_entry(leader, read_format, buf + size);
1777+ if (err < 0)
1778+ return err;
1779+
1780+ size += err;
1781+
1782+ list_for_each_entry(sub, &leader->sibling_list, list_entry) {
1783+ err = perf_counter_read_entry(counter, read_format,
1784+ buf + size);
1785+ if (err < 0)
1786+ return err;
1787+
1788+ size += err;
1789+ }
1790+
1791+ return size;
1792+}
1793+
1794+static int perf_counter_read_one(struct perf_counter *counter,
1795+ u64 read_format, char __user *buf)
1796+{
1797+ u64 values[4];
1798+ int n = 0;
1799+
1800+ values[n++] = perf_counter_read_value(counter);
1801+ if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
1802+ values[n++] = counter->total_time_enabled +
1803+ atomic64_read(&counter->child_total_time_enabled);
1804+ }
1805+ if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
1806+ values[n++] = counter->total_time_running +
1807+ atomic64_read(&counter->child_total_time_running);
1808+ }
1809+ if (read_format & PERF_FORMAT_ID)
1810+ values[n++] = primary_counter_id(counter);
1811+
1812+ if (copy_to_user(buf, values, n * sizeof(u64)))
1813+ return -EFAULT;
1814+
1815+ return n * sizeof(u64);
1816+}
1817+
17061818 /*
17071819 * Read the performance counter - simple non blocking version for now
17081820 */
17091821 static ssize_t
17101822 perf_read_hw(struct perf_counter *counter, char __user *buf, size_t count)
17111823 {
1712− u64 values[4];
1713− int n;
1824+ u64 read_format = counter->attr.read_format;
1825+ int ret;
17141826
17151827 /*
17161828 * Return end-of-file for a read on a counter that is in
@@ -1720,28 +1832,18 @@ perf_read_hw(struct perf_counter *counter, char __user *buf, size_t count) · 3 unmodified lines
17201832 if (counter->state == PERF_COUNTER_STATE_ERROR)
17211833 return 0;
17221834
1835+ if (count < perf_counter_read_size(counter))
1836+ return -ENOSPC;
1837+
17231838 WARN_ON_ONCE(counter->ctx->parent_ctx);
17241839 mutex_lock(&counter->child_mutex);
1725− values[0] = perf_counter_read_tree(counter);
1726− n = 1;
1727− if (counter->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
1728− values[n++] = counter->total_time_enabled +
1729− atomic64_read(&counter->child_total_time_enabled);
1730− if (counter->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
1731− values[n++] = counter->total_time_running +
1732− atomic64_read(&counter->child_total_time_running);
1733− if (counter->attr.read_format & PERF_FORMAT_ID)
1734− values[n++] = primary_counter_id(counter);
1840+ if (read_format & PERF_FORMAT_GROUP)
1841+ ret = perf_counter_read_group(counter, read_format, buf);
1842+ else
1843+ ret = perf_counter_read_one(counter, read_format, buf);
17351844 mutex_unlock(&counter->child_mutex);
17361845
1737− if (count < n * sizeof(u64))
1738− return -EINVAL;
1739− count = n * sizeof(u64);
1740−
1741− if (copy_to_user(buf, values, count))
1742− return -EFAULT;
1743−
1744− return count;
1846+ return ret;
17451847 }
17461848
17471849 static ssize_t
@@ -2245,7 +2347,7 @@ static void perf_pending_counter(struct perf_pending_entry *entry) · 497 unmodified lines
22452347
22462348 if (counter->pending_disable) {
22472349 counter->pending_disable = 0;
2248− perf_counter_disable(counter);
2350+ __perf_counter_disable(counter);
22492351 }
22502352
22512353 if (counter->pending_wakeup) {
@@ -2630,7 +2732,80 @@ static u32 perf_counter_tid(struct perf_counter *counter, struct task_struct *p) · 378 unmodified lines
26302732 return task_pid_nr_ns(p, counter->ns);
26312733 }
26322734
2633−static void perf_counter_output(struct perf_counter *counter, int nmi,
2735+static void perf_output_read_one(struct perf_output_handle *handle,
2736+ struct perf_counter *counter)
2737+{
2738+ u64 read_format = counter->attr.read_format;
2739+ u64 values[4];
2740+ int n = 0;
2741+
2742+ values[n++] = atomic64_read(&counter->count);
2743+ if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
2744+ values[n++] = counter->total_time_enabled +
2745+ atomic64_read(&counter->child_total_time_enabled);
2746+ }
2747+ if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
2748+ values[n++] = counter->total_time_running +
2749+ atomic64_read(&counter->child_total_time_running);
2750+ }
2751+ if (read_format & PERF_FORMAT_ID)
2752+ values[n++] = primary_counter_id(counter);
2753+
2754+ perf_output_copy(handle, values, n * sizeof(u64));
2755+}
2756+
2757+/*
2758+ * XXX PERF_FORMAT_GROUP vs inherited counters seems difficult.
2759+ */
2760+static void perf_output_read_group(struct perf_output_handle *handle,
2761+ struct perf_counter *counter)
2762+{
2763+ struct perf_counter *leader = counter->group_leader, *sub;
2764+ u64 read_format = counter->attr.read_format;
2765+ u64 values[5];
2766+ int n = 0;
2767+
2768+ values[n++] = 1 + leader->nr_siblings;
2769+
2770+ if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
2771+ values[n++] = leader->total_time_enabled;
2772+
2773+ if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
2774+ values[n++] = leader->total_time_running;
2775+
2776+ if (leader != counter)
2777+ leader->pmu->read(leader);
2778+
2779+ values[n++] = atomic64_read(&leader->count);
2780+ if (read_format & PERF_FORMAT_ID)
2781+ values[n++] = primary_counter_id(leader);
2782+
2783+ perf_output_copy(handle, values, n * sizeof(u64));
2784+
2785+ list_for_each_entry(sub, &leader->sibling_list, list_entry) {
2786+ n = 0;
2787+
2788+ if (sub != counter)
2789+ sub->pmu->read(sub);
2790+
2791+ values[n++] = atomic64_read(&sub->count);
2792+ if (read_format & PERF_FORMAT_ID)
2793+ values[n++] = primary_counter_id(sub);
2794+
2795+ perf_output_copy(handle, values, n * sizeof(u64));
2796+ }
2797+}
2798+
2799+static void perf_output_read(struct perf_output_handle *handle,
2800+ struct perf_counter *counter)
2801+{
2802+ if (counter->attr.read_format & PERF_FORMAT_GROUP)
2803+ perf_output_read_group(handle, counter);
2804+ else
2805+ perf_output_read_one(handle, counter);
2806+}
2807+
2808+void perf_counter_output(struct perf_counter *counter, int nmi,
26342809 struct perf_sample_data *data)
26352810 {
26362811 int ret;
@@ -2641,10 +2816,6 @@ static void perf_counter_output(struct perf_counter *counter, int nmi, · 4 unmodified lines
26412816 struct {
26422817 u32 pid, tid;
26432818 } tid_entry;
2644− struct {
2645− u64 id;
2646− u64 counter;
2647− } group_entry;
26482819 struct perf_callchain_entry *callchain = NULL;
26492820 int callchain_size = 0;
26502821 u64 time;
@@ -2699,10 +2870,8 @@ static void perf_counter_output(struct perf_counter *counter, int nmi, · 48 unmodified lines
26992870 if (sample_type & PERF_SAMPLE_PERIOD)
27002871 header.size += sizeof(u64);
27012872
2702− if (sample_type & PERF_SAMPLE_GROUP) {
2703− header.size += sizeof(u64) +
2704− counter->nr_siblings * sizeof(group_entry);
2705− }
2873+ if (sample_type & PERF_SAMPLE_READ)
2874+ header.size += perf_counter_read_size(counter);
27062875
27072876 if (sample_type & PERF_SAMPLE_CALLCHAIN) {
27082877 callchain = perf_callchain(data->regs);
@@ -2759,26 +2928,8 @@ static void perf_counter_output(struct perf_counter *counter, int nmi, · 50 unmodified lines
27592928 if (sample_type & PERF_SAMPLE_PERIOD)
27602929 perf_output_put(&handle, data->period);
27612930
2762− /*
2763− * XXX PERF_SAMPLE_GROUP vs inherited counters seems difficult.
2764− */
2765− if (sample_type & PERF_SAMPLE_GROUP) {
2766− struct perf_counter *leader, *sub;
2767− u64 nr = counter->nr_siblings;
2768−
2769− perf_output_put(&handle, nr);
2770−
2771− leader = counter->group_leader;
2772− list_for_each_entry(sub, &leader->sibling_list, list_entry) {
2773− if (sub != counter)
2774− sub->pmu->read(sub);
2775−
2776− group_entry.id = primary_counter_id(sub);
2777− group_entry.counter = atomic64_read(&sub->count);
2778−
2779− perf_output_put(&handle, group_entry);
2780− }
2781− }
2931+ if (sample_type & PERF_SAMPLE_READ)
2932+ perf_output_read(&handle, counter);
27822933
27832934 if (sample_type & PERF_SAMPLE_CALLCHAIN) {
27842935 if (callchain)
@@ -2817,8 +2968,6 @@ struct perf_read_event { · 32 unmodified lines
28172968
28182969 u32 pid;
28192970 u32 tid;
2820− u64 value;
2821− u64 format[3];
28222971 };
28232972
28242973 static void
@@ -2830,34 +2979,20 @@ perf_counter_read_event(struct perf_counter *counter, · 5 unmodified lines
28302979 .header = {
28312980 .type = PERF_EVENT_READ,
28322981 .misc = 0,
2833− .size = sizeof(event) - sizeof(event.format),
2982+ .size = sizeof(event) + perf_counter_read_size(counter),
28342983 },
28352984 .pid = perf_counter_pid(counter, task),
28362985 .tid = perf_counter_tid(counter, task),
2837− .value = atomic64_read(&counter->count),
28382986 };
2839− int ret, i = 0;
2840−
2841− if (counter->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
2842− event.header.size += sizeof(u64);
2843− event.format[i++] = counter->total_time_enabled;
2844− }
2845−
2846− if (counter->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
2847− event.header.size += sizeof(u64);
2848− event.format[i++] = counter->total_time_running;
2849− }
2850−
2851− if (counter->attr.read_format & PERF_FORMAT_ID) {
2852− event.header.size += sizeof(u64);
2853− event.format[i++] = primary_counter_id(counter);
2854− }
2987+ int ret;
28552988
28562989 ret = perf_output_begin(&handle, counter, event.header.size, 0, 0);
28572990 if (ret)
28582991 return;
28592992
2860− perf_output_copy(&handle, &event, event.header.size);
2993+ perf_output_put(&handle, event);
2994+ perf_output_read(&handle, counter);
2995+
28612996 perf_output_end(&handle);
28622997 }
28632998
@@ -2893,10 +3028,10 @@ static void perf_counter_task_output(struct perf_counter *counter, · 29 unmodified lines
28933028 return;
28943029
28953030 task_event->event.pid = perf_counter_pid(counter, task);
2896− task_event->event.ppid = perf_counter_pid(counter, task->real_parent);
3031+ task_event->event.ppid = perf_counter_pid(counter, current);
28973032
28983033 task_event->event.tid = perf_counter_tid(counter, task);
2899− task_event->event.ptid = perf_counter_tid(counter, task->real_parent);
3034+ task_event->event.ptid = perf_counter_tid(counter, current);
29003035
29013036 perf_output_put(&handle, task_event->event);
29023037 perf_output_end(&handle);
@@ -3443,40 +3578,32 @@ static void perf_swcounter_add(struct perf_counter *counter, u64 nr, · 540 unmodified lines
34433578
34443579 static int perf_swcounter_is_counting(struct perf_counter *counter)
34453580 {
3446− struct perf_counter_context *ctx;
3447− unsigned long flags;
3448− int count;
3449−
3581+ /*
3582+ * The counter is active, we're good!
3583+ */
34503584 if (counter->state == PERF_COUNTER_STATE_ACTIVE)
34513585 return 1;
34523586
3587+ /*
3588+ * The counter is off/error, not counting.
3589+ */
34533590 if (counter->state != PERF_COUNTER_STATE_INACTIVE)
34543591 return 0;
34553592
34563593 /*
3457− * If the counter is inactive, it could be just because
3458− * its task is scheduled out, or because it's in a group
3459− * which could not go on the PMU. We want to count in
3460− * the first case but not the second. If the context is
3461− * currently active then an inactive software counter must
3462− * be the second case. If it's not currently active then
3463− * we need to know whether the counter was active when the
3464− * context was last active, which we can determine by
3465− * comparing counter->tstamp_stopped with ctx->time.
3466− *
3467− * We are within an RCU read-side critical section,
3468− * which protects the existence of *ctx.
3594+ * The counter is inactive, if the context is active
3595+ * we're part of a group that didn't make it on the 'pmu',
3596+ * not counting.
34693597 */
3470− ctx = counter->ctx;
3471− spin_lock_irqsave(&ctx->lock, flags);
3472− count = 1;
3473− /* Re-check state now we have the lock */
3474− if (counter->state < PERF_COUNTER_STATE_INACTIVE ||
3475− counter->ctx->is_active ||
3476− counter->tstamp_stopped < ctx->time)
3477− count = 0;
3478− spin_unlock_irqrestore(&ctx->lock, flags);
3479− return count;
3598+ if (counter->ctx->is_active)
3599+ return 0;
3600+
3601+ /*
3602+ * We're inactive and the context is too, this means the
3603+ * task is scheduled out, we're counting events that happen
3604+ * to us, like migration events.
3605+ */
3606+ return 1;
34803607 }
34813608
34823609 static int perf_swcounter_match(struct perf_counter *counter,
@@ -3928,9 +4055,9 @@ perf_counter_alloc(struct perf_counter_attr *attr, · 445 unmodified lines
39284055 atomic64_set(&hwc->period_left, hwc->sample_period);
39294056
39304057 /*
3931− * we currently do not support PERF_SAMPLE_GROUP on inherited counters
4058+ * we currently do not support PERF_FORMAT_GROUP on inherited counters
39324059 */
3933− if (attr->inherit && (attr->sample_type & PERF_SAMPLE_GROUP))
4060+ if (attr->inherit && (attr->read_format & PERF_FORMAT_GROUP))
39344061 goto done;
39354062
39364063 switch (attr->type) {
@@ -4592,6 +4719,11 @@ perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) · 655 unmodified lines
45924719 perf_counter_init_cpu(cpu);
45934720 break;
45944721
4722+ case CPU_ONLINE:
4723+ case CPU_ONLINE_FROZEN:
4724+ hw_perf_counter_setup_online(cpu);
4725+ break;
4726+
45954727 case CPU_DOWN_PREPARE:
45964728 case CPU_DOWN_PREPARE_FROZEN:
45974729 perf_counter_exit_cpu(cpu);
@@ -4616,6 +4748,8 @@ void __init perf_counter_init(void) · 18 unmodified lines
46164748 {
46174749 perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_UP_PREPARE,
46184750 (void *)(long)smp_processor_id());
4751+ perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_ONLINE,
4752+ (void *)(long)smp_processor_id());
46194753 register_cpu_notifier(&perf_cpu_nb);
46204754 }
46214755