xref: /openbsd-src/share/man/man9/evcount.9 (revision 886cb58392333f0eebacef99b0a957436fadda8d)
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