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