perf-counters: fix non-linux build
[cascardo/ovs.git] / lib / perf-counter.h
1 /*
2  * Copyright (c) 2015 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 __PERF_COUNTER_H
18 #define __PERF_COUNTER_H 1
19
20 /* Motivation
21  * ==========
22  *
23  * It is sometimes desirable to gain performance insights of a program
24  * by using hardware counters.  Recent Linux kernels started to support
25  * a set of portable API for configuring and access those counter across
26  * multiple platforms.
27  *
28  * APIs provided by perf-counter.h provides a set of APIs that are
29  * semi-integrated into OVS user spaces. The infrastructure that initializes,
30  * cleanup, display and clear them at run time is provided. However the
31  * sample points are not. A programmer needs insert sample points when needed.
32  *
33  * Since there is no pre configured sample points, there is no run time
34  * over head for the released product.
35  *
36  * Limitations
37  * ===========
38  * - Hard coded to sample CPU cycle count in user space only.
39  * - Only one counter is sampled.
40  * - Useful macros are only provided for function profiling.
41  * - show and clear command applies to all counters, there is no way
42  *   to select a sub-set of counter.
43  *
44  * Those are not fundamental limits, but only limited by current
45  * implementation.
46  *
47  * Function instruction counter sample point Usage
48  * ================================================
49  *
50  * There are two macros provided:
51  *
52  * Macro 'PERF_FUNCTON_COUNT_BEGIN' needs to be inserted towards the
53  * beginning of the function where local variables are declared.
54  *
55  * Macro 'PERF_FUNCTON_COUNT_END' needs to appear in the same function,
56  * some where below 'PERF_FUNCTION_COUNT_BEGIN', usually towards of
57  * a function.
58  *
59  * For example:
60  *
61  *    void my_func() {
62  *      int some_local_variable;
63  *
64  *      PERF_FUNCTION_COUNT_BEGIN;
65  *
66  *      < implementation >
67  *
68  *      PERF_FUNCTION_COUNT_END
69  *    }
70  *
71  * This will maintain the number of times 'my_func()' is called, total
72  * number of instructions '<implementation>' executed during all those calls.
73  *
74  * Currently there are two limitation:
75  * 1). At most one pair can appear in the same variable scope.
76  * 2). The Macros use function name as the counter name for display.
77  *     Thus, all functions in one annotation session are required to
78  *     have unique names.
79  *
80  * Note, there is no requirement for those macros to be balanced.
81  * For example:
82  *
83  *    void my_func(int i){
84  *
85  *      PERF_FUNCTION_COUNT_BEGIN;
86  *
87  *      if (i == 300) {
88  *          PERF_FUNCTION_COUNT_END;
89  *          return;
90  *      } else {
91  *           <some code>
92  *      }
93  *    }
94  * will work just fine.
95  */
96
97 #ifdef __linux__
98 struct perf_counter {
99     const char *name;
100     bool once;
101     uint64_t n_events;
102     uint64_t total_count;
103 };
104
105 #define PERF_COUNTER_ONCE_INITIALIZER(name)  \
106     {                                        \
107         name,                                \
108         false,                               \
109         0,                                   \
110         0,                                   \
111     }
112
113 void perf_counters_init(void);
114 void perf_counters_destroy(void);
115 void perf_counters_clear(void);
116
117 uint64_t perf_counter_read(uint64_t *counter);
118 void perf_counter_accumulate(struct perf_counter *counter,
119                              uint64_t start_count);
120 char *perf_counters_to_string(void);
121
122 /* User access macros. */
123 #define PERF_FUNCTION_BEGIN \
124     static struct perf_counter x__ = PERF_COUNTER_ONCE_INITIALIZER(__func__); \
125     uint64_t start_count__ = perf_counter_read(&start_count__);               \
126
127 #define PERF_FUNCTION_END \
128     perf_counter_accumulate(&x__, start_count__);
129
130 #else
131
132 #define PERF_FUNCTON_COUNT_BEGIN
133 #define PERF_FUNCTON_COUNT_END
134
135 static inline void perf_counters_init(void) {}
136 static inline void perf_counters_destroy(void) {}
137 static inline void perf_counters_clear(void) {}
138 static inline char *
139 perf_counters_to_string(void)
140 {
141     return xstrdup("Not Supported on this platform. Only available on Linux.");
142 }
143
144 #endif
145
146 #endif