xref: /freebsd/share/man/man9/counter.9 (revision c66ec88fed842fbaad62c30d510644ceb7bd2d71)
1.\"-
2.\" Copyright (c) 2013 Gleb Smirnoff <glebius@FreeBSD.org>
3.\" All rights reserved.
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright
9.\"    notice, this list of conditions and the following disclaimer.
10.\" 2. Redistributions in binary form must reproduce the above copyright
11.\"    notice, this list of conditions and the following disclaimer in the
12.\"    documentation and/or other materials provided with the distribution.
13.\"
14.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24.\" SUCH DAMAGE.
25.\"
26.\" $FreeBSD$
27.\"
28.Dd March 6, 2020
29.Dt COUNTER 9
30.Os
31.Sh NAME
32.Nm counter
33.Nd "SMP-friendly kernel counter implementation"
34.Sh SYNOPSIS
35.In sys/types.h
36.In sys/systm.h
37.In sys/counter.h
38.Ft counter_u64_t
39.Fn counter_u64_alloc "int wait"
40.Ft void
41.Fn counter_u64_free "counter_u64_t c"
42.Ft void
43.Fn counter_u64_add "counter_u64_t c" "int64_t v"
44.Ft void
45.Fn counter_enter
46.Ft void
47.Fn counter_exit
48.Ft void
49.Fn counter_u64_add_protected "counter_u64_t c" "int64_t v"
50.Ft uint64_t
51.Fn counter_u64_fetch "counter_u64_t c"
52.Ft void
53.Fn counter_u64_zero "counter_u64_t c"
54.Ft int64_t
55.Fn counter_ratecheck "struct counter_rate *cr" "int64_t limit"
56.Fn COUNTER_U64_SYSINIT "counter_u64_t c"
57.Fn COUNTER_U64_DEFINE_EARLY "counter_u64_t c"
58.In sys/sysctl.h
59.Fn SYSCTL_COUNTER_U64 parent nbr name access ptr descr
60.Fn SYSCTL_ADD_COUNTER_U64 ctx parent nbr name access ptr descr
61.Fn SYSCTL_COUNTER_U64_ARRAY parent nbr name access ptr len descr
62.Fn SYSCTL_ADD_COUNTER_U64_ARRAY ctx parent nbr name access ptr len descr
63.Sh DESCRIPTION
64.Nm
65is a generic facility to create counters
66that can be utilized for any purpose (such as collecting statistical
67data).
68A
69.Nm
70is guaranteed to be lossless when several kernel threads do simultaneous
71updates.
72However,
73.Nm
74does not block the calling thread,
75also no
76.Xr atomic 9
77operations are used for the update, therefore the counters
78can be used in any non-interrupt context.
79Moreover,
80.Nm
81has special optimisations for SMP environments, making
82.Nm
83update faster than simple arithmetic on the global variable.
84Thus
85.Nm
86is considered suitable for accounting in the performance-critical
87code paths.
88.Bl -tag -width indent
89.It Fn counter_u64_alloc wait
90Allocate a new 64-bit unsigned counter.
91The
92.Fa wait
93argument is the
94.Xr malloc 9
95wait flag, should be either
96.Va M_NOWAIT
97or
98.Va M_WAITOK .
99If
100.Va M_NOWAIT
101is specified the operation may fail.
102.It Fn counter_u64_free c
103Free the previously allocated counter
104.Fa c .
105.It Fn counter_u64_add c v
106Add
107.Fa v
108to
109.Fa c .
110The KPI does not guarantee any protection from wraparound.
111.It Fn counter_enter
112Enter mode that would allow the safe update of several counters via
113.Fn counter_u64_add_protected .
114On some machines this expands to
115.Xr critical 9
116section, while on other is a nop.
117See
118.Sx IMPLEMENTATION DETAILS .
119.It Fn counter_exit
120Exit mode for updating several counters.
121.It Fn counter_u64_add_protected c v
122Same as
123.Fn counter_u64_add ,
124but should be preceded by
125.Fn counter_enter .
126.It Fn counter_u64_fetch c
127Take a snapshot of counter
128.Fa c .
129The data obtained is not guaranteed to reflect the real cumulative
130value for any moment.
131.It Fn counter_u64_zero c
132Clear the counter
133.Fa c
134and set it to zero.
135.It Fn counter_ratecheck cr limit
136The function is a multiprocessor-friendly version of
137.Fn ppsratecheck
138which uses
139.Nm
140internally.
141Returns non-negative value if the rate is not yet reached during the current
142second, and a negative value otherwise.
143If the limit was reached on previous second, but was just reset back to zero,
144then
145.Fn counter_ratecheck
146returns number of events since previous reset.
147.It Fn COUNTER_U64_SYSINIT c
148Define a
149.Xr SYSINIT 9
150initializer for the global counter
151.Fa c .
152.It Fn COUNTER_U64_DEFINE_EARLY c
153Define and initialize a global counter
154.Fa c .
155It is always safe to increment
156.Fa c ,
157though updates prior to the
158.Dv SI_SUB_COUNTER
159.Xr SYSINIT 9
160event are lost.
161.It Fn SYSCTL_COUNTER_U64 parent nbr name access ptr descr
162Declare a static
163.Xr sysctl 9
164oid that would represent a
165.Nm .
166The
167.Fa ptr
168argument should be a pointer to allocated
169.Vt counter_u64_t .
170A read of the oid returns value obtained through
171.Fn counter_u64_fetch .
172Any write to the oid zeroes it.
173.It Fn SYSCTL_ADD_COUNTER_U64 ctx parent nbr name access ptr descr
174Create a
175.Xr sysctl 9
176oid that would represent a
177.Nm .
178The
179.Fa ptr
180argument should be a pointer to allocated
181.Vt counter_u64_t .
182A read of the oid returns value obtained through
183.Fn counter_u64_fetch .
184Any write to the oid zeroes it.
185.It Fn SYSCTL_COUNTER_U64_ARRAY parent nbr name access ptr len descr
186Declare a static
187.Xr sysctl 9
188oid that would represent an array of
189.Nm .
190The
191.Fa ptr
192argument should be a pointer to allocated array of
193.Vt counter_u64_t's .
194The
195.Fa len
196argument should specify number of elements in the array.
197A read of the oid returns len-sized array of
198.Vt uint64_t
199values  obtained through
200.Fn counter_u64_fetch .
201Any write to the oid zeroes all array elements.
202.It Fn SYSCTL_ADD_COUNTER_U64_ARRAY ctx parent nbr name access ptr len descr
203Create a
204.Xr sysctl 9
205oid that would represent an array of
206.Nm .
207The
208.Fa ptr
209argument should be a pointer to allocated array of
210.Vt counter_u64_t's .
211The
212.Fa len
213argument should specify number of elements in the array.
214A read of the oid returns len-sized array of
215.Vt uint64_t
216values obtained through
217.Fn counter_u64_fetch .
218Any write to the oid zeroes all array elements.
219.El
220.Sh IMPLEMENTATION DETAILS
221On all architectures
222.Nm
223is implemented using per-CPU data fields that are specially aligned
224in memory, to avoid inter-CPU bus traffic due to shared use
225of the variables between CPUs.
226These are allocated using
227.Va UMA_ZONE_PCPU
228.Xr uma 9
229zone.
230The update operation only touches the field that is private to current CPU.
231Fetch operation loops through all per-CPU fields and obtains a snapshot
232sum of all fields.
233.Pp
234On amd64 a
235.Nm counter
236update is implemented as a single instruction without lock semantics,
237operating on the private data for the current CPU,
238which is safe against preemption and interrupts.
239.Pp
240On i386 architecture, when machine supports the cmpxchg8 instruction,
241this instruction is used.
242The multi-instruction sequence provides the same guarantees as the
243amd64 single-instruction implementation.
244.Pp
245On some architectures updating a counter require a
246.Xr critical 9
247section.
248.Sh EXAMPLES
249The following example creates a static counter array exported to
250userspace through a sysctl:
251.Bd -literal -offset indent
252#define MY_SIZE 8
253static counter_u64_t array[MY_SIZE];
254SYSCTL_COUNTER_U64_ARRAY(_debug, OID_AUTO, counter_array, CTLFLAG_RW,
255    &array[0], MY_SIZE, "Test counter array");
256.Ed
257.Sh SEE ALSO
258.Xr atomic 9 ,
259.Xr critical 9 ,
260.Xr locking 9 ,
261.Xr malloc 9 ,
262.Xr ratecheck 9 ,
263.Xr sysctl 9 ,
264.Xr SYSINIT 9 ,
265.Xr uma 9
266.Sh HISTORY
267The
268.Nm
269facility first appeared in
270.Fx 10.0 .
271.Sh AUTHORS
272.An -nosplit
273The
274.Nm
275facility was written by
276.An Gleb Smirnoff
277and
278.An Konstantin Belousov .
279