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_start_(const void *timer);
60: void ps_timer_start_fortran_(const void **timer);
61: void ps_timer_stop_(const void *timer);
62: void ps_timer_stop_fortran_(const void **timer);
63: void ps_set_parameter_(const char *parameter_name, int64_t parameter_value);
64: void ps_dynamic_phase_start_(const char *phasePrefix, int iterationIndex);
65: void ps_dynamic_phase_stop_(const char *phasePrefix, int iterationIndex);
66: void* ps_create_counter_(const char *name);
67: void ps_create_counter_fortran_(void ** object, const char *name);
68: void ps_sample_counter_(const void *counter, const double value);
69: void ps_sample_counter_fortran_(const void **counter, const double value);
70: void ps_set_metadata_(const char *name, const char *value);
72: /* data query API */
74: void ps_get_timer_data_(ps_tool_timer_data_t *timer_data, int tool_id);
75: void ps_get_counter_data_(ps_tool_counter_data_t *counter_data, int tool_id);
76: void ps_get_metadata_(ps_tool_metadata_t *metadata, int tool_id);
77: void ps_free_timer_data_(ps_tool_timer_data_t *timer_data, int tool_id);
78: void ps_free_counter_data_(ps_tool_counter_data_t *counter_data, int tool_id);
79: void ps_free_metadata_(ps_tool_metadata_t *metadata, int tool_id);
81: char* ps_make_timer_name_(const char * file, const char * func, int line);
83: #ifdef __cplusplus
84: }
85: #endif
87: /* Macro API for option of entirely disabling at compile time
88: * To use this API, set the Macro PERFSTUBS_USE_TIMERS on the command
89: * line or in a config.h file, however your project does it
90: */
92: #define PERFSTUBS_INITIALIZE() ps_initialize_();
94: #define PERFSTUBS_FINALIZE() ps_finalize_();
96: #define PERFSTUBS_REGISTER_THREAD() ps_register_thread_();
98: #define PERFSTUBS_DUMP_DATA() ps_dump_data_();
100: #define PERFSTUBS_TIMER_START(_timer, _timer_name) \
101: static void * _timer = NULL; \
102: if (perfstubs_initialized == PERFSTUBS_SUCCESS) { \
103: if (_timer == NULL) { \
104: _timer = ps_timer_create_(_timer_name); \
105: } \
106: ps_timer_start_(_timer); \
107: };
109: #define PERFSTUBS_TIMER_STOP(_timer) \
110: if (perfstubs_initialized == PERFSTUBS_SUCCESS) ps_timer_stop_(_timer); \
112: #define PERFSTUBS_SET_PARAMETER(_parameter, _value) \
113: if (perfstubs_initialized == PERFSTUBS_SUCCESS) ps_set_parameter_(_parameter, _value);
115: #define PERFSTUBS_DYNAMIC_PHASE_START(_phase_prefix, _iteration_index) \
116: if (perfstubs_initialized == PERFSTUBS_SUCCESS) \
117: ps_dynamic_phase_start_(_phase_prefix, _iteration_index);
119: #define PERFSTUBS_DYNAMIC_PHASE_STOP(_phase_prefix, _iteration_index) \
120: if (perfstubs_initialized == PERFSTUBS_SUCCESS) \
121: ps_dynamic_phase_stop_(_phase_prefix, _iteration_index);
123: #define PERFSTUBS_TIMER_START_FUNC(_timer) \
124: static void * _timer = NULL; \
125: if (perfstubs_initialized == PERFSTUBS_SUCCESS) { \
126: if (_timer == NULL) { \
127: char * tmpstr = ps_make_timer_name_(__FILE__, \
128: __PERFSTUBS_FUNCTION__, __LINE__); \
129: _timer = ps_timer_create_(tmpstr); \
130: free(tmpstr); \
131: } \
132: ps_timer_start_(_timer); \
133: };
135: #define PERFSTUBS_TIMER_STOP_FUNC(_timer) \
136: if (perfstubs_initialized == PERFSTUBS_SUCCESS) ps_timer_stop_(_timer);
138: #define PERFSTUBS_SAMPLE_COUNTER(_name, _value) \
139: static void * CONCAT(__var,__LINE__) = NULL; \
140: if (perfstubs_initialized == PERFSTUBS_SUCCESS) { \
141: if (CONCAT(__var,__LINE__) == NULL) { \
142: CONCAT(__var,__LINE__) = ps_create_counter_(_name); \
143: } \
144: ps_sample_counter_(CONCAT(__var,__LINE__), _value); \
145: };
147: #define PERFSTUBS_METADATA(_name, _value) \
148: if (perfstubs_initialized == PERFSTUBS_SUCCESS) ps_set_metadata_(_name, _value);
150: #else // defined(PERFSTUBS_USE_TIMERS)
152: #define PERFSTUBS_INITIALIZE()
153: #define PERFSTUBS_FINALIZE()
154: #define PERFSTUBS_REGISTER_THREAD()
155: #define PERFSTUBS_DUMP_DATA()
156: #define PERFSTUBS_TIMER_START(_timer, _timer_name)
157: #define PERFSTUBS_TIMER_STOP(_timer_name)
158: #define PERFSTUBS_SET_PARAMETER(_parameter, _value)
159: #define PERFSTUBS_DYNAMIC_PHASE_START(_phase_prefix, _iteration_index)
160: #define PERFSTUBS_DYNAMIC_PHASE_STOP(_phase_prefix, _iteration_index)
161: #define PERFSTUBS_TIMER_START_FUNC(_timer)
162: #define PERFSTUBS_TIMER_STOP_FUNC(_timer)
163: #define PERFSTUBS_SAMPLE_COUNTER(_name, _value)
164: #define PERFSTUBS_METADATA(_name, _value)
166: #endif // defined(PERFSTUBS_USE_TIMERS)
168: #ifdef __cplusplus
170: #if defined(PERFSTUBS_USE_TIMERS)
172: /*
173: * We allow the namespace to be changed, so that different libraries
174: * can include their own implementation and not have a namespace collision.
175: * For example, library A and executable B could both include the
176: * perfstubs_api code in their source tree, and change the namespace
177: * respectively, instead of linking in the perfstubs library.
178: */
180: #if defined(PERFSTUBS_NAMESPACE)
181: #define PERFSTUBS_INTERNAL_NAMESPACE PERFSTUBS_NAMESPACE
182: #else
183: #define PERFSTUBS_INTERNAL_NAMESPACE perfstubs_profiler
184: #endif
186: #include <memory>
187: #include <sstream>
188: #include <string>
190: namespace external
191: {
193: namespace PERFSTUBS_INTERNAL_NAMESPACE
194: {
196: class ScopedTimer
197: {
198: private:
199: const void * m_timer;
201: public:
202: ScopedTimer(const void * timer) : m_timer(timer)
203: {
204: if (perfstubs_initialized == PERFSTUBS_SUCCESS) ps_timer_start_(m_timer);
205: }
206: ~ScopedTimer()
207: {
208: if (perfstubs_initialized == PERFSTUBS_SUCCESS) ps_timer_stop_(m_timer);
209: }
210: };
212: } // namespace PERFSTUBS_INTERNAL_NAMESPACE
214: } // namespace external
216: namespace PSNS = external::PERFSTUBS_INTERNAL_NAMESPACE;
218: #define PERFSTUBS_SCOPED_TIMER(__name) \
219: static void * CONCAT(__var,__LINE__) = ps_timer_create_(__name); \
220: PSNS::ScopedTimer CONCAT(__var2,__LINE__)(CONCAT(__var,__LINE__));
222: /* The string created by ps_make_timer_name is a memory leak, but
223: * it is only created once per function, since it is called when the
224: * static variable is first initialized. */
225: #define PERFSTUBS_SCOPED_TIMER_FUNC() \
226: static void * CONCAT(__var,__LINE__) = \
227: ps_timer_create_(ps_make_timer_name_(__FILE__, \
228: __PERFSTUBS_FUNCTION__, __LINE__)); \
229: PSNS::ScopedTimer CONCAT(__var2,__LINE__)(CONCAT(__var,__LINE__));
231: #else // defined(PERFSTUBS_USE_TIMERS)
233: #define PERFSTUBS_SCOPED_TIMER(__name)
234: #define PERFSTUBS_SCOPED_TIMER_FUNC()
236: #endif // defined(PERFSTUBS_USE_TIMERS)
238: #endif // ifdef __cplusplus