mirror of
https://github.com/git/git
synced 2024-10-30 14:03:28 +00:00
105 lines
3.1 KiB
C
105 lines
3.1 KiB
C
|
#ifndef TR2_CTR_H
|
||
|
#define TR2_CTR_H
|
||
|
|
||
|
#include "trace2.h"
|
||
|
#include "trace2/tr2_tgt.h"
|
||
|
|
||
|
/*
|
||
|
* Define a mechanism to allow global "counters".
|
||
|
*
|
||
|
* Counters can be used count interesting activity that does not fit
|
||
|
* the "region and data" model, such as code called from many
|
||
|
* different regions and/or where you want to count a number of items,
|
||
|
* but don't have control of when the last item will be processed,
|
||
|
* such as counter the number of calls to `lstat()`.
|
||
|
*
|
||
|
* Counters differ from Trace2 "data" events. Data events are emitted
|
||
|
* immediately and are appropriate for documenting loop counters at
|
||
|
* the end of a region, for example. Counter values are accumulated
|
||
|
* during the program and final counter values are emitted at program
|
||
|
* exit.
|
||
|
*
|
||
|
* To make this model efficient, we define a compile-time fixed set of
|
||
|
* counters and counter ids using a fixed size "counter block" array
|
||
|
* in thread-local storage. This gives us constant time, lock-free
|
||
|
* access to each counter within each thread. This lets us avoid the
|
||
|
* complexities of dynamically allocating a counter and sharing that
|
||
|
* definition with other threads.
|
||
|
*
|
||
|
* Each thread uses the counter block in its thread-local storage to
|
||
|
* increment partial sums for each counter (without locking). When a
|
||
|
* thread exits, those partial sums are (under lock) added to the
|
||
|
* global final sum.
|
||
|
*
|
||
|
* Partial sums for each counter are optionally emitted when a thread
|
||
|
* exits.
|
||
|
*
|
||
|
* Final sums for each counter are emitted between the "exit" and
|
||
|
* "atexit" events.
|
||
|
*
|
||
|
* A parallel "counter metadata" table contains the "category" and
|
||
|
* "name" fields for each counter. This eliminates the need to
|
||
|
* include those args in the various counter APIs.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* The definition of an individual counter as used by an individual
|
||
|
* thread (and later in aggregation).
|
||
|
*/
|
||
|
struct tr2_counter {
|
||
|
uint64_t value;
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* Metadata for a counter.
|
||
|
*/
|
||
|
struct tr2_counter_metadata {
|
||
|
const char *category;
|
||
|
const char *name;
|
||
|
|
||
|
/*
|
||
|
* True if we should emit per-thread events for this counter
|
||
|
* when individual threads exit.
|
||
|
*/
|
||
|
unsigned int want_per_thread_events:1;
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* A compile-time fixed block of counters to insert into thread-local
|
||
|
* storage. This wrapper is used to avoid quirks of C and the usual
|
||
|
* need to pass an array size argument.
|
||
|
*/
|
||
|
struct tr2_counter_block {
|
||
|
struct tr2_counter counter[TRACE2_NUMBER_OF_COUNTERS];
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* Private routines used by trace2.c to increment a counter for the
|
||
|
* current thread.
|
||
|
*/
|
||
|
void tr2_counter_increment(enum trace2_counter_id cid, uint64_t value);
|
||
|
|
||
|
/*
|
||
|
* Add the current thread's counter data to the global totals.
|
||
|
* This is called during thread-exit.
|
||
|
*
|
||
|
* Caller must be holding the tr2tls_mutex.
|
||
|
*/
|
||
|
void tr2_update_final_counters(void);
|
||
|
|
||
|
/*
|
||
|
* Emit per-thread counter data for the current thread.
|
||
|
* This is called during thread-exit.
|
||
|
*/
|
||
|
void tr2_emit_per_thread_counters(tr2_tgt_evt_counter_t *fn_apply);
|
||
|
|
||
|
/*
|
||
|
* Emit global counter values.
|
||
|
* This is called during atexit handling.
|
||
|
*
|
||
|
* Caller must be holding the tr2tls_mutex.
|
||
|
*/
|
||
|
void tr2_emit_final_counters(tr2_tgt_evt_counter_t *fn_apply);
|
||
|
|
||
|
#endif /* TR2_CTR_H */
|