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