Line data Source code
1 1 : /*
2 : * Copyright Runtime.io 2018. All rights reserved.
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : /**
8 : * @file
9 : * @brief Statistics.
10 : *
11 : * Statistics are per-module event counters for troubleshooting, maintenance,
12 : * and usage monitoring. Statistics are organized into named "groups", with
13 : * each group consisting of a set of "entries". An entry corresponds to an
14 : * individual counter. Each entry can optionally be named if the STATS_NAMES
15 : * setting is enabled. Statistics can be retrieved with the mcumgr management
16 : * subsystem.
17 : *
18 : * There are two, largely duplicated, statistics sections here, in order to
19 : * provide the optional ability to name statistics.
20 : *
21 : * STATS_SECT_START/END actually declare the statistics structure definition,
22 : * STATS_SECT_DECL() creates the structure declaration so you can declare
23 : * these statistics as a global structure, and STATS_NAME_START/END are how
24 : * you name the statistics themselves.
25 : *
26 : * Statistics entries can be declared as any of several integer types.
27 : * However, all statistics in a given structure must be of the same size, and
28 : * they are all unsigned.
29 : *
30 : * - STATS_SECT_ENTRY(): default statistic entry, 32-bits.
31 : *
32 : * - STATS_SECT_ENTRY16(): 16-bits. Smaller statistics if you need to fit into
33 : * specific RAM or code size numbers.
34 : *
35 : * - STATS_SECT_ENTRY32(): 32-bits.
36 : *
37 : * - STATS_SECT_ENTRY64(): 64-bits. Useful for storing chunks of data.
38 : *
39 : * Following the static entry declaration is the statistic names declaration.
40 : * This is compiled out when the CONFIGURE_STATS_NAME setting is undefined.
41 : *
42 : * When CONFIG_STATS_NAMES is defined, the statistics names are stored and
43 : * returned to the management APIs. When the setting is undefined, temporary
44 : * names are generated as needed with the following format:
45 : *
46 : * s<stat-idx>
47 : *
48 : * E.g., "s0", "s1", etc.
49 : */
50 :
51 : #ifndef ZEPHYR_INCLUDE_STATS_STATS_H_
52 : #define ZEPHYR_INCLUDE_STATS_STATS_H_
53 :
54 : #include <stddef.h>
55 : #include <zephyr/types.h>
56 :
57 : #ifdef __cplusplus
58 : extern "C" {
59 : #endif
60 :
61 0 : struct stats_name_map {
62 0 : uint16_t snm_off;
63 0 : const char *snm_name;
64 : } __attribute__((packed));
65 :
66 0 : struct stats_hdr {
67 0 : const char *s_name;
68 0 : uint8_t s_size;
69 0 : uint16_t s_cnt;
70 0 : uint8_t s_pad1;
71 : #ifdef CONFIG_STATS_NAMES
72 : const struct stats_name_map *s_map;
73 : int s_map_cnt;
74 : #endif
75 0 : struct stats_hdr *s_next;
76 : };
77 :
78 : /**
79 : * @brief Declares a stat group struct.
80 : *
81 : * @param group__ The name to assign to the structure tag.
82 : */
83 1 : #define STATS_SECT_DECL(group__) \
84 : struct stats_ ## group__
85 :
86 : /**
87 : * @brief Ends a stats group struct definition.
88 : */
89 1 : #define STATS_SECT_END }
90 :
91 : /* The following macros depend on whether CONFIG_STATS is defined. If it is
92 : * not defined, then invocations of these macros get compiled out.
93 : */
94 : #ifdef CONFIG_STATS
95 :
96 : /**
97 : * @brief Begins a stats group struct definition.
98 : *
99 : * @param group__ The stats group struct name.
100 : */
101 : #define STATS_SECT_START(group__) \
102 : STATS_SECT_DECL(group__) { \
103 : struct stats_hdr s_hdr;
104 :
105 : /**
106 : * @brief Declares a 32-bit stat entry inside a group struct.
107 : *
108 : * @param var__ The name to assign to the entry.
109 : */
110 : #define STATS_SECT_ENTRY(var__) uint32_t var__;
111 :
112 : /**
113 : * @brief Declares a 16-bit stat entry inside a group struct.
114 : *
115 : * @param var__ The name to assign to the entry.
116 : */
117 : #define STATS_SECT_ENTRY16(var__) uint16_t var__;
118 :
119 : /**
120 : * @brief Declares a 32-bit stat entry inside a group struct.
121 : *
122 : * @param var__ The name to assign to the entry.
123 : */
124 : #define STATS_SECT_ENTRY32(var__) uint32_t var__;
125 :
126 : /**
127 : * @brief Declares a 64-bit stat entry inside a group struct.
128 : *
129 : * @param var__ The name to assign to the entry.
130 : */
131 : #define STATS_SECT_ENTRY64(var__) uint64_t var__;
132 :
133 : /**
134 : * @brief Increases a statistic entry by the specified amount.
135 : *
136 : * Increases a statistic entry by the specified amount. Compiled out if
137 : * CONFIG_STATS is not defined.
138 : *
139 : * @param group__ The group containing the entry to increase.
140 : * @param var__ The statistic entry to increase.
141 : * @param n__ The amount to increase the statistic entry by.
142 : */
143 : #define STATS_INCN(group__, var__, n__) \
144 : ((group__).var__ += (n__))
145 :
146 : /**
147 : * @brief Increments a statistic entry.
148 : *
149 : * Increments a statistic entry by one. Compiled out if CONFIG_STATS is not
150 : * defined.
151 : *
152 : * @param group__ The group containing the entry to increase.
153 : * @param var__ The statistic entry to increase.
154 : */
155 : #define STATS_INC(group__, var__) \
156 : STATS_INCN(group__, var__, 1)
157 :
158 : /**
159 : * @brief Set a statistic entry to the specified amount.
160 : *
161 : * Set a statistic entry to the specified amount. Compiled out if
162 : * CONFIG_STATS is not defined.
163 : *
164 : * @param group__ The group containing the entry to increase.
165 : * @param var__ The statistic entry to increase.
166 : * @param n__ The amount to set the statistic entry to.
167 : */
168 : #define STATS_SET(group__, var__, n__) \
169 : ((group__).var__ = (n__))
170 :
171 : /**
172 : * @brief Sets a statistic entry to zero.
173 : *
174 : * Sets a statistic entry to zero. Compiled out if CONFIG_STATS is not
175 : * defined.
176 : *
177 : * @param group__ The group containing the entry to clear.
178 : * @param var__ The statistic entry to clear.
179 : */
180 : #define STATS_CLEAR(group__, var__) \
181 : ((group__).var__ = 0)
182 :
183 : #define STATS_SIZE_16 (sizeof(uint16_t))
184 : #define STATS_SIZE_32 (sizeof(uint32_t))
185 : #define STATS_SIZE_64 (sizeof(uint64_t))
186 :
187 : #define STATS_SIZE_INIT_PARMS(group__, size__) \
188 : (size__), \
189 : ((sizeof(group__)) - sizeof(struct stats_hdr)) / (size__)
190 :
191 : /**
192 : * @brief Initializes and registers a statistics group.
193 : *
194 : * @param group__ The statistics group to initialize and
195 : * register.
196 : * @param size__ The size of each entry in the statistics group,
197 : * in bytes. Must be one of: 2 (16-bits), 4
198 : * (32-bits) or 8 (64-bits).
199 : * @param name__ The name of the statistics group to register.
200 : * This name must be unique among all
201 : * statistics groups.
202 : *
203 : * @return 0 on success; negative error code on failure.
204 : */
205 : #define STATS_INIT_AND_REG(group__, size__, name__) \
206 : stats_init_and_reg( \
207 : &(group__).s_hdr, \
208 : (size__), \
209 : (sizeof(group__) - sizeof(struct stats_hdr)) / (size__), \
210 : STATS_NAME_INIT_PARMS(group__), \
211 : (name__))
212 :
213 : /**
214 : * @brief Initializes a statistics group.
215 : *
216 : * @param hdr The header of the statistics structure,
217 : * contains things like statistic section
218 : * name, size of statistics entries, number of
219 : * statistics, etc.
220 : * @param size The size of each individual statistics
221 : * element, in bytes. Must be one of: 2
222 : * (16-bits), 4 (32-bits) or 8 (64-bits).
223 : * @param cnt The number of elements in the stats group.
224 : * @param map The mapping of stat offset to name.
225 : * @param map_cnt The number of items in the statistics map
226 : *
227 : * @param group__ The group containing the entry to clear.
228 : * @param var__ The statistic entry to clear.
229 : */
230 : void stats_init(struct stats_hdr *shdr, uint8_t size, uint16_t cnt,
231 : const struct stats_name_map *map, uint16_t map_cnt);
232 :
233 : /**
234 : * @brief Registers a statistics group to be managed.
235 : *
236 : * @param name The name of the statistics group to register.
237 : * This name must be unique among all
238 : * statistics groups. If the name is a
239 : * duplicate, this function will return
240 : * -EALREADY.
241 : * @param shdr The statistics group to register.
242 : *
243 : * @return 0 on success, non-zero error code on failure.
244 : */
245 : int stats_register(const char *name, struct stats_hdr *shdr);
246 :
247 : /**
248 : * @brief Initializes and registers a statistics group.
249 : *
250 : * Initializes and registers a statistics group. Note: it is recommended to
251 : * use the STATS_INIT_AND_REG macro instead of this function.
252 : *
253 : * @param hdr The header of the statistics group to
254 : * initialize and register.
255 : * @param size The size of each individual statistics
256 : * element, in bytes. Must be one of: 2
257 : * (16-bits), 4 (32-bits) or 8 (64-bits).
258 : * @param cnt The number of elements in the stats group.
259 : * @param map The mapping of stat offset to name.
260 : * @param map_cnt The number of items in the statistics map
261 : * @param name The name of the statistics group to register.
262 : * This name must be unique among all
263 : * statistics groups. If the name is a
264 : * duplicate, this function will return
265 : * -EALREADY.
266 : *
267 : * @return 0 on success; negative error code on failure.
268 : *
269 : * @see STATS_INIT_AND_REG
270 : */
271 : int stats_init_and_reg(struct stats_hdr *hdr, uint8_t size, uint16_t cnt,
272 : const struct stats_name_map *map, uint16_t map_cnt,
273 : const char *name);
274 :
275 : /**
276 : * Zeroes the specified statistics group.
277 : *
278 : * @param shdr The statistics group to clear.
279 : */
280 : void stats_reset(struct stats_hdr *shdr);
281 :
282 : /** @typedef stats_walk_fn
283 : * @brief Function that gets applied to every stat entry during a walk.
284 : *
285 : * @param hdr The group containing the stat entry being
286 : * walked.
287 : * @param arg Optional argument.
288 : * @param name The name of the statistic entry to process
289 : * @param off The offset of the entry, from `hdr`.
290 : *
291 : * @return 0 if the walk should proceed;
292 : * nonzero to abort the walk.
293 : */
294 : typedef int stats_walk_fn(struct stats_hdr *hdr, void *arg,
295 : const char *name, uint16_t off);
296 :
297 : /**
298 : * @brief Applies a function to every stat entry in a group.
299 : *
300 : * @param hdr The stats group to operate on.
301 : * @param walk_cb The function to apply to each stat entry.
302 : * @param arg Optional argument to pass to the callback.
303 : *
304 : * @return 0 if the walk completed;
305 : * nonzero if the walk was aborted.
306 : */
307 : int stats_walk(struct stats_hdr *hdr, stats_walk_fn *walk_cb, void *arg);
308 :
309 : /** @typedef stats_group_walk_fn
310 : * @brief Function that gets applied to every registered stats group.
311 : *
312 : * @param hdr The stats group being walked.
313 : * @param arg Optional argument.
314 : *
315 : * @return 0 if the walk should proceed;
316 : * nonzero to abort the walk.
317 : */
318 : typedef int stats_group_walk_fn(struct stats_hdr *hdr, void *arg);
319 :
320 : /**
321 : * @brief Applies a function every registered statistics group.
322 : *
323 : * @param walk_cb The function to apply to each stat group.
324 : * @param arg Optional argument to pass to the callback.
325 : *
326 : * @return 0 if the walk completed;
327 : * nonzero if the walk was aborted.
328 : */
329 : int stats_group_walk(stats_group_walk_fn *walk_cb, void *arg);
330 :
331 : /**
332 : * @brief Retrieves the next registered statistics group.
333 : *
334 : * @param cur The group whose successor is being retrieved, or
335 : * NULL to retrieve the first group.
336 : *
337 : * @return Pointer to the retrieved group on success;
338 : * NULL if no more groups remain.
339 : */
340 : struct stats_hdr *stats_group_get_next(const struct stats_hdr *cur);
341 :
342 : /**
343 : * @brief Retrieves the statistics group with the specified name.
344 : *
345 : * @param name The name of the statistics group to look up.
346 : *
347 : * @return Pointer to the retrieved group on success;
348 : * NULL if there is no matching registered group.
349 : */
350 : struct stats_hdr *stats_group_find(const char *name);
351 :
352 : #else /* CONFIG_STATS */
353 :
354 0 : #define STATS_SECT_START(group__) \
355 : STATS_SECT_DECL(group__) {
356 :
357 0 : #define STATS_SECT_ENTRY(var__)
358 0 : #define STATS_SECT_ENTRY16(var__)
359 0 : #define STATS_SECT_ENTRY32(var__)
360 0 : #define STATS_SECT_ENTRY64(var__)
361 0 : #define STATS_RESET(var__)
362 0 : #define STATS_SIZE_INIT_PARMS(group__, size__)
363 0 : #define STATS_INCN(group__, var__, n__)
364 0 : #define STATS_INC(group__, var__)
365 0 : #define STATS_SET(group__, var__)
366 0 : #define STATS_CLEAR(group__, var__)
367 0 : #define STATS_INIT_AND_REG(group__, size__, name__) (0)
368 :
369 : #endif /* !CONFIG_STATS */
370 :
371 : #ifdef CONFIG_STATS_NAMES
372 :
373 : #define STATS_NAME_MAP_NAME(sectname__) stats_map_ ## sectname__
374 :
375 : #define STATS_NAME_START(sectname__) \
376 : static const struct stats_name_map STATS_NAME_MAP_NAME(sectname__)[] = {
377 :
378 : #define STATS_NAME(sectname__, entry__) \
379 : { offsetof(STATS_SECT_DECL(sectname__), entry__), #entry__ },
380 :
381 : #define STATS_NAME_END(sectname__) }
382 :
383 : #define STATS_NAME_INIT_PARMS(name__) \
384 : &(STATS_NAME_MAP_NAME(name__)[0]), \
385 : (sizeof(STATS_NAME_MAP_NAME(name__)) / sizeof(struct stats_name_map))
386 :
387 : #else /* CONFIG_STATS_NAMES */
388 :
389 0 : #define STATS_NAME_START(name__)
390 0 : #define STATS_NAME(name__, entry__)
391 0 : #define STATS_NAME_END(name__)
392 0 : #define STATS_NAME_INIT_PARMS(name__) NULL, 0
393 :
394 : #endif /* CONFIG_STATS_NAMES */
395 :
396 : #ifdef __cplusplus
397 : }
398 : #endif
399 :
400 : #endif /* ZEPHYR_INCLUDE_STATS_STATS_H_ */
|