]>
Commit | Line | Data |
---|---|---|
959ef981 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
d11cc69e DW |
2 | /* |
3 | * Copyright (C) 2018 Oracle. All Rights Reserved. | |
d11cc69e | 4 | * Author: Darrick J. Wong <darrick.wong@oracle.com> |
d11cc69e | 5 | */ |
a440f877 | 6 | #include "xfs.h" |
d11cc69e DW |
7 | #include <stdint.h> |
8 | #include <stdlib.h> | |
d11cc69e DW |
9 | #include <string.h> |
10 | #include <assert.h> | |
11 | #include <pthread.h> | |
12 | #include "ptvar.h" | |
13 | #include "counter.h" | |
14 | ||
15 | /* | |
16 | * Per-Thread Counters | |
17 | * | |
18 | * This is a global counter object that uses per-thread counters to | |
19 | * count things without having to content for a single shared lock. | |
20 | * Provided we know the number of threads that will be accessing the | |
21 | * counter, each thread gets its own thread-specific counter variable. | |
22 | * Changing the value is fast, though retrieving the value is expensive | |
23 | * and approximate. | |
24 | */ | |
25 | struct ptcounter { | |
26 | struct ptvar *var; | |
27 | }; | |
28 | ||
29 | /* Initialize per-thread counter. */ | |
30 | struct ptcounter * | |
31 | ptcounter_init( | |
32 | size_t nr) | |
33 | { | |
34 | struct ptcounter *p; | |
35 | ||
36 | p = malloc(sizeof(struct ptcounter)); | |
37 | if (!p) | |
38 | return NULL; | |
39 | p->var = ptvar_init(nr, sizeof(uint64_t)); | |
40 | if (!p->var) { | |
41 | free(p); | |
42 | return NULL; | |
43 | } | |
44 | return p; | |
45 | } | |
46 | ||
47 | /* Free per-thread counter. */ | |
48 | void | |
49 | ptcounter_free( | |
50 | struct ptcounter *ptc) | |
51 | { | |
52 | ptvar_free(ptc->var); | |
53 | free(ptc); | |
54 | } | |
55 | ||
56 | /* Add a quantity to the counter. */ | |
57 | void | |
58 | ptcounter_add( | |
59 | struct ptcounter *ptc, | |
60 | int64_t nr) | |
61 | { | |
62 | uint64_t *p; | |
63 | ||
64 | p = ptvar_get(ptc->var); | |
65 | *p += nr; | |
66 | } | |
67 | ||
68 | static bool | |
69 | ptcounter_val_helper( | |
70 | struct ptvar *ptv, | |
71 | void *data, | |
72 | void *foreach_arg) | |
73 | { | |
74 | uint64_t *sum = foreach_arg; | |
75 | uint64_t *count = data; | |
76 | ||
77 | *sum += *count; | |
78 | return true; | |
79 | } | |
80 | ||
81 | /* Return the approximate value of this counter. */ | |
82 | uint64_t | |
83 | ptcounter_value( | |
84 | struct ptcounter *ptc) | |
85 | { | |
86 | uint64_t sum = 0; | |
87 | ||
88 | ptvar_foreach(ptc->var, ptcounter_val_helper, &sum); | |
89 | return sum; | |
90 | } |