Coverage Report

Created: 2025-08-26 06:59

/src/bind9/lib/isc/counter.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4
 * SPDX-License-Identifier: MPL-2.0
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 https://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
/*! \file */
15
16
#include <stdbool.h>
17
#include <stddef.h>
18
19
#include <isc/atomic.h>
20
#include <isc/counter.h>
21
#include <isc/magic.h>
22
#include <isc/mem.h>
23
#include <isc/refcount.h>
24
#include <isc/util.h>
25
26
0
#define COUNTER_MAGIC  ISC_MAGIC('C', 'n', 't', 'r')
27
#define VALID_COUNTER(r) ISC_MAGIC_VALID(r, COUNTER_MAGIC)
28
29
struct isc_counter {
30
  unsigned int magic;
31
  isc_mem_t *mctx;
32
  isc_refcount_t references;
33
  atomic_uint_fast32_t limit;
34
  atomic_uint_fast32_t used;
35
};
36
37
void
38
0
isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp) {
39
0
  REQUIRE(counterp != NULL && *counterp == NULL);
40
41
0
  isc_counter_t *counter = isc_mem_get(mctx, sizeof(*counter));
42
0
  *counter = (isc_counter_t){
43
0
    .magic = COUNTER_MAGIC,
44
0
    .references = 1,
45
0
    .limit = limit,
46
0
  };
47
48
0
  isc_mem_attach(mctx, &counter->mctx);
49
50
0
  *counterp = counter;
51
0
}
52
53
isc_result_t
54
0
isc_counter_increment(isc_counter_t *counter) {
55
0
  uint_fast32_t used = atomic_fetch_add_relaxed(&counter->used, 1) + 1;
56
0
  uint_fast32_t limit = atomic_load_acquire(&counter->limit);
57
58
0
  if (limit != 0 && used >= limit) {
59
0
    return ISC_R_QUOTA;
60
0
  }
61
62
0
  return ISC_R_SUCCESS;
63
0
}
64
65
unsigned int
66
0
isc_counter_used(isc_counter_t *counter) {
67
0
  REQUIRE(VALID_COUNTER(counter));
68
69
0
  return atomic_load_relaxed(&counter->used);
70
0
}
71
72
void
73
0
isc_counter_setlimit(isc_counter_t *counter, int limit) {
74
0
  REQUIRE(VALID_COUNTER(counter));
75
76
0
  atomic_store_release(&counter->limit, limit);
77
0
}
78
79
unsigned int
80
0
isc_counter_getlimit(isc_counter_t *counter) {
81
0
  REQUIRE(VALID_COUNTER(counter));
82
83
0
  return atomic_load_acquire(&counter->limit);
84
0
}
85
86
static void
87
0
isc__counter_destroy(isc_counter_t *counter) {
88
0
  REQUIRE(VALID_COUNTER(counter));
89
90
0
  isc_refcount_destroy(&counter->references);
91
0
  counter->magic = 0;
92
0
  isc_mem_putanddetach(&counter->mctx, counter, sizeof(*counter));
93
0
}
94
95
ISC_REFCOUNT_IMPL(isc_counter, isc__counter_destroy);