1 .\" $NetBSD: evcnt.9,v 1.16 2007/12/20 03:21:47 uebayasi Exp $
3 .\" Copyright (c) 2000 Christopher G. Demetriou
4 .\" All rights reserved.
6 .\" Redistribution and use in source and binary forms, with or without
7 .\" modification, are permitted provided that the following conditions
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.
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.
33 .\" --(license Id: LICENSE.proto,v 1.1 2000/06/13 21:40:26 cgd Exp )--
40 .Nm evcnt_attach_dynamic ,
41 .Nm evcnt_attach_static ,
43 .Nd generic event counter framework
47 .Fn evcnt_attach_dynamic "struct evcnt *ev" "int type" "const struct evcnt *parent" "const char *group" "const char *name"
49 .Fn evcnt_attach_static "struct evcnt *ev"
51 .Fn evcnt_detach "struct evcnt *ev"
55 generic event counter framework is designed to provide a flexible and
56 hierarchical event counting facility, which is useful for tracking
57 system events (including device interrupts).
59 The fundamental component of this framework is the
62 Its user-accessible fields are:
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 */
76 The system maintains a global linked list of all active event counters.
79 may grow or shrink over time as event counters are dynamically
80 added to and removed from the system.
82 Each event counter is marked (in the
84 field) with the type of event being counted.
85 The following types are currently defined:
86 .Bl -tag -offset indent -width EVCNT_TYPE_MISC -compact
87 .It Ev EVCNT_TYPE_MISC
88 Miscellaneous; doesn't fit into one of the other types.
89 .It Ev EVCNT_TYPE_INTR
90 Interrupt counter, reported by
92 .It Ev EVCNT_TYPE_TRAP
93 Processor trap style events.
96 Each event counter also has a group name
101 which are used to identify the counter.
102 The group name may be shared by a set of counters.
103 For example, device interrupt counters would use the name of the
104 device whose interrupts are being counted as the group name.
106 name is meant to distinguish the counter from others in its group
107 (and need not be unique across groups).
108 Both names should be understandable by users, since they are printed
113 is defined to be the maximum group or event name length in
114 bytes (including the trailing
116 In the current implementation it is 256.
118 To support hierarchical tracking of events, each event counter can
122 For instance, interrupt dispatch code could have an event counter per
123 interrupt line, and devices could each have counters for the number
124 of interrupts that they were responsible for causing.
125 In that case, the counter for a device on a given interrupt line
126 would have the line's counter as its parent.
129 is used to indicate that a counter has no parent.
130 A counter's parent must be attached before the counter is attached,
131 and detached after the counter is detached.
134 .Fn EVCNT_INITIALIZER
135 macro can be used to provide a static initializer for an event
138 .Fn EVCNT_INITIALIZER "type" "parent" "group" "name" ,
139 and its arguments will be placed into the corresponding fields of
140 the event counter structure it is initializing.
145 arguments must be constant strings.
147 The 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"
151 Attach the event counter structure pointed to by
153 to the system event list.
154 The event counter is cleared and its fields initialized using the
155 arguments to the function call.
156 The contents of the remaining elements in the structure (e.g., the
157 name lengths) are calculated, and the counter is added to the
160 The strings specified as the group and
161 counter names must persist (with the same value)
162 throughout the life of the event counter; they are referenced by,
163 not copied into, the counter.
164 .It Fn "void evcnt_attach_static" "struct evcnt *ev"
166 Attach the statically-initialized event counter structure
169 to the system event list.
170 The event counter is assumed to be statically initialized using the
171 .Fn EVCNT_INITIALIZER
173 This 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"
177 Detach the event counter structure pointed to by
179 from the system event list.
182 Note that no method is provided to increment the value of an
184 Code incrementing an event counter should do so by directly accessing its
186 field in a manner that is known to be safe.
187 For instance, additions to a device's event counters in the interrupt
188 handler for that device will often be safe without additional protection
189 (because interrupt handler entries for a given device have to be
191 However, for other uses of event counters, additional locking
192 or use of machine-dependent atomic operation may be appropriate.
193 (The overhead of using a mechanism that is guaranteed to
194 be safe to increment every counter, regardless of actual need
195 for such a mechanism where the counter is being incremented,
197 On some systems, it might involve a global lock and several function calls.)
198 .Sh USING THE FRAMEWORK
199 This section includes a description on basic use of the framework
200 and example usage of its functions.
202 Device drivers can use the
203 .Fn evcnt_attach_dynamic
206 functions to manage device-specific event counters.
207 Statically configured system modules can use
208 .Fn evcnt_attach_static
209 to configure global event counters.
210 Similarly, loadable modules can use
211 .Fn evcnt_attach_static
212 to configure their global event counters,
213 .Fn evcnt_attach_dynamic
214 to attach device-specific event
217 to detach all counters when being unloaded.
219 Device drivers that wish to use the generic event counter
220 framework should place event counter structures in their
223 For example, to keep track of the number of interrupts for a given
224 device (broken down further into
228 interrupts) a device driver might use:
231 struct device sc_dev; /* generic device information */
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 */
240 In the device attach function, those counters would be registered with
242 .Fn evcnt_attach_dynamic
243 function, using code like:
246 fooattach(parent, self, aux)
247 struct device *parent, *self;
250 struct foo_softc *sc = (struct foo_softc *)self;
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");
266 If the device can be detached from the system, its detach
267 function should invoke
269 on each attached counter (making sure to detach any
271 counters only after detaching all children).
273 Code like the following might be used to initialize a static
274 event counter (in this example, one used to track CPU alignment traps):
276 struct evcnt aligntrap_ev = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
277 NULL, "cpu", "aligntrap")
280 To attach this event counter, code like the following could be used:
282 evcnt_attach_static(\*[Am]aligntrap_ev);
285 This section describes places within the
287 source tree where actual
288 code implementing or using the event counter framework can be found.
289 All pathnames are relative to
292 The event counter framework itself is implemented within the file
293 .Pa sys/kern/subr_evcnt.c .
294 Data structures and function prototypes for the framework are located in
295 .Pa sys/sys/device.h .
297 Event counters are used throughout the system.
302 .Pa usr.bin/vmstat/vmstat.c
303 shows an example of how to access event counters from user programs.
307 A set of interrupt counter interfaces with similar names to the interfaces
310 generic event counter framework appeared as part
311 of the new autoconfiguration system in
313 Those interfaces were never widely adopted in
315 because of limitations in their applicability.
316 (Their use was limited to non-hierarchical, dynamically
317 attached device interrupt counters.)
320 generic event counter framework first appeared in
325 generic event counter framework was designed and implemented by