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*51dc8e7fSKristof Provost.Dd March 11, 2021 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" 5216917020SGleb Smirnoff.Ft int64_t 5316917020SGleb Smirnoff.Fn counter_ratecheck "struct counter_rate *cr" "int64_t limit" 54fffcb56fSMark Johnston.Fn COUNTER_U64_SYSINIT "counter_u64_t c" 55fffcb56fSMark Johnston.Fn COUNTER_U64_DEFINE_EARLY "counter_u64_t c" 564e76af6aSGleb Smirnoff.In sys/sysctl.h 57369f5bceSGleb Smirnoff.Fn SYSCTL_COUNTER_U64 parent nbr name access ptr descr 584e76af6aSGleb Smirnoff.Fn SYSCTL_ADD_COUNTER_U64 ctx parent nbr name access ptr descr 59b5b7b142SGleb Smirnoff.Fn SYSCTL_COUNTER_U64_ARRAY parent nbr name access ptr len descr 60b5b7b142SGleb Smirnoff.Fn SYSCTL_ADD_COUNTER_U64_ARRAY ctx parent nbr name access ptr len descr 614e76af6aSGleb Smirnoff.Sh DESCRIPTION 624e76af6aSGleb Smirnoff.Nm 634e76af6aSGleb Smirnoffis a generic facility to create counters 644e76af6aSGleb Smirnoffthat can be utilized for any purpose (such as collecting statistical 654e76af6aSGleb Smirnoffdata). 664e76af6aSGleb SmirnoffA 674e76af6aSGleb Smirnoff.Nm 684e76af6aSGleb Smirnoffis guaranteed to be lossless when several kernel threads do simultaneous 694e76af6aSGleb Smirnoffupdates. 704e76af6aSGleb SmirnoffHowever, 714e76af6aSGleb Smirnoff.Nm 724e76af6aSGleb Smirnoffdoes not block the calling thread, 734e76af6aSGleb Smirnoffalso no 744e76af6aSGleb Smirnoff.Xr atomic 9 754e76af6aSGleb Smirnoffoperations are used for the update, therefore the counters 764e76af6aSGleb Smirnoffcan be used in any non-interrupt context. 774e76af6aSGleb SmirnoffMoreover, 784e76af6aSGleb Smirnoff.Nm 794e76af6aSGleb Smirnoffhas special optimisations for SMP environments, making 804e76af6aSGleb Smirnoff.Nm 814e76af6aSGleb Smirnoffupdate faster than simple arithmetic on the global variable. 824e76af6aSGleb SmirnoffThus 834e76af6aSGleb Smirnoff.Nm 844e76af6aSGleb Smirnoffis considered suitable for accounting in the performance-critical 857c64ddd5SWarren Blockcode paths. 864e76af6aSGleb Smirnoff.Bl -tag -width indent 87fa8175e4SBrad Davis.It Fn counter_u64_alloc wait 884e76af6aSGleb SmirnoffAllocate a new 64-bit unsigned counter. 894e76af6aSGleb SmirnoffThe 904e76af6aSGleb Smirnoff.Fa wait 914e76af6aSGleb Smirnoffargument is the 924e76af6aSGleb Smirnoff.Xr malloc 9 934e76af6aSGleb Smirnoffwait flag, should be either 944e76af6aSGleb Smirnoff.Va M_NOWAIT 954e76af6aSGleb Smirnoffor 964e76af6aSGleb Smirnoff.Va M_WAITOK . 974e76af6aSGleb SmirnoffIf 98c676e669SAlan Somers.Va M_NOWAIT 99*51dc8e7fSKristof Provostis specified the operation may fail and return 100*51dc8e7fSKristof Provost.Dv NULL . 1014e76af6aSGleb Smirnoff.It Fn counter_u64_free c 1024e76af6aSGleb SmirnoffFree the previously allocated counter 1034e76af6aSGleb Smirnoff.Fa c . 104*51dc8e7fSKristof ProvostIt is safe to pass 105*51dc8e7fSKristof Provost.Dv NULL . 1064e76af6aSGleb Smirnoff.It Fn counter_u64_add c v 1074e76af6aSGleb SmirnoffAdd 1084e76af6aSGleb Smirnoff.Fa v 1094e76af6aSGleb Smirnoffto 1104e76af6aSGleb Smirnoff.Fa c . 1114e76af6aSGleb SmirnoffThe KPI does not guarantee any protection from wraparound. 1124e76af6aSGleb Smirnoff.It Fn counter_enter 113640ca09dSEnji CooperEnter mode that would allow the safe update of several counters via 1144e76af6aSGleb Smirnoff.Fn counter_u64_add_protected . 1154e76af6aSGleb SmirnoffOn some machines this expands to 1164e76af6aSGleb Smirnoff.Xr critical 9 1174e76af6aSGleb Smirnoffsection, while on other is a nop. 1184e76af6aSGleb SmirnoffSee 1194e76af6aSGleb Smirnoff.Sx IMPLEMENTATION DETAILS . 1204e76af6aSGleb Smirnoff.It Fn counter_exit 1214e76af6aSGleb SmirnoffExit mode for updating several counters. 1224e76af6aSGleb Smirnoff.It Fn counter_u64_add_protected c v 1234e76af6aSGleb SmirnoffSame as 1244e76af6aSGleb Smirnoff.Fn counter_u64_add , 1254e76af6aSGleb Smirnoffbut should be preceded by 1264e76af6aSGleb Smirnoff.Fn counter_enter . 1274e76af6aSGleb Smirnoff.It Fn counter_u64_fetch c 1284e76af6aSGleb SmirnoffTake a snapshot of counter 1294e76af6aSGleb Smirnoff.Fa c . 1304e76af6aSGleb SmirnoffThe data obtained is not guaranteed to reflect the real cumulative 1314e76af6aSGleb Smirnoffvalue for any moment. 1324e76af6aSGleb Smirnoff.It Fn counter_u64_zero c 1334e76af6aSGleb SmirnoffClear the counter 1344e76af6aSGleb Smirnoff.Fa c 1354e76af6aSGleb Smirnoffand set it to zero. 13616917020SGleb Smirnoff.It Fn counter_ratecheck cr limit 13716917020SGleb SmirnoffThe function is a multiprocessor-friendly version of 13899d528d4SDag-Erling Smørgrav.Fn ppsratecheck 13916917020SGleb Smirnoffwhich uses 14016917020SGleb Smirnoff.Nm 14116917020SGleb Smirnoffinternally. 142640ca09dSEnji CooperReturns non-negative value if the rate is not yet reached during the current 14316917020SGleb Smirnoffsecond, and a negative value otherwise. 14416917020SGleb SmirnoffIf the limit was reached on previous second, but was just reset back to zero, 14516917020SGleb Smirnoffthen 14616917020SGleb Smirnoff.Fn counter_ratecheck 14716917020SGleb Smirnoffreturns number of events since previous reset. 148fffcb56fSMark Johnston.It Fn COUNTER_U64_SYSINIT c 149fffcb56fSMark JohnstonDefine a 150fffcb56fSMark Johnston.Xr SYSINIT 9 151fffcb56fSMark Johnstoninitializer for the global counter 152fffcb56fSMark Johnston.Fa c . 153fffcb56fSMark Johnston.It Fn COUNTER_U64_DEFINE_EARLY c 154fffcb56fSMark JohnstonDefine and initialize a global counter 155fffcb56fSMark Johnston.Fa c . 156fffcb56fSMark JohnstonIt is always safe to increment 157fffcb56fSMark Johnston.Fa c , 158fffcb56fSMark Johnstonthough updates prior to the 159fffcb56fSMark Johnston.Dv SI_SUB_COUNTER 160fffcb56fSMark Johnston.Xr SYSINIT 9 161fffcb56fSMark Johnstonevent are lost. 162369f5bceSGleb Smirnoff.It Fn SYSCTL_COUNTER_U64 parent nbr name access ptr descr 1634e76af6aSGleb SmirnoffDeclare a static 164640ca09dSEnji Cooper.Xr sysctl 9 1654e76af6aSGleb Smirnoffoid that would represent a 1664e76af6aSGleb Smirnoff.Nm . 1674e76af6aSGleb SmirnoffThe 1684e76af6aSGleb Smirnoff.Fa ptr 1694e76af6aSGleb Smirnoffargument should be a pointer to allocated 1704e76af6aSGleb Smirnoff.Vt counter_u64_t . 1714e76af6aSGleb SmirnoffA read of the oid returns value obtained through 1724e76af6aSGleb Smirnoff.Fn counter_u64_fetch . 1734e76af6aSGleb SmirnoffAny write to the oid zeroes it. 1744e76af6aSGleb Smirnoff.It Fn SYSCTL_ADD_COUNTER_U64 ctx parent nbr name access ptr descr 1754e76af6aSGleb SmirnoffCreate a 176640ca09dSEnji Cooper.Xr sysctl 9 1774e76af6aSGleb Smirnoffoid that would represent a 1784e76af6aSGleb Smirnoff.Nm . 1794e76af6aSGleb SmirnoffThe 1804e76af6aSGleb Smirnoff.Fa ptr 1814e76af6aSGleb Smirnoffargument should be a pointer to allocated 1824e76af6aSGleb Smirnoff.Vt counter_u64_t . 1834e76af6aSGleb SmirnoffA read of the oid returns value obtained through 1844e76af6aSGleb Smirnoff.Fn counter_u64_fetch . 1854e76af6aSGleb SmirnoffAny write to the oid zeroes it. 186b5b7b142SGleb Smirnoff.It Fn SYSCTL_COUNTER_U64_ARRAY parent nbr name access ptr len descr 187b5b7b142SGleb SmirnoffDeclare a static 188640ca09dSEnji Cooper.Xr sysctl 9 189b5b7b142SGleb Smirnoffoid that would represent an array of 190b5b7b142SGleb Smirnoff.Nm . 191b5b7b142SGleb SmirnoffThe 192b5b7b142SGleb Smirnoff.Fa ptr 193b5b7b142SGleb Smirnoffargument should be a pointer to allocated array of 194b5b7b142SGleb Smirnoff.Vt counter_u64_t's . 195b5b7b142SGleb SmirnoffThe 196b5b7b142SGleb Smirnoff.Fa len 197b5b7b142SGleb Smirnoffargument should specify number of elements in the array. 198b5b7b142SGleb SmirnoffA read of the oid returns len-sized array of 199b5b7b142SGleb Smirnoff.Vt uint64_t 200b5b7b142SGleb Smirnoffvalues obtained through 201b5b7b142SGleb Smirnoff.Fn counter_u64_fetch . 202b5b7b142SGleb SmirnoffAny write to the oid zeroes all array elements. 203b5b7b142SGleb Smirnoff.It Fn SYSCTL_ADD_COUNTER_U64_ARRAY ctx parent nbr name access ptr len descr 204b5b7b142SGleb SmirnoffCreate a 205640ca09dSEnji Cooper.Xr sysctl 9 206b5b7b142SGleb Smirnoffoid that would represent an array of 207b5b7b142SGleb Smirnoff.Nm . 208b5b7b142SGleb SmirnoffThe 209b5b7b142SGleb Smirnoff.Fa ptr 210b5b7b142SGleb Smirnoffargument should be a pointer to allocated array of 211b5b7b142SGleb Smirnoff.Vt counter_u64_t's . 212b5b7b142SGleb SmirnoffThe 213b5b7b142SGleb Smirnoff.Fa len 214b5b7b142SGleb Smirnoffargument should specify number of elements in the array. 215b5b7b142SGleb SmirnoffA read of the oid returns len-sized array of 216b5b7b142SGleb Smirnoff.Vt uint64_t 217b5b7b142SGleb Smirnoffvalues obtained through 218b5b7b142SGleb Smirnoff.Fn counter_u64_fetch . 219b5b7b142SGleb SmirnoffAny write to the oid zeroes all array elements. 2204e76af6aSGleb Smirnoff.El 2214e76af6aSGleb Smirnoff.Sh IMPLEMENTATION DETAILS 2224e76af6aSGleb SmirnoffOn all architectures 2234e76af6aSGleb Smirnoff.Nm 2244e76af6aSGleb Smirnoffis implemented using per-CPU data fields that are specially aligned 2254e76af6aSGleb Smirnoffin memory, to avoid inter-CPU bus traffic due to shared use 2264e76af6aSGleb Smirnoffof the variables between CPUs. 2274e76af6aSGleb SmirnoffThese are allocated using 2284e76af6aSGleb Smirnoff.Va UMA_ZONE_PCPU 2294e76af6aSGleb Smirnoff.Xr uma 9 2304e76af6aSGleb Smirnoffzone. 2314e76af6aSGleb SmirnoffThe update operation only touches the field that is private to current CPU. 2324e76af6aSGleb SmirnoffFetch operation loops through all per-CPU fields and obtains a snapshot 2334e76af6aSGleb Smirnoffsum of all fields. 2344e76af6aSGleb Smirnoff.Pp 2354e76af6aSGleb SmirnoffOn amd64 a 2364e76af6aSGleb Smirnoff.Nm counter 2374e76af6aSGleb Smirnoffupdate is implemented as a single instruction without lock semantics, 2384e76af6aSGleb Smirnoffoperating on the private data for the current CPU, 2394e76af6aSGleb Smirnoffwhich is safe against preemption and interrupts. 2404e76af6aSGleb Smirnoff.Pp 2414e76af6aSGleb SmirnoffOn i386 architecture, when machine supports the cmpxchg8 instruction, 2424e76af6aSGleb Smirnoffthis instruction is used. 2434e76af6aSGleb SmirnoffThe multi-instruction sequence provides the same guarantees as the 2444e76af6aSGleb Smirnoffamd64 single-instruction implementation. 2454e76af6aSGleb Smirnoff.Pp 2464e76af6aSGleb SmirnoffOn some architectures updating a counter require a 2474e76af6aSGleb Smirnoff.Xr critical 9 2484e76af6aSGleb Smirnoffsection. 249a435d46fSHans Petter Selasky.Sh EXAMPLES 250a435d46fSHans Petter SelaskyThe following example creates a static counter array exported to 251a435d46fSHans Petter Selaskyuserspace through a sysctl: 252a435d46fSHans Petter Selasky.Bd -literal -offset indent 253a435d46fSHans Petter Selasky#define MY_SIZE 8 254a435d46fSHans Petter Selaskystatic counter_u64_t array[MY_SIZE]; 255a435d46fSHans Petter SelaskySYSCTL_COUNTER_U64_ARRAY(_debug, OID_AUTO, counter_array, CTLFLAG_RW, 256a435d46fSHans Petter Selasky &array[0], MY_SIZE, "Test counter array"); 257a435d46fSHans Petter Selasky.Ed 2584e76af6aSGleb Smirnoff.Sh SEE ALSO 2594e76af6aSGleb Smirnoff.Xr atomic 9 , 2604e76af6aSGleb Smirnoff.Xr critical 9 , 2614e76af6aSGleb Smirnoff.Xr locking 9 , 2624e76af6aSGleb Smirnoff.Xr malloc 9 , 26399d528d4SDag-Erling Smørgrav.Xr ratecheck 9 , 2644e76af6aSGleb Smirnoff.Xr sysctl 9 , 265fffcb56fSMark Johnston.Xr SYSINIT 9 , 2664e76af6aSGleb Smirnoff.Xr uma 9 2674e76af6aSGleb Smirnoff.Sh HISTORY 2684e76af6aSGleb SmirnoffThe 2694e76af6aSGleb Smirnoff.Nm 2704e76af6aSGleb Smirnofffacility first appeared in 2714e76af6aSGleb Smirnoff.Fx 10.0 . 2724e76af6aSGleb Smirnoff.Sh AUTHORS 2734e76af6aSGleb Smirnoff.An -nosplit 2744e76af6aSGleb SmirnoffThe 2754e76af6aSGleb Smirnoff.Nm 2764e76af6aSGleb Smirnofffacility was written by 2774e76af6aSGleb Smirnoff.An Gleb Smirnoff 2784e76af6aSGleb Smirnoffand 2794e76af6aSGleb Smirnoff.An Konstantin Belousov . 280