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