/src/openvswitch/lib/coverage.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc. |
3 | | * |
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: |
7 | | * |
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. |
15 | | */ |
16 | | |
17 | | #ifndef COVERAGE_H |
18 | | #define COVERAGE_H 1 |
19 | | |
20 | | /* This file implements a simple form of coverage instrumentation. Points in |
21 | | * source code that are of interest must be explicitly annotated with |
22 | | * COVERAGE_INC. The coverage counters may be logged at any time with |
23 | | * coverage_log(). |
24 | | * |
25 | | * This form of coverage instrumentation is intended to be so lightweight that |
26 | | * it can be enabled in production builds. It is obviously not a substitute |
27 | | * for traditional coverage instrumentation with e.g. "gcov", but it is still |
28 | | * a useful debugging tool. */ |
29 | | |
30 | | #include "ovs-thread.h" |
31 | | #include "compiler.h" |
32 | | |
33 | | /* Makes coverage_run run every 5000 ms (5 seconds). |
34 | | * If this value is redefined, the new value must |
35 | | * divide 60000 (1 minute). */ |
36 | 0 | #define COVERAGE_RUN_INTERVAL 5000 |
37 | | BUILD_ASSERT_DECL(60000 % COVERAGE_RUN_INTERVAL == 0); |
38 | | |
39 | 0 | #define COVERAGE_CLEAR_INTERVAL 1000 |
40 | | BUILD_ASSERT_DECL(COVERAGE_RUN_INTERVAL % COVERAGE_CLEAR_INTERVAL == 0); |
41 | | |
42 | | /* Defines the moving average array length. */ |
43 | 0 | #define MIN_AVG_LEN (60000/COVERAGE_RUN_INTERVAL) |
44 | 0 | #define HR_AVG_LEN 60 |
45 | | |
46 | | /* A coverage counter. */ |
47 | | struct coverage_counter { |
48 | | const char *const name; /* Textual name. */ |
49 | | unsigned int (*const count)(void); /* Gets, zeros this thread's count. */ |
50 | | unsigned long long int total; /* Total count. */ |
51 | | unsigned long long int last_total; |
52 | | /* The moving average arrays. */ |
53 | | unsigned int min[MIN_AVG_LEN]; |
54 | | unsigned int hr[HR_AVG_LEN]; |
55 | | }; |
56 | | |
57 | | void coverage_counter_register(struct coverage_counter*); |
58 | | |
59 | | /* Defines COUNTER. There must be exactly one such definition at file scope |
60 | | * within a program. */ |
61 | | #define COVERAGE_DEFINE(COUNTER) \ |
62 | | DEFINE_STATIC_PER_THREAD_DATA(unsigned int, \ |
63 | | counter_##COUNTER, 0); \ |
64 | | static unsigned int COUNTER##_count(void) \ |
65 | 0 | { \ |
66 | 0 | unsigned int *countp = counter_##COUNTER##_get(); \ |
67 | 0 | unsigned int count = *countp; \ |
68 | 0 | *countp = 0; \ |
69 | 0 | return count; \ |
70 | 0 | } \ Unexecuted instantiation: jsonrpc.c:jsonrpc_recv_incomplete_count Unexecuted instantiation: poll-loop.c:poll_create_node_count Unexecuted instantiation: poll-loop.c:poll_zero_timeout_count Unexecuted instantiation: seq.c:seq_change_count Unexecuted instantiation: stream.c:pstream_open_count Unexecuted instantiation: stream.c:stream_open_count Unexecuted instantiation: timeval.c:long_poll_interval_count Unexecuted instantiation: unixctl.c:unixctl_received_count Unexecuted instantiation: unixctl.c:unixctl_replied_count Unexecuted instantiation: util.c:util_xalloc_count Unexecuted instantiation: hmap.c:hmap_pathological_count Unexecuted instantiation: hmap.c:hmap_expand_count Unexecuted instantiation: hmap.c:hmap_shrink_count Unexecuted instantiation: hmap.c:hmap_reserve_count Unexecuted instantiation: lockfile.c:lockfile_lock_count Unexecuted instantiation: lockfile.c:lockfile_error_count Unexecuted instantiation: lockfile.c:lockfile_unlock_count Unexecuted instantiation: process.c:process_start_count |
71 | | static inline void COUNTER##_add(unsigned int n) \ |
72 | 18.5M | { \ |
73 | 18.5M | *counter_##COUNTER##_get() += n; \ |
74 | 18.5M | } \ Unexecuted instantiation: jsonrpc.c:jsonrpc_recv_incomplete_add Unexecuted instantiation: poll-loop.c:poll_create_node_add Unexecuted instantiation: poll-loop.c:poll_zero_timeout_add Unexecuted instantiation: seq.c:seq_change_add Unexecuted instantiation: stream.c:stream_open_add Unexecuted instantiation: stream.c:pstream_open_add Unexecuted instantiation: timeval.c:long_poll_interval_add Unexecuted instantiation: unixctl.c:unixctl_replied_add Unexecuted instantiation: unixctl.c:unixctl_received_add Line | Count | Source | 72 | 18.5M | { \ | 73 | 18.5M | *counter_##COUNTER##_get() += n; \ | 74 | 18.5M | } \ |
Line | Count | Source | 72 | 7.05k | { \ | 73 | 7.05k | *counter_##COUNTER##_get() += n; \ | 74 | 7.05k | } \ |
hmap.c:hmap_pathological_add Line | Count | Source | 72 | 852 | { \ | 73 | 852 | *counter_##COUNTER##_get() += n; \ | 74 | 852 | } \ |
Unexecuted instantiation: hmap.c:hmap_shrink_add Unexecuted instantiation: hmap.c:hmap_reserve_add Unexecuted instantiation: lockfile.c:lockfile_lock_add Unexecuted instantiation: lockfile.c:lockfile_error_add Unexecuted instantiation: lockfile.c:lockfile_unlock_add Unexecuted instantiation: process.c:process_start_add |
75 | | extern struct coverage_counter counter_##COUNTER; \ |
76 | | struct coverage_counter counter_##COUNTER \ |
77 | | = { #COUNTER, COUNTER##_count, 0, 0, {0}, {0} }; \ |
78 | 36 | OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ |
79 | 36 | coverage_counter_register(&counter_##COUNTER); \ |
80 | 36 | } jsonrpc.c:jsonrpc_recv_incomplete_init_coverage Line | Count | Source | 78 | 2 | OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ | 79 | 2 | coverage_counter_register(&counter_##COUNTER); \ | 80 | 2 | } |
poll-loop.c:poll_create_node_init_coverage Line | Count | Source | 78 | 2 | OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ | 79 | 2 | coverage_counter_register(&counter_##COUNTER); \ | 80 | 2 | } |
poll-loop.c:poll_zero_timeout_init_coverage Line | Count | Source | 78 | 2 | OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ | 79 | 2 | coverage_counter_register(&counter_##COUNTER); \ | 80 | 2 | } |
seq.c:seq_change_init_coverage Line | Count | Source | 78 | 2 | OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ | 79 | 2 | coverage_counter_register(&counter_##COUNTER); \ | 80 | 2 | } |
stream.c:pstream_open_init_coverage Line | Count | Source | 78 | 2 | OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ | 79 | 2 | coverage_counter_register(&counter_##COUNTER); \ | 80 | 2 | } |
stream.c:stream_open_init_coverage Line | Count | Source | 78 | 2 | OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ | 79 | 2 | coverage_counter_register(&counter_##COUNTER); \ | 80 | 2 | } |
timeval.c:long_poll_interval_init_coverage Line | Count | Source | 78 | 2 | OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ | 79 | 2 | coverage_counter_register(&counter_##COUNTER); \ | 80 | 2 | } |
unixctl.c:unixctl_received_init_coverage Line | Count | Source | 78 | 2 | OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ | 79 | 2 | coverage_counter_register(&counter_##COUNTER); \ | 80 | 2 | } |
unixctl.c:unixctl_replied_init_coverage Line | Count | Source | 78 | 2 | OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ | 79 | 2 | coverage_counter_register(&counter_##COUNTER); \ | 80 | 2 | } |
util.c:util_xalloc_init_coverage Line | Count | Source | 78 | 2 | OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ | 79 | 2 | coverage_counter_register(&counter_##COUNTER); \ | 80 | 2 | } |
hmap.c:hmap_pathological_init_coverage Line | Count | Source | 78 | 2 | OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ | 79 | 2 | coverage_counter_register(&counter_##COUNTER); \ | 80 | 2 | } |
hmap.c:hmap_expand_init_coverage Line | Count | Source | 78 | 2 | OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ | 79 | 2 | coverage_counter_register(&counter_##COUNTER); \ | 80 | 2 | } |
hmap.c:hmap_shrink_init_coverage Line | Count | Source | 78 | 2 | OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ | 79 | 2 | coverage_counter_register(&counter_##COUNTER); \ | 80 | 2 | } |
hmap.c:hmap_reserve_init_coverage Line | Count | Source | 78 | 2 | OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ | 79 | 2 | coverage_counter_register(&counter_##COUNTER); \ | 80 | 2 | } |
lockfile.c:lockfile_lock_init_coverage Line | Count | Source | 78 | 2 | OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ | 79 | 2 | coverage_counter_register(&counter_##COUNTER); \ | 80 | 2 | } |
lockfile.c:lockfile_error_init_coverage Line | Count | Source | 78 | 2 | OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ | 79 | 2 | coverage_counter_register(&counter_##COUNTER); \ | 80 | 2 | } |
lockfile.c:lockfile_unlock_init_coverage Line | Count | Source | 78 | 2 | OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ | 79 | 2 | coverage_counter_register(&counter_##COUNTER); \ | 80 | 2 | } |
process.c:process_start_init_coverage Line | Count | Source | 78 | 2 | OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ | 79 | 2 | coverage_counter_register(&counter_##COUNTER); \ | 80 | 2 | } |
|
81 | | |
82 | | /* Adds 1 to COUNTER. */ |
83 | 18.5M | #define COVERAGE_INC(COUNTER) COVERAGE_ADD(COUNTER, 1) |
84 | | |
85 | | /* Adds AMOUNT to COUNTER. */ |
86 | 18.5M | #define COVERAGE_ADD(COUNTER, AMOUNT) COUNTER##_add(AMOUNT) |
87 | | |
88 | | void coverage_init(void); |
89 | | void coverage_log(void); |
90 | | void coverage_clear(void); |
91 | | void coverage_try_clear(void); |
92 | | void coverage_run(void); |
93 | | |
94 | | #endif /* coverage.h */ |