The eighth batch
[git.git] / trace2 / tr2_tmr.h
blobd5753576134aa8bc73d248c179f1201405351b86
1 #ifndef TR2_TMR_H
2 #define TR2_TMR_H
4 #include "trace2.h"
5 #include "trace2/tr2_tgt.h"
7 /*
8 * Define a mechanism to allow "stopwatch" timers.
10 * Timers can be used to measure "interesting" activity that does not
11 * fit the "region" model, such as code called from many different
12 * regions (like zlib) and/or where data for individual calls are not
13 * interesting or are too numerous to be efficiently logged.
15 * Timer values are accumulated during program execution and emitted
16 * to the Trace2 logs at program exit.
18 * To make this model efficient, we define a compile-time fixed set of
19 * timers and timer ids using a "timer block" array in thread-local
20 * storage. This gives us constant time access to each timer within
21 * each thread, since we want start/stop operations to be as fast as
22 * possible. This lets us avoid the complexities of dynamically
23 * allocating a timer on the first use by a thread and/or possibly
24 * sharing that timer definition with other concurrent threads.
25 * However, this does require that we define time the set of timers at
26 * compile time.
28 * Each thread uses the timer block in its thread-local storage to
29 * compute partial sums for each timer (without locking). When a
30 * thread exits, those partial sums are (under lock) added to the
31 * global final sum.
33 * Using this "timer block" model costs ~48 bytes per timer per thread
34 * (we have about six uint64 fields per timer). This does increase
35 * the size of the thread-local storage block, but it is allocated (at
36 * thread create time) and not on the thread stack, so I'm not worried
37 * about the size.
39 * Partial sums for each timer are optionally emitted when a thread
40 * exits.
42 * Final sums for each timer are emitted between the "exit" and
43 * "atexit" events.
45 * A parallel "timer metadata" table contains the "category" and "name"
46 * fields for each timer. This eliminates the need to include those
47 * args in the various timer APIs.
51 * The definition of an individual timer and used by an individual
52 * thread.
54 struct tr2_timer {
56 * Total elapsed time for this timer in this thread in nanoseconds.
58 uint64_t total_ns;
61 * The maximum and minimum interval values observed for this
62 * timer in this thread.
64 uint64_t min_ns;
65 uint64_t max_ns;
68 * The value of the clock when this timer was started in this
69 * thread. (Undefined when the timer is not active in this
70 * thread.)
72 uint64_t start_ns;
75 * Number of times that this timer has been started and stopped
76 * in this thread. (Recursive starts are ignored.)
78 uint64_t interval_count;
81 * Number of nested starts on the stack in this thread. (We
82 * ignore recursive starts and use this to track the recursive
83 * calls.)
85 unsigned int recursion_count;
89 * Metadata for a timer.
91 struct tr2_timer_metadata {
92 const char *category;
93 const char *name;
96 * True if we should emit per-thread events for this timer
97 * when individual threads exit.
99 unsigned int want_per_thread_events:1;
103 * A compile-time fixed-size block of timers to insert into
104 * thread-local storage. This wrapper is used to avoid quirks
105 * of C and the usual need to pass an array size argument.
107 struct tr2_timer_block {
108 struct tr2_timer timer[TRACE2_NUMBER_OF_TIMERS];
112 * Private routines used by trace2.c to actually start/stop an
113 * individual timer in the current thread.
115 void tr2_start_timer(enum trace2_timer_id tid);
116 void tr2_stop_timer(enum trace2_timer_id tid);
119 * Add the current thread's timer data to the global totals.
120 * This is called during thread-exit.
122 * Caller must be holding the tr2tls_mutex.
124 void tr2_update_final_timers(void);
127 * Emit per-thread timer data for the current thread.
128 * This is called during thread-exit.
130 void tr2_emit_per_thread_timers(tr2_tgt_evt_timer_t *fn_apply);
133 * Emit global total timer values.
134 * This is called during atexit handling.
136 * Caller must be holding the tr2tls_mutex.
138 void tr2_emit_final_timers(tr2_tgt_evt_timer_t *fn_apply);
140 #endif /* TR2_TMR_H */