Actual source code: pstimer.c

      1: // Copyright (c) 2019 University of Oregon
      2: // Distributed under the BSD Software License
      3: // (See accompanying file LICENSE.txt)

      5: #ifndef _GNU_SOURCE
      6: #define _GNU_SOURCE // needed to define RTLD_DEFAULT
      7: #endif
      8: #include <stdlib.h>
      9: #include <stdio.h>
     10: #include <math.h>
     11: #ifndef PERFSTUBS_STANDALONE
     12: #include "petscconf.h"
     13: #ifdef PETSC_HAVE_DLFCN_H
     14: #define PERFSTUBS_HAVE_DLFCN_H
     15: #endif
     16: #endif
     17: #if defined(__linux__) && defined(PERFSTUBS_HAVE_DLFCN_H)
     18: #include <dlfcn.h>
     19: #else
     20: #define PERFSTUBS_USE_STATIC 1
     21: #endif
     22: #define PERFSTUBS_USE_TIMERS
     23: #include "timer.h"

     25: #define MAX_TOOLS 1

     27: #if defined(_WIN32)||defined(WIN32)||defined(_WIN64)||defined(WIN64)||defined(__CYGWIN__)||defined(__APPLE__)
     28: #define PERFSTUBS_OFF
     29: #endif

     31: /* Make sure that the Timer singleton is constructed when the
     32:  * library is loaded.  This will ensure (on linux, anyway) that
     33:  * we can assert that we have m_Initialized on the main thread. */
     34: //static void __attribute__((constructor)) initialize_library(void);

     36: /* Globals for the plugin API */

     38: int perfstubs_initialized = PERFSTUBS_UNKNOWN;
     39: int num_tools_registered = 0;
     40: /* Keep track of whether the thread has been registered */
     41: #ifndef PERFSTUBS_OFF
     42: __thread int thread_seen = 0;
     43: #endif
     44: /* Function pointers */

     46: ps_initialize_t initialize_functions[MAX_TOOLS];
     47: ps_register_thread_t register_thread_functions[MAX_TOOLS];
     48: ps_finalize_t finalize_functions[MAX_TOOLS];
     49: ps_dump_data_t dump_data_functions[MAX_TOOLS];
     50: ps_timer_create_t timer_create_functions[MAX_TOOLS];
     51: ps_timer_start_t timer_start_functions[MAX_TOOLS];
     52: ps_timer_stop_t timer_stop_functions[MAX_TOOLS];
     53: ps_set_parameter_t set_parameter_functions[MAX_TOOLS];
     54: ps_dynamic_phase_start_t dynamic_phase_start_functions[MAX_TOOLS];
     55: ps_dynamic_phase_stop_t dynamic_phase_stop_functions[MAX_TOOLS];
     56: ps_create_counter_t create_counter_functions[MAX_TOOLS];
     57: ps_sample_counter_t sample_counter_functions[MAX_TOOLS];
     58: ps_set_metadata_t set_metadata_functions[MAX_TOOLS];
     59: ps_get_timer_data_t get_timer_data_functions[MAX_TOOLS];
     60: ps_get_counter_data_t get_counter_data_functions[MAX_TOOLS];
     61: ps_get_metadata_t get_metadata_functions[MAX_TOOLS];
     62: ps_free_timer_data_t free_timer_data_functions[MAX_TOOLS];
     63: ps_free_counter_data_t free_counter_data_functions[MAX_TOOLS];
     64: ps_free_metadata_t free_metadata_functions[MAX_TOOLS];

     66: #ifndef PERFSTUBS_OFF

     68: #ifdef PERFSTUBS_USE_STATIC

     70: #if defined(__clang__) && defined(__APPLE__)
     71: #define PS_WEAK_PRE
     72: #define PS_WEAK_POST __attribute__((weak_import))
     73: #define PS_WEAK_POST_NULL __attribute__((weak_import))
     74: #else
     75: #define PS_WEAK_PRE __attribute__((weak))
     76: #define PS_WEAK_POST
     77: #define PS_WEAK_POST_NULL
     78: #endif

     80: PS_WEAK_PRE void ps_tool_initialize(void) PS_WEAK_POST;
     81: PS_WEAK_PRE void ps_tool_register_thread(void) PS_WEAK_POST;
     82: PS_WEAK_PRE void ps_tool_finalize(void) PS_WEAK_POST;
     83: PS_WEAK_PRE void ps_tool_dump_data(void) PS_WEAK_POST;
     84: PS_WEAK_PRE void* ps_tool_timer_create(const char *) PS_WEAK_POST;
     85: PS_WEAK_PRE void ps_tool_timer_start(const void *) PS_WEAK_POST;
     86: PS_WEAK_PRE void ps_tool_timer_stop(const void *) PS_WEAK_POST;
     87: PS_WEAK_PRE void ps_tool_set_parameter(const char *, int64_t) PS_WEAK_POST;
     88: PS_WEAK_PRE void ps_tool_dynamic_phase_start(const char *, int) PS_WEAK_POST;
     89: PS_WEAK_PRE void ps_tool_dynamic_phase_stop(const char *, int) PS_WEAK_POST;
     90: PS_WEAK_PRE void* ps_tool_create_counter(const char *) PS_WEAK_POST;
     91: PS_WEAK_PRE void ps_tool_sample_counter(const void *, double) PS_WEAK_POST;
     92: PS_WEAK_PRE void ps_tool_set_metadata(const char *, const char *) PS_WEAK_POST;
     93: PS_WEAK_PRE void ps_tool_get_timer_data(ps_tool_timer_data_t *) PS_WEAK_POST;
     94: PS_WEAK_PRE void ps_tool_get_counter_data(ps_tool_counter_data_t *) PS_WEAK_POST;
     95: PS_WEAK_PRE void ps_tool_get_metadata(ps_tool_metadata_t *) PS_WEAK_POST;
     96: PS_WEAK_PRE void ps_tool_free_timer_data(ps_tool_timer_data_t *) PS_WEAK_POST;
     97: PS_WEAK_PRE void ps_tool_free_counter_data(ps_tool_counter_data_t *) PS_WEAK_POST;
     98: PS_WEAK_PRE void ps_tool_free_metadata(ps_tool_metadata_t *) PS_WEAK_POST;
     99: #endif

    102: // Disable pedantic, see https://stackoverflow.com/a/36385690
    103: #pragma GCC diagnostic push  // Save actual diagnostics state
    104: #pragma GCC diagnostic ignored "-Wpedantic" // Disable pedantic

    106: #endif //PERFSTUBS_OFF

    108: void initialize_library(void) {
    109: #ifndef PERFSTUBS_OFF
    110: #ifdef PERFSTUBS_USE_STATIC
    111:     /* The initialization function is the only required one */
    112:     initialize_functions[0] = &ps_tool_initialize;
    113:     if (initialize_functions[0] == NULL) return;
    114:     printf("Found ps_tool_initialize(), registering tool\n");
    115:     register_thread_functions[0] = &ps_tool_register_thread;
    116:     finalize_functions[0] = &ps_tool_finalize;
    117:     dump_data_functions[0] = &ps_tool_dump_data;
    118:     timer_create_functions[0] = &ps_tool_timer_create;
    119:     timer_start_functions[0] = &ps_tool_timer_start;
    120:     timer_stop_functions[0] = &ps_tool_timer_stop;
    121:     set_parameter_functions[0] = &ps_tool_set_parameter;
    122:     dynamic_phase_start_functions[0] = &ps_tool_dynamic_phase_start;
    123:     dynamic_phase_stop_functions[0] = &ps_tool_dynamic_phase_stop;
    124:     create_counter_functions[0] = &ps_tool_create_counter;
    125:     sample_counter_functions[0] = &ps_tool_sample_counter;
    126:     set_metadata_functions[0] = &ps_tool_set_metadata;
    127:     get_timer_data_functions[0] = &ps_tool_get_timer_data;
    128:     get_counter_data_functions[0] = &ps_tool_get_counter_data;
    129:     get_metadata_functions[0] = &ps_tool_get_metadata;
    130:     free_timer_data_functions[0] = &ps_tool_free_timer_data;
    131:     free_counter_data_functions[0] = &ps_tool_free_counter_data;
    132:     free_metadata_functions[0] = &ps_tool_free_metadata;
    133: #else
    134:     initialize_functions[0] =
    135:         (ps_initialize_t)dlsym(RTLD_DEFAULT, "ps_tool_initialize");
    136:     if (initialize_functions[0] == NULL) {
    137:         perfstubs_initialized = PERFSTUBS_FAILURE;
    138:         return;
    139:     }
    140:     printf("Found ps_tool_initialize(), registering tool\n");
    141:     finalize_functions[0] =
    142:         (ps_finalize_t)dlsym(RTLD_DEFAULT, "ps_tool_finalize");
    143:     register_thread_functions[0] =
    144:         (ps_register_thread_t)dlsym(RTLD_DEFAULT, "ps_tool_register_thread");
    145:     dump_data_functions[0] =
    146:         (ps_dump_data_t)dlsym(RTLD_DEFAULT, "ps_tool_dump_data");
    147:     timer_create_functions[0] =
    148:         (ps_timer_create_t)dlsym(RTLD_DEFAULT,
    149:         "ps_tool_timer_create");
    150:     timer_start_functions[0] =
    151:         (ps_timer_start_t)dlsym(RTLD_DEFAULT, "ps_tool_timer_start");
    152:     timer_stop_functions[0] =
    153:         (ps_timer_stop_t)dlsym(RTLD_DEFAULT, "ps_tool_timer_stop");
    154:     set_parameter_functions[0] =
    155:         (ps_set_parameter_t)dlsym(RTLD_DEFAULT, "ps_tool_set_parameter");
    156:     dynamic_phase_start_functions[0] = (ps_dynamic_phase_start_t)dlsym(
    157:         RTLD_DEFAULT, "ps_tool_dynamic_phase_start");
    158:     dynamic_phase_stop_functions[0] = (ps_dynamic_phase_stop_t)dlsym(
    159:         RTLD_DEFAULT, "ps_tool_dynamic_phase_stop");
    160:     create_counter_functions[0] = (ps_create_counter_t)dlsym(
    161:         RTLD_DEFAULT, "ps_tool_create_counter");
    162:     sample_counter_functions[0] = (ps_sample_counter_t)dlsym(
    163:         RTLD_DEFAULT, "ps_tool_sample_counter");
    164:     set_metadata_functions[0] =
    165:         (ps_set_metadata_t)dlsym(RTLD_DEFAULT, "ps_tool_set_metadata");
    166:     get_timer_data_functions[0] = (ps_get_timer_data_t)dlsym(
    167:         RTLD_DEFAULT, "ps_tool_get_timer_data");
    168:     get_counter_data_functions[0] = (ps_get_counter_data_t)dlsym(
    169:         RTLD_DEFAULT, "ps_tool_get_counter_data");
    170:     get_metadata_functions[0] = (ps_get_metadata_t)dlsym(
    171:         RTLD_DEFAULT, "ps_tool_get_metadata");
    172:     free_timer_data_functions[0] = (ps_free_timer_data_t)dlsym(
    173:         RTLD_DEFAULT, "ps_tool_free_timer_data");
    174:     free_counter_data_functions[0] = (ps_free_counter_data_t)dlsym(
    175:         RTLD_DEFAULT, "ps_tool_free_counter_data");
    176:     free_metadata_functions[0] = (ps_free_metadata_t)dlsym(
    177:         RTLD_DEFAULT, "ps_tool_free_metadata");
    178: #endif
    179:     perfstubs_initialized = PERFSTUBS_SUCCESS;
    180:     /* Increment the number of tools */
    181:     num_tools_registered = 1;
    182: #endif //PERFSTUBS_OFF
    183: }
    184: #ifndef PERFSTUBS_OFF
    185: #pragma GCC diagnostic pop  // Restore diagnostics state
    186: #endif

    188: char * ps_make_timer_name_(const char * file,
    189:     const char * func, int line) {
    190:     #ifndef PERFSTUBS_OFF
    191:   /* The length of the line number as a string is floor(log10(abs(num))) */
    192:   int string_length = (int) ((strlen(file) + strlen(func) + floor(log10(abs(line))) + 11));
    193:     char * name = (char*)calloc(string_length, sizeof(char));
    194:     sprintf(name, "%s [{%s} {%d,0}]", func, file, line);
    195:     return (name);
    196:     #else
    197:     return NULL;
    198:     #endif
    199: }

    201: // used internally to the class
    202: void ps_register_thread_internal(void) {
    203: #ifndef PERFSTUBS_OFF
    204:             int i;
    205:     for (i = 0 ; i < num_tools_registered ; i++) register_thread_functions[i]();
    206:     thread_seen = 1;
    207: #endif
    208: }

    210: /* Initialization */
    211: void ps_initialize_(void) {
    212: #ifndef PERFSTUBS_OFF
    213:     int i;
    214:     initialize_library();
    215:     for (i = 0 ; i < num_tools_registered ; i++) initialize_functions[i]();
    216:     /* No need to register the main thread */
    217:     thread_seen = 1;
    218: #endif
    219: }

    221: void ps_finalize_(void) {
    222:     #ifndef PERFSTUBS_OFF
    223:     int i;
    224:     for (i = 0 ; i < num_tools_registered ; i++) finalize_functions[i]();
    225:     #endif
    226: }

    228: void ps_register_thread_(void) {
    229: #ifndef PERFSTUBS_OFF
    230:     if (thread_seen == 0) ps_register_thread_internal();
    231: #endif
    232: }

    234: void* ps_timer_create_(const char *timer_name) {
    235:     #ifndef PERFSTUBS_OFF
    236:     void ** objects = (void**)calloc(num_tools_registered, sizeof(void*));
    237:     int i;
    238:     for (i = 0 ; i < num_tools_registered ; i++) objects[i] = timer_create_functions[i](timer_name);
    239:     return (void*)(objects);
    240:     #else
    241:     return NULL;
    242:     #endif
    243: }

    245: void ps_timer_destroy_(void *objects) {
    246:     #ifndef PERFSTUBS_OFF
    247:     free(objects);
    248:     #endif
    249: }

    251: void ps_timer_create_fortran_(void ** object, const char *timer_name) {
    252:     #ifndef PERFSTUBS_OFF
    253:     *object = ps_timer_create_(timer_name);
    254:     #endif
    255: }

    257: void ps_timer_start_(const void *timer) {
    258:     #ifndef PERFSTUBS_OFF
    259:     void ** objects = (void**)(timer);
    260:     int i;
    261:     for (i = 0; i < num_tools_registered ; i++) timer_start_functions[i](objects[i]);
    262:     #endif
    263: }

    265: void ps_timer_start_fortran_(const void **timer) {
    266:     #ifndef PERFSTUBS_OFF
    267:     ps_timer_start_(*timer);
    268:     #endif
    269: }

    271: void ps_timer_stop_(const void *timer) {
    272:     #ifndef PERFSTUBS_OFF
    273:     void ** objects = (void**)(timer);
    274:     int i;
    275:     for (i = 0; i < num_tools_registered ; i++) timer_stop_functions[i](objects[i]);
    276:     #endif
    277: }

    279: void ps_timer_stop_fortran_(const void **timer) {
    280:     #ifndef PERFSTUBS_OFF
    281:     ps_timer_stop_(*timer);
    282:     #endif
    283: }

    285: void ps_set_parameter_(const char * parameter_name, int64_t parameter_value) {
    286:     #ifndef PERFSTUBS_OFF
    287:     int i;
    288:     for (i = 0; i < num_tools_registered ; i++) set_parameter_functions[i](parameter_name, parameter_value);
    289:     #endif
    290: }

    292: void ps_dynamic_phase_start_(const char *phase_prefix, int iteration_index) {
    293:     #ifndef PERFSTUBS_OFF
    294:     int i;
    295:     for (i = 0; i < num_tools_registered ; i++) dynamic_phase_start_functions[i](phase_prefix, iteration_index);
    296:     #endif
    297: }

    299: void ps_dynamic_phase_stop_(const char *phase_prefix, int iteration_index) {
    300:     #ifndef PERFSTUBS_OFF
    301:     int i;
    302:     for (i = 0; i < num_tools_registered ; i++) dynamic_phase_stop_functions[i](phase_prefix, iteration_index);
    303:     #endif
    304: }

    306: void* ps_create_counter_(const char *name) {
    307:     #ifndef PERFSTUBS_OFF
    308:     void ** objects = (void**)calloc(num_tools_registered, sizeof(void*));
    309:     int i;
    310:     for (i = 0 ; i < num_tools_registered ; i++) objects[i] = create_counter_functions[i](name);
    311:     return (void*)(objects);
    312:     #else
    313:     return NULL;
    314:     #endif
    315: }

    317: void ps_create_counter_fortran_(void ** object, const char *name) {
    318:     #ifndef PERFSTUBS_OFF
    319:     *object = ps_create_counter_(name);
    320:     #endif
    321: }

    323: void ps_sample_counter_(const void *counter, const double value) {
    324:     #ifndef PERFSTUBS_OFF
    325:     void ** objects = (void**)(counter);
    326:     int i;
    327:     for (i = 0; i < num_tools_registered ; i++) sample_counter_functions[i](objects[i], value);
    328:     #endif
    329: }

    331: void ps_sample_counter_fortran_(const void **counter, const double value) {
    332:     #ifndef PERFSTUBS_OFF
    333:     ps_sample_counter_(*counter, value);
    334:     #endif
    335: }

    337: void ps_set_metadata_(const char *name, const char *value) {
    338:     #ifndef PERFSTUBS_OFF
    339:     int i;
    340:     for (i = 0; i < num_tools_registered ; i++) set_metadata_functions[i](name, value);
    341:     #endif
    342: }

    344: void ps_dump_data_(void) {
    345:     #ifndef PERFSTUBS_OFF
    346:     int i;
    347:     for (i = 0; i < num_tools_registered ; i++) dump_data_functions[i]();
    348:     #endif
    349: }

    351: void ps_get_timer_data_(ps_tool_timer_data_t *timer_data, int tool_id) {
    352:     #ifndef PERFSTUBS_OFF
    353:     if (tool_id < num_tools_registered) get_timer_data_functions[tool_id](timer_data);
    354:     #endif
    355: }

    357: void ps_get_counter_data_(ps_tool_counter_data_t *counter_data, int tool_id) {
    358:     #ifndef PERFSTUBS_OFF
    359:     if (tool_id < num_tools_registered) get_counter_data_functions[tool_id](counter_data);
    360:     #endif
    361: }

    363: void ps_get_metadata_(ps_tool_metadata_t *metadata, int tool_id) {
    364:     #ifndef PERFSTUBS_OFF
    365:     if (tool_id < num_tools_registered) get_metadata_functions[tool_id](metadata);
    366:     #endif
    367: }

    369: void ps_free_timer_data_(ps_tool_timer_data_t *timer_data, int tool_id) {
    370:     #ifndef PERFSTUBS_OFF
    371:     if (tool_id < num_tools_registered) free_timer_data_functions[tool_id](timer_data);
    372:     #endif
    373: }

    375: void ps_free_counter_data_(ps_tool_counter_data_t *counter_data, int tool_id) {
    376:     #ifndef PERFSTUBS_OFF
    377:     if (tool_id < num_tools_registered) free_counter_data_functions[tool_id](counter_data);
    378:     #endif
    379: }

    381: void ps_free_metadata_(ps_tool_metadata_t *metadata, int tool_id) {
    382:     #ifndef PERFSTUBS_OFF
    383:     if (tool_id < num_tools_registered) free_metadata_functions[tool_id](metadata);
    384:     #endif
    385: }