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 11, 2021 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 and return 102.Dv NULL . 103.It Fn counter_u64_free c 104Free the previously allocated counter 105.Fa c . 106It is safe to pass 107.Dv NULL . 108.It Fn counter_u64_add c v 109Add 110.Fa v 111to 112.Fa c . 113The KPI does not guarantee any protection from wraparound. 114.It Fn counter_enter 115Enter mode that would allow the safe update of several counters via 116.Fn counter_u64_add_protected . 117On some machines this expands to 118.Xr critical 9 119section, while on other is a nop. 120See 121.Sx IMPLEMENTATION DETAILS . 122.It Fn counter_exit 123Exit mode for updating several counters. 124.It Fn counter_u64_add_protected c v 125Same as 126.Fn counter_u64_add , 127but should be preceded by 128.Fn counter_enter . 129.It Fn counter_u64_fetch c 130Take a snapshot of counter 131.Fa c . 132The data obtained is not guaranteed to reflect the real cumulative 133value for any moment. 134.It Fn counter_u64_zero c 135Clear the counter 136.Fa c 137and set it to zero. 138.It Fn counter_ratecheck cr limit 139The function is a multiprocessor-friendly version of 140.Fn ppsratecheck 141which uses 142.Nm 143internally. 144Returns non-negative value if the rate is not yet reached during the current 145second, and a negative value otherwise. 146If the limit was reached on previous second, but was just reset back to zero, 147then 148.Fn counter_ratecheck 149returns number of events since previous reset. 150.It Fn COUNTER_U64_SYSINIT c 151Define a 152.Xr SYSINIT 9 153initializer for the global counter 154.Fa c . 155.It Fn COUNTER_U64_DEFINE_EARLY c 156Define and initialize a global counter 157.Fa c . 158It is always safe to increment 159.Fa c , 160though updates prior to the 161.Dv SI_SUB_COUNTER 162.Xr SYSINIT 9 163event are lost. 164.It Fn SYSCTL_COUNTER_U64 parent nbr name access ptr descr 165Declare a static 166.Xr sysctl 9 167oid that would represent a 168.Nm . 169The 170.Fa ptr 171argument should be a pointer to allocated 172.Vt counter_u64_t . 173A read of the oid returns value obtained through 174.Fn counter_u64_fetch . 175Any write to the oid zeroes it. 176.It Fn SYSCTL_ADD_COUNTER_U64 ctx parent nbr name access ptr descr 177Create a 178.Xr sysctl 9 179oid that would represent a 180.Nm . 181The 182.Fa ptr 183argument should be a pointer to allocated 184.Vt counter_u64_t . 185A read of the oid returns value obtained through 186.Fn counter_u64_fetch . 187Any write to the oid zeroes it. 188.It Fn SYSCTL_COUNTER_U64_ARRAY parent nbr name access ptr len descr 189Declare a static 190.Xr sysctl 9 191oid that would represent an array of 192.Nm . 193The 194.Fa ptr 195argument should be a pointer to allocated array of 196.Vt counter_u64_t's . 197The 198.Fa len 199argument should specify number of elements in the array. 200A read of the oid returns len-sized array of 201.Vt uint64_t 202values obtained through 203.Fn counter_u64_fetch . 204Any write to the oid zeroes all array elements. 205.It Fn SYSCTL_ADD_COUNTER_U64_ARRAY ctx parent nbr name access ptr len descr 206Create a 207.Xr sysctl 9 208oid that would represent an array of 209.Nm . 210The 211.Fa ptr 212argument should be a pointer to allocated array of 213.Vt counter_u64_t's . 214The 215.Fa len 216argument should specify number of elements in the array. 217A read of the oid returns len-sized array of 218.Vt uint64_t 219values obtained through 220.Fn counter_u64_fetch . 221Any write to the oid zeroes all array elements. 222.El 223.Sh IMPLEMENTATION DETAILS 224On all architectures 225.Nm 226is implemented using per-CPU data fields that are specially aligned 227in memory, to avoid inter-CPU bus traffic due to shared use 228of the variables between CPUs. 229These are allocated using 230.Va UMA_ZONE_PCPU 231.Xr uma 9 232zone. 233The update operation only touches the field that is private to current CPU. 234Fetch operation loops through all per-CPU fields and obtains a snapshot 235sum of all fields. 236.Pp 237On amd64 a 238.Nm counter 239update is implemented as a single instruction without lock semantics, 240operating on the private data for the current CPU, 241which is safe against preemption and interrupts. 242.Pp 243On i386 architecture, when machine supports the cmpxchg8 instruction, 244this instruction is used. 245The multi-instruction sequence provides the same guarantees as the 246amd64 single-instruction implementation. 247.Pp 248On some architectures updating a counter require a 249.Xr critical 9 250section. 251.Sh EXAMPLES 252The following example creates a static counter array exported to 253userspace through a sysctl: 254.Bd -literal -offset indent 255#define MY_SIZE 8 256static counter_u64_t array[MY_SIZE]; 257SYSCTL_COUNTER_U64_ARRAY(_debug, OID_AUTO, counter_array, CTLFLAG_RW, 258 &array[0], MY_SIZE, "Test counter array"); 259.Ed 260.Sh SEE ALSO 261.Xr atomic 9 , 262.Xr critical 9 , 263.Xr locking 9 , 264.Xr malloc 9 , 265.Xr ratecheck 9 , 266.Xr sysctl 9 , 267.Xr SYSINIT 9 , 268.Xr uma 9 269.Sh HISTORY 270The 271.Nm 272facility first appeared in 273.Fx 10.0 . 274.Sh AUTHORS 275.An -nosplit 276The 277.Nm 278facility was written by 279.An Gleb Smirnoff 280and 281.An Konstantin Belousov . 282