Commit b1e5a9bee3c342dd3281aef76d1be1044dd8addf

Authored by Robert Richter
Committed by Arnaldo Carvalho de Melo
1 parent e20960c027

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>

Showing 3 changed files with 149 additions and 93 deletions Side-by-side Diff

tools/perf/util/header.c
... ... @@ -8,6 +8,7 @@
8 8 #include <stdlib.h>
9 9 #include <linux/list.h>
10 10 #include <linux/kernel.h>
  11 +#include <linux/bitops.h>
11 12 #include <sys/utsname.h>
12 13  
13 14 #include "evlist.h"
... ... @@ -1353,7 +1354,7 @@
1353 1354 "%d, continuing...\n", section->offset, feat);
1354 1355 return 0;
1355 1356 }
1356   - if (feat < HEADER_TRACE_INFO || feat >= HEADER_LAST_FEATURE) {
  1357 + if (feat >= HEADER_LAST_FEATURE) {
1357 1358 pr_warning("unknown feature %d\n", feat);
1358 1359 return 0;
1359 1360 }
... ... @@ -1390,6 +1391,8 @@
1390 1391 int ret = 0;
1391 1392  
1392 1393 if (perf_header__has_feat(h, type)) {
  1394 + if (!feat_ops[type].write)
  1395 + return -1;
1393 1396  
1394 1397 (*p)->offset = lseek(fd, 0, SEEK_CUR);
1395 1398  
... ... @@ -1416,6 +1419,7 @@
1416 1419 struct perf_file_section *feat_sec, *p;
1417 1420 int sec_size;
1418 1421 u64 sec_start;
  1422 + int feat;
1419 1423 int err;
1420 1424  
1421 1425 session = container_of(header, struct perf_session, header);
1422 1426  
... ... @@ -1433,62 +1437,11 @@
1433 1437 sec_start = header->data_offset + header->data_size;
1434 1438 lseek(fd, sec_start + sec_size, SEEK_SET);
1435 1439  
1436   - err = do_write_feat(fd, header, HEADER_TRACE_INFO, &p, evlist);
1437   - if (err)
1438   - perf_header__clear_feat(header, HEADER_TRACE_INFO);
  1440 + for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
  1441 + if (do_write_feat(fd, header, feat, &p, evlist))
  1442 + perf_header__clear_feat(header, feat);
  1443 + }
1439 1444  
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   -
1492 1445 lseek(fd, sec_start, SEEK_SET);
1493 1446 /*
1494 1447 * may write more than needed due to dropped feature, but
1495 1448  
1496 1449  
1497 1450  
... ... @@ -1634,20 +1587,20 @@
1634 1587 int perf_header__process_sections(struct perf_header *header, int fd,
1635 1588 void *data,
1636 1589 int (*process)(struct perf_file_section *section,
1637   - struct perf_header *ph,
1638   - int feat, int fd, void *data))
  1590 + struct perf_header *ph,
  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 1594 int nr_sections;
1642 1595 int sec_size;
1643   - int idx = 0;
1644   - int err = -1, feat = 1;
  1596 + int feat;
  1597 + int err;
1645 1598  
1646 1599 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
1647 1600 if (!nr_sections)
1648 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 1604 if (!feat_sec)
1652 1605 return -1;
1653 1606  
1654 1607  
1655 1608  
... ... @@ -1655,20 +1608,16 @@
1655 1608  
1656 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 1613 goto out_free;
1660 1614  
1661   - err = 0;
1662   - while (idx < nr_sections && feat < HEADER_LAST_FEATURE) {
1663   - if (perf_header__has_feat(header, feat)) {
1664   - struct perf_file_section *sec = &feat_sec[idx++];
1665   -
1666   - err = process(sec, header, feat, fd, data);
1667   - if (err < 0)
1668   - break;
1669   - }
1670   - ++feat;
  1615 + for_each_set_bit(feat, header->adds_features, HEADER_LAST_FEATURE) {
  1616 + err = process(sec++, header, feat, fd, data);
  1617 + if (err < 0)
  1618 + goto out_free;
1671 1619 }
  1620 + err = 0;
1672 1621 out_free:
1673 1622 free(feat_sec);
1674 1623 return err;
1675 1624  
1676 1625  
1677 1626  
... ... @@ -1903,32 +1852,21 @@
1903 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 1860 switch (feat) {
1907 1861 case HEADER_TRACE_INFO:
1908 1862 trace_report(fd, false);
1909 1863 break;
1910   -
1911 1864 case HEADER_BUILD_ID:
1912 1865 if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
1913 1866 pr_debug("Failed to read buildids, continuing...\n");
1914 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 1868 default:
1931   - pr_debug("unknown feature %d, continuing...\n", feat);
  1869 + break;
1932 1870 }
1933 1871  
1934 1872 return 0;
tools/perf/util/header.h
... ... @@ -10,7 +10,8 @@
10 10 #include <linux/bitmap.h>
11 11  
12 12 enum {
13   - HEADER_TRACE_INFO = 1,
  13 + HEADER_RESERVED = 0, /* always cleared */
  14 + HEADER_TRACE_INFO = 1,
14 15 HEADER_BUILD_ID,
15 16  
16 17 HEADER_HOSTNAME,
17 18  
... ... @@ -27,9 +28,8 @@
27 28 HEADER_NUMA_TOPOLOGY,
28 29  
29 30 HEADER_LAST_FEATURE,
  31 + HEADER_FEAT_BITS = 256,
30 32 };
31   -
32   -#define HEADER_FEAT_BITS 256
33 33  
34 34 struct perf_file_section {
35 35 u64 offset;
tools/perf/util/include/linux/bitops.h
... ... @@ -9,6 +9,17 @@
9 9 #define BITS_PER_BYTE 8
10 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 23 static inline void set_bit(int nr, unsigned long *addr)
13 24 {
14 25 addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
... ... @@ -28,6 +39,113 @@
28 39 static inline unsigned long hweight_long(unsigned long w)
29 40 {
30 41 return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
  42 +}
  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);
31 149 }
32 150  
33 151 #endif