This looks good to me, The only issue may be that some comments need to be changed:
-/* Sorts coverage counters in descending order by count, within equal counts - * alphabetically by name. */ +/* Sorts coverage counters in descending order by total count, + * within equal total counts alphabetically by name. */ static int compare_coverage_counters(const void *a_, const void *b_) { @@ -108,7 +108,7 @@ coverage_hash(void) uint32_t hash = 0; int n_groups, i; - /* Sort coverage counters into groups with equal counts. */ + /* Sort coverage counters into groups with equal total counts. */ c = xmalloc(n_coverage_counters * sizeof *c); ovs_mutex_lock(&coverage_mutex); for (i = 0; i < n_coverage_counters; i++) { On Fri, Aug 16, 2013 at 3:47 PM, Ben Pfaff <b...@nicira.com> wrote: > This makes each of the coverage counters per-thread. It abandons the > idea of trying to keep track of the number of hits in the "current" poll > loop, since there are many poll loops running, each in its own thread, as > well as the idea of numbering epochs for the same reason. Instead, we > just keep track of overall totals for the process for each coverage > counter, accumulating per-thread counts into the global total each time > a thread's main loop passes through poll_block(). > > Signed-off-by: Ben Pfaff <b...@nicira.com> > --- > lib/coverage.c | 73 > +++++++++++++++++++++++++++++++------------------------- > lib/coverage.h | 41 ++++++++++++++++++++++--------- > 2 files changed, 71 insertions(+), 43 deletions(-) > > diff --git a/lib/coverage.c b/lib/coverage.c > index f152474..ac5dd67 100644 > --- a/lib/coverage.c > +++ b/lib/coverage.c > @@ -1,5 +1,5 @@ > /* > - * Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc. > + * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc. > * > * Licensed under the Apache License, Version 2.0 (the "License"); > * you may not use this file except in compliance with the License. > @@ -35,7 +35,19 @@ extern struct coverage_counter *__stop_coverage[]; > #define coverage_counters __start_coverage > #define n_coverage_counters (__stop_coverage - __start_coverage) > #else /* !USE_LINKER_SECTIONS */ > -#define COVERAGE_COUNTER(NAME) COVERAGE_DEFINE__(NAME); > +#define COVERAGE_COUNTER(COUNTER) \ > + DECLARE_EXTERN_PER_THREAD_DATA(unsigned int, \ > + counter_##COUNTER); \ > + DEFINE_EXTERN_PER_THREAD_DATA(counter_##COUNTER, 0); \ > + static unsigned int COUNTER##_count(void) \ > + { \ > + unsigned int *countp = counter_##COUNTER##_get(); \ > + unsigned int count = *countp; \ > + *countp = 0; \ > + return count; \ > + } \ > + struct coverage_counter counter_##COUNTER \ > + = { #COUNTER, COUNTER##_count, 0 }; > #include "coverage.def" > #undef COVERAGE_COUNTER > > @@ -47,7 +59,7 @@ struct coverage_counter *coverage_counters[] = { > #define n_coverage_counters ARRAY_SIZE(coverage_counters) > #endif /* !USE_LINKER_SECTIONS */ > > -static unsigned int epoch; > +static struct ovs_mutex coverage_mutex = OVS_MUTEX_INITIALIZER; > > static void coverage_read(struct svec *); > > @@ -82,8 +94,8 @@ compare_coverage_counters(const void *a_, const void *b_) > const struct coverage_counter *const *bp = b_; > const struct coverage_counter *a = *ap; > const struct coverage_counter *b = *bp; > - if (a->count != b->count) { > - return a->count < b->count ? 1 : -1; > + if (a->total != b->total) { > + return a->total < b->total ? 1 : -1; > } else { > return strcmp(a->name, b->name); > } > @@ -98,9 +110,11 @@ coverage_hash(void) > > /* Sort coverage counters into groups with equal counts. */ > c = xmalloc(n_coverage_counters * sizeof *c); > + ovs_mutex_lock(&coverage_mutex); > for (i = 0; i < n_coverage_counters; i++) { > c[i] = coverage_counters[i]; > } > + ovs_mutex_unlock(&coverage_mutex); > qsort(c, n_coverage_counters, sizeof *c, compare_coverage_counters); > > /* Hash the names in each group along with the rank. */ > @@ -108,13 +122,13 @@ coverage_hash(void) > for (i = 0; i < n_coverage_counters; ) { > int j; > > - if (!c[i]->count) { > + if (!c[i]->total) { > break; > } > n_groups++; > hash = hash_int(i, hash); > for (j = i; j < n_coverage_counters; j++) { > - if (c[j]->count != c[i]->count) { > + if (c[j]->total != c[i]->total) { > break; > } > hash = hash_string(c[j]->name, hash); > @@ -170,7 +184,7 @@ coverage_log(void) > uint32_t hash = coverage_hash(); > if (coverage_hit(hash)) { > VLOG_INFO("Skipping details of duplicate event coverage for " > - "hash=%08"PRIx32" in epoch %u", hash, epoch); > + "hash=%08"PRIx32, hash); > } else { > struct svec lines; > const char *line; > @@ -186,17 +200,11 @@ coverage_log(void) > } > } > > -static void > -coverage_read_counter(struct svec *lines, const struct coverage_counter > *c) > -{ > - svec_add_nocopy(lines, xasprintf("%-24s %5u / %9llu", > - c->name, c->count, c->count + > c->total)); > -} > - > /* Adds coverage counter information to 'lines'. */ > static void > coverage_read(struct svec *lines) > { > + unsigned long long int *totals; > size_t n_never_hit; > uint32_t hash; > size_t i; > @@ -204,37 +212,38 @@ coverage_read(struct svec *lines) > hash = coverage_hash(); > > n_never_hit = 0; > - svec_add_nocopy(lines, xasprintf("Event coverage (epoch %u/entire > run), " > - "hash=%08"PRIx32":", epoch, hash)); > + svec_add_nocopy(lines, > + xasprintf("Event coverage, hash=%08"PRIx32":", hash)); > + > + totals = xmalloc(n_coverage_counters * sizeof *totals); > + ovs_mutex_lock(&coverage_mutex); > for (i = 0; i < n_coverage_counters; i++) { > - struct coverage_counter *c = coverage_counters[i]; > - if (c->count) { > - coverage_read_counter(lines, c); > - } > + totals[i] = coverage_counters[i]->total; > } > + ovs_mutex_unlock(&coverage_mutex); > + > for (i = 0; i < n_coverage_counters; i++) { > - struct coverage_counter *c = coverage_counters[i]; > - if (!c->count) { > - if (c->total) { > - coverage_read_counter(lines, c); > - } else { > - n_never_hit++; > - } > + if (totals[i]) { > + svec_add_nocopy(lines, xasprintf("%-24s %9llu", > + coverage_counters[i]->name, > + totals[i])); > + } else { > + n_never_hit++; > } > } > svec_add_nocopy(lines, xasprintf("%zu events never hit", > n_never_hit)); > + free(totals); > } > > -/* Advances to the next epoch of coverage, resetting all the counters to > 0. */ > void > coverage_clear(void) > { > size_t i; > > - epoch++; > + ovs_mutex_lock(&coverage_mutex); > for (i = 0; i < n_coverage_counters; i++) { > struct coverage_counter *c = coverage_counters[i]; > - c->total += c->count; > - c->count = 0; > + c->total += c->count(); > } > + ovs_mutex_unlock(&coverage_mutex); > } > diff --git a/lib/coverage.h b/lib/coverage.h > index 968c489..73b027a 100644 > --- a/lib/coverage.h > +++ b/lib/coverage.h > @@ -1,5 +1,5 @@ > /* > - * Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc. > + * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc. > * > * Licensed under the Apache License, Version 2.0 (the "License"); > * you may not use this file except in compliance with the License. > @@ -27,33 +27,54 @@ > * for traditional coverage instrumentation with e.g. "gcov", but it is > still > * a useful debugging tool. */ > > +#include "ovs-thread.h" > #include "vlog.h" > > /* A coverage counter. */ > struct coverage_counter { > - const char *name; /* Textual name. */ > - unsigned int count; /* Count within the current epoch. */ > - unsigned long long int total; /* Total count over all epochs. */ > + const char *const name; /* Textual name. */ > + unsigned int (*const count)(void); /* Gets, zeros this thread's > count. */ > + unsigned long long int total; /* Total count. */ > }; > > /* Defines COUNTER. There must be exactly one such definition at file > scope > * within a program. */ > #if USE_LINKER_SECTIONS > #define COVERAGE_DEFINE(COUNTER) \ > - COVERAGE_DEFINE__(COUNTER); \ > + DEFINE_STATIC_PER_THREAD_DATA(unsigned int, \ > + counter_##COUNTER, 0); \ > + static unsigned int COUNTER##_count(void) \ > + { \ > + unsigned int *countp = counter_##COUNTER##_get(); \ > + unsigned int count = *countp; \ > + *countp = 0; \ > + return count; \ > + } \ > + static inline void COUNTER##_add(unsigned int n) \ > + { \ > + *counter_##COUNTER##_get() += n; \ > + } \ > + struct coverage_counter counter_##COUNTER \ > + = { #COUNTER, COUNTER##_count, 0 }; \ > extern struct coverage_counter *counter_ptr_##COUNTER; \ > struct coverage_counter *counter_ptr_##COUNTER \ > __attribute__((section("coverage"))) = &counter_##COUNTER > #else > -#define COVERAGE_DEFINE(MODULE) \ > - extern struct coverage_counter counter_##MODULE > +#define COVERAGE_DEFINE(COUNTER) \ > + DECLARE_EXTERN_PER_THREAD_DATA(unsigned int, \ > + counter_##COUNTER); \ > + static inline void COUNTER##_add(unsigned int n) \ > + { \ > + *counter_##COUNTER##_get() += n; \ > + } \ > + extern struct coverage_counter counter_##COUNTER > #endif > > /* Adds 1 to COUNTER. */ > -#define COVERAGE_INC(COUNTER) counter_##COUNTER.count++; > +#define COVERAGE_INC(COUNTER) COVERAGE_ADD(COUNTER, 1) > > /* Adds AMOUNT to COUNTER. */ > -#define COVERAGE_ADD(COUNTER, AMOUNT) counter_##COUNTER.count += (AMOUNT); > +#define COVERAGE_ADD(COUNTER, AMOUNT) COUNTER##_add(AMOUNT) > > void coverage_init(void); > void coverage_log(void); > @@ -61,7 +82,5 @@ void coverage_clear(void); > > /* Implementation detail. */ > #define COVERAGE_DEFINE__(COUNTER) \ > - extern struct coverage_counter counter_##COUNTER; \ > - struct coverage_counter counter_##COUNTER = { #COUNTER, 0, 0 } > > #endif /* coverage.h */ > -- > 1.7.10.4 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev >
_______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev