]> git.proxmox.com Git - ovs.git/blame - lib/coverage.c
tests: Fix deprecated use of qw.
[ovs.git] / lib / coverage.c
CommitLineData
064af421 1/*
67a4917b 2 * Copyright (c) 2009, 2010 Nicira Networks.
064af421 3 *
a14bc59f
BP
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
064af421 7 *
a14bc59f
BP
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
064af421
BP
15 */
16
17#include <config.h>
18#include "coverage.h"
19#include <inttypes.h>
20#include <stdlib.h>
064af421
BP
21#include "dynamic-string.h"
22#include "hash.h"
f5c6854a 23#include "unixctl.h"
064af421 24#include "util.h"
064af421
BP
25#include "vlog.h"
26
d98e6007 27VLOG_DEFINE_THIS_MODULE(coverage);
5136ce49 28
d76f09ea
BP
29/* The coverage counters. */
30#if USE_LINKER_SECTIONS
31extern struct coverage_counter *__start_coverage[];
32extern struct coverage_counter *__stop_coverage[];
33#define coverage_counters __start_coverage
34#define n_coverage_counters (__stop_coverage - __start_coverage)
35#else /* !USE_LINKER_SECTIONS */
36#define COVERAGE_COUNTER(NAME) COVERAGE_DEFINE__(NAME);
37#include "coverage.def"
38#undef COVERAGE_COUNTER
39
40struct coverage_counter *coverage_counters[] = {
41#define COVERAGE_COUNTER(NAME) &counter_##NAME,
42#include "coverage.def"
43#undef COVERAGE_COUNTER
44};
45#define n_coverage_counters ARRAY_SIZE(coverage_counters)
46#endif /* !USE_LINKER_SECTIONS */
47
064af421
BP
48static unsigned int epoch;
49
f5c6854a 50static void
c69ee87c
BP
51coverage_unixctl_log(struct unixctl_conn *conn, const char *args OVS_UNUSED,
52 void *aux OVS_UNUSED)
f5c6854a
JP
53{
54 coverage_log(VLL_WARN, false);
55 unixctl_command_reply(conn, 200, NULL);
56}
57
f5c6854a
JP
58void
59coverage_init(void)
60{
8ca79daa 61 unixctl_command_register("coverage/log", coverage_unixctl_log, NULL);
f5c6854a
JP
62}
63
064af421
BP
64/* Sorts coverage counters in descending order by count, within equal counts
65 * alphabetically by name. */
66static int
67compare_coverage_counters(const void *a_, const void *b_)
68{
69 const struct coverage_counter *const *ap = a_;
70 const struct coverage_counter *const *bp = b_;
71 const struct coverage_counter *a = *ap;
72 const struct coverage_counter *b = *bp;
73 if (a->count != b->count) {
74 return a->count < b->count ? 1 : -1;
75 } else {
76 return strcmp(a->name, b->name);
77 }
78}
79
80static uint32_t
81coverage_hash(void)
82{
83 struct coverage_counter **c;
84 uint32_t hash = 0;
85 int n_groups, i;
86
87 /* Sort coverage counters into groups with equal counts. */
d76f09ea
BP
88 c = xmalloc(n_coverage_counters * sizeof *c);
89 for (i = 0; i < n_coverage_counters; i++) {
064af421
BP
90 c[i] = coverage_counters[i];
91 }
d76f09ea 92 qsort(c, n_coverage_counters, sizeof *c, compare_coverage_counters);
064af421
BP
93
94 /* Hash the names in each group along with the rank. */
95 n_groups = 0;
d76f09ea 96 for (i = 0; i < n_coverage_counters; ) {
064af421
BP
97 int j;
98
99 if (!c[i]->count) {
100 break;
101 }
102 n_groups++;
103 hash = hash_int(i, hash);
d76f09ea 104 for (j = i; j < n_coverage_counters; j++) {
064af421
BP
105 if (c[j]->count != c[i]->count) {
106 break;
107 }
108 hash = hash_string(c[j]->name, hash);
109 }
110 i = j;
111 }
112
113 free(c);
114
115 return hash_int(n_groups, hash);
116}
117
118static bool
119coverage_hit(uint32_t hash)
120{
121 enum { HIT_BITS = 1024, BITS_PER_WORD = 32 };
122 static uint32_t hit[HIT_BITS / BITS_PER_WORD];
123 BUILD_ASSERT_DECL(IS_POW2(HIT_BITS));
124
125 unsigned int bit_index = hash & (HIT_BITS - 1);
126 unsigned int word_index = bit_index / BITS_PER_WORD;
127 unsigned int word_mask = 1u << (bit_index % BITS_PER_WORD);
128
129 if (hit[word_index] & word_mask) {
c69ee87c 130 return true;
064af421
BP
131 } else {
132 hit[word_index] |= word_mask;
133 return false;
134 }
135}
136
137static void
138coverage_log_counter(enum vlog_level level, const struct coverage_counter *c)
139{
140 VLOG(level, "%-24s %5u / %9llu", c->name, c->count, c->count + c->total);
141}
142
f5c6854a 143/* Logs the coverage counters at the given vlog 'level'. If
d295e8e9 144 * 'suppress_dups' is true, then duplicate events are not displayed.
6bc995e4
JP
145 * Care should be taken in the value used for 'level'. Depending on the
146 * configuration, syslog can write changes synchronously, which can
147 * cause the coverage messages to take several seconds to write. */
064af421 148void
f5c6854a 149coverage_log(enum vlog_level level, bool suppress_dups)
064af421
BP
150{
151 size_t n_never_hit;
152 uint32_t hash;
153 size_t i;
154
155 if (!vlog_is_enabled(THIS_MODULE, level)) {
156 return;
157 }
158
e775da14 159 hash = coverage_hash();
f5c6854a 160 if (suppress_dups) {
f5c6854a
JP
161 if (coverage_hit(hash)) {
162 VLOG(level, "Skipping details of duplicate event coverage for "
163 "hash=%08"PRIx32" in epoch %u", hash, epoch);
164 return;
165 }
064af421
BP
166 }
167
168 n_never_hit = 0;
169 VLOG(level, "Event coverage (epoch %u/entire run), hash=%08"PRIx32":",
170 epoch, hash);
d76f09ea 171 for (i = 0; i < n_coverage_counters; i++) {
064af421
BP
172 struct coverage_counter *c = coverage_counters[i];
173 if (c->count) {
174 coverage_log_counter(level, c);
175 }
176 }
d76f09ea 177 for (i = 0; i < n_coverage_counters; i++) {
064af421
BP
178 struct coverage_counter *c = coverage_counters[i];
179 if (!c->count) {
180 if (c->total) {
181 coverage_log_counter(level, c);
182 } else {
183 n_never_hit++;
184 }
185 }
186 }
187 VLOG(level, "%zu events never hit", n_never_hit);
188}
189
190/* Advances to the next epoch of coverage, resetting all the counters to 0. */
191void
192coverage_clear(void)
193{
194 size_t i;
195
196 epoch++;
d76f09ea 197 for (i = 0; i < n_coverage_counters; i++) {
064af421
BP
198 struct coverage_counter *c = coverage_counters[i];
199 c->total += c->count;
200 c->count = 0;
201 }
202}