1*4e76af6aSGleb Smirnoff /*- 2*4e76af6aSGleb Smirnoff * Copyright (c) 2012 Gleb Smirnoff <glebius@FreeBSD.org> 3*4e76af6aSGleb Smirnoff * All rights reserved. 4*4e76af6aSGleb Smirnoff * 5*4e76af6aSGleb Smirnoff * Redistribution and use in source and binary forms, with or without 6*4e76af6aSGleb Smirnoff * modification, are permitted provided that the following conditions 7*4e76af6aSGleb Smirnoff * are met: 8*4e76af6aSGleb Smirnoff * 1. Redistributions of source code must retain the above copyright 9*4e76af6aSGleb Smirnoff * notice, this list of conditions and the following disclaimer. 10*4e76af6aSGleb Smirnoff * 2. Redistributions in binary form must reproduce the above copyright 11*4e76af6aSGleb Smirnoff * notice, this list of conditions and the following disclaimer in the 12*4e76af6aSGleb Smirnoff * documentation and/or other materials provided with the distribution. 13*4e76af6aSGleb Smirnoff * 14*4e76af6aSGleb Smirnoff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*4e76af6aSGleb Smirnoff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*4e76af6aSGleb Smirnoff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*4e76af6aSGleb Smirnoff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*4e76af6aSGleb Smirnoff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*4e76af6aSGleb Smirnoff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*4e76af6aSGleb Smirnoff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*4e76af6aSGleb Smirnoff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*4e76af6aSGleb Smirnoff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*4e76af6aSGleb Smirnoff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*4e76af6aSGleb Smirnoff * SUCH DAMAGE. 25*4e76af6aSGleb Smirnoff */ 26*4e76af6aSGleb Smirnoff 27*4e76af6aSGleb Smirnoff #include <sys/cdefs.h> 28*4e76af6aSGleb Smirnoff __FBSDID("$FreeBSD$"); 29*4e76af6aSGleb Smirnoff 30*4e76af6aSGleb Smirnoff #include <sys/param.h> 31*4e76af6aSGleb Smirnoff #include <sys/systm.h> 32*4e76af6aSGleb Smirnoff #include <sys/counter.h> 33*4e76af6aSGleb Smirnoff #include <sys/kernel.h> 34*4e76af6aSGleb Smirnoff #include <sys/smp.h> 35*4e76af6aSGleb Smirnoff #include <sys/sysctl.h> 36*4e76af6aSGleb Smirnoff #include <vm/uma.h> 37*4e76af6aSGleb Smirnoff 38*4e76af6aSGleb Smirnoff static uma_zone_t uint64_pcpu_zone; 39*4e76af6aSGleb Smirnoff 40*4e76af6aSGleb Smirnoff void 41*4e76af6aSGleb Smirnoff counter_u64_zero(counter_u64_t c) 42*4e76af6aSGleb Smirnoff { 43*4e76af6aSGleb Smirnoff int i; 44*4e76af6aSGleb Smirnoff 45*4e76af6aSGleb Smirnoff for (i = 0; i < mp_ncpus; i++) 46*4e76af6aSGleb Smirnoff *(uint64_t *)((char *)c + sizeof(struct pcpu) * i) = 0; 47*4e76af6aSGleb Smirnoff } 48*4e76af6aSGleb Smirnoff 49*4e76af6aSGleb Smirnoff uint64_t 50*4e76af6aSGleb Smirnoff counter_u64_fetch(counter_u64_t c) 51*4e76af6aSGleb Smirnoff { 52*4e76af6aSGleb Smirnoff uint64_t r; 53*4e76af6aSGleb Smirnoff int i; 54*4e76af6aSGleb Smirnoff 55*4e76af6aSGleb Smirnoff r = 0; 56*4e76af6aSGleb Smirnoff for (i = 0; i < mp_ncpus; i++) 57*4e76af6aSGleb Smirnoff r += *(uint64_t *)((char *)c + sizeof(struct pcpu) * i); 58*4e76af6aSGleb Smirnoff 59*4e76af6aSGleb Smirnoff return (r); 60*4e76af6aSGleb Smirnoff } 61*4e76af6aSGleb Smirnoff 62*4e76af6aSGleb Smirnoff counter_u64_t 63*4e76af6aSGleb Smirnoff counter_u64_alloc(int flags) 64*4e76af6aSGleb Smirnoff { 65*4e76af6aSGleb Smirnoff counter_u64_t r; 66*4e76af6aSGleb Smirnoff 67*4e76af6aSGleb Smirnoff r = uma_zalloc(uint64_pcpu_zone, flags); 68*4e76af6aSGleb Smirnoff if (r != NULL) 69*4e76af6aSGleb Smirnoff counter_u64_zero(r); 70*4e76af6aSGleb Smirnoff 71*4e76af6aSGleb Smirnoff return (r); 72*4e76af6aSGleb Smirnoff } 73*4e76af6aSGleb Smirnoff 74*4e76af6aSGleb Smirnoff void 75*4e76af6aSGleb Smirnoff counter_u64_free(counter_u64_t c) 76*4e76af6aSGleb Smirnoff { 77*4e76af6aSGleb Smirnoff 78*4e76af6aSGleb Smirnoff uma_zfree(uint64_pcpu_zone, c); 79*4e76af6aSGleb Smirnoff } 80*4e76af6aSGleb Smirnoff 81*4e76af6aSGleb Smirnoff int 82*4e76af6aSGleb Smirnoff sysctl_handle_counter_u64(SYSCTL_HANDLER_ARGS) 83*4e76af6aSGleb Smirnoff { 84*4e76af6aSGleb Smirnoff uint64_t out; 85*4e76af6aSGleb Smirnoff int error; 86*4e76af6aSGleb Smirnoff 87*4e76af6aSGleb Smirnoff out = counter_u64_fetch(*(counter_u64_t *)arg1); 88*4e76af6aSGleb Smirnoff 89*4e76af6aSGleb Smirnoff error = SYSCTL_OUT(req, &out, sizeof(uint64_t)); 90*4e76af6aSGleb Smirnoff 91*4e76af6aSGleb Smirnoff if (error || !req->newptr) 92*4e76af6aSGleb Smirnoff return (error); 93*4e76af6aSGleb Smirnoff 94*4e76af6aSGleb Smirnoff /* 95*4e76af6aSGleb Smirnoff * Any write attempt to a counter zeroes it. 96*4e76af6aSGleb Smirnoff */ 97*4e76af6aSGleb Smirnoff counter_u64_zero(*(counter_u64_t *)arg1); 98*4e76af6aSGleb Smirnoff 99*4e76af6aSGleb Smirnoff return (0); 100*4e76af6aSGleb Smirnoff } 101*4e76af6aSGleb Smirnoff 102*4e76af6aSGleb Smirnoff static void 103*4e76af6aSGleb Smirnoff counter_startup(void) 104*4e76af6aSGleb Smirnoff { 105*4e76af6aSGleb Smirnoff 106*4e76af6aSGleb Smirnoff uint64_pcpu_zone = uma_zcreate("uint64 pcpu", sizeof(uint64_t), 107*4e76af6aSGleb Smirnoff NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_PCPU); 108*4e76af6aSGleb Smirnoff } 109*4e76af6aSGleb Smirnoff SYSINIT(counter, SI_SUB_KMEM, SI_ORDER_ANY, counter_startup, NULL); 110