diff options
author | Robert Richter <robert.richter@amd.com> | 2011-12-07 04:02:57 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-12-23 14:03:36 -0500 |
commit | b1e5a9bee3c342dd3281aef76d1be1044dd8addf (patch) | |
tree | 2e82e69f1f4d2ac04cb5d71f16bdbf254edd6b0c /tools/perf | |
parent | e20960c0271f91aead94746872fd976326a703b3 (diff) |
perf tools: Use for_each_set_bit() to iterate over feature flags
This patch introduces the for_each_set_bit() macro and modifies feature
implementation to use it.
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1323248577-11268-8-git-send-email-robert.richter@amd.com
Signed-off-by: Robert Richter <robert.richter@amd.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/util/header.c | 118 | ||||
-rw-r--r-- | tools/perf/util/header.h | 6 | ||||
-rw-r--r-- | tools/perf/util/include/linux/bitops.h | 118 |
3 files changed, 149 insertions, 93 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 71326836921b..e509a9dea00b 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <stdlib.h> | 8 | #include <stdlib.h> |
9 | #include <linux/list.h> | 9 | #include <linux/list.h> |
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/bitops.h> | ||
11 | #include <sys/utsname.h> | 12 | #include <sys/utsname.h> |
12 | 13 | ||
13 | #include "evlist.h" | 14 | #include "evlist.h" |
@@ -1353,7 +1354,7 @@ static int perf_file_section__fprintf_info(struct perf_file_section *section, | |||
1353 | "%d, continuing...\n", section->offset, feat); | 1354 | "%d, continuing...\n", section->offset, feat); |
1354 | return 0; | 1355 | return 0; |
1355 | } | 1356 | } |
1356 | if (feat < HEADER_TRACE_INFO || feat >= HEADER_LAST_FEATURE) { | 1357 | if (feat >= HEADER_LAST_FEATURE) { |
1357 | pr_warning("unknown feature %d\n", feat); | 1358 | pr_warning("unknown feature %d\n", feat); |
1358 | return 0; | 1359 | return 0; |
1359 | } | 1360 | } |
@@ -1390,6 +1391,8 @@ static int do_write_feat(int fd, struct perf_header *h, int type, | |||
1390 | int ret = 0; | 1391 | int ret = 0; |
1391 | 1392 | ||
1392 | if (perf_header__has_feat(h, type)) { | 1393 | if (perf_header__has_feat(h, type)) { |
1394 | if (!feat_ops[type].write) | ||
1395 | return -1; | ||
1393 | 1396 | ||
1394 | (*p)->offset = lseek(fd, 0, SEEK_CUR); | 1397 | (*p)->offset = lseek(fd, 0, SEEK_CUR); |
1395 | 1398 | ||
@@ -1416,6 +1419,7 @@ static int perf_header__adds_write(struct perf_header *header, | |||
1416 | struct perf_file_section *feat_sec, *p; | 1419 | struct perf_file_section *feat_sec, *p; |
1417 | int sec_size; | 1420 | int sec_size; |
1418 | u64 sec_start; | 1421 | u64 sec_start; |
1422 | int feat; | ||
1419 | int err; | 1423 | int err; |
1420 | 1424 | ||
1421 | session = container_of(header, struct perf_session, header); | 1425 | session = container_of(header, struct perf_session, header); |
@@ -1433,61 +1437,10 @@ static int perf_header__adds_write(struct perf_header *header, | |||
1433 | sec_start = header->data_offset + header->data_size; | 1437 | sec_start = header->data_offset + header->data_size; |
1434 | lseek(fd, sec_start + sec_size, SEEK_SET); | 1438 | lseek(fd, sec_start + sec_size, SEEK_SET); |
1435 | 1439 | ||
1436 | err = do_write_feat(fd, header, HEADER_TRACE_INFO, &p, evlist); | 1440 | for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) { |
1437 | if (err) | 1441 | if (do_write_feat(fd, header, feat, &p, evlist)) |
1438 | perf_header__clear_feat(header, HEADER_TRACE_INFO); | 1442 | perf_header__clear_feat(header, feat); |
1439 | 1443 | } | |
1440 | err = do_write_feat(fd, header, HEADER_BUILD_ID, &p, evlist); | ||
1441 | if (err) | ||
1442 | perf_header__clear_feat(header, HEADER_BUILD_ID); | ||
1443 | |||
1444 | err = do_write_feat(fd, header, HEADER_HOSTNAME, &p, evlist); | ||
1445 | if (err) | ||
1446 | perf_header__clear_feat(header, HEADER_HOSTNAME); | ||
1447 | |||
1448 | err = do_write_feat(fd, header, HEADER_OSRELEASE, &p, evlist); | ||
1449 | if (err) | ||
1450 | perf_header__clear_feat(header, HEADER_OSRELEASE); | ||
1451 | |||
1452 | err = do_write_feat(fd, header, HEADER_VERSION, &p, evlist); | ||
1453 | if (err) | ||
1454 | perf_header__clear_feat(header, HEADER_VERSION); | ||
1455 | |||
1456 | err = do_write_feat(fd, header, HEADER_ARCH, &p, evlist); | ||
1457 | if (err) | ||
1458 | perf_header__clear_feat(header, HEADER_ARCH); | ||
1459 | |||
1460 | err = do_write_feat(fd, header, HEADER_NRCPUS, &p, evlist); | ||
1461 | if (err) | ||
1462 | perf_header__clear_feat(header, HEADER_NRCPUS); | ||
1463 | |||
1464 | err = do_write_feat(fd, header, HEADER_CPUDESC, &p, evlist); | ||
1465 | if (err) | ||
1466 | perf_header__clear_feat(header, HEADER_CPUDESC); | ||
1467 | |||
1468 | err = do_write_feat(fd, header, HEADER_CPUID, &p, evlist); | ||
1469 | if (err) | ||
1470 | perf_header__clear_feat(header, HEADER_CPUID); | ||
1471 | |||
1472 | err = do_write_feat(fd, header, HEADER_TOTAL_MEM, &p, evlist); | ||
1473 | if (err) | ||
1474 | perf_header__clear_feat(header, HEADER_TOTAL_MEM); | ||
1475 | |||
1476 | err = do_write_feat(fd, header, HEADER_CMDLINE, &p, evlist); | ||
1477 | if (err) | ||
1478 | perf_header__clear_feat(header, HEADER_CMDLINE); | ||
1479 | |||
1480 | err = do_write_feat(fd, header, HEADER_EVENT_DESC, &p, evlist); | ||
1481 | if (err) | ||
1482 | perf_header__clear_feat(header, HEADER_EVENT_DESC); | ||
1483 | |||
1484 | err = do_write_feat(fd, header, HEADER_CPU_TOPOLOGY, &p, evlist); | ||
1485 | if (err) | ||
1486 | perf_header__clear_feat(header, HEADER_CPU_TOPOLOGY); | ||
1487 | |||
1488 | err = do_write_feat(fd, header, HEADER_NUMA_TOPOLOGY, &p, evlist); | ||
1489 | if (err) | ||
1490 | perf_header__clear_feat(header, HEADER_NUMA_TOPOLOGY); | ||
1491 | 1444 | ||
1492 | lseek(fd, sec_start, SEEK_SET); | 1445 | lseek(fd, sec_start, SEEK_SET); |
1493 | /* | 1446 | /* |
@@ -1634,20 +1587,20 @@ static int perf_header__getbuffer64(struct perf_header *header, | |||
1634 | int perf_header__process_sections(struct perf_header *header, int fd, | 1587 | int perf_header__process_sections(struct perf_header *header, int fd, |
1635 | void *data, | 1588 | void *data, |
1636 | int (*process)(struct perf_file_section *section, | 1589 | int (*process)(struct perf_file_section *section, |
1637 | struct perf_header *ph, | 1590 | struct perf_header *ph, |
1638 | int feat, int fd, void *data)) | 1591 | int feat, int fd, void *data)) |
1639 | { | 1592 | { |
1640 | struct perf_file_section *feat_sec; | 1593 | struct perf_file_section *feat_sec, *sec; |
1641 | int nr_sections; | 1594 | int nr_sections; |
1642 | int sec_size; | 1595 | int sec_size; |
1643 | int idx = 0; | 1596 | int feat; |
1644 | int err = -1, feat = 1; | 1597 | int err; |
1645 | 1598 | ||
1646 | nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS); | 1599 | nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS); |
1647 | if (!nr_sections) | 1600 | if (!nr_sections) |
1648 | return 0; | 1601 | return 0; |
1649 | 1602 | ||
1650 | feat_sec = calloc(sizeof(*feat_sec), nr_sections); | 1603 | feat_sec = sec = calloc(sizeof(*feat_sec), nr_sections); |
1651 | if (!feat_sec) | 1604 | if (!feat_sec) |
1652 | return -1; | 1605 | return -1; |
1653 | 1606 | ||
@@ -1655,20 +1608,16 @@ int perf_header__process_sections(struct perf_header *header, int fd, | |||
1655 | 1608 | ||
1656 | lseek(fd, header->data_offset + header->data_size, SEEK_SET); | 1609 | lseek(fd, header->data_offset + header->data_size, SEEK_SET); |
1657 | 1610 | ||
1658 | if (perf_header__getbuffer64(header, fd, feat_sec, sec_size)) | 1611 | err = perf_header__getbuffer64(header, fd, feat_sec, sec_size); |
1612 | if (err < 0) | ||
1659 | goto out_free; | 1613 | goto out_free; |
1660 | 1614 | ||
1661 | err = 0; | 1615 | for_each_set_bit(feat, header->adds_features, HEADER_LAST_FEATURE) { |
1662 | while (idx < nr_sections && feat < HEADER_LAST_FEATURE) { | 1616 | err = process(sec++, header, feat, fd, data); |
1663 | if (perf_header__has_feat(header, feat)) { | 1617 | if (err < 0) |
1664 | struct perf_file_section *sec = &feat_sec[idx++]; | 1618 | goto out_free; |
1665 | |||
1666 | err = process(sec, header, feat, fd, data); | ||
1667 | if (err < 0) | ||
1668 | break; | ||
1669 | } | ||
1670 | ++feat; | ||
1671 | } | 1619 | } |
1620 | err = 0; | ||
1672 | out_free: | 1621 | out_free: |
1673 | free(feat_sec); | 1622 | free(feat_sec); |
1674 | return err; | 1623 | return err; |
@@ -1903,32 +1852,21 @@ static int perf_file_section__process(struct perf_file_section *section, | |||
1903 | return 0; | 1852 | return 0; |
1904 | } | 1853 | } |
1905 | 1854 | ||
1855 | if (feat >= HEADER_LAST_FEATURE) { | ||
1856 | pr_debug("unknown feature %d, continuing...\n", feat); | ||
1857 | return 0; | ||
1858 | } | ||
1859 | |||
1906 | switch (feat) { | 1860 | switch (feat) { |
1907 | case HEADER_TRACE_INFO: | 1861 | case HEADER_TRACE_INFO: |
1908 | trace_report(fd, false); | 1862 | trace_report(fd, false); |
1909 | break; | 1863 | break; |
1910 | |||
1911 | case HEADER_BUILD_ID: | 1864 | case HEADER_BUILD_ID: |
1912 | if (perf_header__read_build_ids(ph, fd, section->offset, section->size)) | 1865 | if (perf_header__read_build_ids(ph, fd, section->offset, section->size)) |
1913 | pr_debug("Failed to read buildids, continuing...\n"); | 1866 | pr_debug("Failed to read buildids, continuing...\n"); |
1914 | break; | 1867 | break; |
1915 | |||
1916 | case HEADER_HOSTNAME: | ||
1917 | case HEADER_OSRELEASE: | ||
1918 | case HEADER_VERSION: | ||
1919 | case HEADER_ARCH: | ||
1920 | case HEADER_NRCPUS: | ||
1921 | case HEADER_CPUDESC: | ||
1922 | case HEADER_CPUID: | ||
1923 | case HEADER_TOTAL_MEM: | ||
1924 | case HEADER_CMDLINE: | ||
1925 | case HEADER_EVENT_DESC: | ||
1926 | case HEADER_CPU_TOPOLOGY: | ||
1927 | case HEADER_NUMA_TOPOLOGY: | ||
1928 | break; | ||
1929 | |||
1930 | default: | 1868 | default: |
1931 | pr_debug("unknown feature %d, continuing...\n", feat); | 1869 | break; |
1932 | } | 1870 | } |
1933 | 1871 | ||
1934 | return 0; | 1872 | return 0; |
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 09365b32098e..ac4ec956024e 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h | |||
@@ -10,7 +10,8 @@ | |||
10 | #include <linux/bitmap.h> | 10 | #include <linux/bitmap.h> |
11 | 11 | ||
12 | enum { | 12 | enum { |
13 | HEADER_TRACE_INFO = 1, | 13 | HEADER_RESERVED = 0, /* always cleared */ |
14 | HEADER_TRACE_INFO = 1, | ||
14 | HEADER_BUILD_ID, | 15 | HEADER_BUILD_ID, |
15 | 16 | ||
16 | HEADER_HOSTNAME, | 17 | HEADER_HOSTNAME, |
@@ -27,10 +28,9 @@ enum { | |||
27 | HEADER_NUMA_TOPOLOGY, | 28 | HEADER_NUMA_TOPOLOGY, |
28 | 29 | ||
29 | HEADER_LAST_FEATURE, | 30 | HEADER_LAST_FEATURE, |
31 | HEADER_FEAT_BITS = 256, | ||
30 | }; | 32 | }; |
31 | 33 | ||
32 | #define HEADER_FEAT_BITS 256 | ||
33 | |||
34 | struct perf_file_section { | 34 | struct perf_file_section { |
35 | u64 offset; | 35 | u64 offset; |
36 | u64 size; | 36 | u64 size; |
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h index 305c8484f200..62cdee78db7b 100644 --- a/tools/perf/util/include/linux/bitops.h +++ b/tools/perf/util/include/linux/bitops.h | |||
@@ -9,6 +9,17 @@ | |||
9 | #define BITS_PER_BYTE 8 | 9 | #define BITS_PER_BYTE 8 |
10 | #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) | 10 | #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) |
11 | 11 | ||
12 | #define for_each_set_bit(bit, addr, size) \ | ||
13 | for ((bit) = find_first_bit((addr), (size)); \ | ||
14 | (bit) < (size); \ | ||
15 | (bit) = find_next_bit((addr), (size), (bit) + 1)) | ||
16 | |||
17 | /* same as for_each_set_bit() but use bit as value to start with */ | ||
18 | #define for_each_set_bit_cont(bit, addr, size) \ | ||
19 | for ((bit) = find_next_bit((addr), (size), (bit)); \ | ||
20 | (bit) < (size); \ | ||
21 | (bit) = find_next_bit((addr), (size), (bit) + 1)) | ||
22 | |||
12 | static inline void set_bit(int nr, unsigned long *addr) | 23 | static inline void set_bit(int nr, unsigned long *addr) |
13 | { | 24 | { |
14 | addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG); | 25 | addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG); |
@@ -30,4 +41,111 @@ static inline unsigned long hweight_long(unsigned long w) | |||
30 | return sizeof(w) == 4 ? hweight32(w) : hweight64(w); | 41 | return sizeof(w) == 4 ? hweight32(w) : hweight64(w); |
31 | } | 42 | } |
32 | 43 | ||
44 | #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) | ||
45 | |||
46 | /** | ||
47 | * __ffs - find first bit in word. | ||
48 | * @word: The word to search | ||
49 | * | ||
50 | * Undefined if no bit exists, so code should check against 0 first. | ||
51 | */ | ||
52 | static __always_inline unsigned long __ffs(unsigned long word) | ||
53 | { | ||
54 | int num = 0; | ||
55 | |||
56 | #if BITS_PER_LONG == 64 | ||
57 | if ((word & 0xffffffff) == 0) { | ||
58 | num += 32; | ||
59 | word >>= 32; | ||
60 | } | ||
61 | #endif | ||
62 | if ((word & 0xffff) == 0) { | ||
63 | num += 16; | ||
64 | word >>= 16; | ||
65 | } | ||
66 | if ((word & 0xff) == 0) { | ||
67 | num += 8; | ||
68 | word >>= 8; | ||
69 | } | ||
70 | if ((word & 0xf) == 0) { | ||
71 | num += 4; | ||
72 | word >>= 4; | ||
73 | } | ||
74 | if ((word & 0x3) == 0) { | ||
75 | num += 2; | ||
76 | word >>= 2; | ||
77 | } | ||
78 | if ((word & 0x1) == 0) | ||
79 | num += 1; | ||
80 | return num; | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * Find the first set bit in a memory region. | ||
85 | */ | ||
86 | static inline unsigned long | ||
87 | find_first_bit(const unsigned long *addr, unsigned long size) | ||
88 | { | ||
89 | const unsigned long *p = addr; | ||
90 | unsigned long result = 0; | ||
91 | unsigned long tmp; | ||
92 | |||
93 | while (size & ~(BITS_PER_LONG-1)) { | ||
94 | if ((tmp = *(p++))) | ||
95 | goto found; | ||
96 | result += BITS_PER_LONG; | ||
97 | size -= BITS_PER_LONG; | ||
98 | } | ||
99 | if (!size) | ||
100 | return result; | ||
101 | |||
102 | tmp = (*p) & (~0UL >> (BITS_PER_LONG - size)); | ||
103 | if (tmp == 0UL) /* Are any bits set? */ | ||
104 | return result + size; /* Nope. */ | ||
105 | found: | ||
106 | return result + __ffs(tmp); | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * Find the next set bit in a memory region. | ||
111 | */ | ||
112 | static inline unsigned long | ||
113 | find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset) | ||
114 | { | ||
115 | const unsigned long *p = addr + BITOP_WORD(offset); | ||
116 | unsigned long result = offset & ~(BITS_PER_LONG-1); | ||
117 | unsigned long tmp; | ||
118 | |||
119 | if (offset >= size) | ||
120 | return size; | ||
121 | size -= result; | ||
122 | offset %= BITS_PER_LONG; | ||
123 | if (offset) { | ||
124 | tmp = *(p++); | ||
125 | tmp &= (~0UL << offset); | ||
126 | if (size < BITS_PER_LONG) | ||
127 | goto found_first; | ||
128 | if (tmp) | ||
129 | goto found_middle; | ||
130 | size -= BITS_PER_LONG; | ||
131 | result += BITS_PER_LONG; | ||
132 | } | ||
133 | while (size & ~(BITS_PER_LONG-1)) { | ||
134 | if ((tmp = *(p++))) | ||
135 | goto found_middle; | ||
136 | result += BITS_PER_LONG; | ||
137 | size -= BITS_PER_LONG; | ||
138 | } | ||
139 | if (!size) | ||
140 | return result; | ||
141 | tmp = *p; | ||
142 | |||
143 | found_first: | ||
144 | tmp &= (~0UL >> (BITS_PER_LONG - size)); | ||
145 | if (tmp == 0UL) /* Are any bits set? */ | ||
146 | return result + size; /* Nope. */ | ||
147 | found_middle: | ||
148 | return result + __ffs(tmp); | ||
149 | } | ||
150 | |||
33 | #endif | 151 | #endif |