Coverage Report

Created: 2025-12-31 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/git/trace2/tr2_ctr.c
Line
Count
Source
1
#include "git-compat-util.h"
2
#include "trace2/tr2_tgt.h"
3
#include "trace2/tr2_tls.h"
4
#include "trace2/tr2_ctr.h"
5
6
/*
7
 * A global counter block to aggregate values from the partial sums
8
 * from each thread.
9
 */
10
static struct tr2_counter_block final_counter_block; /* access under tr2tls_mutex */
11
12
/*
13
 * Define metadata for each global counter.
14
 *
15
 * This array must match the "enum trace2_counter_id" and the values
16
 * in "struct tr2_counter_block.counter[*]".
17
 */
18
static struct tr2_counter_metadata tr2_counter_metadata[TRACE2_NUMBER_OF_COUNTERS] = {
19
  [TRACE2_COUNTER_ID_TEST1] = {
20
    .category = "test",
21
    .name = "test1",
22
    .want_per_thread_events = 0,
23
  },
24
  [TRACE2_COUNTER_ID_TEST2] = {
25
    .category = "test",
26
    .name = "test2",
27
    .want_per_thread_events = 1,
28
  },
29
  [TRACE2_COUNTER_ID_PACKED_REFS_JUMPS] = {
30
    .category = "packed-refs",
31
    .name = "jumps_made",
32
    .want_per_thread_events = 0,
33
  },
34
  [TRACE2_COUNTER_ID_REFTABLE_RESEEKS] = {
35
    .category = "reftable",
36
    .name = "reseeks_made",
37
    .want_per_thread_events = 0,
38
  },
39
  [TRACE2_COUNTER_ID_FSYNC_WRITEOUT_ONLY] = {
40
    .category = "fsync",
41
    .name = "writeout-only",
42
    .want_per_thread_events = 0,
43
  },
44
  [TRACE2_COUNTER_ID_FSYNC_HARDWARE_FLUSH] = {
45
    .category = "fsync",
46
    .name = "hardware-flush",
47
    .want_per_thread_events = 0,
48
  },
49
50
  /* Add additional metadata before here. */
51
};
52
53
void tr2_counter_increment(enum trace2_counter_id cid, uint64_t value)
54
0
{
55
0
  struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
56
0
  struct tr2_counter *c = &ctx->counter_block.counter[cid];
57
58
0
  c->value += value;
59
60
0
  ctx->used_any_counter = 1;
61
0
  if (tr2_counter_metadata[cid].want_per_thread_events)
62
0
    ctx->used_any_per_thread_counter = 1;
63
0
}
64
65
void tr2_update_final_counters(void)
66
0
{
67
0
  struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
68
0
  enum trace2_counter_id cid;
69
70
0
  if (!ctx->used_any_counter)
71
0
    return;
72
73
  /*
74
   * Access `final_counter_block` requires holding `tr2tls_mutex`.
75
   * We assume that our caller is holding the lock.
76
   */
77
78
0
  for (cid = 0; cid < TRACE2_NUMBER_OF_COUNTERS; cid++) {
79
0
    struct tr2_counter *c_final = &final_counter_block.counter[cid];
80
0
    const struct tr2_counter *c = &ctx->counter_block.counter[cid];
81
82
0
    c_final->value += c->value;
83
0
  }
84
0
}
85
86
void tr2_emit_per_thread_counters(tr2_tgt_evt_counter_t *fn_apply)
87
0
{
88
0
  struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
89
0
  enum trace2_counter_id cid;
90
91
0
  if (!ctx->used_any_per_thread_counter)
92
0
    return;
93
94
  /*
95
   * For each counter, if the counter wants per-thread events
96
   * and this thread used it (the value is non-zero), emit it.
97
   */
98
0
  for (cid = 0; cid < TRACE2_NUMBER_OF_COUNTERS; cid++)
99
0
    if (tr2_counter_metadata[cid].want_per_thread_events &&
100
0
        ctx->counter_block.counter[cid].value)
101
0
      fn_apply(&tr2_counter_metadata[cid],
102
0
         &ctx->counter_block.counter[cid],
103
0
         0);
104
0
}
105
106
void tr2_emit_final_counters(tr2_tgt_evt_counter_t *fn_apply)
107
0
{
108
0
  enum trace2_counter_id cid;
109
110
  /*
111
   * Access `final_counter_block` requires holding `tr2tls_mutex`.
112
   * We assume that our caller is holding the lock.
113
   */
114
115
0
  for (cid = 0; cid < TRACE2_NUMBER_OF_COUNTERS; cid++)
116
0
    if (final_counter_block.counter[cid].value)
117
0
      fn_apply(&tr2_counter_metadata[cid],
118
0
         &final_counter_block.counter[cid],
119
0
         1);
120
0
}