|  | /* | 
|  | * Copyright Runtime.io 2018. All rights reserved. | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | /** | 
|  | * @file | 
|  | * @brief Statistics. | 
|  | * | 
|  | * Statistics are per-module event counters for troubleshooting, maintenance, | 
|  | * and usage monitoring.  Statistics are organized into named "groups", with | 
|  | * each group consisting of a set of "entries".  An entry corresponds to an | 
|  | * individual counter.  Each entry can optionally be named if the STATS_NAMES | 
|  | * setting is enabled.  Statistics can be retrieved with the mcumgr management | 
|  | * subsystem. | 
|  | * | 
|  | * There are two, largely duplicated, statistics sections here, in order to | 
|  | * provide the optional ability to name statistics. | 
|  | * | 
|  | * STATS_SECT_START/END actually declare the statistics structure definition, | 
|  | * STATS_SECT_DECL() creates the structure declaration so you can declare | 
|  | * these statistics as a global structure, and STATS_NAME_START/END are how | 
|  | * you name the statistics themselves. | 
|  | * | 
|  | * Statistics entries can be declared as any of several integer types. | 
|  | * However, all statistics in a given structure must be of the same size, and | 
|  | * they are all unsigned. | 
|  | * | 
|  | * - STATS_SECT_ENTRY(): default statistic entry, 32-bits. | 
|  | * | 
|  | * - STATS_SECT_ENTRY16(): 16-bits.  Smaller statistics if you need to fit into | 
|  | *   specific RAM or code size numbers. | 
|  | * | 
|  | * - STATS_SECT_ENTRY32(): 32-bits. | 
|  | * | 
|  | * - STATS_SECT_ENTRY64(): 64-bits.  Useful for storing chunks of data. | 
|  | * | 
|  | * Following the static entry declaration is the statistic names declaration. | 
|  | * This is compiled out when the CONFIGURE_STATS_NAME setting is undefined. | 
|  | * | 
|  | * When CONFIG_STATS_NAMES is defined, the statistics names are stored and | 
|  | * returned to the management APIs.  When the setting is undefined, temporary | 
|  | * names are generated as needed with the following format: | 
|  | * | 
|  | *     s<stat-idx> | 
|  | * | 
|  | * E.g., "s0", "s1", etc. | 
|  | */ | 
|  |  | 
|  | #ifndef ZEPHYR_INCLUDE_STATS_STATS_H_ | 
|  | #define ZEPHYR_INCLUDE_STATS_STATS_H_ | 
|  |  | 
|  | #include <stddef.h> | 
|  | #include <zephyr/types.h> | 
|  |  | 
|  | #ifdef __cplusplus | 
|  | extern "C" { | 
|  | #endif | 
|  |  | 
|  | struct stats_name_map { | 
|  | uint16_t snm_off; | 
|  | const char *snm_name; | 
|  | } __attribute__((packed)); | 
|  |  | 
|  | struct stats_hdr { | 
|  | const char *s_name; | 
|  | uint8_t s_size; | 
|  | uint16_t s_cnt; | 
|  | uint8_t s_pad1; | 
|  | #ifdef CONFIG_STATS_NAMES | 
|  | const struct stats_name_map *s_map; | 
|  | int s_map_cnt; | 
|  | #endif | 
|  | struct stats_hdr *s_next; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * @brief Declares a stat group struct. | 
|  | * | 
|  | * @param group__               The name to assign to the structure tag. | 
|  | */ | 
|  | #define STATS_SECT_DECL(group__) \ | 
|  | struct stats_ ## group__ | 
|  |  | 
|  | /** | 
|  | * @brief Ends a stats group struct definition. | 
|  | */ | 
|  | #define STATS_SECT_END } | 
|  |  | 
|  | /* The following macros depend on whether CONFIG_STATS is defined.  If it is | 
|  | * not defined, then invocations of these macros get compiled out. | 
|  | */ | 
|  | #ifdef CONFIG_STATS | 
|  |  | 
|  | /** | 
|  | * @brief Begins a stats group struct definition. | 
|  | * | 
|  | * @param group__               The stats group struct name. | 
|  | */ | 
|  | #define STATS_SECT_START(group__)  \ | 
|  | STATS_SECT_DECL(group__) { \ | 
|  | struct stats_hdr s_hdr; | 
|  |  | 
|  | /** | 
|  | * @brief Declares a 32-bit stat entry inside a group struct. | 
|  | * | 
|  | * @param var__                 The name to assign to the entry. | 
|  | */ | 
|  | #define STATS_SECT_ENTRY(var__) uint32_t var__; | 
|  |  | 
|  | /** | 
|  | * @brief Declares a 16-bit stat entry inside a group struct. | 
|  | * | 
|  | * @param var__                 The name to assign to the entry. | 
|  | */ | 
|  | #define STATS_SECT_ENTRY16(var__) uint16_t var__; | 
|  |  | 
|  | /** | 
|  | * @brief Declares a 32-bit stat entry inside a group struct. | 
|  | * | 
|  | * @param var__                 The name to assign to the entry. | 
|  | */ | 
|  | #define STATS_SECT_ENTRY32(var__) uint32_t var__; | 
|  |  | 
|  | /** | 
|  | * @brief Declares a 64-bit stat entry inside a group struct. | 
|  | * | 
|  | * @param var__                 The name to assign to the entry. | 
|  | */ | 
|  | #define STATS_SECT_ENTRY64(var__) uint64_t var__; | 
|  |  | 
|  | /** | 
|  | * @brief Increases a statistic entry by the specified amount. | 
|  | * | 
|  | * Increases a statistic entry by the specified amount.  Compiled out if | 
|  | * CONFIG_STATS is not defined. | 
|  | * | 
|  | * @param group__               The group containing the entry to increase. | 
|  | * @param var__                 The statistic entry to increase. | 
|  | * @param n__                   The amount to increase the statistic entry by. | 
|  | */ | 
|  | #define STATS_INCN(group__, var__, n__)	\ | 
|  | ((group__).var__ += (n__)) | 
|  |  | 
|  | /** | 
|  | * @brief Increments a statistic entry. | 
|  | * | 
|  | * Increments a statistic entry by one.  Compiled out if CONFIG_STATS is not | 
|  | * defined. | 
|  | * | 
|  | * @param group__               The group containing the entry to increase. | 
|  | * @param var__                 The statistic entry to increase. | 
|  | */ | 
|  | #define STATS_INC(group__, var__) \ | 
|  | STATS_INCN(group__, var__, 1) | 
|  |  | 
|  | /** | 
|  | * @brief Set a statistic entry to the specified amount. | 
|  | * | 
|  | * Set a statistic entry to the specified amount.  Compiled out if | 
|  | * CONFIG_STATS is not defined. | 
|  | * | 
|  | * @param group__               The group containing the entry to increase. | 
|  | * @param var__                 The statistic entry to increase. | 
|  | * @param n__                   The amount to set the statistic entry to. | 
|  | */ | 
|  | #define STATS_SET(group__, var__, n__)	\ | 
|  | ((group__).var__ = (n__)) | 
|  |  | 
|  | /** | 
|  | * @brief Sets a statistic entry to zero. | 
|  | * | 
|  | * Sets a statistic entry to zero.  Compiled out if CONFIG_STATS is not | 
|  | * defined. | 
|  | * | 
|  | * @param group__               The group containing the entry to clear. | 
|  | * @param var__                 The statistic entry to clear. | 
|  | */ | 
|  | #define STATS_CLEAR(group__, var__) \ | 
|  | ((group__).var__ = 0) | 
|  |  | 
|  | #define STATS_SIZE_16 (sizeof(uint16_t)) | 
|  | #define STATS_SIZE_32 (sizeof(uint32_t)) | 
|  | #define STATS_SIZE_64 (sizeof(uint64_t)) | 
|  |  | 
|  | #define STATS_SIZE_INIT_PARMS(group__, size__) \ | 
|  | (size__),			       \ | 
|  | ((sizeof(group__)) - sizeof(struct stats_hdr)) / (size__) | 
|  |  | 
|  | /** | 
|  | * @brief Initializes and registers a statistics group. | 
|  | * | 
|  | * @param group__               The statistics group to initialize and | 
|  | *                                  register. | 
|  | * @param size__                The size of each entry in the statistics group, | 
|  | *                                  in bytes.  Must be one of: 2 (16-bits), 4 | 
|  | *                                  (32-bits) or 8 (64-bits). | 
|  | * @param name__                The name of the statistics group to register. | 
|  | *                                  This name must be unique among all | 
|  | *                                  statistics groups. | 
|  | * | 
|  | * @return                      0 on success; negative error code on failure. | 
|  | */ | 
|  | #define STATS_INIT_AND_REG(group__, size__, name__)			 \ | 
|  | stats_init_and_reg(						 \ | 
|  | &(group__).s_hdr,					 \ | 
|  | (size__),						 \ | 
|  | (sizeof(group__) - sizeof(struct stats_hdr)) / (size__), \ | 
|  | STATS_NAME_INIT_PARMS(group__),				 \ | 
|  | (name__)) | 
|  |  | 
|  | /** | 
|  | * @brief Initializes a statistics group. | 
|  | * | 
|  | * @param hdr                   The header of the statistics structure, | 
|  | *                                  contains things like statistic section | 
|  | *                                  name, size of statistics entries, number of | 
|  | *                                  statistics, etc. | 
|  | * @param size                  The size of each individual statistics | 
|  | *                                  element, in bytes.  Must be one of: 2 | 
|  | *                                  (16-bits), 4 (32-bits) or 8 (64-bits). | 
|  | * @param cnt                   The number of elements in the stats group. | 
|  | * @param map                   The mapping of stat offset to name. | 
|  | * @param map_cnt               The number of items in the statistics map | 
|  | * | 
|  | * @param group__               The group containing the entry to clear. | 
|  | * @param var__                 The statistic entry to clear. | 
|  | */ | 
|  | void stats_init(struct stats_hdr *shdr, uint8_t size, uint16_t cnt, | 
|  | const struct stats_name_map *map, uint16_t map_cnt); | 
|  |  | 
|  | /** | 
|  | * @brief Registers a statistics group to be managed. | 
|  | * | 
|  | * @param name                  The name of the statistics group to register. | 
|  | *                                 This name must be unique among all | 
|  | *                                 statistics groups.  If the name is a | 
|  | *                                 duplicate, this function will return | 
|  | *                                 -EALREADY. | 
|  | * @param shdr                  The statistics group to register. | 
|  | * | 
|  | * @return 0 on success, non-zero error code on failure. | 
|  | */ | 
|  | int stats_register(const char *name, struct stats_hdr *shdr); | 
|  |  | 
|  | /** | 
|  | * @brief Initializes and registers a statistics group. | 
|  | * | 
|  | * Initializes and registers a statistics group.  Note: it is recommended to | 
|  | * use the STATS_INIT_AND_REG macro instead of this function. | 
|  | * | 
|  | * @param hdr                   The header of the statistics group to | 
|  | *                                  initialize and register. | 
|  | * @param size                  The size of each individual statistics | 
|  | *                                  element, in bytes.  Must be one of: 2 | 
|  | *                                  (16-bits), 4 (32-bits) or 8 (64-bits). | 
|  | * @param cnt                   The number of elements in the stats group. | 
|  | * @param map                   The mapping of stat offset to name. | 
|  | * @param map_cnt               The number of items in the statistics map | 
|  | * @param name                  The name of the statistics group to register. | 
|  | *                                  This name must be unique among all | 
|  | *                                  statistics groups.  If the name is a | 
|  | *                                  duplicate, this function will return | 
|  | *                                  -EALREADY. | 
|  | * | 
|  | * @return                      0 on success; negative error code on failure. | 
|  | * | 
|  | * @see STATS_INIT_AND_REG | 
|  | */ | 
|  | int stats_init_and_reg(struct stats_hdr *hdr, uint8_t size, uint16_t cnt, | 
|  | const struct stats_name_map *map, uint16_t map_cnt, | 
|  | const char *name); | 
|  |  | 
|  | /** | 
|  | * Zeroes the specified statistics group. | 
|  | * | 
|  | * @param shdr                  The statistics group to clear. | 
|  | */ | 
|  | void stats_reset(struct stats_hdr *shdr); | 
|  |  | 
|  | /** @typedef stats_walk_fn | 
|  | * @brief Function that gets applied to every stat entry during a walk. | 
|  | * | 
|  | * @param hdr                   The group containing the stat entry being | 
|  | *                                  walked. | 
|  | * @param arg                   Optional argument. | 
|  | * @param name                  The name of the statistic entry to process | 
|  | * @param off                   The offset of the entry, from `hdr`. | 
|  | * | 
|  | * @return                      0 if the walk should proceed; | 
|  | *                              nonzero to abort the walk. | 
|  | */ | 
|  | typedef int stats_walk_fn(struct stats_hdr *hdr, void *arg, | 
|  | const char *name, uint16_t off); | 
|  |  | 
|  | /** | 
|  | * @brief Applies a function to every stat entry in a group. | 
|  | * | 
|  | * @param hdr                   The stats group to operate on. | 
|  | * @param walk_cb               The function to apply to each stat entry. | 
|  | * @param arg                   Optional argument to pass to the callback. | 
|  | * | 
|  | * @return                      0 if the walk completed; | 
|  | *                              nonzero if the walk was aborted. | 
|  | */ | 
|  | int stats_walk(struct stats_hdr *hdr, stats_walk_fn *walk_cb, void *arg); | 
|  |  | 
|  | /** @typedef stats_group_walk_fn | 
|  | * @brief Function that gets applied to every registered stats group. | 
|  | * | 
|  | * @param hdr                   The stats group being walked. | 
|  | * @param arg                   Optional argument. | 
|  | * | 
|  | * @return                      0 if the walk should proceed; | 
|  | *                              nonzero to abort the walk. | 
|  | */ | 
|  | typedef int stats_group_walk_fn(struct stats_hdr *hdr, void *arg); | 
|  |  | 
|  | /** | 
|  | * @brief Applies a function every registered statistics group. | 
|  | * | 
|  | * @param walk_cb               The function to apply to each stat group. | 
|  | * @param arg                   Optional argument to pass to the callback. | 
|  | * | 
|  | * @return                      0 if the walk completed; | 
|  | *                              nonzero if the walk was aborted. | 
|  | */ | 
|  | int stats_group_walk(stats_group_walk_fn *walk_cb, void *arg); | 
|  |  | 
|  | /** | 
|  | * @brief Retrieves the next registered statistics group. | 
|  | * | 
|  | * @param cur                   The group whose successor is being retrieved, or | 
|  | *                                  NULL to retrieve the first group. | 
|  | * | 
|  | * @return                      Pointer to the retrieved group on success; | 
|  | *                              NULL if no more groups remain. | 
|  | */ | 
|  | struct stats_hdr *stats_group_get_next(const struct stats_hdr *cur); | 
|  |  | 
|  | /** | 
|  | * @brief Retrieves the statistics group with the specified name. | 
|  | * | 
|  | * @param name                  The name of the statistics group to look up. | 
|  | * | 
|  | * @return                      Pointer to the retrieved group on success; | 
|  | *                              NULL if there is no matching registered group. | 
|  | */ | 
|  | struct stats_hdr *stats_group_find(const char *name); | 
|  |  | 
|  | #else /* CONFIG_STATS */ | 
|  |  | 
|  | #define STATS_SECT_START(group__) \ | 
|  | STATS_SECT_DECL(group__) { | 
|  |  | 
|  | #define STATS_SECT_ENTRY(var__) | 
|  | #define STATS_SECT_ENTRY16(var__) | 
|  | #define STATS_SECT_ENTRY32(var__) | 
|  | #define STATS_SECT_ENTRY64(var__) | 
|  | #define STATS_RESET(var__) | 
|  | #define STATS_SIZE_INIT_PARMS(group__, size__) | 
|  | #define STATS_INCN(group__, var__, n__) | 
|  | #define STATS_INC(group__, var__) | 
|  | #define STATS_SET(group__, var__) | 
|  | #define STATS_CLEAR(group__, var__) | 
|  | #define STATS_INIT_AND_REG(group__, size__, name__) (0) | 
|  |  | 
|  | #endif /* !CONFIG_STATS */ | 
|  |  | 
|  | #ifdef CONFIG_STATS_NAMES | 
|  |  | 
|  | #define STATS_NAME_MAP_NAME(sectname__) stats_map_ ## sectname__ | 
|  |  | 
|  | #define STATS_NAME_START(sectname__) \ | 
|  | static const struct stats_name_map STATS_NAME_MAP_NAME(sectname__)[] = { | 
|  |  | 
|  | #define STATS_NAME(sectname__, entry__)	\ | 
|  | { offsetof(STATS_SECT_DECL(sectname__), entry__), #entry__ }, | 
|  |  | 
|  | #define STATS_NAME_END(sectname__) } | 
|  |  | 
|  | #define STATS_NAME_INIT_PARMS(name__)	    \ | 
|  | &(STATS_NAME_MAP_NAME(name__)[0]), \ | 
|  | (sizeof(STATS_NAME_MAP_NAME(name__)) / sizeof(struct stats_name_map)) | 
|  |  | 
|  | #else /* CONFIG_STATS_NAMES */ | 
|  |  | 
|  | #define STATS_NAME_START(name__) | 
|  | #define STATS_NAME(name__, entry__) | 
|  | #define STATS_NAME_END(name__) | 
|  | #define STATS_NAME_INIT_PARMS(name__) NULL, 0 | 
|  |  | 
|  | #endif /* CONFIG_STATS_NAMES */ | 
|  |  | 
|  | #ifdef __cplusplus | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #endif /* ZEPHYR_INCLUDE_STATS_STATS_H_ */ |