Actual source code: timer.h
1: // Copyright (c) 2019 University of Oregon
2: // Distributed under the BSD Software License
3: // (See accompanying file LICENSE.txt)
5: #pragma once
6: #define PERFSTUBS_USE_TIMERS
8: #include <stdint.h>
9: #include <stdlib.h>
10: #include <string.h>
11: #include <stdio.h>
12: #include "config.h"
13: #include "tool.h"
15: /* These macros help generate unique variable names within a function
16: * based on the source code line number */
17: #define CONCAT_(x,y) x##y
18: #define CONCAT(x,y) CONCAT_(x,y)
20: /* ------------------------------------------------------------------ */
21: /* Define the C API and PerfStubs glue class first */
22: /* ------------------------------------------------------------------ */
24: /* Pretty functions will include the return type and argument types,
25: * not just the function name. If the compiler doesn't support it,
26: * just use the function name. */
28: #if defined(__GNUC__)
30: #else
32: #endif
34: #define PERFSTUBS_UNKNOWN 0
35: #define PERFSTUBS_SUCCESS 1
36: #define PERFSTUBS_FAILURE 2
37: #define PERFSTUBS_FINALIZED 3
39: extern int perfstubs_initialized;
41: /* ------------------------------------------------------------------ */
42: /* Now define the C API */
43: /* ------------------------------------------------------------------ */
45: #if defined(PERFSTUBS_USE_TIMERS)
47: /* regular C API */
49: #ifdef __cplusplus
50: extern "C" {
51: #endif
53: void ps_initialize_(void);
54: void ps_finalize_(void);
55: void ps_register_thread_(void);
56: void ps_dump_data_(void);
57: void* ps_timer_create_(const char *timer_name);
58: void ps_timer_create_fortran_(void ** object, const char *timer_name);
59: void ps_timer_destroy_(void *);
60: void ps_timer_start_(const void *timer);
61: void ps_timer_start_fortran_(const void **timer);
62: void ps_timer_stop_(const void *timer);
63: void ps_timer_stop_fortran_(const void **timer);
64: void ps_set_parameter_(const char *parameter_name, int64_t parameter_value);
65: void ps_dynamic_phase_start_(const char *phasePrefix, int iterationIndex);
66: void ps_dynamic_phase_stop_(const char *phasePrefix, int iterationIndex);
67: void* ps_create_counter_(const char *name);
68: void ps_create_counter_fortran_(void ** object, const char *name);
69: void ps_sample_counter_(const void *counter, const double value);
70: void ps_sample_counter_fortran_(const void **counter, const double value);
71: void ps_set_metadata_(const char *name, const char *value);
73: /* data query API */
75: void ps_get_timer_data_(ps_tool_timer_data_t *timer_data, int tool_id);
76: void ps_get_counter_data_(ps_tool_counter_data_t *counter_data, int tool_id);
77: void ps_get_metadata_(ps_tool_metadata_t *metadata, int tool_id);
78: void ps_free_timer_data_(ps_tool_timer_data_t *timer_data, int tool_id);
79: void ps_free_counter_data_(ps_tool_counter_data_t *counter_data, int tool_id);
80: void ps_free_metadata_(ps_tool_metadata_t *metadata, int tool_id);
82: char* ps_make_timer_name_(const char * file, const char * func, int line);
84: #ifdef __cplusplus
85: }
86: #endif
88: /* Macro API for option of entirely disabling at compile time
89: * To use this API, set the Macro PERFSTUBS_USE_TIMERS on the command
90: * line or in a config.h file, however your project does it
91: */
93: #define PERFSTUBS_INITIALIZE() ps_initialize_();
95: #define PERFSTUBS_FINALIZE() ps_finalize_();
97: #define PERFSTUBS_REGISTER_THREAD() ps_register_thread_();
99: #define PERFSTUBS_DUMP_DATA() ps_dump_data_();
101: #define PERFSTUBS_TIMER_START(_timer, _timer_name) \
102: static void * _timer = NULL; \
103: if (perfstubs_initialized == PERFSTUBS_SUCCESS) { \
104: if (_timer == NULL) { \
105: _timer = ps_timer_create_(_timer_name); \
106: } \
107: ps_timer_start_(_timer); \
108: };
110: #define PERFSTUBS_TIMER_STOP(_timer) \
111: if (perfstubs_initialized == PERFSTUBS_SUCCESS) ps_timer_stop_(_timer); \
113: #define PERFSTUBS_SET_PARAMETER(_parameter, _value) \
114: if (perfstubs_initialized == PERFSTUBS_SUCCESS) ps_set_parameter_(_parameter, _value);
116: #define PERFSTUBS_DYNAMIC_PHASE_START(_phase_prefix, _iteration_index) \
117: if (perfstubs_initialized == PERFSTUBS_SUCCESS) \
118: ps_dynamic_phase_start_(_phase_prefix, _iteration_index);
120: #define PERFSTUBS_DYNAMIC_PHASE_STOP(_phase_prefix, _iteration_index) \
121: if (perfstubs_initialized == PERFSTUBS_SUCCESS) \
122: ps_dynamic_phase_stop_(_phase_prefix, _iteration_index);
124: #define PERFSTUBS_TIMER_START_FUNC(_timer) \
125: static void * _timer = NULL; \
126: if (perfstubs_initialized == PERFSTUBS_SUCCESS) { \
127: if (_timer == NULL) { \
128: char * tmpstr = ps_make_timer_name_(__FILE__, \
129: __PERFSTUBS_FUNCTION__, __LINE__); \
130: _timer = ps_timer_create_(tmpstr); \
131: free(tmpstr); \
132: } \
133: ps_timer_start_(_timer); \
134: };
136: #define PERFSTUBS_TIMER_STOP_FUNC(_timer) \
137: if (perfstubs_initialized == PERFSTUBS_SUCCESS) ps_timer_stop_(_timer);
139: #define PERFSTUBS_SAMPLE_COUNTER(_name, _value) \
140: static void * CONCAT(__var,__LINE__) = NULL; \
141: if (perfstubs_initialized == PERFSTUBS_SUCCESS) { \
142: if (CONCAT(__var,__LINE__) == NULL) { \
143: CONCAT(__var,__LINE__) = ps_create_counter_(_name); \
144: } \
145: ps_sample_counter_(CONCAT(__var,__LINE__), _value); \
146: };
148: #define PERFSTUBS_METADATA(_name, _value) \
149: if (perfstubs_initialized == PERFSTUBS_SUCCESS) ps_set_metadata_(_name, _value);
151: #else // defined(PERFSTUBS_USE_TIMERS)
153: #define PERFSTUBS_INITIALIZE()
154: #define PERFSTUBS_FINALIZE()
155: #define PERFSTUBS_REGISTER_THREAD()
156: #define PERFSTUBS_DUMP_DATA()
157: #define PERFSTUBS_TIMER_START(_timer, _timer_name)
158: #define PERFSTUBS_TIMER_STOP(_timer_name)
159: #define PERFSTUBS_SET_PARAMETER(_parameter, _value)
160: #define PERFSTUBS_DYNAMIC_PHASE_START(_phase_prefix, _iteration_index)
161: #define PERFSTUBS_DYNAMIC_PHASE_STOP(_phase_prefix, _iteration_index)
162: #define PERFSTUBS_TIMER_START_FUNC(_timer)
163: #define PERFSTUBS_TIMER_STOP_FUNC(_timer)
164: #define PERFSTUBS_SAMPLE_COUNTER(_name, _value)
165: #define PERFSTUBS_METADATA(_name, _value)
167: #endif // defined(PERFSTUBS_USE_TIMERS)
169: #ifdef __cplusplus
171: #if defined(PERFSTUBS_USE_TIMERS)
173: /*
174: * We allow the namespace to be changed, so that different libraries
175: * can include their own implementation and not have a namespace collision.
176: * For example, library A and executable B could both include the
177: * perfstubs_api code in their source tree, and change the namespace
178: * respectively, instead of linking in the perfstubs library.
179: */
181: #if defined(PERFSTUBS_NAMESPACE)
182: #define PERFSTUBS_INTERNAL_NAMESPACE PERFSTUBS_NAMESPACE
183: #else
184: #define PERFSTUBS_INTERNAL_NAMESPACE perfstubs_profiler
185: #endif
187: #include <memory>
188: #include <sstream>
189: #include <string>
191: namespace external
192: {
194: namespace PERFSTUBS_INTERNAL_NAMESPACE
195: {
197: class ScopedTimer
198: {
199: private:
200: const void * m_timer;
202: public:
203: ScopedTimer(const void * timer) : m_timer(timer)
204: {
205: if (perfstubs_initialized == PERFSTUBS_SUCCESS) ps_timer_start_(m_timer);
206: }
207: ~ScopedTimer()
208: {
209: if (perfstubs_initialized == PERFSTUBS_SUCCESS) ps_timer_stop_(m_timer);
210: }
211: };
213: } // namespace PERFSTUBS_INTERNAL_NAMESPACE
215: } // namespace external
217: namespace PSNS = external::PERFSTUBS_INTERNAL_NAMESPACE;
219: #define PERFSTUBS_SCOPED_TIMER(__name) \
220: static void * CONCAT(__var,__LINE__) = ps_timer_create_(__name); \
221: PSNS::ScopedTimer CONCAT(__var2,__LINE__)(CONCAT(__var,__LINE__));
223: /* The string created by ps_make_timer_name is a memory leak, but
224: * it is only created once per function, since it is called when the
225: * static variable is first initialized. */
226: #define PERFSTUBS_SCOPED_TIMER_FUNC() \
227: static void * CONCAT(__var,__LINE__) = \
228: ps_timer_create_(ps_make_timer_name_(__FILE__, \
229: __PERFSTUBS_FUNCTION__, __LINE__)); \
230: PSNS::ScopedTimer CONCAT(__var2,__LINE__)(CONCAT(__var,__LINE__));
232: #else // defined(PERFSTUBS_USE_TIMERS)
234: #define PERFSTUBS_SCOPED_TIMER(__name)
235: #define PERFSTUBS_SCOPED_TIMER_FUNC()
237: #endif // defined(PERFSTUBS_USE_TIMERS)
239: #endif // ifdef __cplusplus