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 = (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: }