1.\" $OpenBSD: evcount.9,v 1.8 2022/11/10 07:05:41 jmatthew Exp $ 2.\" Written by Jared Yanovich 3.\" This file belongs to the public domain, 11/02/2004. 4.Dd $Mdocdate: November 10 2022 $ 5.Dt EVCOUNT 9 6.Os 7.Sh NAME 8.Nm evcount , 9.Nm evcount_attach , 10.Nm evcount_detach , 11.Nm evcount_percpu , 12.Nm evcount_inc 13.Nd generic interrupt and event counter kernel API 14.Sh SYNOPSIS 15.In sys/evcount.h 16.Ft void 17.Fn evcount_attach "struct evcount *ec" "const char *name" "void *data" 18.Ft void 19.Fn evcount_percpu "struct evcount *ec" 20.Ft void 21.Fn evcount_inc "struct evcount *ec" 22.Ft void 23.Fn evcount_detach "struct evcount *ec" 24.Sh DESCRIPTION 25The 26.Nm 27API provides an interface for generic event and interrupt counting, 28whose statistics are made available to machine-independent 29.Xr sysctl 2 30nodes. 31.Ss Overview 32With 33.Nm , 34an architecture can collect interrupt counting for any device. 35All registered counters will be made available under the 36.Va kern.evcount 37.Xr sysctl 2 38node as a flat list. 39The following is a sample list of counters provided by some 40common architectures: 41.Pp 42.Bl -tag -width 8n -offset indent -compact 43.It clock 44Interrupt counter for the system clock 45.It stat 46Second-level interrupt decrementer counter 47.It rtc 48Real-time clock counter 49.It prof 50System profiler counter 51.It pciide0 52PCI IDE controller counter (see 53.Xr pciide 4 ) 54.It uhci0 55USB 1.0 controller counter (see 56.Xr usb 4 ) 57.El 58.Pp 59See 60.Xr intro 4 61for a list of devices for any of which 62.Nm 63may track interrupt counting. 64.Pp 65The 66.Xr systat 1 67and 68.Xr vmstat 8 69utilities can be used to view interrupts collected by 70.Nm . 71.Ss The API 72The 73.Vt evcount 74structure has the following definition: 75.Bd -literal -offset indent 76struct evcount { 77 u_int64_t ec_count; /* main counter */ 78 int ec_id; /* counter ID */ 79 const char *ec_name; /* counter name */ 80 void *ec_data; /* user data */ 81 struct cpumem *ec_cpumem; /* per-cpu counter */ 82 83 TAILQ_ENTRY(evcount) next; 84}; 85.Ed 86.Pp 87The 88.Fn evcount_attach ec name data 89function adds the given event counter to the system's counter list. 90.Fa name 91provides the counter name, which is modeled after a 92device, such as 93.Dq clock 94or 95.Dq pciide0 . 96.Fa data 97provides a chunk of data that will be made available through the 98.Xr sysctl 2 99call. 100.Pp 101The 102.Fn evcount_percpu ec 103function configures 104.Fa ec 105with one counter for each CPU in the system. 106It should be used when 107.Fa ec Ns 's 108corresponding interrupt can occur simultaneously on multiple CPUs. 109It must be called immediately after 110.Fn evcount_attach 111is called for a given counter. 112.Pp 113The 114.Fn evcount_inc ec 115function increments the given counter. 116.Pp 117The 118.Fn evcount_detach ec 119function removes the given event counter 120.Fa ec 121from the counter list. 122.Sh EXAMPLES 123The following is an outline of code that provides routines to register 124and de-register interrupt handlers for devices, plugging the counting of 125interrupts generated by them during system operation into the 126.Nm 127framework. 128.Bd -literal 129#include <sys/evcount.h> 130#include <machine/intr.h> 131 132/* 133 * machine/intr.h provides a structure, intrhand, which is 134 * machine-dependent but is usually similar to this: 135 * 136 * struct intrhand { 137 * int (*ih_fun)(void *); 138 * void *ih_arg; 139 * int ih_level; 140 * struct intrhand *ih_next; 141 * int ih_irq; 142 * struct evcount ih_count; 143 * } 144 */ 145 146/* 147 * Register an interrupt handler. 148 */ 149void * 150intr_establish(void *lcv, int irq, int type, int level, 151 int (*ih_fun)(void *), void *ih_arg, char *name) 152{ 153 struct intrhand *ih, **p; 154 155 /* 156 * Allocate memory for the handler, sanity-check incoming 157 * values (IRQ#, etc.), and link the handler into 158 * machine-dependent data structures. 159 */ 160 161 /* 162 * Fill out the handler. 163 */ 164 ih->ih_fun = ih_fun; 165 ih->ih_arg = ih_arg; 166 ih->ih_next = NULL; 167 ih->ih_level = level; 168 ih->ih_irq = irq; 169 170 /* 171 * Attach it. 172 */ 173 evcount_attach(&ih->ih_count, name, &ih->ih_irq); 174 175 return (ih); 176} 177 178/* 179 * Deregister an interrupt handler. 180 */ 181void 182intr_disestablish(void *lcp, void *arg) 183{ 184 struct intrhand *ih = arg; 185 186 /* 187 * Sanity-check incoming values (IRQ, etc.) and remove 188 * the interrupt handler from machine-dependent data 189 * structures. 190 */ 191 192 evcount_detach(&ih->ih_count); 193 194 /* 195 * Free up memory and install a null interrupt handler. 196 */ 197} 198.Ed 199.Pp 200An interrupt handler for a device will be registered during 201.Xr autoconf 9 202with a call to the above 203.Fn intr_establish . 204.Pp 205The main external interrupt handler, which handles all system 206interrupts, will select the appropriate handler for the device 207that created the interrupt when an interrupt is generated. 208In this case, the handler is the routine assigned to 209.Va ih_fun , 210and 211.Nm 212will be made aware of interrupt occurrence. 213.Sh SEE ALSO 214.Xr systat 1 , 215.Xr sysctl 2 , 216.Xr queue 3 , 217.Xr intro 4 , 218.Xr vmstat 8 , 219.Xr autoconf 9 , 220.Xr counters_alloc 9 221.Sh AUTHORS 222.An -nosplit 223The 224.Nm 225API was written by 226.An Artur Grabowski 227and 228.An Aaron Campbell 229for 230.Ox 3.6 . 231