-.\" $OpenBSD: evcount.9,v 1.7 2018/04/23 10:31:24 dlg Exp $
+.\" $OpenBSD: evcount.9,v 1.8 2022/11/10 07:05:41 jmatthew Exp $
.\" Written by Jared Yanovich
.\" This file belongs to the public domain, 11/02/2004.
-.Dd $Mdocdate: April 23 2018 $
+.Dd $Mdocdate: November 10 2022 $
.Dt EVCOUNT 9
.Os
.Sh NAME
.Nm evcount ,
.Nm evcount_attach ,
-.Nm evcount_detach
+.Nm evcount_detach ,
+.Nm evcount_percpu ,
+.Nm evcount_inc
.Nd generic interrupt and event counter kernel API
.Sh SYNOPSIS
.In sys/evcount.h
.Ft void
.Fn evcount_attach "struct evcount *ec" "const char *name" "void *data"
.Ft void
+.Fn evcount_percpu "struct evcount *ec"
+.Ft void
+.Fn evcount_inc "struct evcount *ec"
+.Ft void
.Fn evcount_detach "struct evcount *ec"
.Sh DESCRIPTION
The
int ec_id; /* counter ID */
const char *ec_name; /* counter name */
void *ec_data; /* user data */
+ struct cpumem *ec_cpumem; /* per-cpu counter */
TAILQ_ENTRY(evcount) next;
};
call.
.Pp
The
+.Fn evcount_percpu ec
+function configures
+.Fa ec
+with one counter for each CPU in the system.
+It should be used when
+.Fa ec Ns 's
+corresponding interrupt can occur simultaneously on multiple CPUs.
+It must be called immediately after
+.Fn evcount_attach
+is called for a given counter.
+.Pp
+The
+.Fn evcount_inc ec
+function increments the given counter.
+.Pp
+The
.Fn evcount_detach ec
function removes the given event counter
.Fa ec
.Xr queue 3 ,
.Xr intro 4 ,
.Xr vmstat 8 ,
-.Xr autoconf 9
+.Xr autoconf 9 ,
+.Xr counters_alloc 9
.Sh AUTHORS
.An -nosplit
The
-/* $OpenBSD: init_main.c,v 1.318 2022/10/30 17:43:40 guenther Exp $ */
+/* $OpenBSD: init_main.c,v 1.319 2022/11/10 07:05:41 jmatthew Exp $ */
/* $NetBSD: init_main.c,v 1.84.4.1 1996/06/02 09:08:06 mrg Exp $ */
/*
#include <sys/pipe.h>
#include <sys/witness.h>
#include <sys/smr.h>
+#include <sys/evcount.h>
#include <sys/syscallargs.h>
mbcpuinit();
kqueue_init_percpu();
uvm_init_percpu();
+ evcount_init_percpu();
/* init exec */
init_exec();
-/* $OpenBSD: subr_evcount.c,v 1.13 2022/08/14 01:58:28 jsg Exp $ */
+/* $OpenBSD: subr_evcount.c,v 1.14 2022/11/10 07:05:41 jmatthew Exp $ */
/*
* Copyright (c) 2004 Artur Grabowski <art@openbsd.org>
* Copyright (c) 2004 Aaron Campbell <aaron@openbsd.org>
#include <sys/evcount.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
+#include <sys/percpu.h>
static TAILQ_HEAD(,evcount) evcount_list = TAILQ_HEAD_INITIALIZER(evcount_list);
+static TAILQ_HEAD(,evcount) evcount_percpu_init_list =
+ TAILQ_HEAD_INITIALIZER(evcount_percpu_init_list);
+static int evcount_percpu_done;
void
evcount_attach(struct evcount *ec, const char *name, void *data)
TAILQ_INSERT_TAIL(&evcount_list, ec, next);
}
+void
+evcount_percpu(struct evcount *ec)
+{
+ if (evcount_percpu_done == 0) {
+ TAILQ_REMOVE(&evcount_list, ec, next);
+ TAILQ_INSERT_TAIL(&evcount_percpu_init_list, ec, next);
+ } else {
+ ec->ec_percpu = counters_alloc(1);
+ TAILQ_INSERT_TAIL(&evcount_list, ec, next);
+ }
+}
+
+void
+evcount_init_percpu(void)
+{
+ struct evcount *ec;
+
+ KASSERT(evcount_percpu_done == 0);
+ TAILQ_FOREACH(ec, &evcount_percpu_init_list, next) {
+ ec->ec_percpu = counters_alloc(1);
+ counters_add(ec->ec_percpu, 0, ec->ec_count);
+ ec->ec_count = 0;
+ }
+ TAILQ_CONCAT(&evcount_list, &evcount_percpu_init_list, next);
+ evcount_percpu_done = 1;
+}
+
void
evcount_detach(struct evcount *ec)
{
TAILQ_REMOVE(&evcount_list, ec, next);
+ if (ec->ec_percpu != NULL) {
+ counters_free(ec->ec_percpu, 1);
+ ec->ec_percpu = NULL;
+ }
+}
+
+void
+evcount_inc(struct evcount *ec)
+{
+ if (ec->ec_percpu != NULL)
+ counters_inc(ec->ec_percpu, 0);
+ else
+ ec->ec_count++;
}
#ifndef SMALL_KERNEL
case KERN_INTRCNT_CNT:
if (ec == NULL)
return (ENOENT);
- s = splhigh();
- count = ec->ec_count;
- splx(s);
+ if (ec->ec_percpu != NULL) {
+ counters_read(ec->ec_percpu, &count, 1);
+ } else {
+ s = splhigh();
+ count = ec->ec_count;
+ splx(s);
+ }
error = sysctl_rdquad(oldp, oldlenp, NULL, count);
break;
case KERN_INTRCNT_NAME:
-/* $OpenBSD: evcount.h,v 1.3 2010/09/20 06:33:46 matthew Exp $ */
+/* $OpenBSD: evcount.h,v 1.4 2022/11/10 07:05:41 jmatthew Exp $ */
/*
* Copyright (c) 2004 Artur Grabowski <art@openbsd.org>
* Copyright (c) 2004 Aaron Campbell <aaron@openbsd.org>
#include <sys/queue.h>
+struct cpumem;
+
struct evcount {
u_int64_t ec_count; /* main counter */
int ec_id; /* counter ID */
const char *ec_name; /* counter name */
void *ec_data; /* user data */
+ struct cpumem *ec_percpu; /* per-cpu counter */
TAILQ_ENTRY(evcount) next;
};
void evcount_attach(struct evcount *, const char *, void *);
void evcount_detach(struct evcount *);
+void evcount_inc(struct evcount *);
+void evcount_init_percpu(void);
+void evcount_percpu(struct evcount *);
int evcount_sysctl(int *, u_int, void *, size_t *, void *, size_t);
#endif /* _KERNEL */