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