xref: /freebsd/share/man/man9/counter.9 (revision 1cd5c35d136e2c8605b9ba23e6a5879539411947)
14e76af6aSGleb Smirnoff.\"-
24e76af6aSGleb Smirnoff.\" Copyright (c) 2013 Gleb Smirnoff <glebius@FreeBSD.org>
34e76af6aSGleb Smirnoff.\" All rights reserved.
44e76af6aSGleb Smirnoff.\"
54e76af6aSGleb Smirnoff.\" Redistribution and use in source and binary forms, with or without
64e76af6aSGleb Smirnoff.\" modification, are permitted provided that the following conditions
74e76af6aSGleb Smirnoff.\" are met:
84e76af6aSGleb Smirnoff.\" 1. Redistributions of source code must retain the above copyright
94e76af6aSGleb Smirnoff.\"    notice, this list of conditions and the following disclaimer.
104e76af6aSGleb Smirnoff.\" 2. Redistributions in binary form must reproduce the above copyright
114e76af6aSGleb Smirnoff.\"    notice, this list of conditions and the following disclaimer in the
124e76af6aSGleb Smirnoff.\"    documentation and/or other materials provided with the distribution.
134e76af6aSGleb Smirnoff.\"
144e76af6aSGleb Smirnoff.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
154e76af6aSGleb Smirnoff.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
164e76af6aSGleb Smirnoff.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
174e76af6aSGleb Smirnoff.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
184e76af6aSGleb Smirnoff.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
194e76af6aSGleb Smirnoff.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
204e76af6aSGleb Smirnoff.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
214e76af6aSGleb Smirnoff.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
224e76af6aSGleb Smirnoff.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
234e76af6aSGleb Smirnoff.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
244e76af6aSGleb Smirnoff.\" SUCH DAMAGE.
254e76af6aSGleb Smirnoff.\"
26*1cd5c35dSKristof Provost.Dd June 19, 2025
274e76af6aSGleb Smirnoff.Dt COUNTER 9
284e76af6aSGleb Smirnoff.Os
294e76af6aSGleb Smirnoff.Sh NAME
304e76af6aSGleb Smirnoff.Nm counter
314e76af6aSGleb Smirnoff.Nd "SMP-friendly kernel counter implementation"
324e76af6aSGleb Smirnoff.Sh SYNOPSIS
334e76af6aSGleb Smirnoff.In sys/types.h
342d875db3SGleb Smirnoff.In sys/systm.h
354e76af6aSGleb Smirnoff.In sys/counter.h
364e76af6aSGleb Smirnoff.Ft counter_u64_t
374e76af6aSGleb Smirnoff.Fn counter_u64_alloc "int wait"
384e76af6aSGleb Smirnoff.Ft void
394e76af6aSGleb Smirnoff.Fn counter_u64_free "counter_u64_t c"
404e76af6aSGleb Smirnoff.Ft void
414e76af6aSGleb Smirnoff.Fn counter_u64_add "counter_u64_t c" "int64_t v"
424e76af6aSGleb Smirnoff.Ft void
434e76af6aSGleb Smirnoff.Fn counter_enter
444e76af6aSGleb Smirnoff.Ft void
454e76af6aSGleb Smirnoff.Fn counter_exit
464e76af6aSGleb Smirnoff.Ft void
474e76af6aSGleb Smirnoff.Fn counter_u64_add_protected "counter_u64_t c" "int64_t v"
484e76af6aSGleb Smirnoff.Ft uint64_t
494e76af6aSGleb Smirnoff.Fn counter_u64_fetch "counter_u64_t c"
504e76af6aSGleb Smirnoff.Ft void
514e76af6aSGleb Smirnoff.Fn counter_u64_zero "counter_u64_t c"
52*1cd5c35dSKristof Provost.Ft struct counter_rate *
53*1cd5c35dSKristof Provost.Fn counter_rate_alloc "int flags" "int period"
5416917020SGleb Smirnoff.Ft int64_t
5516917020SGleb Smirnoff.Fn counter_ratecheck "struct counter_rate *cr" "int64_t limit"
56*1cd5c35dSKristof Provost.Ft uint64_t
57*1cd5c35dSKristof Provost.Fn counter_rate_get "struct counter_rate *cr"
58*1cd5c35dSKristof Provost.Ft void
59*1cd5c35dSKristof Provost.Fn counter_rate_free "struct counter_rate *cr"
60fffcb56fSMark Johnston.Fn COUNTER_U64_SYSINIT "counter_u64_t c"
61fffcb56fSMark Johnston.Fn COUNTER_U64_DEFINE_EARLY "counter_u64_t c"
624e76af6aSGleb Smirnoff.In sys/sysctl.h
63369f5bceSGleb Smirnoff.Fn SYSCTL_COUNTER_U64 parent nbr name access ptr descr
644e76af6aSGleb Smirnoff.Fn SYSCTL_ADD_COUNTER_U64 ctx parent nbr name access ptr descr
65b5b7b142SGleb Smirnoff.Fn SYSCTL_COUNTER_U64_ARRAY parent nbr name access ptr len descr
66b5b7b142SGleb Smirnoff.Fn SYSCTL_ADD_COUNTER_U64_ARRAY ctx parent nbr name access ptr len descr
674e76af6aSGleb Smirnoff.Sh DESCRIPTION
684e76af6aSGleb Smirnoff.Nm
694e76af6aSGleb Smirnoffis a generic facility to create counters
704e76af6aSGleb Smirnoffthat can be utilized for any purpose (such as collecting statistical
714e76af6aSGleb Smirnoffdata).
724e76af6aSGleb SmirnoffA
734e76af6aSGleb Smirnoff.Nm
744e76af6aSGleb Smirnoffis guaranteed to be lossless when several kernel threads do simultaneous
754e76af6aSGleb Smirnoffupdates.
764e76af6aSGleb SmirnoffHowever,
774e76af6aSGleb Smirnoff.Nm
784e76af6aSGleb Smirnoffdoes not block the calling thread,
794e76af6aSGleb Smirnoffalso no
804e76af6aSGleb Smirnoff.Xr atomic 9
814e76af6aSGleb Smirnoffoperations are used for the update, therefore the counters
824e76af6aSGleb Smirnoffcan be used in any non-interrupt context.
834e76af6aSGleb SmirnoffMoreover,
844e76af6aSGleb Smirnoff.Nm
854e76af6aSGleb Smirnoffhas special optimisations for SMP environments, making
864e76af6aSGleb Smirnoff.Nm
874e76af6aSGleb Smirnoffupdate faster than simple arithmetic on the global variable.
884e76af6aSGleb SmirnoffThus
894e76af6aSGleb Smirnoff.Nm
904e76af6aSGleb Smirnoffis considered suitable for accounting in the performance-critical
917c64ddd5SWarren Blockcode paths.
924e76af6aSGleb Smirnoff.Bl -tag -width indent
93fa8175e4SBrad Davis.It Fn counter_u64_alloc wait
944e76af6aSGleb SmirnoffAllocate a new 64-bit unsigned counter.
954e76af6aSGleb SmirnoffThe
964e76af6aSGleb Smirnoff.Fa wait
974e76af6aSGleb Smirnoffargument is the
984e76af6aSGleb Smirnoff.Xr malloc 9
994e76af6aSGleb Smirnoffwait flag, should be either
1004e76af6aSGleb Smirnoff.Va M_NOWAIT
1014e76af6aSGleb Smirnoffor
1024e76af6aSGleb Smirnoff.Va M_WAITOK .
1034e76af6aSGleb SmirnoffIf
104c676e669SAlan Somers.Va M_NOWAIT
10551dc8e7fSKristof Provostis specified the operation may fail and return
10651dc8e7fSKristof Provost.Dv NULL .
1074e76af6aSGleb Smirnoff.It Fn counter_u64_free c
1084e76af6aSGleb SmirnoffFree the previously allocated counter
1094e76af6aSGleb Smirnoff.Fa c .
11051dc8e7fSKristof ProvostIt is safe to pass
11151dc8e7fSKristof Provost.Dv NULL .
1124e76af6aSGleb Smirnoff.It Fn counter_u64_add c v
1134e76af6aSGleb SmirnoffAdd
1144e76af6aSGleb Smirnoff.Fa v
1154e76af6aSGleb Smirnoffto
1164e76af6aSGleb Smirnoff.Fa c .
1174e76af6aSGleb SmirnoffThe KPI does not guarantee any protection from wraparound.
1184e76af6aSGleb Smirnoff.It Fn counter_enter
119640ca09dSEnji CooperEnter mode that would allow the safe update of several counters via
1204e76af6aSGleb Smirnoff.Fn counter_u64_add_protected .
1214e76af6aSGleb SmirnoffOn some machines this expands to
1224e76af6aSGleb Smirnoff.Xr critical 9
1234e76af6aSGleb Smirnoffsection, while on other is a nop.
1244e76af6aSGleb SmirnoffSee
1254e76af6aSGleb Smirnoff.Sx IMPLEMENTATION DETAILS .
1264e76af6aSGleb Smirnoff.It Fn counter_exit
1274e76af6aSGleb SmirnoffExit mode for updating several counters.
1284e76af6aSGleb Smirnoff.It Fn counter_u64_add_protected c v
1294e76af6aSGleb SmirnoffSame as
1304e76af6aSGleb Smirnoff.Fn counter_u64_add ,
1314e76af6aSGleb Smirnoffbut should be preceded by
1324e76af6aSGleb Smirnoff.Fn counter_enter .
1334e76af6aSGleb Smirnoff.It Fn counter_u64_fetch c
1344e76af6aSGleb SmirnoffTake a snapshot of counter
1354e76af6aSGleb Smirnoff.Fa c .
1364e76af6aSGleb SmirnoffThe data obtained is not guaranteed to reflect the real cumulative
1374e76af6aSGleb Smirnoffvalue for any moment.
1384e76af6aSGleb Smirnoff.It Fn counter_u64_zero c
1394e76af6aSGleb SmirnoffClear the counter
1404e76af6aSGleb Smirnoff.Fa c
1414e76af6aSGleb Smirnoffand set it to zero.
142*1cd5c35dSKristof Provost.It Fn counter_rate_alloc flags period
143*1cd5c35dSKristof ProvostAllocate a new struct counter_rate.
144*1cd5c35dSKristof Provost.Fa flags
145*1cd5c35dSKristof Provostis passed to
146*1cd5c35dSKristof Provost.Xr malloc 9 .
147*1cd5c35dSKristof Provost.Fa period
148*1cd5c35dSKristof Provostis the time over which the rate is checked.
14916917020SGleb Smirnoff.It Fn counter_ratecheck cr limit
15016917020SGleb SmirnoffThe function is a multiprocessor-friendly version of
15199d528d4SDag-Erling Smørgrav.Fn ppsratecheck
15216917020SGleb Smirnoffwhich uses
15316917020SGleb Smirnoff.Nm
15416917020SGleb Smirnoffinternally.
155640ca09dSEnji CooperReturns non-negative value if the rate is not yet reached during the current
156*1cd5c35dSKristof Provostperiod, and a negative value otherwise.
157*1cd5c35dSKristof ProvostIf the limit was reached during the previous period, but was just reset back
158*1cd5c35dSKristof Provostto zero, then
15916917020SGleb Smirnoff.Fn counter_ratecheck
16016917020SGleb Smirnoffreturns number of events since previous reset.
161*1cd5c35dSKristof Provost.It Fn counter_rate_get cr
162*1cd5c35dSKristof ProvostThe number of hits to this check within the current period.
163*1cd5c35dSKristof Provost.It Fn counter_rate_free cr
164*1cd5c35dSKristof ProvostFree the
165*1cd5c35dSKristof Provost.Fa cr
166*1cd5c35dSKristof Provostcounter.
167fffcb56fSMark Johnston.It Fn COUNTER_U64_SYSINIT c
168fffcb56fSMark JohnstonDefine a
169fffcb56fSMark Johnston.Xr SYSINIT 9
170fffcb56fSMark Johnstoninitializer for the global counter
171fffcb56fSMark Johnston.Fa c .
172fffcb56fSMark Johnston.It Fn COUNTER_U64_DEFINE_EARLY c
173fffcb56fSMark JohnstonDefine and initialize a global counter
174fffcb56fSMark Johnston.Fa c .
175fffcb56fSMark JohnstonIt is always safe to increment
176fffcb56fSMark Johnston.Fa c ,
177fffcb56fSMark Johnstonthough updates prior to the
178fffcb56fSMark Johnston.Dv SI_SUB_COUNTER
179fffcb56fSMark Johnston.Xr SYSINIT 9
180fffcb56fSMark Johnstonevent are lost.
181369f5bceSGleb Smirnoff.It Fn SYSCTL_COUNTER_U64 parent nbr name access ptr descr
1824e76af6aSGleb SmirnoffDeclare a static
183640ca09dSEnji Cooper.Xr sysctl 9
1844e76af6aSGleb Smirnoffoid that would represent a
1854e76af6aSGleb Smirnoff.Nm .
1864e76af6aSGleb SmirnoffThe
1874e76af6aSGleb Smirnoff.Fa ptr
1884e76af6aSGleb Smirnoffargument should be a pointer to allocated
1894e76af6aSGleb Smirnoff.Vt counter_u64_t .
1904e76af6aSGleb SmirnoffA read of the oid returns value obtained through
1914e76af6aSGleb Smirnoff.Fn counter_u64_fetch .
1924e76af6aSGleb SmirnoffAny write to the oid zeroes it.
1934e76af6aSGleb Smirnoff.It Fn SYSCTL_ADD_COUNTER_U64 ctx parent nbr name access ptr descr
1944e76af6aSGleb SmirnoffCreate a
195640ca09dSEnji Cooper.Xr sysctl 9
1964e76af6aSGleb Smirnoffoid that would represent a
1974e76af6aSGleb Smirnoff.Nm .
1984e76af6aSGleb SmirnoffThe
1994e76af6aSGleb Smirnoff.Fa ptr
2004e76af6aSGleb Smirnoffargument should be a pointer to allocated
2014e76af6aSGleb Smirnoff.Vt counter_u64_t .
2024e76af6aSGleb SmirnoffA read of the oid returns value obtained through
2034e76af6aSGleb Smirnoff.Fn counter_u64_fetch .
2044e76af6aSGleb SmirnoffAny write to the oid zeroes it.
205b5b7b142SGleb Smirnoff.It Fn SYSCTL_COUNTER_U64_ARRAY parent nbr name access ptr len descr
206b5b7b142SGleb SmirnoffDeclare a static
207640ca09dSEnji Cooper.Xr sysctl 9
208b5b7b142SGleb Smirnoffoid that would represent an array of
209b5b7b142SGleb Smirnoff.Nm .
210b5b7b142SGleb SmirnoffThe
211b5b7b142SGleb Smirnoff.Fa ptr
212b5b7b142SGleb Smirnoffargument should be a pointer to allocated array of
213b5b7b142SGleb Smirnoff.Vt counter_u64_t's .
214b5b7b142SGleb SmirnoffThe
215b5b7b142SGleb Smirnoff.Fa len
216b5b7b142SGleb Smirnoffargument should specify number of elements in the array.
217b5b7b142SGleb SmirnoffA read of the oid returns len-sized array of
218b5b7b142SGleb Smirnoff.Vt uint64_t
219b5b7b142SGleb Smirnoffvalues  obtained through
220b5b7b142SGleb Smirnoff.Fn counter_u64_fetch .
221b5b7b142SGleb SmirnoffAny write to the oid zeroes all array elements.
222b5b7b142SGleb Smirnoff.It Fn SYSCTL_ADD_COUNTER_U64_ARRAY ctx parent nbr name access ptr len descr
223b5b7b142SGleb SmirnoffCreate a
224640ca09dSEnji Cooper.Xr sysctl 9
225b5b7b142SGleb Smirnoffoid that would represent an array of
226b5b7b142SGleb Smirnoff.Nm .
227b5b7b142SGleb SmirnoffThe
228b5b7b142SGleb Smirnoff.Fa ptr
229b5b7b142SGleb Smirnoffargument should be a pointer to allocated array of
230b5b7b142SGleb Smirnoff.Vt counter_u64_t's .
231b5b7b142SGleb SmirnoffThe
232b5b7b142SGleb Smirnoff.Fa len
233b5b7b142SGleb Smirnoffargument should specify number of elements in the array.
234b5b7b142SGleb SmirnoffA read of the oid returns len-sized array of
235b5b7b142SGleb Smirnoff.Vt uint64_t
236b5b7b142SGleb Smirnoffvalues obtained through
237b5b7b142SGleb Smirnoff.Fn counter_u64_fetch .
238b5b7b142SGleb SmirnoffAny write to the oid zeroes all array elements.
2394e76af6aSGleb Smirnoff.El
2404e76af6aSGleb Smirnoff.Sh IMPLEMENTATION DETAILS
2414e76af6aSGleb SmirnoffOn all architectures
2424e76af6aSGleb Smirnoff.Nm
2434e76af6aSGleb Smirnoffis implemented using per-CPU data fields that are specially aligned
2444e76af6aSGleb Smirnoffin memory, to avoid inter-CPU bus traffic due to shared use
2454e76af6aSGleb Smirnoffof the variables between CPUs.
2464e76af6aSGleb SmirnoffThese are allocated using
2474e76af6aSGleb Smirnoff.Va UMA_ZONE_PCPU
2484e76af6aSGleb Smirnoff.Xr uma 9
2494e76af6aSGleb Smirnoffzone.
2504e76af6aSGleb SmirnoffThe update operation only touches the field that is private to current CPU.
2514e76af6aSGleb SmirnoffFetch operation loops through all per-CPU fields and obtains a snapshot
2524e76af6aSGleb Smirnoffsum of all fields.
2534e76af6aSGleb Smirnoff.Pp
2544e76af6aSGleb SmirnoffOn amd64 a
2554e76af6aSGleb Smirnoff.Nm counter
2564e76af6aSGleb Smirnoffupdate is implemented as a single instruction without lock semantics,
2574e76af6aSGleb Smirnoffoperating on the private data for the current CPU,
2584e76af6aSGleb Smirnoffwhich is safe against preemption and interrupts.
2594e76af6aSGleb Smirnoff.Pp
2604e76af6aSGleb SmirnoffOn i386 architecture, when machine supports the cmpxchg8 instruction,
2614e76af6aSGleb Smirnoffthis instruction is used.
2624e76af6aSGleb SmirnoffThe multi-instruction sequence provides the same guarantees as the
2634e76af6aSGleb Smirnoffamd64 single-instruction implementation.
2644e76af6aSGleb Smirnoff.Pp
2654e76af6aSGleb SmirnoffOn some architectures updating a counter require a
2664e76af6aSGleb Smirnoff.Xr critical 9
2674e76af6aSGleb Smirnoffsection.
268a435d46fSHans Petter Selasky.Sh EXAMPLES
269a435d46fSHans Petter SelaskyThe following example creates a static counter array exported to
270a435d46fSHans Petter Selaskyuserspace through a sysctl:
271a435d46fSHans Petter Selasky.Bd -literal -offset indent
272a435d46fSHans Petter Selasky#define MY_SIZE 8
273a435d46fSHans Petter Selaskystatic counter_u64_t array[MY_SIZE];
274a435d46fSHans Petter SelaskySYSCTL_COUNTER_U64_ARRAY(_debug, OID_AUTO, counter_array, CTLFLAG_RW,
275a435d46fSHans Petter Selasky    &array[0], MY_SIZE, "Test counter array");
276a435d46fSHans Petter Selasky.Ed
2774e76af6aSGleb Smirnoff.Sh SEE ALSO
2784e76af6aSGleb Smirnoff.Xr atomic 9 ,
2794e76af6aSGleb Smirnoff.Xr critical 9 ,
2804e76af6aSGleb Smirnoff.Xr locking 9 ,
2814e76af6aSGleb Smirnoff.Xr malloc 9 ,
28299d528d4SDag-Erling Smørgrav.Xr ratecheck 9 ,
2834e76af6aSGleb Smirnoff.Xr sysctl 9 ,
284fffcb56fSMark Johnston.Xr SYSINIT 9 ,
2854e76af6aSGleb Smirnoff.Xr uma 9
2864e76af6aSGleb Smirnoff.Sh HISTORY
2874e76af6aSGleb SmirnoffThe
2884e76af6aSGleb Smirnoff.Nm
2894e76af6aSGleb Smirnofffacility first appeared in
2904e76af6aSGleb Smirnoff.Fx 10.0 .
2914e76af6aSGleb Smirnoff.Sh AUTHORS
2924e76af6aSGleb Smirnoff.An -nosplit
2934e76af6aSGleb SmirnoffThe
2944e76af6aSGleb Smirnoff.Nm
2954e76af6aSGleb Smirnofffacility was written by
2964e76af6aSGleb Smirnoff.An Gleb Smirnoff
2974e76af6aSGleb Smirnoffand
2984e76af6aSGleb Smirnoff.An Konstantin Belousov .
299