lkml.org 
[lkml]   [2011]   [Dec]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 14/15] perf tools: Use for_each_set_bit() to iterate over feature flags
    Date
    From: Robert Richter <robert.richter@amd.com>

    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>
    ---
    tools/perf/util/header.c | 118 ++++++++------------------------
    tools/perf/util/header.h | 6 +-
    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 7132683..e509a9d 100644
    --- a/tools/perf/util/header.c
    +++ b/tools/perf/util/header.c
    @@ -8,6 +8,7 @@
    #include <stdlib.h>
    #include <linux/list.h>
    #include <linux/kernel.h>
    +#include <linux/bitops.h>
    #include <sys/utsname.h>

    #include "evlist.h"
    @@ -1353,7 +1354,7 @@ static int perf_file_section__fprintf_info(struct perf_file_section *section,
    "%d, continuing...\n", section->offset, feat);
    return 0;
    }
    - if (feat < HEADER_TRACE_INFO || feat >= HEADER_LAST_FEATURE) {
    + if (feat >= HEADER_LAST_FEATURE) {
    pr_warning("unknown feature %d\n", feat);
    return 0;
    }
    @@ -1390,6 +1391,8 @@ static int do_write_feat(int fd, struct perf_header *h, int type,
    int ret = 0;

    if (perf_header__has_feat(h, type)) {
    + if (!feat_ops[type].write)
    + return -1;

    (*p)->offset = lseek(fd, 0, SEEK_CUR);

    @@ -1416,6 +1419,7 @@ static int perf_header__adds_write(struct perf_header *header,
    struct perf_file_section *feat_sec, *p;
    int sec_size;
    u64 sec_start;
    + int feat;
    int err;

    session = container_of(header, struct perf_session, header);
    @@ -1433,61 +1437,10 @@ static int perf_header__adds_write(struct perf_header *header,
    sec_start = header->data_offset + header->data_size;
    lseek(fd, sec_start + sec_size, SEEK_SET);

    - err = do_write_feat(fd, header, HEADER_TRACE_INFO, &p, evlist);
    - if (err)
    - perf_header__clear_feat(header, HEADER_TRACE_INFO);
    -
    - err = do_write_feat(fd, header, HEADER_BUILD_ID, &p, evlist);
    - if (err)
    - perf_header__clear_feat(header, HEADER_BUILD_ID);
    -
    - err = do_write_feat(fd, header, HEADER_HOSTNAME, &p, evlist);
    - if (err)
    - perf_header__clear_feat(header, HEADER_HOSTNAME);
    -
    - err = do_write_feat(fd, header, HEADER_OSRELEASE, &p, evlist);
    - if (err)
    - perf_header__clear_feat(header, HEADER_OSRELEASE);
    -
    - err = do_write_feat(fd, header, HEADER_VERSION, &p, evlist);
    - if (err)
    - perf_header__clear_feat(header, HEADER_VERSION);
    -
    - err = do_write_feat(fd, header, HEADER_ARCH, &p, evlist);
    - if (err)
    - perf_header__clear_feat(header, HEADER_ARCH);
    -
    - err = do_write_feat(fd, header, HEADER_NRCPUS, &p, evlist);
    - if (err)
    - perf_header__clear_feat(header, HEADER_NRCPUS);
    -
    - err = do_write_feat(fd, header, HEADER_CPUDESC, &p, evlist);
    - if (err)
    - perf_header__clear_feat(header, HEADER_CPUDESC);
    -
    - err = do_write_feat(fd, header, HEADER_CPUID, &p, evlist);
    - if (err)
    - perf_header__clear_feat(header, HEADER_CPUID);
    -
    - err = do_write_feat(fd, header, HEADER_TOTAL_MEM, &p, evlist);
    - if (err)
    - perf_header__clear_feat(header, HEADER_TOTAL_MEM);
    -
    - err = do_write_feat(fd, header, HEADER_CMDLINE, &p, evlist);
    - if (err)
    - perf_header__clear_feat(header, HEADER_CMDLINE);
    -
    - err = do_write_feat(fd, header, HEADER_EVENT_DESC, &p, evlist);
    - if (err)
    - perf_header__clear_feat(header, HEADER_EVENT_DESC);
    -
    - err = do_write_feat(fd, header, HEADER_CPU_TOPOLOGY, &p, evlist);
    - if (err)
    - perf_header__clear_feat(header, HEADER_CPU_TOPOLOGY);
    -
    - err = do_write_feat(fd, header, HEADER_NUMA_TOPOLOGY, &p, evlist);
    - if (err)
    - perf_header__clear_feat(header, HEADER_NUMA_TOPOLOGY);
    + for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
    + if (do_write_feat(fd, header, feat, &p, evlist))
    + perf_header__clear_feat(header, feat);
    + }

    lseek(fd, sec_start, SEEK_SET);
    /*
    @@ -1634,20 +1587,20 @@ static int perf_header__getbuffer64(struct perf_header *header,
    int perf_header__process_sections(struct perf_header *header, int fd,
    void *data,
    int (*process)(struct perf_file_section *section,
    - struct perf_header *ph,
    - int feat, int fd, void *data))
    + struct perf_header *ph,
    + int feat, int fd, void *data))
    {
    - struct perf_file_section *feat_sec;
    + struct perf_file_section *feat_sec, *sec;
    int nr_sections;
    int sec_size;
    - int idx = 0;
    - int err = -1, feat = 1;
    + int feat;
    + int err;

    nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
    if (!nr_sections)
    return 0;

    - feat_sec = calloc(sizeof(*feat_sec), nr_sections);
    + feat_sec = sec = calloc(sizeof(*feat_sec), nr_sections);
    if (!feat_sec)
    return -1;

    @@ -1655,20 +1608,16 @@ int perf_header__process_sections(struct perf_header *header, int fd,

    lseek(fd, header->data_offset + header->data_size, SEEK_SET);

    - if (perf_header__getbuffer64(header, fd, feat_sec, sec_size))
    + err = perf_header__getbuffer64(header, fd, feat_sec, sec_size);
    + if (err < 0)
    goto out_free;

    - err = 0;
    - while (idx < nr_sections && feat < HEADER_LAST_FEATURE) {
    - if (perf_header__has_feat(header, feat)) {
    - struct perf_file_section *sec = &feat_sec[idx++];
    -
    - err = process(sec, header, feat, fd, data);
    - if (err < 0)
    - break;
    - }
    - ++feat;
    + for_each_set_bit(feat, header->adds_features, HEADER_LAST_FEATURE) {
    + err = process(sec++, header, feat, fd, data);
    + if (err < 0)
    + goto out_free;
    }
    + err = 0;
    out_free:
    free(feat_sec);
    return err;
    @@ -1903,32 +1852,21 @@ static int perf_file_section__process(struct perf_file_section *section,
    return 0;
    }

    + if (feat >= HEADER_LAST_FEATURE) {
    + pr_debug("unknown feature %d, continuing...\n", feat);
    + return 0;
    + }
    +
    switch (feat) {
    case HEADER_TRACE_INFO:
    trace_report(fd, false);
    break;
    -
    case HEADER_BUILD_ID:
    if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
    pr_debug("Failed to read buildids, continuing...\n");
    break;
    -
    - case HEADER_HOSTNAME:
    - case HEADER_OSRELEASE:
    - case HEADER_VERSION:
    - case HEADER_ARCH:
    - case HEADER_NRCPUS:
    - case HEADER_CPUDESC:
    - case HEADER_CPUID:
    - case HEADER_TOTAL_MEM:
    - case HEADER_CMDLINE:
    - case HEADER_EVENT_DESC:
    - case HEADER_CPU_TOPOLOGY:
    - case HEADER_NUMA_TOPOLOGY:
    - break;
    -
    default:
    - pr_debug("unknown feature %d, continuing...\n", feat);
    + break;
    }

    return 0;
    diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
    index 09365b3..ac4ec95 100644
    --- a/tools/perf/util/header.h
    +++ b/tools/perf/util/header.h
    @@ -10,7 +10,8 @@
    #include <linux/bitmap.h>

    enum {
    - HEADER_TRACE_INFO = 1,
    + HEADER_RESERVED = 0, /* always cleared */
    + HEADER_TRACE_INFO = 1,
    HEADER_BUILD_ID,

    HEADER_HOSTNAME,
    @@ -27,10 +28,9 @@ enum {
    HEADER_NUMA_TOPOLOGY,

    HEADER_LAST_FEATURE,
    + HEADER_FEAT_BITS = 256,
    };

    -#define HEADER_FEAT_BITS 256
    -
    struct perf_file_section {
    u64 offset;
    u64 size;
    diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h
    index 305c848..62cdee7 100644
    --- a/tools/perf/util/include/linux/bitops.h
    +++ b/tools/perf/util/include/linux/bitops.h
    @@ -9,6 +9,17 @@
    #define BITS_PER_BYTE 8
    #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))

    +#define for_each_set_bit(bit, addr, size) \
    + for ((bit) = find_first_bit((addr), (size)); \
    + (bit) < (size); \
    + (bit) = find_next_bit((addr), (size), (bit) + 1))
    +
    +/* same as for_each_set_bit() but use bit as value to start with */
    +#define for_each_set_bit_cont(bit, addr, size) \
    + for ((bit) = find_next_bit((addr), (size), (bit)); \
    + (bit) < (size); \
    + (bit) = find_next_bit((addr), (size), (bit) + 1))
    +
    static inline void set_bit(int nr, unsigned long *addr)
    {
    addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
    @@ -30,4 +41,111 @@ static inline unsigned long hweight_long(unsigned long w)
    return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
    }

    +#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
    +
    +/**
    + * __ffs - find first bit in word.
    + * @word: The word to search
    + *
    + * Undefined if no bit exists, so code should check against 0 first.
    + */
    +static __always_inline unsigned long __ffs(unsigned long word)
    +{
    + int num = 0;
    +
    +#if BITS_PER_LONG == 64
    + if ((word & 0xffffffff) == 0) {
    + num += 32;
    + word >>= 32;
    + }
    +#endif
    + if ((word & 0xffff) == 0) {
    + num += 16;
    + word >>= 16;
    + }
    + if ((word & 0xff) == 0) {
    + num += 8;
    + word >>= 8;
    + }
    + if ((word & 0xf) == 0) {
    + num += 4;
    + word >>= 4;
    + }
    + if ((word & 0x3) == 0) {
    + num += 2;
    + word >>= 2;
    + }
    + if ((word & 0x1) == 0)
    + num += 1;
    + return num;
    +}
    +
    +/*
    + * Find the first set bit in a memory region.
    + */
    +static inline unsigned long
    +find_first_bit(const unsigned long *addr, unsigned long size)
    +{
    + const unsigned long *p = addr;
    + unsigned long result = 0;
    + unsigned long tmp;
    +
    + while (size & ~(BITS_PER_LONG-1)) {
    + if ((tmp = *(p++)))
    + goto found;
    + result += BITS_PER_LONG;
    + size -= BITS_PER_LONG;
    + }
    + if (!size)
    + return result;
    +
    + tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
    + if (tmp == 0UL) /* Are any bits set? */
    + return result + size; /* Nope. */
    +found:
    + return result + __ffs(tmp);
    +}
    +
    +/*
    + * Find the next set bit in a memory region.
    + */
    +static inline unsigned long
    +find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset)
    +{
    + const unsigned long *p = addr + BITOP_WORD(offset);
    + unsigned long result = offset & ~(BITS_PER_LONG-1);
    + unsigned long tmp;
    +
    + if (offset >= size)
    + return size;
    + size -= result;
    + offset %= BITS_PER_LONG;
    + if (offset) {
    + tmp = *(p++);
    + tmp &= (~0UL << offset);
    + if (size < BITS_PER_LONG)
    + goto found_first;
    + if (tmp)
    + goto found_middle;
    + size -= BITS_PER_LONG;
    + result += BITS_PER_LONG;
    + }
    + while (size & ~(BITS_PER_LONG-1)) {
    + if ((tmp = *(p++)))
    + goto found_middle;
    + result += BITS_PER_LONG;
    + size -= BITS_PER_LONG;
    + }
    + if (!size)
    + return result;
    + tmp = *p;
    +
    +found_first:
    + tmp &= (~0UL >> (BITS_PER_LONG - size));
    + if (tmp == 0UL) /* Are any bits set? */
    + return result + size; /* Nope. */
    +found_middle:
    + return result + __ffs(tmp);
    +}
    +
    #endif
    --
    1.7.8.rc0.35.gee6df


    \
     
     \ /
      Last update: 2011-12-23 22:57    [W:0.038 / U:243.832 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site