The
NetBSD generic event counter framework is designed to provide a flexible and hierarchical event counting facility, which is useful for tracking system events (including device interrupts).
The fundamental component of this framework is the
evcnt structure. Its user-accessible fields are:
struct evcnt {
uint64_t ev_count; /* how many have occurred */
TAILQ_ENTRY(evcnt) ev_list; /* entry on list of all counters */
unsigned char ev_type; /* counter type; see below */
unsigned char ev_grouplen; /* 'group' len, excluding NUL */
unsigned char ev_namelen; /* 'name' len, excluding NUL */
const struct evcnt *ev_parent; /* parent, for hierarchical ctrs */
const char *ev_group; /* name of group */
const char *ev_name; /* name of specific event */
};
The system maintains a global linked list of all active event counters. This list, called
allevents, may grow or shrink over time as event counters are dynamically added to and removed from the system.
Each event counter is marked (in the
ev_type field) with the type of event being counted. The following types are currently defined:
EVCNT_TYPE_MISC
Miscellaneous; doesn't fit into one of the other types.
EVCNT_TYPE_INTR
Interrupt counter, reported by vmstat -i.
EVCNT_TYPE_TRAP
Processor trap style events.
Each event counter also has a group name (
ev_group) and an event name (
ev_name) which are used to identify the counter. The group name may be shared by a set of counters. For example, device interrupt counters would use the name of the device whose interrupts are being counted as the group name. The counter name is meant to distinguish the counter from others in its group (and need not be unique across groups). Both names should be understandable by users, since they are printed by commands like
vmstat(1). The constant
EVCNT_STRING_MAX is defined to be the maximum group or event name length in bytes (including the trailing
NUL). In the current implementation it is 256.
To support hierarchical tracking of events, each event counter can name a “parent” event counter. For instance, interrupt dispatch code could have an event counter per interrupt line, and devices could each have counters for the number of interrupts that they were responsible for causing. In that case, the counter for a device on a given interrupt line would have the line's counter as its parent. The value
NULL is used to indicate that a counter has no parent. A counter's parent must be attached before the counter is attached, and detached after the counter is detached.
The
EVCNT_INITIALIZER() macro can be used to provide a static initializer for an event counter structure. It is invoked as
EVCNT_INITIALIZER(
type,
parent,
group,
name), and its arguments will be placed into the corresponding fields of the event counter structure it is initializing. The
group and
name arguments must be constant strings.