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

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

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

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

227: void ps_finalize_(void) {
228:     #ifndef PERFSTUBS_OFF
229:     int i;
230:     for (i = 0 ; i < num_tools_registered ; i++) {
231:         finalize_functions[i]();
232:     }
233:     #endif
234: }

236: void ps_register_thread_(void) {
237: #ifndef PERFSTUBS_OFF        
238:     if (thread_seen == 0) {
239:         ps_register_thread_internal();
240:     }
241: #endif
242: }

244: void* ps_timer_create_(const char *timer_name) {
245:     #ifndef PERFSTUBS_OFF
246:     void ** objects = (void**)calloc(num_tools_registered, sizeof(void*));
247:     int i;
248:     for (i = 0 ; i < num_tools_registered ; i++) {
249:         objects[i] = (void*)timer_create_functions[i](timer_name);
250:     }
251:     return (void*)(objects);
252:     #else
253:     return NULL;
254:     #endif
255: }

257: void ps_timer_destroy_(void *objects) {
258:     #ifndef PERFSTUBS_OFF
259:     free(objects);
260:     #endif
261: }

263: void ps_timer_create_fortran_(void ** object, const char *timer_name) {
264:     #ifndef PERFSTUBS_OFF
265:     *object = ps_timer_create_(timer_name);
266:     #endif
267: }

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

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

285: void ps_timer_stop_(const void *timer) {
286:     #ifndef PERFSTUBS_OFF
287:     void ** objects = (void**)(timer);
288:     int i;
289:     for (i = 0; i < num_tools_registered ; i++) {
290:         timer_stop_functions[i](objects[i]);
291:     }
292:     #endif
293: }

295: void ps_timer_stop_fortran_(const void **timer) {
296:     #ifndef PERFSTUBS_OFF
297:     ps_timer_stop_(*timer);
298:     #endif
299: }

301: void ps_set_parameter_(const char * parameter_name, int64_t parameter_value) {
302:     #ifndef PERFSTUBS_OFF
303:     int i;
304:     for (i = 0; i < num_tools_registered ; i++) {
305:         set_parameter_functions[i](parameter_name, parameter_value);
306:     }
307:     #endif
308: }

310: void ps_dynamic_phase_start_(const char *phase_prefix, int iteration_index) {
311:     #ifndef PERFSTUBS_OFF
312:     int i;
313:     for (i = 0; i < num_tools_registered ; i++) {
314:         dynamic_phase_start_functions[i](phase_prefix, iteration_index);
315:     }
316:     #endif
317: }

319: void ps_dynamic_phase_stop_(const char *phase_prefix, int iteration_index) {
320:     #ifndef PERFSTUBS_OFF
321:     int i;
322:     for (i = 0; i < num_tools_registered ; i++) {
323:         dynamic_phase_stop_functions[i](phase_prefix, iteration_index);
324:     }
325:     #endif
326: }

328: void* ps_create_counter_(const char *name) {
329:     #ifndef PERFSTUBS_OFF
330:     void ** objects = (void**)calloc(num_tools_registered, sizeof(void*));
331:     int i;
332:     for (i = 0 ; i < num_tools_registered ; i++) {
333:         objects[i] = (void*)create_counter_functions[i](name);
334:     }
335:     return (void*)(objects);
336:     #else
337:     return NULL;
338:     #endif
339: }

341: void ps_create_counter_fortran_(void ** object, const char *name) {
342:     #ifndef PERFSTUBS_OFF
343:     *object = ps_create_counter_(name);
344:     #endif
345: }

347: void ps_sample_counter_(const void *counter, const double value) {
348:     #ifndef PERFSTUBS_OFF
349:     void ** objects = (void**)(counter);
350:     int i;
351:     for (i = 0; i < num_tools_registered ; i++) {
352:         sample_counter_functions[i](objects[i], value);
353:     }
354:     #endif
355: }

357: void ps_sample_counter_fortran_(const void **counter, const double value) {
358:     #ifndef PERFSTUBS_OFF
359:     ps_sample_counter_(*counter, value);
360:     #endif
361: }

363: void ps_set_metadata_(const char *name, const char *value) {
364:     #ifndef PERFSTUBS_OFF
365:     int i;
366:     for (i = 0; i < num_tools_registered ; i++) {
367:         set_metadata_functions[i](name, value);
368:     }
369:     #endif
370: }

372: void ps_dump_data_(void) {
373:     #ifndef PERFSTUBS_OFF
374:     int i;
375:     for (i = 0; i < num_tools_registered ; i++) {
376:         dump_data_functions[i]();
377:     }
378:     #endif
379: }

381: void ps_get_timer_data_(ps_tool_timer_data_t *timer_data, int tool_id) {
382:     #ifndef PERFSTUBS_OFF
383:     if (tool_id < num_tools_registered) {
384:         get_timer_data_functions[tool_id](timer_data);
385:     }
386:     #endif
387: }

389: void ps_get_counter_data_(ps_tool_counter_data_t *counter_data, int tool_id) {
390:     #ifndef PERFSTUBS_OFF
391:     if (tool_id < num_tools_registered) {
392:         get_counter_data_functions[tool_id](counter_data);
393:     }
394:     #endif
395: }

397: void ps_get_metadata_(ps_tool_metadata_t *metadata, int tool_id) {
398:     #ifndef PERFSTUBS_OFF
399:     if (tool_id < num_tools_registered) {
400:         get_metadata_functions[tool_id](metadata);
401:     }
402:     #endif
403: }

405: void ps_free_timer_data_(ps_tool_timer_data_t *timer_data, int tool_id) {
406:     #ifndef PERFSTUBS_OFF
407:     if (tool_id < num_tools_registered) {
408:         free_timer_data_functions[tool_id](timer_data);
409:     }
410:     #endif
411: }

413: void ps_free_counter_data_(ps_tool_counter_data_t *counter_data, int tool_id) {
414:     #ifndef PERFSTUBS_OFF
415:     if (tool_id < num_tools_registered) {
416:         free_counter_data_functions[tool_id](counter_data);
417:     }
418:     #endif
419: }

421: void ps_free_metadata_(ps_tool_metadata_t *metadata, int tool_id) {
422:     #ifndef PERFSTUBS_OFF
423:     if (tool_id < num_tools_registered) {
424:         free_metadata_functions[tool_id](metadata);
425:     }
426:     #endif
427: }