2 * Copyright (c) 2009 Nicira Networks.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 #include "coverage-counters.h"
22 #include "dynamic-string.h"
26 #define THIS_MODULE VLM_coverage
29 static unsigned int epoch
;
31 /* Sorts coverage counters in descending order by count, within equal counts
32 * alphabetically by name. */
34 compare_coverage_counters(const void *a_
, const void *b_
)
36 const struct coverage_counter
*const *ap
= a_
;
37 const struct coverage_counter
*const *bp
= b_
;
38 const struct coverage_counter
*a
= *ap
;
39 const struct coverage_counter
*b
= *bp
;
40 if (a
->count
!= b
->count
) {
41 return a
->count
< b
->count
? 1 : -1;
43 return strcmp(a
->name
, b
->name
);
50 struct coverage_counter
**c
;
54 /* Sort coverage counters into groups with equal counts. */
55 c
= xmalloc(coverage_n_counters
* sizeof *c
);
56 for (i
= 0; i
< coverage_n_counters
; i
++) {
57 c
[i
] = coverage_counters
[i
];
59 qsort(c
, coverage_n_counters
, sizeof *c
, compare_coverage_counters
);
61 /* Hash the names in each group along with the rank. */
63 for (i
= 0; i
< coverage_n_counters
; ) {
70 hash
= hash_int(i
, hash
);
71 for (j
= i
; j
< coverage_n_counters
; j
++) {
72 if (c
[j
]->count
!= c
[i
]->count
) {
75 hash
= hash_string(c
[j
]->name
, hash
);
82 return hash_int(n_groups
, hash
);
86 coverage_hit(uint32_t hash
)
88 enum { HIT_BITS
= 1024, BITS_PER_WORD
= 32 };
89 static uint32_t hit
[HIT_BITS
/ BITS_PER_WORD
];
90 BUILD_ASSERT_DECL(IS_POW2(HIT_BITS
));
92 unsigned int bit_index
= hash
& (HIT_BITS
- 1);
93 unsigned int word_index
= bit_index
/ BITS_PER_WORD
;
94 unsigned int word_mask
= 1u << (bit_index
% BITS_PER_WORD
);
96 if (hit
[word_index
] & word_mask
) {
99 hit
[word_index
] |= word_mask
;
105 coverage_log_counter(enum vlog_level level
, const struct coverage_counter
*c
)
107 VLOG(level
, "%-24s %5u / %9llu", c
->name
, c
->count
, c
->count
+ c
->total
);
110 /* Logs the coverage counters at the given vlog 'level'. */
112 coverage_log(enum vlog_level level
)
118 if (!vlog_is_enabled(THIS_MODULE
, level
)) {
122 hash
= coverage_hash();
123 if (coverage_hit(hash
)) {
124 VLOG(level
, "Skipping details of duplicate event coverage for "
125 "hash=%08"PRIx32
" in epoch %u", hash
, epoch
);
130 VLOG(level
, "Event coverage (epoch %u/entire run), hash=%08"PRIx32
":",
132 for (i
= 0; i
< coverage_n_counters
; i
++) {
133 struct coverage_counter
*c
= coverage_counters
[i
];
135 coverage_log_counter(level
, c
);
138 for (i
= 0; i
< coverage_n_counters
; i
++) {
139 struct coverage_counter
*c
= coverage_counters
[i
];
142 coverage_log_counter(level
, c
);
148 VLOG(level
, "%zu events never hit", n_never_hit
);
151 /* Advances to the next epoch of coverage, resetting all the counters to 0. */
158 for (i
= 0; i
< coverage_n_counters
; i
++) {
159 struct coverage_counter
*c
= coverage_counters
[i
];
160 c
->total
+= c
->count
;