| #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 */ |