zephyr/include/stats/stats.h
Tom Burdick f523c336ef pm: Use stats subsys for tracking system states
Uses the stats subsys to provide simple but useful debugging stats for
power management state changes and timing.

Removes the no longer needed PM_DEBUG config option

Replaces the use of PM_DEBUG for a test clock output pin for mec1501 and
adds in its place an SoC Kconfig option to enable it.

Adds a STATS_SET macro for assigning a value to a stat group field

Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
2021-10-17 10:56:21 -04:00

401 lines
13 KiB
C

/*
* 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__) \
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_ */