Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 8 Apr 2013 19:40:53 +0000 (UTC)
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r249268 - in head: share/man/man9 sys/amd64/include sys/arm/include sys/conf sys/i386/include sys/ia64/include sys/kern sys/mips/include sys/pc98/include sys/powerpc/include sys/sparc64...
Message-ID:  <201304081940.r38JerAB096616@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: glebius
Date: Mon Apr  8 19:40:53 2013
New Revision: 249268
URL: http://svnweb.freebsd.org/changeset/base/249268

Log:
  Merge from projects/counters: counter(9).
  
    Introduce counter(9) API, that implements fast and raceless counters,
  provided (but not limited to) for gathering of statistical data.
  
  See http://lists.freebsd.org/pipermail/freebsd-arch/2013-April/014204.html
  for more details.
  
  In collaboration with:	kib
  Reviewed by:		luigi
  Tested by:		ae, ray
  Sponsored by:		Nginx, Inc.

Added:
  head/share/man/man9/counter.9   (contents, props changed)
  head/sys/amd64/include/counter.h   (contents, props changed)
  head/sys/arm/include/counter.h   (contents, props changed)
  head/sys/i386/include/counter.h   (contents, props changed)
  head/sys/ia64/include/counter.h   (contents, props changed)
  head/sys/kern/subr_counter.c   (contents, props changed)
  head/sys/mips/include/counter.h   (contents, props changed)
  head/sys/pc98/include/counter.h   (contents, props changed)
  head/sys/powerpc/include/counter.h   (contents, props changed)
  head/sys/sparc64/include/counter.h   (contents, props changed)
  head/sys/sys/counter.h   (contents, props changed)
Modified:
  head/share/man/man9/Makefile
  head/sys/conf/files
  head/sys/sys/sysctl.h

Modified: head/share/man/man9/Makefile
==============================================================================
--- head/share/man/man9/Makefile	Mon Apr  8 19:23:22 2013	(r249267)
+++ head/share/man/man9/Makefile	Mon Apr  8 19:40:53 2013	(r249268)
@@ -51,6 +51,7 @@ MAN=	accept_filter.9 \
 	config_intrhook.9 \
 	contigmalloc.9 \
 	copy.9 \
+	counter.9 \
 	cr_cansee.9 \
 	critical_enter.9 \
 	cr_seeothergids.9 \
@@ -569,6 +570,14 @@ MLINKS+=copy.9 copyin.9 \
 	copy.9 copyout.9 \
 	copy.9 copyout_nofault.9 \
 	copy.9 copystr.9
+MLINKS+=counter.9 counter_u64_alloc.9 \
+	counter.9 counter_u64_free.9 \
+	counter.9 counter_u64_add.9 \
+	counter.9 counter_enter.9 \
+	counter.9 counter_exit.9 \
+	counter.9 counter_u64_add_protected.9 \
+	counter.9 counter_u64_fetch.9 \
+	counter.9 counter_u64_zero.9
 MLINKS+=critical_enter.9 critical.9 \
 	critical_enter.9 critical_exit.9
 MLINKS+=crypto.9 crypto_dispatch.9 \

Added: head/share/man/man9/counter.9
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/share/man/man9/counter.9	Mon Apr  8 19:40:53 2013	(r249268)
@@ -0,0 +1,200 @@
+.\"-
+.\" Copyright (c) 2013 Gleb Smirnoff <glebius@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd April 3, 2013
+.Dt COUNTER 9
+.Os
+.Sh NAME
+.Nm counter
+.Nd "SMP-friendly kernel counter implementation"
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/counter.h
+.Ft counter_u64_t
+.Fn counter_u64_alloc "int wait"
+.Ft void
+.Fn counter_u64_free "counter_u64_t c"
+.Ft void
+.Fn counter_u64_add "counter_u64_t c" "int64_t v"
+.Ft void
+.Fn counter_enter
+.Ft void
+.Fn counter_exit
+.Ft void
+.Fn counter_u64_add_protected "counter_u64_t c" "int64_t v"
+.Ft uint64_t
+.Fn counter_u64_fetch "counter_u64_t c"
+.Ft void
+.Fn counter_u64_zero "counter_u64_t c"
+.In sys/sysctl.h
+.Fn SYSCTL_COUNTER_U64 parent nbr name access ptr val descr
+.Fn SYSCTL_ADD_COUNTER_U64 ctx parent nbr name access ptr descr
+.Sh DESCRIPTION
+.Nm
+is a generic facility to create counters
+that can be utilized for any purpose (such as collecting statistical
+data).
+A
+.Nm
+is guaranteed to be lossless when several kernel threads do simultaneous
+updates.
+However,
+.Nm
+does not block the calling thread,
+also no
+.Xr atomic 9
+operations are used for the update, therefore the counters
+can be used in any non-interrupt context.
+Moreover,
+.Nm
+has special optimisations for SMP environments, making
+.Nm
+update faster than simple arithmetic on the global variable.
+Thus
+.Nm
+is considered suitable for accounting in the performance-critical
+code pathes.
+.Bl -tag -width indent
+.It Fn counter_u64_alloc how
+Allocate a new 64-bit unsigned counter.
+The
+.Fa wait
+argument is the
+.Xr malloc 9
+wait flag, should be either
+.Va M_NOWAIT
+or
+.Va M_WAITOK .
+If
+.Va M_WAITOK
+is specified the operation may fail.
+.It Fn counter_u64_free c
+Free the previously allocated counter
+.Fa c .
+.It Fn counter_u64_add c v
+Add
+.Fa v
+to
+.Fa c .
+The KPI does not guarantee any protection from wraparound.
+.It Fn counter_enter
+Enter mode that would allow to safely update several counters via
+.Fn counter_u64_add_protected .
+On some machines this expands to
+.Xr critical 9
+section, while on other is a nop.
+See
+.Sx IMPLEMENTATION DETAILS .
+.It Fn counter_exit
+Exit mode for updating several counters.
+.It Fn counter_u64_add_protected c v
+Same as
+.Fn counter_u64_add ,
+but should be preceded by
+.Fn counter_enter .
+.It Fn counter_u64_fetch c
+Take a snapshot of counter
+.Fa c .
+The data obtained is not guaranteed to reflect the real cumulative
+value for any moment.
+.It Fn counter_u64_zero c
+Clear the counter
+.Fa c
+and set it to zero.
+.It Fn SYSCTL_COUNTER_U64 parent nbr name access ptr val descr
+Declare a static
+.Xr sysctl
+oid that would represent a
+.Nm .
+The
+.Fa ptr
+argument should be a pointer to allocated
+.Vt counter_u64_t .
+A read of the oid returns value obtained through
+.Fn counter_u64_fetch .
+Any write to the oid zeroes it.
+.It Fn SYSCTL_ADD_COUNTER_U64 ctx parent nbr name access ptr descr
+Create a
+.Xr sysctl
+oid that would represent a
+.Nm .
+The
+.Fa ptr
+argument should be a pointer to allocated
+.Vt counter_u64_t .
+A read of the oid returns value obtained through
+.Fn counter_u64_fetch .
+Any write to the oid zeroes it.
+.El
+.Sh IMPLEMENTATION DETAILS
+On all architectures
+.Nm
+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
+.Va UMA_ZONE_PCPU
+.Xr 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.
+.Pp
+On amd64 a
+.Nm 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.
+.Pp
+On i386 architecture, when machine supports the cmpxchg8 instruction,
+this instruction is used.
+The multi-instruction sequence provides the same guarantees as the
+amd64 single-instruction implementation.
+.Pp
+On some architectures updating a counter require a
+.Xr critical 9
+section.
+.Sh SEE ALSO
+.Xr atomic 9 ,
+.Xr critical 9 ,
+.Xr locking 9 ,
+.Xr malloc 9 ,
+.Xr sysctl 9 ,
+.Xr uma 9
+.Sh HISTORY
+The
+.Nm
+facility first appeared in
+.Fx 10.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+facility was written by
+.An Gleb Smirnoff
+and
+.An Konstantin Belousov .

Added: head/sys/amd64/include/counter.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/amd64/include/counter.h	Mon Apr  8 19:40:53 2013	(r249268)
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2012 Konstantin Belousov <kib@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __MACHINE_COUNTER_H__
+#define __MACHINE_COUNTER_H__
+
+#include <sys/pcpu.h>
+
+extern struct pcpu __pcpu[1];
+
+#define	counter_enter()	do {} while (0)
+#define	counter_exit()	do {} while (0)
+
+#define	counter_u64_add_protected(c, i)	counter_u64_add(c, i)
+
+static inline void
+counter_u64_add(counter_u64_t c, int64_t inc)
+{
+
+	__asm __volatile("addq\t%1,%%gs:(%0)"
+	    :
+	    : "r" ((char *)c - (char *)&__pcpu[0]), "r" (inc)
+	    : "memory", "cc");
+}
+
+#endif	/* ! __MACHINE_COUNTER_H__ */

Added: head/sys/arm/include/counter.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/include/counter.h	Mon Apr  8 19:40:53 2013	(r249268)
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2012 Konstantin Belousov <kib@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __MACHINE_COUNTER_H__
+#define __MACHINE_COUNTER_H__
+
+#include <sys/pcpu.h>
+#ifdef INVARIANTS
+#include <sys/proc.h>
+#endif
+
+#define	counter_enter()	critical_enter()
+#define	counter_exit()	critical_exit()
+
+#define	counter_u64_add_protected(c, inc)	do {	\
+	CRITICAL_ASSERT(curthread);			\
+	*(uint64_t *)zpcpu_get(c) += (inc);		\
+} while (0)
+
+static inline void
+counter_u64_add(counter_u64_t c, int64_t inc)
+{
+
+	counter_enter();
+	counter_u64_add_protected(c, inc);
+	counter_exit();
+}
+
+#endif	/* ! __MACHINE_COUNTER_H__ */

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Mon Apr  8 19:23:22 2013	(r249267)
+++ head/sys/conf/files	Mon Apr  8 19:40:53 2013	(r249268)
@@ -2683,6 +2683,7 @@ kern/subr_bus.c			standard
 kern/subr_bus_dma.c		standard
 kern/subr_bufring.c		standard
 kern/subr_clock.c		standard
+kern/subr_counter.c		standard
 kern/subr_devstat.c		standard
 kern/subr_disk.c		standard
 kern/subr_eventhandler.c	standard

Added: head/sys/i386/include/counter.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/i386/include/counter.h	Mon Apr  8 19:40:53 2013	(r249268)
@@ -0,0 +1,89 @@
+/*-
+ * Copyright (c) 2012 Konstantin Belousov <kib@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __MACHINE_COUNTER_H__
+#define __MACHINE_COUNTER_H__
+
+#include <sys/pcpu.h>
+#ifdef INVARIANTS
+#include <sys/proc.h>
+#endif
+#include <machine/md_var.h>
+#include <machine/specialreg.h>
+
+#define	counter_enter()	do {				\
+	if ((cpu_feature & CPUID_CX8) == 0)		\
+		critical_enter();			\
+} while (0)
+
+#define	counter_exit()	do {				\
+	if ((cpu_feature & CPUID_CX8) == 0)		\
+		critical_exit();			\
+} while (0)
+
+static inline void
+counter_64_inc_8b(uint64_t *p, int64_t inc)
+{
+
+	__asm __volatile(
+	"movl	%%fs:(%%esi),%%eax\n\t"
+	"movl	%%fs:4(%%esi),%%edx\n"
+"1:\n\t"
+	"movl	%%eax,%%ebx\n\t"
+	"movl	%%edx,%%ecx\n\t"
+	"addl	(%%edi),%%ebx\n\t"
+	"adcl	4(%%edi),%%ecx\n\t"
+	"cmpxchg8b %%fs:(%%esi)\n\t"
+	"jnz	1b"
+	:
+	: "S" (p), "D" (&inc)
+	: "memory", "cc", "eax", "edx", "ebx", "ecx");
+}
+
+#define	counter_u64_add_protected(c, inc)	do {	\
+	if ((cpu_feature & CPUID_CX8) == 0) {		\
+		CRITICAL_ASSERT(curthread);		\
+		*(uint64_t *)zpcpu_get(c) += (inc);	\
+	} else						\
+		counter_64_inc_8b((c), (inc));		\
+} while (0)
+
+static inline void
+counter_u64_add(counter_u64_t c, int64_t inc)
+{
+
+	if ((cpu_feature & CPUID_CX8) == 0) {
+		critical_enter();
+		*(uint64_t *)zpcpu_get(c) += inc;
+		critical_exit();
+	} else {
+		counter_64_inc_8b(c, inc);
+	}
+}
+
+#endif	/* ! __MACHINE_COUNTER_H__ */

Added: head/sys/ia64/include/counter.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/ia64/include/counter.h	Mon Apr  8 19:40:53 2013	(r249268)
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2012 Konstantin Belousov <kib@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __MACHINE_COUNTER_H__
+#define __MACHINE_COUNTER_H__
+
+#include <sys/pcpu.h>
+#ifdef INVARIANTS
+#include <sys/proc.h>
+#endif
+
+#define	counter_enter()	critical_enter()
+#define	counter_exit()	critical_exit()
+
+#define	counter_u64_add_protected(c, inc)	do {	\
+	CRITICAL_ASSERT(curthread);			\
+	*(uint64_t *)zpcpu_get(c) += (inc);		\
+} while (0)
+
+static inline void
+counter_u64_add(counter_u64_t c, int64_t inc)
+{
+
+	counter_enter();
+	counter_u64_add_protected(c, inc);
+	counter_exit();
+}
+
+#endif	/* ! __MACHINE_COUNTER_H__ */

Added: head/sys/kern/subr_counter.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/kern/subr_counter.c	Mon Apr  8 19:40:53 2013	(r249268)
@@ -0,0 +1,109 @@
+/*-
+ * Copyright (c) 2012 Gleb Smirnoff <glebius@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/counter.h>
+#include <sys/kernel.h>
+#include <sys/smp.h>
+#include <sys/sysctl.h>
+#include <vm/uma.h>
+ 
+static uma_zone_t uint64_pcpu_zone;
+
+void
+counter_u64_zero(counter_u64_t c)
+{
+	int i;
+
+	for (i = 0; i < mp_ncpus; i++)
+		*(uint64_t *)((char *)c + sizeof(struct pcpu) * i) = 0;
+}
+
+uint64_t
+counter_u64_fetch(counter_u64_t c)
+{
+	uint64_t r;
+	int i;
+
+	r = 0;
+	for (i = 0; i < mp_ncpus; i++)
+		r += *(uint64_t *)((char *)c + sizeof(struct pcpu) * i);
+
+	return (r);
+}
+
+counter_u64_t
+counter_u64_alloc(int flags)
+{
+	counter_u64_t r;
+
+	r = uma_zalloc(uint64_pcpu_zone, flags);
+	if (r != NULL)
+		counter_u64_zero(r);
+
+	return (r);
+}
+
+void
+counter_u64_free(counter_u64_t c)
+{
+
+	uma_zfree(uint64_pcpu_zone, c);
+}
+
+int
+sysctl_handle_counter_u64(SYSCTL_HANDLER_ARGS)
+{
+	uint64_t out;
+	int error;
+
+	out = counter_u64_fetch(*(counter_u64_t *)arg1);
+
+	error = SYSCTL_OUT(req, &out, sizeof(uint64_t));
+
+	if (error || !req->newptr)
+		return (error);
+
+	/*
+	 * Any write attempt to a counter zeroes it.
+	 */
+	counter_u64_zero(*(counter_u64_t *)arg1);
+
+	return (0);
+}
+
+static void
+counter_startup(void)
+{
+
+	uint64_pcpu_zone = uma_zcreate("uint64 pcpu", sizeof(uint64_t),
+	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_PCPU);
+}
+SYSINIT(counter, SI_SUB_KMEM, SI_ORDER_ANY, counter_startup, NULL);

Added: head/sys/mips/include/counter.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/mips/include/counter.h	Mon Apr  8 19:40:53 2013	(r249268)
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2012 Konstantin Belousov <kib@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __MACHINE_COUNTER_H__
+#define __MACHINE_COUNTER_H__
+
+#include <sys/pcpu.h>
+#ifdef INVARIANTS
+#include <sys/proc.h>
+#endif
+
+#define	counter_enter()	critical_enter()
+#define	counter_exit()	critical_exit()
+
+#define	counter_u64_add_protected(c, inc)	do {	\
+	CRITICAL_ASSERT(curthread);			\
+	*(uint64_t *)zpcpu_get(c) += (inc);		\
+} while (0)
+
+static inline void
+counter_u64_add(counter_u64_t c, int64_t inc)
+{
+
+	counter_enter();
+	counter_u64_add_protected(c, inc);
+	counter_exit();
+}
+
+#endif	/* ! __MACHINE_COUNTER_H__ */

Added: head/sys/pc98/include/counter.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/pc98/include/counter.h	Mon Apr  8 19:40:53 2013	(r249268)
@@ -0,0 +1,6 @@
+/*-
+ * This file is in the public domain.
+ */
+/* $FreeBSD$ */
+
+#include <i386/counter.h>

Added: head/sys/powerpc/include/counter.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/powerpc/include/counter.h	Mon Apr  8 19:40:53 2013	(r249268)
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 2012, 2013 Konstantin Belousov <kib@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __MACHINE_COUNTER_H__
+#define __MACHINE_COUNTER_H__
+
+#include <sys/pcpu.h>
+#ifdef INVARIANTS
+#include <sys/proc.h>
+#endif
+
+#if defined(AIM) && defined(__powerpc64__)
+
+#define	counter_enter()	do {} while (0)
+#define	counter_exit()	do {} while (0)
+
+#define	counter_u64_add_protected(c, i)	counter_u64_add(c, i)
+
+static inline void
+counter_u64_add(counter_u64_t c, int64_t inc)
+{
+	uint64_t ccpu, old;
+
+	__asm __volatile("\n"
+      "1:\n\t"
+	    "mfsprg	%0, 0\n\t"
+	    "ldarx	%1, %0, %2\n\t"
+	    "add	%1, %1, %3\n\t"
+	    "stdcx.	%1, %0, %2\n\t"
+	    "bne-	1b"
+	    : "=&b" (ccpu), "=&r" (old)
+	    : "r" ((char *)c - (char *)&__pcpu[0]), "r" (inc)
+	    : "cc", "memory");
+}
+
+#else	/* !AIM || !64bit */
+
+#define	counter_enter()	critical_enter()
+#define	counter_exit()	critical_exit()
+
+#define	counter_u64_add_protected(c, inc)	do {	\
+	CRITICAL_ASSERT(curthread);			\
+	*(uint64_t *)zpcpu_get(c) += (inc);		\
+} while (0)
+
+static inline void
+counter_u64_add(counter_u64_t c, int64_t inc)
+{
+
+	counter_enter();
+	counter_u64_add_protected(c, inc);
+	counter_exit();
+}
+
+#endif	/* AIM 64bit */
+
+#endif	/* ! __MACHINE_COUNTER_H__ */

Added: head/sys/sparc64/include/counter.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/sparc64/include/counter.h	Mon Apr  8 19:40:53 2013	(r249268)
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2012 Konstantin Belousov <kib@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __MACHINE_COUNTER_H__
+#define __MACHINE_COUNTER_H__
+
+#include <sys/pcpu.h>
+#ifdef INVARIANTS
+#include <sys/proc.h>
+#endif
+
+#define	counter_enter()	critical_enter()
+#define	counter_exit()	critical_exit()
+
+#define	counter_u64_add_protected(c, inc)	do {	\
+	CRITICAL_ASSERT(curthread);			\
+	*(uint64_t *)zpcpu_get(c) += (inc);		\
+} while (0)
+
+static inline void
+counter_u64_add(counter_u64_t c, int64_t inc)
+{
+
+	counter_enter();
+	counter_u64_add_protected(c, inc);
+	counter_exit();
+}
+
+#endif	/* ! __MACHINE_COUNTER_H__ */

Added: head/sys/sys/counter.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/sys/counter.h	Mon Apr  8 19:40:53 2013	(r249268)
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 2012 Gleb Smirnoff <glebius@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __SYS_COUNTER_H__
+#define __SYS_COUNTER_H__
+
+typedef uint64_t *counter_u64_t;
+
+#include <machine/counter.h>
+
+counter_u64_t	counter_u64_alloc(int);
+void		counter_u64_free(counter_u64_t);
+
+void		counter_u64_zero(counter_u64_t);
+uint64_t	counter_u64_fetch(counter_u64_t);
+
+#endif	/* ! __SYS_COUNTER_H__ */

Modified: head/sys/sys/sysctl.h
==============================================================================
--- head/sys/sys/sysctl.h	Mon Apr  8 19:23:22 2013	(r249267)
+++ head/sys/sys/sysctl.h	Mon Apr  8 19:40:53 2013	(r249268)
@@ -184,6 +184,7 @@ int sysctl_handle_long(SYSCTL_HANDLER_AR
 int sysctl_handle_64(SYSCTL_HANDLER_ARGS);
 int sysctl_handle_string(SYSCTL_HANDLER_ARGS);
 int sysctl_handle_opaque(SYSCTL_HANDLER_ARGS);
+int sysctl_handle_counter_u64(SYSCTL_HANDLER_ARGS);
 
 int sysctl_dpcpu_int(SYSCTL_HANDLER_ARGS);
 int sysctl_dpcpu_long(SYSCTL_HANDLER_ARGS);
@@ -379,6 +380,19 @@ SYSCTL_ALLOWED_TYPES(UINT64, uint64_t *a
 	    SYSCTL_ADD_ASSERT_TYPE(UINT64, ptr), 0,			\
 	    sysctl_handle_64, "QU", __DESCR(descr))
 
+/* Oid for a 64-bin unsigned counter(9).  The pointer must be non NULL. */
+#define	SYSCTL_COUNTER_U64(parent, nbr, name, access, ptr, val, descr)	\
+	SYSCTL_ASSERT_TYPE(UINT64, ptr, parent, name);			\
+	SYSCTL_OID(parent, nbr, name,					\
+	    CTLTYPE_U64 | CTLFLAG_MPSAFE | (access),			\
+	    ptr, val, sysctl_handle_counter_u64, "QU", descr)
+
+#define	SYSCTL_ADD_COUNTER_U64(ctx, parent, nbr, name, access, ptr, descr)\
+	sysctl_add_oid(ctx, parent, nbr, name,				\
+	    CTLTYPE_U64 | CTLFLAG_MPSAFE | (access),			\
+	    SYSCTL_ADD_ASSERT_TYPE(UINT64, ptr), 0,			\
+	    sysctl_handle_counter_u64, "QU", __DESCR(descr))
+
 /* Oid for an opaque object.  Specified by a pointer and a length. */
 #define SYSCTL_OPAQUE(parent, nbr, name, access, ptr, len, fmt, descr) \
 	SYSCTL_OID(parent, nbr, name, CTLTYPE_OPAQUE|(access), \



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201304081940.r38JerAB096616>