Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Robert Richter and committed by
Arnaldo Carvalho de Melo
b1e5a9be e20960c0

+149 -93
+28 -90
tools/perf/util/header.c
··· 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" ··· 1354 1353 "%d, continuing...\n", section->offset, feat); 1355 1354 return 0; 1356 1355 } 1357 - if (feat < HEADER_TRACE_INFO || feat >= HEADER_LAST_FEATURE) { 1356 + if (feat >= HEADER_LAST_FEATURE) { 1358 1357 pr_warning("unknown feature %d\n", feat); 1359 1358 return 0; 1360 1359 } ··· 1391 1390 int ret = 0; 1392 1391 1393 1392 if (perf_header__has_feat(h, type)) { 1393 + if (!feat_ops[type].write) 1394 + return -1; 1394 1395 1395 1396 (*p)->offset = lseek(fd, 0, SEEK_CUR); 1396 1397 ··· 1419 1416 struct perf_file_section *feat_sec, *p; 1420 1417 int sec_size; 1421 1418 u64 sec_start; 1419 + int feat; 1422 1420 int err; 1423 1421 1424 1422 session = container_of(header, struct perf_session, header); ··· 1437 1433 sec_start = header->data_offset + header->data_size; 1438 1434 lseek(fd, sec_start + sec_size, SEEK_SET); 1439 1435 1440 - err = do_write_feat(fd, header, HEADER_TRACE_INFO, &p, evlist); 1441 - if (err) 1442 - perf_header__clear_feat(header, HEADER_TRACE_INFO); 1443 - 1444 - err = do_write_feat(fd, header, HEADER_BUILD_ID, &p, evlist); 1445 - if (err) 1446 - perf_header__clear_feat(header, HEADER_BUILD_ID); 1447 - 1448 - err = do_write_feat(fd, header, HEADER_HOSTNAME, &p, evlist); 1449 - if (err) 1450 - perf_header__clear_feat(header, HEADER_HOSTNAME); 1451 - 1452 - err = do_write_feat(fd, header, HEADER_OSRELEASE, &p, evlist); 1453 - if (err) 1454 - perf_header__clear_feat(header, HEADER_OSRELEASE); 1455 - 1456 - err = do_write_feat(fd, header, HEADER_VERSION, &p, evlist); 1457 - if (err) 1458 - perf_header__clear_feat(header, HEADER_VERSION); 1459 - 1460 - err = do_write_feat(fd, header, HEADER_ARCH, &p, evlist); 1461 - if (err) 1462 - perf_header__clear_feat(header, HEADER_ARCH); 1463 - 1464 - err = do_write_feat(fd, header, HEADER_NRCPUS, &p, evlist); 1465 - if (err) 1466 - perf_header__clear_feat(header, HEADER_NRCPUS); 1467 - 1468 - err = do_write_feat(fd, header, HEADER_CPUDESC, &p, evlist); 1469 - if (err) 1470 - perf_header__clear_feat(header, HEADER_CPUDESC); 1471 - 1472 - err = do_write_feat(fd, header, HEADER_CPUID, &p, evlist); 1473 - if (err) 1474 - perf_header__clear_feat(header, HEADER_CPUID); 1475 - 1476 - err = do_write_feat(fd, header, HEADER_TOTAL_MEM, &p, evlist); 1477 - if (err) 1478 - perf_header__clear_feat(header, HEADER_TOTAL_MEM); 1479 - 1480 - err = do_write_feat(fd, header, HEADER_CMDLINE, &p, evlist); 1481 - if (err) 1482 - perf_header__clear_feat(header, HEADER_CMDLINE); 1483 - 1484 - err = do_write_feat(fd, header, HEADER_EVENT_DESC, &p, evlist); 1485 - if (err) 1486 - perf_header__clear_feat(header, HEADER_EVENT_DESC); 1487 - 1488 - err = do_write_feat(fd, header, HEADER_CPU_TOPOLOGY, &p, evlist); 1489 - if (err) 1490 - perf_header__clear_feat(header, HEADER_CPU_TOPOLOGY); 1491 - 1492 - err = do_write_feat(fd, header, HEADER_NUMA_TOPOLOGY, &p, evlist); 1493 - if (err) 1494 - perf_header__clear_feat(header, HEADER_NUMA_TOPOLOGY); 1436 + for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) { 1437 + if (do_write_feat(fd, header, feat, &p, evlist)) 1438 + perf_header__clear_feat(header, feat); 1439 + } 1495 1440 1496 1441 lseek(fd, sec_start, SEEK_SET); 1497 1442 /* ··· 1587 1634 int perf_header__process_sections(struct perf_header *header, int fd, 1588 1635 void *data, 1589 1636 int (*process)(struct perf_file_section *section, 1590 - struct perf_header *ph, 1591 - int feat, int fd, void *data)) 1637 + struct perf_header *ph, 1638 + int feat, int fd, void *data)) 1592 1639 { 1593 - struct perf_file_section *feat_sec; 1640 + struct perf_file_section *feat_sec, *sec; 1594 1641 int nr_sections; 1595 1642 int sec_size; 1596 - int idx = 0; 1597 - int err = -1, feat = 1; 1643 + int feat; 1644 + int err; 1598 1645 1599 1646 nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS); 1600 1647 if (!nr_sections) 1601 1648 return 0; 1602 1649 1603 - feat_sec = calloc(sizeof(*feat_sec), nr_sections); 1650 + feat_sec = sec = calloc(sizeof(*feat_sec), nr_sections); 1604 1651 if (!feat_sec) 1605 1652 return -1; 1606 1653 ··· 1608 1655 1609 1656 lseek(fd, header->data_offset + header->data_size, SEEK_SET); 1610 1657 1611 - if (perf_header__getbuffer64(header, fd, feat_sec, sec_size)) 1658 + err = perf_header__getbuffer64(header, fd, feat_sec, sec_size); 1659 + if (err < 0) 1612 1660 goto out_free; 1613 1661 1614 - err = 0; 1615 - while (idx < nr_sections && feat < HEADER_LAST_FEATURE) { 1616 - if (perf_header__has_feat(header, feat)) { 1617 - struct perf_file_section *sec = &feat_sec[idx++]; 1618 - 1619 - err = process(sec, header, feat, fd, data); 1620 - if (err < 0) 1621 - break; 1622 - } 1623 - ++feat; 1662 + for_each_set_bit(feat, header->adds_features, HEADER_LAST_FEATURE) { 1663 + err = process(sec++, header, feat, fd, data); 1664 + if (err < 0) 1665 + goto out_free; 1624 1666 } 1667 + err = 0; 1625 1668 out_free: 1626 1669 free(feat_sec); 1627 1670 return err; ··· 1852 1903 return 0; 1853 1904 } 1854 1905 1906 + if (feat >= HEADER_LAST_FEATURE) { 1907 + pr_debug("unknown feature %d, continuing...\n", feat); 1908 + return 0; 1909 + } 1910 + 1855 1911 switch (feat) { 1856 1912 case HEADER_TRACE_INFO: 1857 1913 trace_report(fd, false); 1858 1914 break; 1859 - 1860 1915 case HEADER_BUILD_ID: 1861 1916 if (perf_header__read_build_ids(ph, fd, section->offset, section->size)) 1862 1917 pr_debug("Failed to read buildids, continuing...\n"); 1863 1918 break; 1864 - 1865 - case HEADER_HOSTNAME: 1866 - case HEADER_OSRELEASE: 1867 - case HEADER_VERSION: 1868 - case HEADER_ARCH: 1869 - case HEADER_NRCPUS: 1870 - case HEADER_CPUDESC: 1871 - case HEADER_CPUID: 1872 - case HEADER_TOTAL_MEM: 1873 - case HEADER_CMDLINE: 1874 - case HEADER_EVENT_DESC: 1875 - case HEADER_CPU_TOPOLOGY: 1876 - case HEADER_NUMA_TOPOLOGY: 1877 - break; 1878 - 1879 1919 default: 1880 - pr_debug("unknown feature %d, continuing...\n", feat); 1920 + break; 1881 1921 } 1882 1922 1883 1923 return 0;
+3 -3
tools/perf/util/header.h
··· 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, ··· 28 27 HEADER_NUMA_TOPOLOGY, 29 28 30 29 HEADER_LAST_FEATURE, 30 + HEADER_FEAT_BITS = 256, 31 31 }; 32 - 33 - #define HEADER_FEAT_BITS 256 34 32 35 33 struct perf_file_section { 36 34 u64 offset;
+118
tools/perf/util/include/linux/bitops.h
··· 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); ··· 39 28 static inline unsigned long hweight_long(unsigned long w) 40 29 { 41 30 return sizeof(w) == 4 ? hweight32(w) : hweight64(w); 31 + } 32 + 33 + #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) 34 + 35 + /** 36 + * __ffs - find first bit in word. 37 + * @word: The word to search 38 + * 39 + * Undefined if no bit exists, so code should check against 0 first. 40 + */ 41 + static __always_inline unsigned long __ffs(unsigned long word) 42 + { 43 + int num = 0; 44 + 45 + #if BITS_PER_LONG == 64 46 + if ((word & 0xffffffff) == 0) { 47 + num += 32; 48 + word >>= 32; 49 + } 50 + #endif 51 + if ((word & 0xffff) == 0) { 52 + num += 16; 53 + word >>= 16; 54 + } 55 + if ((word & 0xff) == 0) { 56 + num += 8; 57 + word >>= 8; 58 + } 59 + if ((word & 0xf) == 0) { 60 + num += 4; 61 + word >>= 4; 62 + } 63 + if ((word & 0x3) == 0) { 64 + num += 2; 65 + word >>= 2; 66 + } 67 + if ((word & 0x1) == 0) 68 + num += 1; 69 + return num; 70 + } 71 + 72 + /* 73 + * Find the first set bit in a memory region. 74 + */ 75 + static inline unsigned long 76 + find_first_bit(const unsigned long *addr, unsigned long size) 77 + { 78 + const unsigned long *p = addr; 79 + unsigned long result = 0; 80 + unsigned long tmp; 81 + 82 + while (size & ~(BITS_PER_LONG-1)) { 83 + if ((tmp = *(p++))) 84 + goto found; 85 + result += BITS_PER_LONG; 86 + size -= BITS_PER_LONG; 87 + } 88 + if (!size) 89 + return result; 90 + 91 + tmp = (*p) & (~0UL >> (BITS_PER_LONG - size)); 92 + if (tmp == 0UL) /* Are any bits set? */ 93 + return result + size; /* Nope. */ 94 + found: 95 + return result + __ffs(tmp); 96 + } 97 + 98 + /* 99 + * Find the next set bit in a memory region. 100 + */ 101 + static inline unsigned long 102 + find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset) 103 + { 104 + const unsigned long *p = addr + BITOP_WORD(offset); 105 + unsigned long result = offset & ~(BITS_PER_LONG-1); 106 + unsigned long tmp; 107 + 108 + if (offset >= size) 109 + return size; 110 + size -= result; 111 + offset %= BITS_PER_LONG; 112 + if (offset) { 113 + tmp = *(p++); 114 + tmp &= (~0UL << offset); 115 + if (size < BITS_PER_LONG) 116 + goto found_first; 117 + if (tmp) 118 + goto found_middle; 119 + size -= BITS_PER_LONG; 120 + result += BITS_PER_LONG; 121 + } 122 + while (size & ~(BITS_PER_LONG-1)) { 123 + if ((tmp = *(p++))) 124 + goto found_middle; 125 + result += BITS_PER_LONG; 126 + size -= BITS_PER_LONG; 127 + } 128 + if (!size) 129 + return result; 130 + tmp = *p; 131 + 132 + found_first: 133 + tmp &= (~0UL >> (BITS_PER_LONG - size)); 134 + if (tmp == 0UL) /* Are any bits set? */ 135 + return result + size; /* Nope. */ 136 + found_middle: 137 + return result + __ffs(tmp); 42 138 } 43 139 44 140 #endif