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 struct stats_name_map { 62 uint16_t snm_off; 63 const char *snm_name; 64 } __attribute__((packed)); 65 66 struct stats_hdr { 67 const char *s_name; 68 uint8_t s_size; 69 uint16_t s_cnt; 70 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 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 #define STATS_SECT_DECL(group__) \ 84 struct stats_ ## group__ 85 86 /** 87 * @brief Ends a stats group struct definition. 88 */ 89 #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 #define STATS_SECT_START(group__) \ 355 STATS_SECT_DECL(group__) { 356 357 #define STATS_SECT_ENTRY(var__) 358 #define STATS_SECT_ENTRY16(var__) 359 #define STATS_SECT_ENTRY32(var__) 360 #define STATS_SECT_ENTRY64(var__) 361 #define STATS_RESET(var__) 362 #define STATS_SIZE_INIT_PARMS(group__, size__) 363 #define STATS_INCN(group__, var__, n__) 364 #define STATS_INC(group__, var__) 365 #define STATS_SET(group__, var__) 366 #define STATS_CLEAR(group__, var__) 367 #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 #define STATS_NAME_START(name__) 390 #define STATS_NAME(name__, entry__) 391 #define STATS_NAME_END(name__) 392 #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_ */ 401