Date: Fri, 23 Nov 2012 13:47:42 +0000 (UTC) From: Gleb Smirnoff <glebius@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r243451 - in projects/counters/sys: conf kern sys Message-ID: <201211231347.qANDlg7N024809@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: glebius Date: Fri Nov 23 13:47:41 2012 New Revision: 243451 URL: http://svnweb.freebsd.org/changeset/base/243451 Log: Prototype a simple API for per-cpu counters, right now only 64-bit. A counter can be allocated, zeroed, freed, incremented and decremented. The incremention/decremention functions are going to MD. Right now amd64 implementation is put into MI file, while the project branch is pre-alpha state. A dummy implementation on 64-bit arch would pin to current CPU, calculate address of counter for this cpu, update it and unpin. We may provide a racy non-pinning interface, that can lead the update going to other's CPU counter. A smart implementation for amd64 does a one-instruction update, thus doesn't require any pinning. This is achieved due to the fact that UMA_ZONE_PCPU zone guarantees us that per-cpu counters are aligned by the size of struct pcpu from each other. And we have address of static struct pcpu in %gs register always. This nice implementation is submitted by kib@. Implementation for 32-bit arches would require critical section for update. Added: projects/counters/sys/kern/subr_counter.c (contents, props changed) projects/counters/sys/sys/counter.h (contents, props changed) Modified: projects/counters/sys/conf/files Modified: projects/counters/sys/conf/files ============================================================================== --- projects/counters/sys/conf/files Fri Nov 23 13:43:51 2012 (r243450) +++ projects/counters/sys/conf/files Fri Nov 23 13:47:41 2012 (r243451) @@ -2667,6 +2667,7 @@ kern/subr_blist.c standard kern/subr_bus.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: projects/counters/sys/kern/subr_counter.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/counters/sys/kern/subr_counter.c Fri Nov 23 13:47:41 2012 (r243451) @@ -0,0 +1,82 @@ +/*- + * 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$ + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/counter.h> +#include <vm/uma.h> + +static uma_zone_t uint64_pcpu_zone; + +void +counter_u64_zero(counter_u64_t c) +{ + + for (int 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; + + r = 0; + for (int 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) + counter_u64_zero(r); + + return (r); +} + +void +counter_u64_free(counter_u64_t c) +{ + + uma_zfree(uint64_pcpu_zone, c); +} + +static void +counter_startup() +{ + + 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: projects/counters/sys/sys/counter.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/counters/sys/sys/counter.h Fri Nov 23 13:47:41 2012 (r243451) @@ -0,0 +1,70 @@ +/*- + * 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. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * 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__ + +#include <sys/param.h> +#include <sys/pcpu.h> +#include <sys/smp.h> + +typedef uint64_t * counter_u64_t; + +/* + * XXXGL: to be MD. Just testing now. + */ +extern struct pcpu __pcpu[1]; + +static __inline void +counter_u64_inc(counter_u64_t c, uint64_t inc) +{ + + __asm __volatile("addq\t%1,%%gs:(%0)" : : + "r" ((char *)c - (char *)&__pcpu[0]), + "r" (inc)); +} + +static __inline void +counter_u64_dec(counter_u64_t c, uint64_t dec) +{ + + __asm __volatile("subq\t%1,%%gs:(%0)" : : + "r" ((char *)c - (char *)&__pcpu[0]), + "r" (dec)); +} + +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__ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201211231347.qANDlg7N024809>