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