1249268Sglebius/*- 2249268Sglebius * Copyright (c) 2012 Gleb Smirnoff <glebius@FreeBSD.org> 3249268Sglebius * All rights reserved. 4249268Sglebius * 5249268Sglebius * Redistribution and use in source and binary forms, with or without 6249268Sglebius * modification, are permitted provided that the following conditions 7249268Sglebius * are met: 8249268Sglebius * 1. Redistributions of source code must retain the above copyright 9249268Sglebius * notice, this list of conditions and the following disclaimer. 10249268Sglebius * 2. Redistributions in binary form must reproduce the above copyright 11249268Sglebius * notice, this list of conditions and the following disclaimer in the 12249268Sglebius * documentation and/or other materials provided with the distribution. 13249268Sglebius * 14249268Sglebius * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15249268Sglebius * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16249268Sglebius * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17249268Sglebius * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18249268Sglebius * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19249268Sglebius * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20249268Sglebius * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21249268Sglebius * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22249268Sglebius * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23249268Sglebius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24249268Sglebius * SUCH DAMAGE. 25249268Sglebius */ 26249268Sglebius 27249268Sglebius#include <sys/cdefs.h> 28249268Sglebius__FBSDID("$FreeBSD$"); 29249268Sglebius 30249268Sglebius#include <sys/param.h> 31249268Sglebius#include <sys/systm.h> 32249268Sglebius#include <sys/kernel.h> 33252434Skib#include <sys/lock.h> 34252434Skib#include <sys/mutex.h> 35252434Skib#include <sys/proc.h> 36252434Skib#include <sys/sched.h> 37249268Sglebius#include <sys/smp.h> 38249268Sglebius#include <sys/sysctl.h> 39249268Sglebius#include <vm/uma.h> 40252434Skib 41252434Skib#define IN_SUBR_COUNTER_C 42252434Skib#include <sys/counter.h> 43249268Sglebius 44249268Sglebiusvoid 45249268Sglebiuscounter_u64_zero(counter_u64_t c) 46249268Sglebius{ 47249268Sglebius 48252434Skib counter_u64_zero_inline(c); 49249268Sglebius} 50249268Sglebius 51249268Sglebiusuint64_t 52249268Sglebiuscounter_u64_fetch(counter_u64_t c) 53249268Sglebius{ 54249268Sglebius 55252434Skib return (counter_u64_fetch_inline(c)); 56249268Sglebius} 57249268Sglebius 58249268Sglebiuscounter_u64_t 59249268Sglebiuscounter_u64_alloc(int flags) 60249268Sglebius{ 61249268Sglebius counter_u64_t r; 62249268Sglebius 63261725Sglebius r = uma_zalloc(pcpu_zone_64, flags); 64249268Sglebius if (r != NULL) 65249268Sglebius counter_u64_zero(r); 66249268Sglebius 67249268Sglebius return (r); 68249268Sglebius} 69249268Sglebius 70249268Sglebiusvoid 71249268Sglebiuscounter_u64_free(counter_u64_t c) 72249268Sglebius{ 73249268Sglebius 74261725Sglebius uma_zfree(pcpu_zone_64, c); 75249268Sglebius} 76249268Sglebius 77249268Sglebiusint 78249268Sglebiussysctl_handle_counter_u64(SYSCTL_HANDLER_ARGS) 79249268Sglebius{ 80249268Sglebius uint64_t out; 81249268Sglebius int error; 82249268Sglebius 83249268Sglebius out = counter_u64_fetch(*(counter_u64_t *)arg1); 84249268Sglebius 85249268Sglebius error = SYSCTL_OUT(req, &out, sizeof(uint64_t)); 86249268Sglebius 87249268Sglebius if (error || !req->newptr) 88249268Sglebius return (error); 89249268Sglebius 90249268Sglebius /* 91249268Sglebius * Any write attempt to a counter zeroes it. 92249268Sglebius */ 93249268Sglebius counter_u64_zero(*(counter_u64_t *)arg1); 94249268Sglebius 95249268Sglebius return (0); 96249268Sglebius} 97296880Sglebius 98296880Sglebiusint 99296880Sglebiussysctl_handle_counter_u64_array(SYSCTL_HANDLER_ARGS) 100296880Sglebius{ 101296880Sglebius uint64_t *out; 102296880Sglebius int error; 103296880Sglebius 104296880Sglebius out = malloc(arg2 * sizeof(uint64_t), M_TEMP, M_WAITOK); 105296880Sglebius for (int i = 0; i < arg2; i++) 106296880Sglebius out[i] = counter_u64_fetch(((counter_u64_t *)arg1)[i]); 107296880Sglebius 108296880Sglebius error = SYSCTL_OUT(req, out, arg2 * sizeof(uint64_t)); 109296883Sglebius free(out, M_TEMP); 110296880Sglebius 111296880Sglebius if (error || !req->newptr) 112296880Sglebius return (error); 113296880Sglebius 114296880Sglebius /* 115296880Sglebius * Any write attempt to a counter zeroes it. 116296880Sglebius */ 117296880Sglebius for (int i = 0; i < arg2; i++) 118296880Sglebius counter_u64_zero(((counter_u64_t *)arg1)[i]); 119296880Sglebius 120296880Sglebius return (0); 121296880Sglebius} 122