]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - scrub/counter.c
xfs_scrub: thread-safe stats counter
[thirdparty/xfsprogs-dev.git] / scrub / counter.c
CommitLineData
d11cc69e
DW
1/*
2 * Copyright (C) 2018 Oracle. All Rights Reserved.
3 *
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it would be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20#include <stdint.h>
21#include <stdlib.h>
22#include <stdbool.h>
23#include <string.h>
24#include <assert.h>
25#include <pthread.h>
26#include "ptvar.h"
27#include "counter.h"
28
29/*
30 * Per-Thread Counters
31 *
32 * This is a global counter object that uses per-thread counters to
33 * count things without having to content for a single shared lock.
34 * Provided we know the number of threads that will be accessing the
35 * counter, each thread gets its own thread-specific counter variable.
36 * Changing the value is fast, though retrieving the value is expensive
37 * and approximate.
38 */
39struct ptcounter {
40 struct ptvar *var;
41};
42
43/* Initialize per-thread counter. */
44struct ptcounter *
45ptcounter_init(
46 size_t nr)
47{
48 struct ptcounter *p;
49
50 p = malloc(sizeof(struct ptcounter));
51 if (!p)
52 return NULL;
53 p->var = ptvar_init(nr, sizeof(uint64_t));
54 if (!p->var) {
55 free(p);
56 return NULL;
57 }
58 return p;
59}
60
61/* Free per-thread counter. */
62void
63ptcounter_free(
64 struct ptcounter *ptc)
65{
66 ptvar_free(ptc->var);
67 free(ptc);
68}
69
70/* Add a quantity to the counter. */
71void
72ptcounter_add(
73 struct ptcounter *ptc,
74 int64_t nr)
75{
76 uint64_t *p;
77
78 p = ptvar_get(ptc->var);
79 *p += nr;
80}
81
82static bool
83ptcounter_val_helper(
84 struct ptvar *ptv,
85 void *data,
86 void *foreach_arg)
87{
88 uint64_t *sum = foreach_arg;
89 uint64_t *count = data;
90
91 *sum += *count;
92 return true;
93}
94
95/* Return the approximate value of this counter. */
96uint64_t
97ptcounter_value(
98 struct ptcounter *ptc)
99{
100 uint64_t sum = 0;
101
102 ptvar_foreach(ptc->var, ptcounter_val_helper, &sum);
103 return sum;
104}