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