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