Home | History | Annotate | Line # | Download | only in isc
stats.c revision 1.4.4.1
      1 /*	$NetBSD: stats.c,v 1.4.4.1 2019/09/12 19:18:16 martin Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * This Source Code Form is subject to the terms of the Mozilla Public
      7  * License, v. 2.0. If a copy of the MPL was not distributed with this
      8  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
      9  *
     10  * See the COPYRIGHT file distributed with this work for additional
     11  * information regarding copyright ownership.
     12  */
     13 
     14 
     15 /*! \file */
     16 
     17 #include <config.h>
     18 
     19 #include <inttypes.h>
     20 #include <string.h>
     21 
     22 #include <isc/atomic.h>
     23 #include <isc/buffer.h>
     24 #include <isc/magic.h>
     25 #include <isc/mem.h>
     26 #include <isc/platform.h>
     27 #include <isc/print.h>
     28 #include <isc/refcount.h>
     29 #include <isc/stats.h>
     30 #include <isc/util.h>
     31 
     32 #define ISC_STATS_MAGIC			ISC_MAGIC('S', 't', 'a', 't')
     33 #define ISC_STATS_VALID(x)		ISC_MAGIC_VALID(x, ISC_STATS_MAGIC)
     34 
     35 #if (defined(_WIN32) && !defined(_WIN64)) || !defined(_LP64)
     36 typedef atomic_int_fast32_t isc_stat_t;
     37 #else
     38 typedef atomic_int_fast64_t isc_stat_t;
     39 #endif
     40 
     41 struct isc_stats {
     42 	unsigned int		magic;
     43 	isc_mem_t		*mctx;
     44 	isc_refcount_t		refs;
     45 	int			ncounters;
     46 	isc_stat_t		*counters;
     47 };
     48 
     49 static isc_result_t
     50 create_stats(isc_mem_t *mctx, int ncounters, isc_stats_t **statsp) {
     51 	isc_stats_t *stats;
     52 
     53 	REQUIRE(statsp != NULL && *statsp == NULL);
     54 
     55 	stats = isc_mem_get(mctx, sizeof(*stats));
     56 	stats->counters = isc_mem_get(mctx, sizeof(isc_stat_t) * ncounters);
     57 	isc_refcount_init(&stats->refs, 1);
     58 	memset(stats->counters, 0, sizeof(isc_stat_t) * ncounters);
     59 	stats->mctx = NULL;
     60 	isc_mem_attach(mctx, &stats->mctx);
     61 	stats->ncounters = ncounters;
     62 	stats->magic = ISC_STATS_MAGIC;
     63 	*statsp = stats;
     64 
     65 	return (ISC_R_SUCCESS);
     66 }
     67 
     68 void
     69 isc_stats_attach(isc_stats_t *stats, isc_stats_t **statsp) {
     70 	REQUIRE(ISC_STATS_VALID(stats));
     71 	REQUIRE(statsp != NULL && *statsp == NULL);
     72 
     73 	isc_refcount_increment(&stats->refs);
     74 	*statsp = stats;
     75 }
     76 
     77 void
     78 isc_stats_detach(isc_stats_t **statsp) {
     79 	isc_stats_t *stats;
     80 
     81 	REQUIRE(statsp != NULL && ISC_STATS_VALID(*statsp));
     82 
     83 	stats = *statsp;
     84 	*statsp = NULL;
     85 
     86 	if (isc_refcount_decrement(&stats->refs) == 1) {
     87 		isc_mem_put(stats->mctx, stats->counters,
     88 			    sizeof(isc_stat_t) * stats->ncounters);
     89 		isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats));
     90 	}
     91 }
     92 
     93 int
     94 isc_stats_ncounters(isc_stats_t *stats) {
     95 	REQUIRE(ISC_STATS_VALID(stats));
     96 
     97 	return (stats->ncounters);
     98 }
     99 
    100 isc_result_t
    101 isc_stats_create(isc_mem_t *mctx, isc_stats_t **statsp, int ncounters) {
    102 	REQUIRE(statsp != NULL && *statsp == NULL);
    103 
    104 	return (create_stats(mctx, ncounters, statsp));
    105 }
    106 
    107 void
    108 isc_stats_increment(isc_stats_t *stats, isc_statscounter_t counter) {
    109 	REQUIRE(ISC_STATS_VALID(stats));
    110 	REQUIRE(counter < stats->ncounters);
    111 
    112 	atomic_fetch_add_explicit(&stats->counters[counter], 1,
    113 				  memory_order_relaxed);
    114 }
    115 
    116 void
    117 isc_stats_decrement(isc_stats_t *stats, isc_statscounter_t counter) {
    118 	REQUIRE(ISC_STATS_VALID(stats));
    119 	REQUIRE(counter < stats->ncounters);
    120 
    121 	atomic_fetch_sub_explicit(&stats->counters[counter], 1,
    122 				  memory_order_relaxed);
    123 }
    124 
    125 void
    126 isc_stats_dump(isc_stats_t *stats, isc_stats_dumper_t dump_fn,
    127 	       void *arg, unsigned int options)
    128 {
    129 	int i;
    130 
    131 	REQUIRE(ISC_STATS_VALID(stats));
    132 
    133 	for (i = 0; i < stats->ncounters; i++) {
    134 		uint32_t counter = atomic_load_explicit(&stats->counters[i],
    135 							memory_order_relaxed);
    136 		if ((options & ISC_STATSDUMP_VERBOSE) == 0 && counter == 0) {
    137 			continue;
    138 		}
    139 		dump_fn((isc_statscounter_t)i, counter, arg);
    140 	}
    141 }
    142 
    143 void
    144 isc_stats_set(isc_stats_t *stats, uint64_t val,
    145 	      isc_statscounter_t counter)
    146 {
    147 	REQUIRE(ISC_STATS_VALID(stats));
    148 	REQUIRE(counter < stats->ncounters);
    149 
    150 	atomic_store_explicit(&stats->counters[counter], val,
    151 			      memory_order_relaxed);
    152 }
    153