xref: /netbsd-src/share/man/man9/evcnt.9 (revision 274254cdae52594c1aa480a736aef78313d15c9c)
1.\" $NetBSD: evcnt.9,v 1.17 2008/02/11 03:49:13 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 11, 2005
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" "int type" "const struct evcnt *parent" "const char *group" "const char *name"
48.Ft void
49.Fn evcnt_attach_static "struct evcnt *ev"
50.Ft void
51.Fn evcnt_detach "struct evcnt *ev"
52.Sh DESCRIPTION
53The
54.Nx
55generic event counter framework is designed to provide a flexible and
56hierarchical event counting facility, which is useful for tracking
57system events (including device interrupts).
58.Pp
59The fundamental component of this framework is the
60.Nm evcnt
61structure.
62Its user-accessible fields are:
63.Bd -literal
64struct evcnt {
65	uint64_t	ev_count;	/* how many have occurred */
66	TAILQ_ENTRY(evcnt) ev_list;	/* entry on list of all counters */
67	unsigned char	ev_type;	/* counter type; see below */
68	unsigned char	ev_grouplen;	/* 'group' len, excluding NUL */
69	unsigned char	ev_namelen;	/* 'name' len, excluding NUL */
70	const struct evcnt *ev_parent;	/* parent, for hierarchical ctrs */
71	const char	*ev_group;	/* name of group */
72	const char	*ev_name;	/* name of specific event */
73};
74.Ed
75.Pp
76The system maintains a global linked list of all active event counters.
77This list, called
78.Nm allevents ,
79may grow or shrink over time as event counters are dynamically
80added to and removed from the system.
81.Pp
82Each event counter is marked (in the
83.Fa ev_type
84field) with the type of event being counted.
85The following types are currently defined:
86.Bl -tag -offset indent -width EVCNT_TYPE_MISC -compact
87.It Ev EVCNT_TYPE_MISC
88Miscellaneous; doesn't fit into one of the other types.
89.It Ev EVCNT_TYPE_INTR
90Interrupt counter, reported by
91.Ic vmstat -i .
92.It Ev EVCNT_TYPE_TRAP
93Processor trap style events.
94.El
95.Pp
96Each event counter also has a group name
97.Pq Fa ev_group
98and
99an event name
100.Pq Fa ev_name
101which are used to identify the counter.
102The group name may be shared by a set of counters.
103For example, device interrupt counters would use the name of the
104device whose interrupts are being counted as the group name.
105The counter
106name is meant to distinguish the counter from others in its group
107(and need not be unique across groups).
108Both names should be understandable by users, since they are printed
109by commands like
110.Xr vmstat 1 .
111The constant
112.Dv EVCNT_STRING_MAX
113is defined to be the maximum group or event name length in
114bytes (including the trailing
115.Dv NUL ) .
116In the current implementation it is 256.
117.Pp
118To support hierarchical tracking of events, each event counter can
119name a
120.Dq parent
121event counter.
122For instance, interrupt dispatch code could have an event counter per
123interrupt line, and devices could each have counters for the number
124of interrupts that they were responsible for causing.
125In that case, the counter for a device on a given interrupt line
126would have the line's counter as its parent.
127The value
128.Dv NULL
129is used to indicate that a counter has no parent.
130A counter's parent must be attached before the counter is attached,
131and detached after the counter is detached.
132.Pp
133The
134.Fn EVCNT_INITIALIZER
135macro can be used to provide a static initializer for an event
136counter structure.
137It is invoked as
138.Fn EVCNT_INITIALIZER "type" "parent" "group" "name" ,
139and its arguments will be placed into the corresponding fields of
140the event counter structure it is initializing.
141The
142.Fa group
143and
144.Fa name
145arguments must be constant strings.
146.Pp
147The following is a brief description of each function in the framework:
148.Bl -tag -width indent
149.It Fn "void evcnt_attach_dynamic" "struct evcnt *ev" "int type" "const struct evcnt *parent" "const char *group" "const char *name"
150.Pp
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 "void evcnt_attach_static" "struct evcnt *ev"
165.Pp
166Attach the statically-initialized event counter structure
167pointed to by
168.Fa ev
169to the system event list.
170The event counter is assumed to be statically initialized using the
171.Fn EVCNT_INITIALIZER
172macro.
173This function simply calculates structure elements' values as appropriate
174(e.g., the string lengths), and adds the counter to the system event list.
175.It Fn "void evcnt_detach" "struct evcnt *ev"
176.Pp
177Detach the event counter structure pointed to by
178.Fa ev
179from the system event list.
180.El
181.Pp
182Note that no method is provided to increment the value of an
183event counter.
184Code incrementing an event counter should do so by directly accessing its
185.Fa ev_count
186field in a manner that is known to be safe.
187For instance, additions to a device's event counters in the interrupt
188handler for that device will often be safe without additional protection
189(because interrupt handler entries for a given device have to be
190serialized).
191However, for other uses of event counters, additional locking
192or use of machine-dependent atomic operation may be appropriate.
193(The overhead of using a mechanism that is guaranteed to
194be safe to increment every counter, regardless of actual need
195for such a mechanism where the counter is being incremented,
196would be too great.
197On some systems, it might involve a global lock and several function calls.)
198.Sh USING THE FRAMEWORK
199This section includes a description on basic use of the framework
200and example usage of its functions.
201.Pp
202Device drivers can use the
203.Fn evcnt_attach_dynamic
204and
205.Fn evcnt_detach
206functions to manage device-specific event counters.
207Statically configured system modules can use
208.Fn evcnt_attach_static
209to configure global event counters.
210Similarly, loadable modules can use
211.Fn evcnt_attach_static
212to configure their global event counters,
213.Fn evcnt_attach_dynamic
214to attach device-specific event
215counters, and
216.Fn evcnt_detach
217to detach all counters when being unloaded.
218.Pp
219Device drivers that wish to use the generic event counter
220framework should place event counter structures in their
221.Dq softc
222structures.
223For example, to keep track of the number of interrupts for a given
224device (broken down further into
225.Dq device readable
226and
227.Dq device writable
228interrupts) a device driver might use:
229.Bd -literal
230struct foo_softc {
231	struct device sc_dev;		/* generic device information */
232	[ . . . ]
233	struct evcnt sc_ev_intr;	/* interrupt count */
234	struct evcnt sc_ev_intr_rd;	/* 'readable' interrupt count */
235	struct evcnt sc_ev_intr_wr;	/* 'writable' interrupt count */
236	[ . . . ]
237};
238.Ed
239.Pp
240In the device attach function, those counters would be registered with
241the system using the
242.Fn evcnt_attach_dynamic
243function, using code like:
244.Bd -literal
245void
246fooattach(parent, self, aux)
247	struct device *parent, *self;
248	void *aux;
249{
250	struct foo_softc *sc = (struct foo_softc *)self;
251
252	[ . . . ]
253
254	/* Initialize and attach event counters. */
255	evcnt_attach_dynamic(\*[Am]sc-\*[Gt]sc_ev, EVCNT_TYPE_INTR,
256	    NULL, sc-\*[Gt]sc_dev.dv_xname, "intr");
257	evcnt_attach_dynamic(\*[Am]sc-\*[Gt]sc_ev_rd, EVCNT_TYPE_INTR,
258	    \*[Am]sc-\*[Gt]sc_ev, sc-\*[Gt]sc_dev.dv_xname, "intr rd");
259	evcnt_attach_dynamic(\*[Am]sc-\*[Gt]sc_ev_wr, EVCNT_TYPE_INTR,
260	    \*[Am]sc-\*[Gt]sc_ev, sc-\*[Gt]sc_dev.dv_xname, "intr wr");
261
262	[ . . . ]
263}
264.Ed
265.Pp
266If the device can be detached from the system, its detach
267function should invoke
268.Fn evcnt_detach
269on each attached counter (making sure to detach any
270.Dq parent
271counters only after detaching all children).
272.Pp
273Code like the following might be used to initialize a static
274event counter (in this example, one used to track CPU alignment traps):
275.Bd -literal
276	struct evcnt aligntrap_ev = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
277	    NULL, "cpu", "aligntrap")
278.Ed
279.Pp
280To attach this event counter, code like the following could be used:
281.Bd -literal
282	evcnt_attach_static(\*[Am]aligntrap_ev);
283.Ed
284.Sh CODE REFERENCES
285This section describes places within the
286.Nx
287source tree where actual
288code implementing or using the event counter framework can be found.
289All pathnames are relative to
290.Pa /usr/src .
291.Pp
292The event counter framework itself is implemented within the file
293.Pa sys/kern/subr_evcnt.c .
294Data structures and function prototypes for the framework are located in
295.Pa sys/sys/device.h .
296.Pp
297Event counters are used throughout the system.
298.Pp
299The
300.Xr vmstat 1
301source file
302.Pa usr.bin/vmstat/vmstat.c
303shows an example of how to access event counters from user programs.
304.Sh SEE ALSO
305.Xr vmstat 1
306.Sh HISTORY
307A set of interrupt counter interfaces with similar names to the interfaces
308in the
309.Nx
310generic event counter framework appeared as part
311of the new autoconfiguration system in
312.Bx 4.4 .
313Those interfaces were never widely adopted in
314.Nx
315because of limitations in their applicability.
316(Their use was limited to non-hierarchical, dynamically
317attached device interrupt counters.)
318The
319.Nx
320generic event counter framework first appeared in
321.Nx 1.5 .
322.Sh AUTHORS
323The
324.Nx
325generic event counter framework was designed and implemented by
326.An Chris Demetriou
327.Aq cgd@NetBSD.org .
328