xref: /minix3/external/bsd/bind/dist/lib/isc/stats.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: stats.c,v 1.5 2014/12/10 04:37:59 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2009, 2012-2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  *
6*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
7*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
8*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
9*00b67f09SDavid van Moolenbroek  *
10*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
17*00b67f09SDavid van Moolenbroek  */
18*00b67f09SDavid van Moolenbroek 
19*00b67f09SDavid van Moolenbroek /* Id */
20*00b67f09SDavid van Moolenbroek 
21*00b67f09SDavid van Moolenbroek /*! \file */
22*00b67f09SDavid van Moolenbroek 
23*00b67f09SDavid van Moolenbroek #include <config.h>
24*00b67f09SDavid van Moolenbroek 
25*00b67f09SDavid van Moolenbroek #include <string.h>
26*00b67f09SDavid van Moolenbroek 
27*00b67f09SDavid van Moolenbroek #include <isc/atomic.h>
28*00b67f09SDavid van Moolenbroek #include <isc/buffer.h>
29*00b67f09SDavid van Moolenbroek #include <isc/magic.h>
30*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
31*00b67f09SDavid van Moolenbroek #include <isc/platform.h>
32*00b67f09SDavid van Moolenbroek #include <isc/print.h>
33*00b67f09SDavid van Moolenbroek #include <isc/rwlock.h>
34*00b67f09SDavid van Moolenbroek #include <isc/stats.h>
35*00b67f09SDavid van Moolenbroek #include <isc/util.h>
36*00b67f09SDavid van Moolenbroek 
37*00b67f09SDavid van Moolenbroek #define ISC_STATS_MAGIC			ISC_MAGIC('S', 't', 'a', 't')
38*00b67f09SDavid van Moolenbroek #define ISC_STATS_VALID(x)		ISC_MAGIC_VALID(x, ISC_STATS_MAGIC)
39*00b67f09SDavid van Moolenbroek 
40*00b67f09SDavid van Moolenbroek #ifndef ISC_STATS_USEMULTIFIELDS
41*00b67f09SDavid van Moolenbroek #if defined(ISC_RWLOCK_USEATOMIC) && defined(ISC_PLATFORM_HAVEXADD) && !defined(ISC_PLATFORM_HAVEXADDQ)
42*00b67f09SDavid van Moolenbroek #define ISC_STATS_USEMULTIFIELDS 1
43*00b67f09SDavid van Moolenbroek #else
44*00b67f09SDavid van Moolenbroek #define ISC_STATS_USEMULTIFIELDS 0
45*00b67f09SDavid van Moolenbroek #endif
46*00b67f09SDavid van Moolenbroek #endif	/* ISC_STATS_USEMULTIFIELDS */
47*00b67f09SDavid van Moolenbroek 
48*00b67f09SDavid van Moolenbroek #if ISC_STATS_USEMULTIFIELDS
49*00b67f09SDavid van Moolenbroek typedef struct {
50*00b67f09SDavid van Moolenbroek 	isc_uint32_t hi;
51*00b67f09SDavid van Moolenbroek 	isc_uint32_t lo;
52*00b67f09SDavid van Moolenbroek } isc_stat_t;
53*00b67f09SDavid van Moolenbroek #else
54*00b67f09SDavid van Moolenbroek typedef isc_uint64_t isc_stat_t;
55*00b67f09SDavid van Moolenbroek #endif
56*00b67f09SDavid van Moolenbroek 
57*00b67f09SDavid van Moolenbroek struct isc_stats {
58*00b67f09SDavid van Moolenbroek 	/*% Unlocked */
59*00b67f09SDavid van Moolenbroek 	unsigned int	magic;
60*00b67f09SDavid van Moolenbroek 	isc_mem_t	*mctx;
61*00b67f09SDavid van Moolenbroek 	int		ncounters;
62*00b67f09SDavid van Moolenbroek 
63*00b67f09SDavid van Moolenbroek 	isc_mutex_t	lock;
64*00b67f09SDavid van Moolenbroek 	unsigned int	references; /* locked by lock */
65*00b67f09SDavid van Moolenbroek 
66*00b67f09SDavid van Moolenbroek 	/*%
67*00b67f09SDavid van Moolenbroek 	 * Locked by counterlock or unlocked if efficient rwlock is not
68*00b67f09SDavid van Moolenbroek 	 * available.
69*00b67f09SDavid van Moolenbroek 	 */
70*00b67f09SDavid van Moolenbroek #ifdef ISC_RWLOCK_USEATOMIC
71*00b67f09SDavid van Moolenbroek 	isc_rwlock_t	counterlock;
72*00b67f09SDavid van Moolenbroek #endif
73*00b67f09SDavid van Moolenbroek 	isc_stat_t	*counters;
74*00b67f09SDavid van Moolenbroek 
75*00b67f09SDavid van Moolenbroek 	/*%
76*00b67f09SDavid van Moolenbroek 	 * We don't want to lock the counters while we are dumping, so we first
77*00b67f09SDavid van Moolenbroek 	 * copy the current counter values into a local array.  This buffer
78*00b67f09SDavid van Moolenbroek 	 * will be used as the copy destination.  It's allocated on creation
79*00b67f09SDavid van Moolenbroek 	 * of the stats structure so that the dump operation won't fail due
80*00b67f09SDavid van Moolenbroek 	 * to memory allocation failure.
81*00b67f09SDavid van Moolenbroek 	 * XXX: this approach is weird for non-threaded build because the
82*00b67f09SDavid van Moolenbroek 	 * additional memory and the copy overhead could be avoided.  We prefer
83*00b67f09SDavid van Moolenbroek 	 * simplicity here, however, under the assumption that this function
84*00b67f09SDavid van Moolenbroek 	 * should be only rarely called.
85*00b67f09SDavid van Moolenbroek 	 */
86*00b67f09SDavid van Moolenbroek 	isc_uint64_t	*copiedcounters;
87*00b67f09SDavid van Moolenbroek };
88*00b67f09SDavid van Moolenbroek 
89*00b67f09SDavid van Moolenbroek static isc_result_t
create_stats(isc_mem_t * mctx,int ncounters,isc_stats_t ** statsp)90*00b67f09SDavid van Moolenbroek create_stats(isc_mem_t *mctx, int ncounters, isc_stats_t **statsp) {
91*00b67f09SDavid van Moolenbroek 	isc_stats_t *stats;
92*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
93*00b67f09SDavid van Moolenbroek 
94*00b67f09SDavid van Moolenbroek 	REQUIRE(statsp != NULL && *statsp == NULL);
95*00b67f09SDavid van Moolenbroek 
96*00b67f09SDavid van Moolenbroek 	stats = isc_mem_get(mctx, sizeof(*stats));
97*00b67f09SDavid van Moolenbroek 	if (stats == NULL)
98*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
99*00b67f09SDavid van Moolenbroek 
100*00b67f09SDavid van Moolenbroek 	result = isc_mutex_init(&stats->lock);
101*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
102*00b67f09SDavid van Moolenbroek 		goto clean_stats;
103*00b67f09SDavid van Moolenbroek 
104*00b67f09SDavid van Moolenbroek 	stats->counters = isc_mem_get(mctx, sizeof(isc_stat_t) * ncounters);
105*00b67f09SDavid van Moolenbroek 	if (stats->counters == NULL) {
106*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOMEMORY;
107*00b67f09SDavid van Moolenbroek 		goto clean_mutex;
108*00b67f09SDavid van Moolenbroek 	}
109*00b67f09SDavid van Moolenbroek 	stats->copiedcounters = isc_mem_get(mctx,
110*00b67f09SDavid van Moolenbroek 					    sizeof(isc_uint64_t) * ncounters);
111*00b67f09SDavid van Moolenbroek 	if (stats->copiedcounters == NULL) {
112*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOMEMORY;
113*00b67f09SDavid van Moolenbroek 		goto clean_counters;
114*00b67f09SDavid van Moolenbroek 	}
115*00b67f09SDavid van Moolenbroek 
116*00b67f09SDavid van Moolenbroek #ifdef ISC_RWLOCK_USEATOMIC
117*00b67f09SDavid van Moolenbroek 	result = isc_rwlock_init(&stats->counterlock, 0, 0);
118*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
119*00b67f09SDavid van Moolenbroek 		goto clean_copiedcounters;
120*00b67f09SDavid van Moolenbroek #endif
121*00b67f09SDavid van Moolenbroek 
122*00b67f09SDavid van Moolenbroek 	stats->references = 1;
123*00b67f09SDavid van Moolenbroek 	memset(stats->counters, 0, sizeof(isc_stat_t) * ncounters);
124*00b67f09SDavid van Moolenbroek 	stats->mctx = NULL;
125*00b67f09SDavid van Moolenbroek 	isc_mem_attach(mctx, &stats->mctx);
126*00b67f09SDavid van Moolenbroek 	stats->ncounters = ncounters;
127*00b67f09SDavid van Moolenbroek 	stats->magic = ISC_STATS_MAGIC;
128*00b67f09SDavid van Moolenbroek 
129*00b67f09SDavid van Moolenbroek 	*statsp = stats;
130*00b67f09SDavid van Moolenbroek 
131*00b67f09SDavid van Moolenbroek 	return (result);
132*00b67f09SDavid van Moolenbroek 
133*00b67f09SDavid van Moolenbroek clean_counters:
134*00b67f09SDavid van Moolenbroek 	isc_mem_put(mctx, stats->counters, sizeof(isc_stat_t) * ncounters);
135*00b67f09SDavid van Moolenbroek 
136*00b67f09SDavid van Moolenbroek #ifdef ISC_RWLOCK_USEATOMIC
137*00b67f09SDavid van Moolenbroek clean_copiedcounters:
138*00b67f09SDavid van Moolenbroek 	isc_mem_put(mctx, stats->copiedcounters,
139*00b67f09SDavid van Moolenbroek 		    sizeof(isc_stat_t) * ncounters);
140*00b67f09SDavid van Moolenbroek #endif
141*00b67f09SDavid van Moolenbroek 
142*00b67f09SDavid van Moolenbroek clean_mutex:
143*00b67f09SDavid van Moolenbroek 	DESTROYLOCK(&stats->lock);
144*00b67f09SDavid van Moolenbroek 
145*00b67f09SDavid van Moolenbroek clean_stats:
146*00b67f09SDavid van Moolenbroek 	isc_mem_put(mctx, stats, sizeof(*stats));
147*00b67f09SDavid van Moolenbroek 
148*00b67f09SDavid van Moolenbroek 	return (result);
149*00b67f09SDavid van Moolenbroek }
150*00b67f09SDavid van Moolenbroek 
151*00b67f09SDavid van Moolenbroek void
isc_stats_attach(isc_stats_t * stats,isc_stats_t ** statsp)152*00b67f09SDavid van Moolenbroek isc_stats_attach(isc_stats_t *stats, isc_stats_t **statsp) {
153*00b67f09SDavid van Moolenbroek 	REQUIRE(ISC_STATS_VALID(stats));
154*00b67f09SDavid van Moolenbroek 	REQUIRE(statsp != NULL && *statsp == NULL);
155*00b67f09SDavid van Moolenbroek 
156*00b67f09SDavid van Moolenbroek 	LOCK(&stats->lock);
157*00b67f09SDavid van Moolenbroek 	stats->references++;
158*00b67f09SDavid van Moolenbroek 	UNLOCK(&stats->lock);
159*00b67f09SDavid van Moolenbroek 
160*00b67f09SDavid van Moolenbroek 	*statsp = stats;
161*00b67f09SDavid van Moolenbroek }
162*00b67f09SDavid van Moolenbroek 
163*00b67f09SDavid van Moolenbroek void
isc_stats_detach(isc_stats_t ** statsp)164*00b67f09SDavid van Moolenbroek isc_stats_detach(isc_stats_t **statsp) {
165*00b67f09SDavid van Moolenbroek 	isc_stats_t *stats;
166*00b67f09SDavid van Moolenbroek 
167*00b67f09SDavid van Moolenbroek 	REQUIRE(statsp != NULL && ISC_STATS_VALID(*statsp));
168*00b67f09SDavid van Moolenbroek 
169*00b67f09SDavid van Moolenbroek 	stats = *statsp;
170*00b67f09SDavid van Moolenbroek 	*statsp = NULL;
171*00b67f09SDavid van Moolenbroek 
172*00b67f09SDavid van Moolenbroek 	LOCK(&stats->lock);
173*00b67f09SDavid van Moolenbroek 	stats->references--;
174*00b67f09SDavid van Moolenbroek 	UNLOCK(&stats->lock);
175*00b67f09SDavid van Moolenbroek 
176*00b67f09SDavid van Moolenbroek 	if (stats->references == 0) {
177*00b67f09SDavid van Moolenbroek 		isc_mem_put(stats->mctx, stats->copiedcounters,
178*00b67f09SDavid van Moolenbroek 			    sizeof(isc_stat_t) * stats->ncounters);
179*00b67f09SDavid van Moolenbroek 		isc_mem_put(stats->mctx, stats->counters,
180*00b67f09SDavid van Moolenbroek 			    sizeof(isc_stat_t) * stats->ncounters);
181*00b67f09SDavid van Moolenbroek 		DESTROYLOCK(&stats->lock);
182*00b67f09SDavid van Moolenbroek #ifdef ISC_RWLOCK_USEATOMIC
183*00b67f09SDavid van Moolenbroek 		isc_rwlock_destroy(&stats->counterlock);
184*00b67f09SDavid van Moolenbroek #endif
185*00b67f09SDavid van Moolenbroek 		isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats));
186*00b67f09SDavid van Moolenbroek 	}
187*00b67f09SDavid van Moolenbroek }
188*00b67f09SDavid van Moolenbroek 
189*00b67f09SDavid van Moolenbroek int
isc_stats_ncounters(isc_stats_t * stats)190*00b67f09SDavid van Moolenbroek isc_stats_ncounters(isc_stats_t *stats) {
191*00b67f09SDavid van Moolenbroek 	REQUIRE(ISC_STATS_VALID(stats));
192*00b67f09SDavid van Moolenbroek 
193*00b67f09SDavid van Moolenbroek 	return (stats->ncounters);
194*00b67f09SDavid van Moolenbroek }
195*00b67f09SDavid van Moolenbroek 
196*00b67f09SDavid van Moolenbroek static inline void
incrementcounter(isc_stats_t * stats,int counter)197*00b67f09SDavid van Moolenbroek incrementcounter(isc_stats_t *stats, int counter) {
198*00b67f09SDavid van Moolenbroek 	isc_int32_t prev;
199*00b67f09SDavid van Moolenbroek 
200*00b67f09SDavid van Moolenbroek #ifdef ISC_RWLOCK_USEATOMIC
201*00b67f09SDavid van Moolenbroek 	/*
202*00b67f09SDavid van Moolenbroek 	 * We use a "read" lock to prevent other threads from reading the
203*00b67f09SDavid van Moolenbroek 	 * counter while we "writing" a counter field.  The write access itself
204*00b67f09SDavid van Moolenbroek 	 * is protected by the atomic operation.
205*00b67f09SDavid van Moolenbroek 	 */
206*00b67f09SDavid van Moolenbroek 	isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_read);
207*00b67f09SDavid van Moolenbroek #endif
208*00b67f09SDavid van Moolenbroek 
209*00b67f09SDavid van Moolenbroek #if ISC_STATS_USEMULTIFIELDS
210*00b67f09SDavid van Moolenbroek 	prev = isc_atomic_xadd((isc_int32_t *)&stats->counters[counter].lo, 1);
211*00b67f09SDavid van Moolenbroek 	/*
212*00b67f09SDavid van Moolenbroek 	 * If the lower 32-bit field overflows, increment the higher field.
213*00b67f09SDavid van Moolenbroek 	 * Note that it's *theoretically* possible that the lower field
214*00b67f09SDavid van Moolenbroek 	 * overlaps again before the higher field is incremented.  It doesn't
215*00b67f09SDavid van Moolenbroek 	 * matter, however, because we don't read the value until
216*00b67f09SDavid van Moolenbroek 	 * isc_stats_copy() is called where the whole process is protected
217*00b67f09SDavid van Moolenbroek 	 * by the write (exclusive) lock.
218*00b67f09SDavid van Moolenbroek 	 */
219*00b67f09SDavid van Moolenbroek 	if (prev == (isc_int32_t)0xffffffff)
220*00b67f09SDavid van Moolenbroek 		isc_atomic_xadd((isc_int32_t *)&stats->counters[counter].hi, 1);
221*00b67f09SDavid van Moolenbroek #elif defined(ISC_PLATFORM_HAVEXADDQ)
222*00b67f09SDavid van Moolenbroek 	UNUSED(prev);
223*00b67f09SDavid van Moolenbroek 	isc_atomic_xaddq((isc_int64_t *)&stats->counters[counter], 1);
224*00b67f09SDavid van Moolenbroek #else
225*00b67f09SDavid van Moolenbroek 	UNUSED(prev);
226*00b67f09SDavid van Moolenbroek 	stats->counters[counter]++;
227*00b67f09SDavid van Moolenbroek #endif
228*00b67f09SDavid van Moolenbroek 
229*00b67f09SDavid van Moolenbroek #ifdef ISC_RWLOCK_USEATOMIC
230*00b67f09SDavid van Moolenbroek 	isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_read);
231*00b67f09SDavid van Moolenbroek #endif
232*00b67f09SDavid van Moolenbroek }
233*00b67f09SDavid van Moolenbroek 
234*00b67f09SDavid van Moolenbroek static inline void
decrementcounter(isc_stats_t * stats,int counter)235*00b67f09SDavid van Moolenbroek decrementcounter(isc_stats_t *stats, int counter) {
236*00b67f09SDavid van Moolenbroek 	isc_int32_t prev;
237*00b67f09SDavid van Moolenbroek 
238*00b67f09SDavid van Moolenbroek #ifdef ISC_RWLOCK_USEATOMIC
239*00b67f09SDavid van Moolenbroek 	isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_read);
240*00b67f09SDavid van Moolenbroek #endif
241*00b67f09SDavid van Moolenbroek 
242*00b67f09SDavid van Moolenbroek #if ISC_STATS_USEMULTIFIELDS
243*00b67f09SDavid van Moolenbroek 	prev = isc_atomic_xadd((isc_int32_t *)&stats->counters[counter].lo, -1);
244*00b67f09SDavid van Moolenbroek 	if (prev == 0)
245*00b67f09SDavid van Moolenbroek 		isc_atomic_xadd((isc_int32_t *)&stats->counters[counter].hi,
246*00b67f09SDavid van Moolenbroek 				-1);
247*00b67f09SDavid van Moolenbroek #elif defined(ISC_PLATFORM_HAVEXADDQ)
248*00b67f09SDavid van Moolenbroek 	UNUSED(prev);
249*00b67f09SDavid van Moolenbroek 	isc_atomic_xaddq((isc_int64_t *)&stats->counters[counter], -1);
250*00b67f09SDavid van Moolenbroek #else
251*00b67f09SDavid van Moolenbroek 	UNUSED(prev);
252*00b67f09SDavid van Moolenbroek 	stats->counters[counter]--;
253*00b67f09SDavid van Moolenbroek #endif
254*00b67f09SDavid van Moolenbroek 
255*00b67f09SDavid van Moolenbroek #ifdef ISC_RWLOCK_USEATOMIC
256*00b67f09SDavid van Moolenbroek 	isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_read);
257*00b67f09SDavid van Moolenbroek #endif
258*00b67f09SDavid van Moolenbroek }
259*00b67f09SDavid van Moolenbroek 
260*00b67f09SDavid van Moolenbroek static void
copy_counters(isc_stats_t * stats)261*00b67f09SDavid van Moolenbroek copy_counters(isc_stats_t *stats) {
262*00b67f09SDavid van Moolenbroek 	int i;
263*00b67f09SDavid van Moolenbroek 
264*00b67f09SDavid van Moolenbroek #ifdef ISC_RWLOCK_USEATOMIC
265*00b67f09SDavid van Moolenbroek 	/*
266*00b67f09SDavid van Moolenbroek 	 * We use a "write" lock before "reading" the statistics counters as
267*00b67f09SDavid van Moolenbroek 	 * an exclusive lock.
268*00b67f09SDavid van Moolenbroek 	 */
269*00b67f09SDavid van Moolenbroek 	isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_write);
270*00b67f09SDavid van Moolenbroek #endif
271*00b67f09SDavid van Moolenbroek 
272*00b67f09SDavid van Moolenbroek #if ISC_STATS_USEMULTIFIELDS
273*00b67f09SDavid van Moolenbroek 	for (i = 0; i < stats->ncounters; i++) {
274*00b67f09SDavid van Moolenbroek 		stats->copiedcounters[i] =
275*00b67f09SDavid van Moolenbroek 				(isc_uint64_t)(stats->counters[i].hi) << 32 |
276*00b67f09SDavid van Moolenbroek 				stats->counters[i].lo;
277*00b67f09SDavid van Moolenbroek 	}
278*00b67f09SDavid van Moolenbroek #else
279*00b67f09SDavid van Moolenbroek 	UNUSED(i);
280*00b67f09SDavid van Moolenbroek 	memmove(stats->copiedcounters, stats->counters,
281*00b67f09SDavid van Moolenbroek 		stats->ncounters * sizeof(isc_stat_t));
282*00b67f09SDavid van Moolenbroek #endif
283*00b67f09SDavid van Moolenbroek 
284*00b67f09SDavid van Moolenbroek #ifdef ISC_RWLOCK_USEATOMIC
285*00b67f09SDavid van Moolenbroek 	isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_write);
286*00b67f09SDavid van Moolenbroek #endif
287*00b67f09SDavid van Moolenbroek }
288*00b67f09SDavid van Moolenbroek 
289*00b67f09SDavid van Moolenbroek isc_result_t
isc_stats_create(isc_mem_t * mctx,isc_stats_t ** statsp,int ncounters)290*00b67f09SDavid van Moolenbroek isc_stats_create(isc_mem_t *mctx, isc_stats_t **statsp, int ncounters) {
291*00b67f09SDavid van Moolenbroek 	REQUIRE(statsp != NULL && *statsp == NULL);
292*00b67f09SDavid van Moolenbroek 
293*00b67f09SDavid van Moolenbroek 	return (create_stats(mctx, ncounters, statsp));
294*00b67f09SDavid van Moolenbroek }
295*00b67f09SDavid van Moolenbroek 
296*00b67f09SDavid van Moolenbroek void
isc_stats_increment(isc_stats_t * stats,isc_statscounter_t counter)297*00b67f09SDavid van Moolenbroek isc_stats_increment(isc_stats_t *stats, isc_statscounter_t counter) {
298*00b67f09SDavid van Moolenbroek 	REQUIRE(ISC_STATS_VALID(stats));
299*00b67f09SDavid van Moolenbroek 	REQUIRE(counter < stats->ncounters);
300*00b67f09SDavid van Moolenbroek 
301*00b67f09SDavid van Moolenbroek 	incrementcounter(stats, (int)counter);
302*00b67f09SDavid van Moolenbroek }
303*00b67f09SDavid van Moolenbroek 
304*00b67f09SDavid van Moolenbroek void
isc_stats_decrement(isc_stats_t * stats,isc_statscounter_t counter)305*00b67f09SDavid van Moolenbroek isc_stats_decrement(isc_stats_t *stats, isc_statscounter_t counter) {
306*00b67f09SDavid van Moolenbroek 	REQUIRE(ISC_STATS_VALID(stats));
307*00b67f09SDavid van Moolenbroek 	REQUIRE(counter < stats->ncounters);
308*00b67f09SDavid van Moolenbroek 
309*00b67f09SDavid van Moolenbroek 	decrementcounter(stats, (int)counter);
310*00b67f09SDavid van Moolenbroek }
311*00b67f09SDavid van Moolenbroek 
312*00b67f09SDavid van Moolenbroek void
isc_stats_dump(isc_stats_t * stats,isc_stats_dumper_t dump_fn,void * arg,unsigned int options)313*00b67f09SDavid van Moolenbroek isc_stats_dump(isc_stats_t *stats, isc_stats_dumper_t dump_fn,
314*00b67f09SDavid van Moolenbroek 	       void *arg, unsigned int options)
315*00b67f09SDavid van Moolenbroek {
316*00b67f09SDavid van Moolenbroek 	int i;
317*00b67f09SDavid van Moolenbroek 
318*00b67f09SDavid van Moolenbroek 	REQUIRE(ISC_STATS_VALID(stats));
319*00b67f09SDavid van Moolenbroek 
320*00b67f09SDavid van Moolenbroek 	copy_counters(stats);
321*00b67f09SDavid van Moolenbroek 
322*00b67f09SDavid van Moolenbroek 	for (i = 0; i < stats->ncounters; i++) {
323*00b67f09SDavid van Moolenbroek 		if ((options & ISC_STATSDUMP_VERBOSE) == 0 &&
324*00b67f09SDavid van Moolenbroek 		    stats->copiedcounters[i] == 0)
325*00b67f09SDavid van Moolenbroek 				continue;
326*00b67f09SDavid van Moolenbroek 		dump_fn((isc_statscounter_t)i, stats->copiedcounters[i], arg);
327*00b67f09SDavid van Moolenbroek 	}
328*00b67f09SDavid van Moolenbroek }
329*00b67f09SDavid van Moolenbroek 
330*00b67f09SDavid van Moolenbroek void
isc_stats_set(isc_stats_t * stats,isc_uint64_t val,isc_statscounter_t counter)331*00b67f09SDavid van Moolenbroek isc_stats_set(isc_stats_t *stats, isc_uint64_t val,
332*00b67f09SDavid van Moolenbroek 	      isc_statscounter_t counter)
333*00b67f09SDavid van Moolenbroek {
334*00b67f09SDavid van Moolenbroek 	REQUIRE(ISC_STATS_VALID(stats));
335*00b67f09SDavid van Moolenbroek 	REQUIRE(counter < stats->ncounters);
336*00b67f09SDavid van Moolenbroek 
337*00b67f09SDavid van Moolenbroek #ifdef ISC_RWLOCK_USEATOMIC
338*00b67f09SDavid van Moolenbroek 	/*
339*00b67f09SDavid van Moolenbroek 	 * We use a "write" lock before "reading" the statistics counters as
340*00b67f09SDavid van Moolenbroek 	 * an exclusive lock.
341*00b67f09SDavid van Moolenbroek 	 */
342*00b67f09SDavid van Moolenbroek 	isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_write);
343*00b67f09SDavid van Moolenbroek #endif
344*00b67f09SDavid van Moolenbroek 
345*00b67f09SDavid van Moolenbroek #if ISC_STATS_USEMULTIFIELDS
346*00b67f09SDavid van Moolenbroek 	stats->counters[counter].hi = (isc_uint32_t)((val >> 32) & 0xffffffff);
347*00b67f09SDavid van Moolenbroek 	stats->counters[counter].lo = (isc_uint32_t)(val & 0xffffffff);
348*00b67f09SDavid van Moolenbroek #else
349*00b67f09SDavid van Moolenbroek 	stats->counters[counter] = val;
350*00b67f09SDavid van Moolenbroek #endif
351*00b67f09SDavid van Moolenbroek 
352*00b67f09SDavid van Moolenbroek #ifdef ISC_RWLOCK_USEATOMIC
353*00b67f09SDavid van Moolenbroek 	isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_write);
354*00b67f09SDavid van Moolenbroek #endif
355*00b67f09SDavid van Moolenbroek }
356*00b67f09SDavid van Moolenbroek 
357