xref: /netbsd/share/man/man9/evcnt.9 (revision 6550d01e)
1.\" $NetBSD: evcnt.9,v 1.21 2011/01/14 18:34:44 dyoung Exp $
2.\"
3.\" Copyright (c) 2000 Christopher G. Demetriou
4.\" All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\"    notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\"    notice, this list of conditions and the following disclaimer in the
13.\"    documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\"    must display the following acknowledgement:
16.\"          This product includes software developed for the
17.\"          NetBSD Project.  See http://www.NetBSD.org/ for
18.\"          information about NetBSD.
19.\" 4. The name of the author may not be used to endorse or promote products
20.\"    derived from this software without specific prior written permission.
21.\"
22.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32.\"
33.\" --(license Id: LICENSE.proto,v 1.1 2000/06/13 21:40:26 cgd Exp )--
34.\"
35.Dd January 14, 2011
36.Dt EVCNT 9
37.Os
38.Sh NAME
39.Nm evcnt ,
40.Nm evcnt_attach_dynamic ,
41.Nm evcnt_attach_static ,
42.Nm evcnt_detach
43.Nd generic event counter framework
44.Sh SYNOPSIS
45.In sys/evcnt.h
46.Ft void
47.Fn evcnt_attach_dynamic "struct evcnt *ev" \
48"int type" "const struct evcnt *parent" "const char *group" "const char *name"
49.Ft void
50.Fn evcnt_attach_static "struct evcnt *ev"
51.Ft void
52.Fn evcnt_detach "struct evcnt *ev"
53.Sh DESCRIPTION
54The
55.Nx
56generic event counter framework is designed to provide a flexible and
57hierarchical event counting facility, which is useful for tracking
58system events (including device interrupts).
59.Pp
60The fundamental component of this framework is the
61.Em evcnt
62structure.
63Its user-accessible fields are:
64.Bd -literal
65struct evcnt {
66	uint64_t	ev_count;	/* how many have occurred */
67	TAILQ_ENTRY(evcnt) ev_list;	/* entry on list of all counters */
68	unsigned char	ev_type;	/* counter type; see below */
69	unsigned char	ev_grouplen;	/* 'group' len, excluding NUL */
70	unsigned char	ev_namelen;	/* 'name' len, excluding NUL */
71	const struct evcnt *ev_parent;	/* parent, for hierarchical ctrs */
72	const char	*ev_group;	/* name of group */
73	const char	*ev_name;	/* name of specific event */
74};
75.Ed
76.Pp
77The system maintains a global linked list of all active event counters.
78This list, called
79.Nm allevents ,
80may grow or shrink over time as event counters are dynamically
81added to and removed from the system.
82.Pp
83Each event counter is marked (in the
84.Fa ev_type
85field) with the type of event being counted.
86The following types are currently defined:
87.Bl -tag -offset indent -width EVCNT_TYPE_MISC
88.It Ev EVCNT_TYPE_MISC
89Miscellaneous; doesn't fit into one of the other types.
90.It Ev EVCNT_TYPE_INTR
91Interrupt counter, reported by
92.Ic vmstat -i .
93.It Ev EVCNT_TYPE_TRAP
94Processor trap style events.
95.El
96.Pp
97Each event counter also has a group name
98.Pq Fa ev_group
99and
100an event name
101.Pq Fa ev_name
102which are used to identify the counter.
103The group name may be shared by a set of counters.
104For example, device interrupt counters would use the name of the
105device whose interrupts are being counted as the group name.
106The counter
107name is meant to distinguish the counter from others in its group
108(and need not be unique across groups).
109Both names should be understandable by users, since they are printed
110by commands like
111.Xr vmstat 1 .
112The constant
113.Dv EVCNT_STRING_MAX
114is defined to be the maximum group or event name length in
115bytes (including the trailing
116.Dv NUL ) .
117In the current implementation it is 256.
118.Pp
119To support hierarchical tracking of events, each event counter can
120name a
121.Dq parent
122event counter.
123For instance, interrupt dispatch code could have an event counter per
124interrupt line, and devices could each have counters for the number
125of interrupts that they were responsible for causing.
126In that case, the counter for a device on a given interrupt line
127would have the line's counter as its parent.
128The value
129.Dv NULL
130is used to indicate that a counter has no parent.
131A counter's parent must be attached before the counter is attached,
132and detached after the counter is detached.
133.Pp
134The
135.Fn EVCNT_INITIALIZER
136macro can be used to provide a static initializer for an event
137counter structure.
138It is invoked as
139.Fn EVCNT_INITIALIZER "type" "parent" "group" "name" ,
140and its arguments will be placed into the corresponding fields of
141the event counter structure it is initializing.
142The
143.Fa group
144and
145.Fa name
146arguments must be constant strings.
147.Sh FUNCTIONS
148The following is a brief description of each function in the framework:
149.Bl -tag -width indent
150.It Fn evcnt_attach_dynamic "ev" "type" "parent" "group" "name"
151Attach the event counter structure pointed to by
152.Fa ev
153to the system event list.
154The event counter is cleared and its fields initialized using the
155arguments to the function call.
156The contents of the remaining elements in the structure (e.g., the
157name lengths) are calculated, and the counter is added to the
158system event list.
159.Pp
160The strings specified as the group and
161counter names must persist (with the same value)
162throughout the life of the event counter; they are referenced by,
163not copied into, the counter.
164.It Fn evcnt_attach_static "ev"
165Attach the statically-initialized event counter structure
166pointed to by
167.Fa ev
168to the system event list.
169The event counter is assumed to be statically initialized using the
170.Fn EVCNT_INITIALIZER
171macro.
172This function simply calculates structure elements' values as appropriate
173(e.g., the string lengths), and adds the counter to the system event list.
174.It Fn evcnt_detach "ev"
175Detach the event counter structure pointed to by
176.Fa ev
177from the system event list.
178.El
179.Pp
180Note that no method is provided to increment the value of an
181event counter.
182Code incrementing an event counter should do so by directly accessing its
183.Fa ev_count
184field in a manner that is known to be safe.
185For instance, additions to a device's event counters in the interrupt
186handler for that device will often be safe without additional protection
187(because interrupt handler entries for a given device have to be
188serialized).
189However, for other uses of event counters, additional locking
190or use of machine-dependent atomic operation may be appropriate.
191(The overhead of using a mechanism that is guaranteed to
192be safe to increment every counter, regardless of actual need
193for such a mechanism where the counter is being incremented,
194would be too great.
195On some systems, it might involve a global lock and several function calls.)
196.Sh EXAMPLES
197This section includes a description on basic use of the framework
198and example usage of its functions.
199.Pp
200Device drivers can use the
201.Fn evcnt_attach_dynamic
202and
203.Fn evcnt_detach
204functions to manage device-specific event counters.
205Statically configured system modules can use
206.Fn evcnt_attach_static
207to configure global event counters.
208Similarly, loadable modules can use
209.Fn evcnt_attach_static
210to configure their global event counters,
211.Fn evcnt_attach_dynamic
212to attach device-specific event
213counters, and
214.Fn evcnt_detach
215to detach all counters when being unloaded.
216.Pp
217Device drivers that wish to use the generic event counter
218framework should place event counter structures in their
219.Dq softc
220structures.
221For example, to keep track of the number of interrupts for a given
222device (broken down further into
223.Dq device readable
224and
225.Dq device writable
226interrupts) a device driver might use:
227.Bd -literal
228struct foo_softc {
229	[ . . . ]
230	struct evcnt sc_ev_intr;	/* interrupt count */
231	struct evcnt sc_ev_intr_rd;	/* 'readable' interrupt count */
232	struct evcnt sc_ev_intr_wr;	/* 'writable' interrupt count */
233	[ . . . ]
234};
235.Ed
236.Pp
237In the device attach function, those counters would be registered with
238the system using the
239.Fn evcnt_attach_dynamic
240function, using code like:
241.Bd -literal
242void
243fooattach(device_t parent, device_t self, void *aux)
244{
245	struct foo_softc *sc = device_private(self);
246
247	[ . . . ]
248
249	/* Initialize and attach event counters. */
250	evcnt_attach_dynamic(\*[Am]sc-\*[Gt]sc_ev, EVCNT_TYPE_INTR,
251	    NULL, device_xname(self), "intr");
252	evcnt_attach_dynamic(\*[Am]sc-\*[Gt]sc_ev_rd, EVCNT_TYPE_INTR,
253	    \*[Am]sc-\*[Gt]sc_ev, device_xname(self), "intr rd");
254	evcnt_attach_dynamic(\*[Am]sc-\*[Gt]sc_ev_wr, EVCNT_TYPE_INTR,
255	    \*[Am]sc-\*[Gt]sc_ev, device_xname(self), "intr wr");
256
257	[ . . . ]
258}
259.Ed
260.Pp
261If the device can be detached from the system, its detach
262function should invoke
263.Fn evcnt_detach
264on each attached counter (making sure to detach any
265.Dq parent
266counters only after detaching all children).
267.Pp
268Code like the following might be used to initialize a static
269event counter (in this example, one used to track CPU alignment traps):
270.Bd -literal
271	struct evcnt aligntrap_ev = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
272	    NULL, "cpu", "aligntrap")
273.Ed
274.Pp
275To attach this event counter, code like the following could be used:
276.Bd -literal
277	evcnt_attach_static(\*[Am]aligntrap_ev);
278.Ed
279.Sh CODE REFERENCES
280The event counter framework itself is implemented within the file
281.Pa sys/kern/subr_evcnt.c .
282Data structures and function prototypes for the framework are located in
283.Pa sys/sys/device.h .
284.Pp
285Event counters are used throughout the system.
286.Pp
287The
288.Xr vmstat 1
289source file
290.Pa usr.bin/vmstat/vmstat.c
291shows an example of how to access event counters from user programs.
292.Sh SEE ALSO
293.Xr vmstat 1
294.Sh HISTORY
295A set of interrupt counter interfaces with similar names to the interfaces
296in the
297.Nx
298generic event counter framework appeared as part
299of the new autoconfiguration system in
300.Bx 4.4 .
301Those interfaces were never widely adopted in
302.Nx
303because of limitations in their applicability.
304(Their use was limited to non-hierarchical, dynamically
305attached device interrupt counters.)
306The
307.Nx
308generic event counter framework first appeared in
309.Nx 1.5 .
310.Sh AUTHORS
311The
312.Nx
313generic event counter framework was designed and implemented by
314.An Chris Demetriou
315.Aq cgd@NetBSD.org .
316