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