aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/perf_event.c
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2009-11-20 16:19:55 -0500
committerIngo Molnar <mingo@elte.hu>2009-11-21 08:11:40 -0500
commit59ed446f792cc07d37b1536b9c4664d14e25e425 (patch)
tree707c009e252b082ffac5c5209f4bdc013b1b5c62 /kernel/perf_event.c
parent2b8988c9f7defe319cffe0cd362a7cd356c86f62 (diff)
perf: Fix event scaling for inherited counters
Properly account the full hierarchy of counters for both the count (we already did so) and the scale times (new). Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <20091120212509.153379276@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/perf_event.c')
-rw-r--r--kernel/perf_event.c48
1 files changed, 26 insertions, 22 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index fdfae888a67c..80f40da9a01e 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -1774,14 +1774,25 @@ static int perf_event_read_size(struct perf_event *event)
1774 return size; 1774 return size;
1775} 1775}
1776 1776
1777u64 perf_event_read_value(struct perf_event *event) 1777u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running)
1778{ 1778{
1779 struct perf_event *child; 1779 struct perf_event *child;
1780 u64 total = 0; 1780 u64 total = 0;
1781 1781
1782 *enabled = 0;
1783 *running = 0;
1784
1782 total += perf_event_read(event); 1785 total += perf_event_read(event);
1783 list_for_each_entry(child, &event->child_list, child_list) 1786 *enabled += event->total_time_enabled +
1787 atomic64_read(&event->child_total_time_enabled);
1788 *running += event->total_time_running +
1789 atomic64_read(&event->child_total_time_running);
1790
1791 list_for_each_entry(child, &event->child_list, child_list) {
1784 total += perf_event_read(child); 1792 total += perf_event_read(child);
1793 *enabled += child->total_time_enabled;
1794 *running += child->total_time_running;
1795 }
1785 1796
1786 return total; 1797 return total;
1787} 1798}
@@ -1793,19 +1804,15 @@ static int perf_event_read_group(struct perf_event *event,
1793 struct perf_event *leader = event->group_leader, *sub; 1804 struct perf_event *leader = event->group_leader, *sub;
1794 int n = 0, size = 0, ret = 0; 1805 int n = 0, size = 0, ret = 0;
1795 u64 values[5]; 1806 u64 values[5];
1796 u64 count; 1807 u64 count, enabled, running;
1797 1808
1798 count = perf_event_read_value(leader); 1809 count = perf_event_read_value(leader, &enabled, &running);
1799 1810
1800 values[n++] = 1 + leader->nr_siblings; 1811 values[n++] = 1 + leader->nr_siblings;
1801 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) { 1812 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
1802 values[n++] = leader->total_time_enabled + 1813 values[n++] = enabled;
1803 atomic64_read(&leader->child_total_time_enabled); 1814 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
1804 } 1815 values[n++] = running;
1805 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
1806 values[n++] = leader->total_time_running +
1807 atomic64_read(&leader->child_total_time_running);
1808 }
1809 values[n++] = count; 1816 values[n++] = count;
1810 if (read_format & PERF_FORMAT_ID) 1817 if (read_format & PERF_FORMAT_ID)
1811 values[n++] = primary_event_id(leader); 1818 values[n++] = primary_event_id(leader);
@@ -1820,7 +1827,7 @@ static int perf_event_read_group(struct perf_event *event,
1820 list_for_each_entry(sub, &leader->sibling_list, group_entry) { 1827 list_for_each_entry(sub, &leader->sibling_list, group_entry) {
1821 n = 0; 1828 n = 0;
1822 1829
1823 values[n++] = perf_event_read_value(sub); 1830 values[n++] = perf_event_read_value(sub, &enabled, &running);
1824 if (read_format & PERF_FORMAT_ID) 1831 if (read_format & PERF_FORMAT_ID)
1825 values[n++] = primary_event_id(sub); 1832 values[n++] = primary_event_id(sub);
1826 1833
@@ -1838,18 +1845,15 @@ static int perf_event_read_group(struct perf_event *event,
1838static int perf_event_read_one(struct perf_event *event, 1845static int perf_event_read_one(struct perf_event *event,
1839 u64 read_format, char __user *buf) 1846 u64 read_format, char __user *buf)
1840{ 1847{
1848 u64 enabled, running;
1841 u64 values[4]; 1849 u64 values[4];
1842 int n = 0; 1850 int n = 0;
1843 1851
1844 values[n++] = perf_event_read_value(event); 1852 values[n++] = perf_event_read_value(event, &enabled, &running);
1845 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) { 1853 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
1846 values[n++] = event->total_time_enabled + 1854 values[n++] = enabled;
1847 atomic64_read(&event->child_total_time_enabled); 1855 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
1848 } 1856 values[n++] = running;
1849 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
1850 values[n++] = event->total_time_running +
1851 atomic64_read(&event->child_total_time_running);
1852 }
1853 if (read_format & PERF_FORMAT_ID) 1857 if (read_format & PERF_FORMAT_ID)
1854 values[n++] = primary_event_id(event); 1858 values[n++] = primary_event_id(event);
1855 1859