COUNTER(9)
π COUNTER(9) β SMP-friendly kernel counter realness π
okay so bestie, this is the Kernel Developer's Manual page for counter, and it is literally the βSMP-friendly kernel counter implementation.β no cap, every function and flag is staying right here. β¨
πΈ NAME πΈ
counter β SMP-friendly kernel counter implementation
π¦ SYNOPSIS π¦
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/counter.h>
counter_u64_t
counter_u64_alloc(int wait);
void
counter_u64_free(counter_u64_t c);
void
counter_u64_add(counter_u64_t c, int64_t v);
void
counter_enter();
void
counter_exit();
void
counter_u64_add_protected(counter_u64_t c, int64_t v);
uint64_t
counter_u64_fetch(counter_u64_t c);
void
counter_u64_zero(counter_u64_t c);
struct counter_rate *
counter_rate_alloc(int flags, int period);
int64_t
counter_ratecheck(struct counter_rate *cr, int64_t limit);
uint64_t
counter_rate_get(struct counter_rate *cr);
void
counter_rate_free(struct counter_rate *cr);
COUNTER_U64_SYSINIT(counter_u64_t c);
COUNTER_U64_DEFINE_EARLY(counter_u64_t c);
#include <sys/sysctl.h>
SYSCTL_COUNTER_U64(parent, nbr, name, access, ptr, descr);
SYSCTL_ADD_COUNTER_U64(ctx, parent, nbr, name, access, ptr, descr);
SYSCTL_COUNTER_U64_ARRAY(parent, nbr, name, access, ptr, len, descr);
SYSCTL_ADD_COUNTER_U64_ARRAY(ctx, parent, nbr, name, access, ptr, len,
descr);
π DESCRIPTION π
counter is a generic facility to create counters that can be used for any purpose β collecting statistical data is the classic vibe. A counter is guaranteed to be lossless when several kernel threads do simultaneous updates. π«Ά
But here's the important part, bestie: counter does not block the calling thread, and no atomic(9) operations are used for the update. So the counters can be used in any non-interrupt context. β¨
Moreover, counter has special optimisations for SMP environments, making counter update faster than simple arithmetic on the global variable. Thus counter is considered suitable for accounting in the performance-critical code paths. π₯
counter_u64_alloc(wait)β Allocate a new 64-bit unsigned counter. Thewaitargument is themalloc(9)wait flag, should be eitherM_NOWAITorM_WAITOK. IfM_NOWAITis specified the operation may fail and returnNULL. πcounter_u64_free(c)β Free the previously allocated counterc. It is safe to passNULL. π§counter_u64_add(c, v)β Addvtoc. The KPI does not guarantee any protection from wraparound β so don't come expecting wraparound protection, because it is literally not promised. πcounter_enter()β Enter mode that would allow the safe update of several counters viacounter_u64_add_protected(). On some machines this expands tocritical(9)section, while on other is anop. See βIMPLEMENTATION DETAILSβ. πcounter_exit()β Exit mode for updating several counters. πcounter_u64_add_protected(c, v)β Same ascounter_u64_add(), but should be preceded bycounter_enter(). πcounter_u64_fetch(c)β Take a snapshot of counterc. The data obtained is not guaranteed to reflect the real cumulative value for any moment. πcounter_u64_zero(c)β Clear the countercand set it to zero. β¨counter_rate_alloc(flags, period)β Allocate a newstruct counter_rate.flagsis passed tomalloc(9).periodis the time over which the rate is checked. π¦counter_ratecheck(cr, limit)β The function is a multiprocessor-friendly version ofppsratecheck()which usescounterinternally. Returns non-negative value if the rate is not yet reached during the current period, and a negative value otherwise. If the limit was reached during the previous period, but was just reset back to zero, thencounter_ratecheck()returns number of events since previous reset. π₯counter_rate_get(cr)β The number of hits to this check within the current period. βcounter_rate_free(cr)β Free thecrcounter. πCOUNTER_U64_SYSINIT(c)β Define aSYSINIT(9)initializer for the global counterc. πCOUNTER_U64_DEFINE_EARLY(c)β Define and initialize a global counterc. It is always safe to incrementc, though updates prior to theSI_SUB_COUNTERSYSINIT(9)event are lost. πSYSCTL_COUNTER_U64(parent, nbr, name, access, ptr, descr)β Declare a staticsysctl(9)oid that would represent a counter. Theptrargument should be a pointer to allocatedcounter_u64_t. A read of the oid returns value obtained throughcounter_u64_fetch(). Any write to the oid zeroes it. π«ΆSYSCTL_ADD_COUNTER_U64(ctx, parent, nbr, name, access, ptr, descr)β Create asysctl(9)oid that would represent a counter. Theptrargument should be a pointer to allocatedcounter_u64_t. A read of the oid returns value obtained throughcounter_u64_fetch(). Any write to the oid zeroes it. πΈSYSCTL_COUNTER_U64_ARRAY(parent, nbr, name, access, ptr, len, descr)β Declare a staticsysctl(9)oid that would represent an array of counter. Theptrargument should be a pointer to allocated array ofcounter_u64_t's. Thelenargument should specify number of elements in the array. A read of the oid returnslen-sized array ofuint64_tvalues obtained throughcounter_u64_fetch(). Any write to the oid zeroes all array elements. π¦SYSCTL_ADD_COUNTER_U64_ARRAY(ctx, parent, nbr, name, access, ptr, len, descr)β Create asysctl(9)oid that would represent an array of counter. Theptrargument should be a pointer to allocated array ofcounter_u64_t's. Thelenargument should specify number of elements in the array. A read of the oid returnslen-sized array ofuint64_tvalues obtained throughcounter_u64_fetch(). Any write to the oid zeroes all array elements. π
π§ IMPLEMENTATION DETAILS π§
On all architectures counter is implemented using per-CPU data fields that are specially aligned in memory, to avoid inter-CPU bus traffic due to shared use of the variables between CPUs. These are allocated using UMA_ZONE_PCPU uma(9) zone. The update operation only touches the field that is private to current CPU. Fetch operation loops through all per-CPU fields and obtains a snapshot sum of all fields. π
- On
amd64a counter update is implemented as a single instruction without lock semantics, operating on the private data for the current CPU, which is safe against preemption and interrupts. π₯ - On
i386architecture, when machine supports thecmpxchg8instruction, this instruction is used. The multi-instruction sequence provides the same guarantees as theamd64single-instruction implementation. β - On some architectures updating a counter require a
critical(9)section. π
π EXAMPLES π
The following example creates a static counter array exported to userspace through a sysctl:
#define MY_SIZE 8
static counter_u64_t array[MY_SIZE];
SYSCTL_COUNTER_U64_ARRAY(_debug, OID_AUTO, counter_array, CTLFLAG_RW,
&array[0], MY_SIZE, "Test counter array");
π SEE ALSO π
π¦ HISTORY π¦
The counter facility first appeared in FreeBSD 10.0. π
π AUTHORS π
The counter facility was written by Gleb Smirnoff and Konstantin Belousov. π«Ά
π That's the whole page, bestie β source/version is Debian, dated June 19, 2025, and the manpage tag is COUNTER(9). π
π¦ where this page comes from
- freebsd 15.1: base 15.1
- Copyright (c) 2013 Gleb Smirnoff <glebius@FreeBSD.org>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms