File: | projects/openmp/runtime/src/ompt-specific.cpp |
Warning: | line 423, column 23 Dereference of null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * ompt-general.cpp -- OMPT implementation of interface functions | |||
3 | */ | |||
4 | ||||
5 | //===----------------------------------------------------------------------===// | |||
6 | // | |||
7 | // The LLVM Compiler Infrastructure | |||
8 | // | |||
9 | // This file is dual licensed under the MIT and the University of Illinois Open | |||
10 | // Source Licenses. See LICENSE.txt for details. | |||
11 | // | |||
12 | //===----------------------------------------------------------------------===// | |||
13 | ||||
14 | /***************************************************************************** | |||
15 | * system include files | |||
16 | ****************************************************************************/ | |||
17 | ||||
18 | #include <assert.h> | |||
19 | ||||
20 | #include <stdint.h> | |||
21 | #include <stdio.h> | |||
22 | #include <stdlib.h> | |||
23 | #include <string.h> | |||
24 | #if KMP_OS_UNIX1 | |||
25 | #include <dlfcn.h> | |||
26 | #endif | |||
27 | ||||
28 | /***************************************************************************** | |||
29 | * ompt include files | |||
30 | ****************************************************************************/ | |||
31 | ||||
32 | #include "ompt-specific.cpp" | |||
33 | ||||
34 | /***************************************************************************** | |||
35 | * macros | |||
36 | ****************************************************************************/ | |||
37 | ||||
38 | #define ompt_get_callback_success1 1 | |||
39 | #define ompt_get_callback_failure0 0 | |||
40 | ||||
41 | #define no_tool_present0 0 | |||
42 | ||||
43 | #define OMPT_API_ROUTINEstatic static | |||
44 | ||||
45 | #ifndef OMPT_STR_MATCH | |||
46 | #define OMPT_STR_MATCH(haystack, needle)__kmp_str_match(haystack, 0, needle) (!strcasecmp(haystack, needle)) | |||
47 | #endif | |||
48 | ||||
49 | /***************************************************************************** | |||
50 | * types | |||
51 | ****************************************************************************/ | |||
52 | ||||
53 | typedef struct { | |||
54 | const char *state_name; | |||
55 | omp_state_t state_id; | |||
56 | } omp_state_info_t; | |||
57 | ||||
58 | typedef struct { | |||
59 | const char *name; | |||
60 | kmp_mutex_impl_t id; | |||
61 | } kmp_mutex_impl_info_t; | |||
62 | ||||
63 | enum tool_setting_e { | |||
64 | omp_tool_error, | |||
65 | omp_tool_unset, | |||
66 | omp_tool_disabled, | |||
67 | omp_tool_enabled | |||
68 | }; | |||
69 | ||||
70 | /***************************************************************************** | |||
71 | * global variables | |||
72 | ****************************************************************************/ | |||
73 | ||||
74 | ompt_callbacks_active_t ompt_enabled; | |||
75 | ||||
76 | omp_state_info_t omp_state_info[] = { | |||
77 | #define omp_state_macro(state, code) {#state, state}, | |||
78 | FOREACH_OMP_STATE(omp_state_macro)omp_state_macro (omp_state_undefined, 0x102) omp_state_macro ( omp_state_work_serial, 0x000) omp_state_macro (omp_state_work_parallel , 0x001) omp_state_macro (omp_state_work_reduction, 0x002) omp_state_macro (omp_state_wait_barrier, 0x010) omp_state_macro (omp_state_wait_barrier_implicit_parallel , 0x011) omp_state_macro (omp_state_wait_barrier_implicit_workshare , 0x012) omp_state_macro (omp_state_wait_barrier_implicit, 0x013 ) omp_state_macro (omp_state_wait_barrier_explicit, 0x014) omp_state_macro (omp_state_wait_taskwait, 0x020) omp_state_macro (omp_state_wait_taskgroup , 0x021) omp_state_macro (omp_state_wait_mutex, 0x040) omp_state_macro (omp_state_wait_lock, 0x041) omp_state_macro (omp_state_wait_critical , 0x042) omp_state_macro (omp_state_wait_atomic, 0x043) omp_state_macro (omp_state_wait_ordered, 0x044) omp_state_macro (omp_state_wait_target , 0x080) omp_state_macro (omp_state_wait_target_map, 0x081) omp_state_macro (omp_state_wait_target_update, 0x082) omp_state_macro (omp_state_idle , 0x100) omp_state_macro (omp_state_overhead, 0x101) | |||
79 | #undef omp_state_macro | |||
80 | }; | |||
81 | ||||
82 | kmp_mutex_impl_info_t kmp_mutex_impl_info[] = { | |||
83 | #define kmp_mutex_impl_macro(name, id) {#name, name}, | |||
84 | FOREACH_KMP_MUTEX_IMPL(kmp_mutex_impl_macro)kmp_mutex_impl_macro (ompt_mutex_impl_unknown, 0) kmp_mutex_impl_macro (kmp_mutex_impl_spin, 1) kmp_mutex_impl_macro (kmp_mutex_impl_queuing , 2) kmp_mutex_impl_macro (kmp_mutex_impl_speculative, 3) | |||
85 | #undef kmp_mutex_impl_macro | |||
86 | }; | |||
87 | ||||
88 | ompt_callbacks_internal_t ompt_callbacks; | |||
89 | ||||
90 | static ompt_start_tool_result_t *ompt_start_tool_result = NULL__null; | |||
91 | ||||
92 | /***************************************************************************** | |||
93 | * forward declarations | |||
94 | ****************************************************************************/ | |||
95 | ||||
96 | static ompt_interface_fn_t ompt_fn_lookup(const char *s); | |||
97 | ||||
98 | OMPT_API_ROUTINEstatic ompt_data_t *ompt_get_thread_data(void); | |||
99 | ||||
100 | /***************************************************************************** | |||
101 | * initialization and finalization (private operations) | |||
102 | ****************************************************************************/ | |||
103 | ||||
104 | typedef ompt_start_tool_result_t *(*ompt_start_tool_t)(unsigned int, | |||
105 | const char *); | |||
106 | ||||
107 | #if KMP_OS_DARWIN0 | |||
108 | ||||
109 | // While Darwin supports weak symbols, the library that wishes to provide a new | |||
110 | // implementation has to link against this runtime which defeats the purpose | |||
111 | // of having tools that are agnostic of the underlying runtime implementation. | |||
112 | // | |||
113 | // Fortunately, the linker includes all symbols of an executable in the global | |||
114 | // symbol table by default so dlsym() even finds static implementations of | |||
115 | // ompt_start_tool. For this to work on Linux, -Wl,--export-dynamic needs to be | |||
116 | // passed when building the application which we don't want to rely on. | |||
117 | ||||
118 | static ompt_start_tool_result_t *ompt_tool_darwin(unsigned int omp_version, | |||
119 | const char *runtime_version) { | |||
120 | ompt_start_tool_result_t *ret = NULL__null; | |||
121 | // Search symbol in the current address space. | |||
122 | ompt_start_tool_t start_tool = | |||
123 | (ompt_start_tool_t)dlsym(RTLD_DEFAULT((void *) 0), "ompt_start_tool"); | |||
124 | if (start_tool) { | |||
125 | ret = start_tool(omp_version, runtime_version); | |||
126 | } | |||
127 | return ret; | |||
128 | } | |||
129 | ||||
130 | #elif OMPT_HAVE_WEAK_ATTRIBUTE1 | |||
131 | ||||
132 | // On Unix-like systems that support weak symbols the following implementation | |||
133 | // of ompt_start_tool() will be used in case no tool-supplied implementation of | |||
134 | // this function is present in the address space of a process. | |||
135 | ||||
136 | _OMP_EXTERNextern "C" OMPT_WEAK_ATTRIBUTE__attribute__((weak)) ompt_start_tool_result_t * | |||
137 | ompt_start_tool(unsigned int omp_version, const char *runtime_version) { | |||
138 | ompt_start_tool_result_t *ret = NULL__null; | |||
139 | // Search next symbol in the current address space. This can happen if the | |||
140 | // runtime library is linked before the tool. Since glibc 2.2 strong symbols | |||
141 | // don't override weak symbols that have been found before unless the user | |||
142 | // sets the environment variable LD_DYNAMIC_WEAK. | |||
143 | ompt_start_tool_t next_tool = | |||
144 | (ompt_start_tool_t)dlsym(RTLD_NEXT((void *) -1l), "ompt_start_tool"); | |||
145 | if (next_tool) { | |||
146 | ret = next_tool(omp_version, runtime_version); | |||
147 | } | |||
148 | return ret; | |||
149 | } | |||
150 | ||||
151 | #elif OMPT_HAVE_PSAPI0 | |||
152 | ||||
153 | // On Windows, the ompt_tool_windows function is used to find the | |||
154 | // ompt_start_tool symbol across all modules loaded by a process. If | |||
155 | // ompt_start_tool is found, ompt_start_tool's return value is used to | |||
156 | // initialize the tool. Otherwise, NULL is returned and OMPT won't be enabled. | |||
157 | ||||
158 | #include <psapi.h> | |||
159 | #pragma comment(lib, "psapi.lib") | |||
160 | ||||
161 | // The number of loaded modules to start enumeration with EnumProcessModules() | |||
162 | #define NUM_MODULES 128 | |||
163 | ||||
164 | static ompt_start_tool_result_t * | |||
165 | ompt_tool_windows(unsigned int omp_version, const char *runtime_version) { | |||
166 | int i; | |||
167 | DWORD needed, new_size; | |||
168 | HMODULE *modules; | |||
169 | HANDLE process = GetCurrentProcess(); | |||
170 | modules = (HMODULE *)malloc(NUM_MODULES * sizeof(HMODULE)); | |||
171 | ompt_start_tool_t ompt_tool_p = NULL__null; | |||
172 | ||||
173 | #if OMPT_DEBUG0 | |||
174 | printf("ompt_tool_windows(): looking for ompt_start_tool\n"); | |||
175 | #endif | |||
176 | if (!EnumProcessModules(process, modules, NUM_MODULES * sizeof(HMODULE), | |||
177 | &needed)) { | |||
178 | // Regardless of the error reason use the stub initialization function | |||
179 | free(modules); | |||
180 | return NULL__null; | |||
181 | } | |||
182 | // Check if NUM_MODULES is enough to list all modules | |||
183 | new_size = needed / sizeof(HMODULE); | |||
184 | if (new_size > NUM_MODULES) { | |||
185 | #if OMPT_DEBUG0 | |||
186 | printf("ompt_tool_windows(): resize buffer to %d bytes\n", needed); | |||
187 | #endif | |||
188 | modules = (HMODULE *)realloc(modules, needed); | |||
189 | // If resizing failed use the stub function. | |||
190 | if (!EnumProcessModules(process, modules, needed, &needed)) { | |||
191 | free(modules); | |||
192 | return NULL__null; | |||
193 | } | |||
194 | } | |||
195 | for (i = 0; i < new_size; ++i) { | |||
196 | (FARPROC &)ompt_tool_p = GetProcAddress(modules[i], "ompt_start_tool"); | |||
197 | if (ompt_tool_p) { | |||
198 | #if OMPT_DEBUG0 | |||
199 | TCHAR modName[MAX_PATH]; | |||
200 | if (GetModuleFileName(modules[i], modName, MAX_PATH)) | |||
201 | printf("ompt_tool_windows(): ompt_start_tool found in module %s\n", | |||
202 | modName); | |||
203 | #endif | |||
204 | free(modules); | |||
205 | return (*ompt_tool_p)(omp_version, runtime_version); | |||
206 | } | |||
207 | #if OMPT_DEBUG0 | |||
208 | else { | |||
209 | TCHAR modName[MAX_PATH]; | |||
210 | if (GetModuleFileName(modules[i], modName, MAX_PATH)) | |||
211 | printf("ompt_tool_windows(): ompt_start_tool not found in module %s\n", | |||
212 | modName); | |||
213 | } | |||
214 | #endif | |||
215 | } | |||
216 | free(modules); | |||
217 | return NULL__null; | |||
218 | } | |||
219 | #else | |||
220 | #error Activation of OMPT is not supported on this platform. | |||
221 | #endif | |||
222 | ||||
223 | static ompt_start_tool_result_t * | |||
224 | ompt_try_start_tool(unsigned int omp_version, const char *runtime_version) { | |||
225 | ompt_start_tool_result_t *ret = NULL__null; | |||
226 | ompt_start_tool_t start_tool = NULL__null; | |||
227 | #if KMP_OS_WINDOWS0 | |||
228 | // Cannot use colon to describe a list of absolute paths on Windows | |||
229 | const char *sep = ";"; | |||
230 | #else | |||
231 | const char *sep = ":"; | |||
232 | #endif | |||
233 | ||||
234 | #if KMP_OS_DARWIN0 | |||
235 | // Try in the current address space | |||
236 | ret = ompt_tool_darwin(omp_version, runtime_version); | |||
237 | #elif OMPT_HAVE_WEAK_ATTRIBUTE1 | |||
238 | ret = ompt_start_tool(omp_version, runtime_version); | |||
239 | #elif OMPT_HAVE_PSAPI0 | |||
240 | ret = ompt_tool_windows(omp_version, runtime_version); | |||
241 | #else | |||
242 | #error Activation of OMPT is not supported on this platform. | |||
243 | #endif | |||
244 | if (ret) | |||
245 | return ret; | |||
246 | ||||
247 | // Try tool-libraries-var ICV | |||
248 | const char *tool_libs = getenv("OMP_TOOL_LIBRARIES"); | |||
249 | if (tool_libs) { | |||
250 | char *libs = __kmp_str_format("%s", tool_libs); | |||
251 | char *buf; | |||
252 | char *fname = __kmp_str_token(libs, sep, &buf); | |||
253 | while (fname) { | |||
254 | #if KMP_OS_UNIX1 | |||
255 | void *h = dlopen(fname, RTLD_LAZY0x00001); | |||
256 | if (h) { | |||
257 | start_tool = (ompt_start_tool_t)dlsym(h, "ompt_start_tool"); | |||
258 | #elif KMP_OS_WINDOWS0 | |||
259 | HMODULE h = LoadLibrary(fname); | |||
260 | if (h) { | |||
261 | start_tool = (ompt_start_tool_t)GetProcAddress(h, "ompt_start_tool"); | |||
262 | #else | |||
263 | #error Activation of OMPT is not supported on this platform. | |||
264 | #endif | |||
265 | if (start_tool && (ret = (*start_tool)(omp_version, runtime_version))) | |||
266 | break; | |||
267 | } | |||
268 | fname = __kmp_str_token(NULL__null, sep, &buf); | |||
269 | } | |||
270 | __kmp_str_free(&libs); | |||
271 | } | |||
272 | return ret; | |||
273 | } | |||
274 | ||||
275 | void ompt_pre_init() { | |||
276 | //-------------------------------------------------- | |||
277 | // Execute the pre-initialization logic only once. | |||
278 | //-------------------------------------------------- | |||
279 | static int ompt_pre_initialized = 0; | |||
280 | ||||
281 | if (ompt_pre_initialized) | |||
282 | return; | |||
283 | ||||
284 | ompt_pre_initialized = 1; | |||
285 | ||||
286 | //-------------------------------------------------- | |||
287 | // Use a tool iff a tool is enabled and available. | |||
288 | //-------------------------------------------------- | |||
289 | const char *ompt_env_var = getenv("OMP_TOOL"); | |||
290 | tool_setting_e tool_setting = omp_tool_error; | |||
291 | ||||
292 | if (!ompt_env_var || !strcmp(ompt_env_var, "")) | |||
293 | tool_setting = omp_tool_unset; | |||
294 | else if (OMPT_STR_MATCH(ompt_env_var, "disabled")__kmp_str_match(ompt_env_var, 0, "disabled")) | |||
295 | tool_setting = omp_tool_disabled; | |||
296 | else if (OMPT_STR_MATCH(ompt_env_var, "enabled")__kmp_str_match(ompt_env_var, 0, "enabled")) | |||
297 | tool_setting = omp_tool_enabled; | |||
298 | ||||
299 | #if OMPT_DEBUG0 | |||
300 | printf("ompt_pre_init(): tool_setting = %d\n", tool_setting); | |||
301 | #endif | |||
302 | switch (tool_setting) { | |||
303 | case omp_tool_disabled: | |||
304 | break; | |||
305 | ||||
306 | case omp_tool_unset: | |||
307 | case omp_tool_enabled: | |||
308 | ||||
309 | //-------------------------------------------------- | |||
310 | // Load tool iff specified in environment variable | |||
311 | //-------------------------------------------------- | |||
312 | ompt_start_tool_result = | |||
313 | ompt_try_start_tool(__kmp_openmp_version, ompt_get_runtime_version()); | |||
314 | ||||
315 | memset(&ompt_enabled, 0, sizeof(ompt_enabled)); | |||
316 | break; | |||
317 | ||||
318 | case omp_tool_error: | |||
319 | fprintf(stderrstderr, "Warning: OMP_TOOL has invalid value \"%s\".\n" | |||
320 | " legal values are (NULL,\"\",\"disabled\"," | |||
321 | "\"enabled\").\n", | |||
322 | ompt_env_var); | |||
323 | break; | |||
324 | } | |||
325 | #if OMPT_DEBUG0 | |||
326 | printf("ompt_pre_init(): ompt_enabled = %d\n", ompt_enabled); | |||
327 | #endif | |||
328 | } | |||
329 | ||||
330 | void ompt_post_init() { | |||
331 | //-------------------------------------------------- | |||
332 | // Execute the post-initialization logic only once. | |||
333 | //-------------------------------------------------- | |||
334 | static int ompt_post_initialized = 0; | |||
335 | ||||
336 | if (ompt_post_initialized) | |||
337 | return; | |||
338 | ||||
339 | ompt_post_initialized = 1; | |||
340 | ||||
341 | //-------------------------------------------------- | |||
342 | // Initialize the tool if so indicated. | |||
343 | //-------------------------------------------------- | |||
344 | if (ompt_start_tool_result) { | |||
345 | ompt_enabled.enabled = !!ompt_start_tool_result->initialize( | |||
346 | ompt_fn_lookup, &(ompt_start_tool_result->tool_data)); | |||
347 | ||||
348 | if (!ompt_enabled.enabled) { | |||
349 | // tool not enabled, zero out the bitmap, and done | |||
350 | memset(&ompt_enabled, 0, sizeof(ompt_enabled)); | |||
351 | return; | |||
352 | } | |||
353 | ||||
354 | kmp_info_t *root_thread = ompt_get_thread(); | |||
355 | ||||
356 | ompt_set_thread_state(root_thread, omp_state_overhead); | |||
357 | ||||
358 | if (ompt_enabled.ompt_callback_thread_begin) { | |||
359 | ompt_callbacks.ompt_callback(ompt_callback_thread_begin)ompt_callback_thread_begin_callback( | |||
360 | ompt_thread_initial, __ompt_get_thread_data_internal()); | |||
361 | } | |||
362 | ompt_data_t *task_data; | |||
363 | __ompt_get_task_info_internal(0, NULL__null, &task_data, NULL__null, NULL__null, NULL__null); | |||
364 | if (ompt_enabled.ompt_callback_task_create) { | |||
365 | ompt_callbacks.ompt_callback(ompt_callback_task_create)ompt_callback_task_create_callback( | |||
366 | NULL__null, NULL__null, task_data, ompt_task_initial, 0, NULL__null); | |||
367 | } | |||
368 | ||||
369 | ompt_set_thread_state(root_thread, omp_state_work_serial); | |||
370 | } | |||
371 | } | |||
372 | ||||
373 | void ompt_fini() { | |||
374 | if (ompt_enabled.enabled) { | |||
375 | ompt_start_tool_result->finalize(&(ompt_start_tool_result->tool_data)); | |||
376 | } | |||
377 | ||||
378 | memset(&ompt_enabled, 0, sizeof(ompt_enabled)); | |||
379 | } | |||
380 | ||||
381 | /***************************************************************************** | |||
382 | * interface operations | |||
383 | ****************************************************************************/ | |||
384 | ||||
385 | /***************************************************************************** | |||
386 | * state | |||
387 | ****************************************************************************/ | |||
388 | ||||
389 | OMPT_API_ROUTINEstatic int ompt_enumerate_states(int current_state, int *next_state, | |||
390 | const char **next_state_name) { | |||
391 | const static int len = sizeof(omp_state_info) / sizeof(omp_state_info_t); | |||
392 | int i = 0; | |||
393 | ||||
394 | for (i = 0; i < len - 1; i++) { | |||
395 | if (omp_state_info[i].state_id == current_state) { | |||
396 | *next_state = omp_state_info[i + 1].state_id; | |||
397 | *next_state_name = omp_state_info[i + 1].state_name; | |||
398 | return 1; | |||
399 | } | |||
400 | } | |||
401 | ||||
402 | return 0; | |||
403 | } | |||
404 | ||||
405 | OMPT_API_ROUTINEstatic int ompt_enumerate_mutex_impls(int current_impl, | |||
406 | int *next_impl, | |||
407 | const char **next_impl_name) { | |||
408 | const static int len = | |||
409 | sizeof(kmp_mutex_impl_info) / sizeof(kmp_mutex_impl_info_t); | |||
410 | int i = 0; | |||
411 | for (i = 0; i < len - 1; i++) { | |||
412 | if (kmp_mutex_impl_info[i].id != current_impl) | |||
413 | continue; | |||
414 | *next_impl = kmp_mutex_impl_info[i + 1].id; | |||
415 | *next_impl_name = kmp_mutex_impl_info[i + 1].name; | |||
416 | return 1; | |||
417 | } | |||
418 | return 0; | |||
419 | } | |||
420 | ||||
421 | /***************************************************************************** | |||
422 | * callbacks | |||
423 | ****************************************************************************/ | |||
424 | ||||
425 | OMPT_API_ROUTINEstatic int ompt_set_callback(ompt_callbacks_t which, | |||
426 | ompt_callback_t callback) { | |||
427 | switch (which) { | |||
428 | ||||
429 | #define ompt_event_macro(event_name, callback_type, event_id) \ | |||
430 | case event_name: \ | |||
431 | if (ompt_event_implementation_status(event_name)event_name_implemented) { \ | |||
432 | ompt_callbacks.ompt_callback(event_name)event_name_callback = (callback_type)callback; \ | |||
433 | ompt_enabled.event_name = (callback != 0); \ | |||
434 | } \ | |||
435 | if (callback) \ | |||
436 | return ompt_event_implementation_status(event_name)event_name_implemented; \ | |||
437 | else \ | |||
438 | return ompt_set_always; | |||
439 | ||||
440 | FOREACH_OMPT_EVENT(ompt_event_macro)ompt_event_macro (ompt_callback_thread_begin, ompt_callback_thread_begin_t , 1) ompt_event_macro (ompt_callback_thread_end, ompt_callback_thread_end_t , 2) ompt_event_macro (ompt_callback_parallel_begin, ompt_callback_parallel_begin_t , 3) ompt_event_macro (ompt_callback_parallel_end, ompt_callback_parallel_end_t , 4) ompt_event_macro (ompt_callback_task_create, ompt_callback_task_create_t , 5) ompt_event_macro (ompt_callback_task_schedule, ompt_callback_task_schedule_t , 6) ompt_event_macro (ompt_callback_implicit_task, ompt_callback_implicit_task_t , 7) ompt_event_macro (ompt_callback_target, ompt_callback_target_t , 8) ompt_event_macro (ompt_callback_target_data_op, ompt_callback_target_data_op_t , 9) ompt_event_macro (ompt_callback_target_submit, ompt_callback_target_submit_t , 10) ompt_event_macro (ompt_callback_control_tool, ompt_callback_control_tool_t , 11) ompt_event_macro (ompt_callback_device_initialize, ompt_callback_device_initialize_t , 12) ompt_event_macro (ompt_callback_device_finalize, ompt_callback_device_finalize_t , 13) ompt_event_macro (ompt_callback_device_load, ompt_callback_device_load_t , 14) ompt_event_macro (ompt_callback_device_unload, ompt_callback_device_unload_t , 15) ompt_event_macro (ompt_callback_sync_region_wait, ompt_callback_sync_region_t , 16) ompt_event_macro (ompt_callback_mutex_released, ompt_callback_mutex_t , 17) ompt_event_macro (ompt_callback_task_dependences, ompt_callback_task_dependences_t , 18) ompt_event_macro (ompt_callback_task_dependence, ompt_callback_task_dependence_t , 19) ompt_event_macro (ompt_callback_work, ompt_callback_work_t , 20) ompt_event_macro (ompt_callback_master, ompt_callback_master_t , 21) ompt_event_macro (ompt_callback_target_map, ompt_callback_target_map_t , 22) ompt_event_macro (ompt_callback_sync_region, ompt_callback_sync_region_t , 23) ompt_event_macro (ompt_callback_lock_init, ompt_callback_mutex_acquire_t , 24) ompt_event_macro (ompt_callback_lock_destroy, ompt_callback_mutex_t , 25) ompt_event_macro (ompt_callback_mutex_acquire, ompt_callback_mutex_acquire_t , 26) ompt_event_macro (ompt_callback_mutex_acquired, ompt_callback_mutex_t , 27) ompt_event_macro (ompt_callback_nest_lock, ompt_callback_nest_lock_t , 28) ompt_event_macro (ompt_callback_flush, ompt_callback_flush_t , 29) ompt_event_macro (ompt_callback_cancel, ompt_callback_cancel_t , 30) ompt_event_macro (ompt_callback_reduction, ompt_callback_sync_region_t , 31) ompt_event_macro (ompt_callback_dispatch, ompt_callback_dispatch_t , 32) | |||
441 | ||||
442 | #undef ompt_event_macro | |||
443 | ||||
444 | default: | |||
445 | return ompt_set_error; | |||
446 | } | |||
447 | } | |||
448 | ||||
449 | OMPT_API_ROUTINEstatic int ompt_get_callback(ompt_callbacks_t which, | |||
450 | ompt_callback_t *callback) { | |||
451 | switch (which) { | |||
452 | ||||
453 | #define ompt_event_macro(event_name, callback_type, event_id) \ | |||
454 | case event_name: \ | |||
455 | if (ompt_event_implementation_status(event_name)event_name_implemented) { \ | |||
456 | ompt_callback_t mycb = \ | |||
457 | (ompt_callback_t)ompt_callbacks.ompt_callback(event_name)event_name_callback; \ | |||
458 | if (mycb) { \ | |||
459 | *callback = mycb; \ | |||
460 | return ompt_get_callback_success1; \ | |||
461 | } \ | |||
462 | } \ | |||
463 | return ompt_get_callback_failure0; | |||
464 | ||||
465 | FOREACH_OMPT_EVENT(ompt_event_macro)ompt_event_macro (ompt_callback_thread_begin, ompt_callback_thread_begin_t , 1) ompt_event_macro (ompt_callback_thread_end, ompt_callback_thread_end_t , 2) ompt_event_macro (ompt_callback_parallel_begin, ompt_callback_parallel_begin_t , 3) ompt_event_macro (ompt_callback_parallel_end, ompt_callback_parallel_end_t , 4) ompt_event_macro (ompt_callback_task_create, ompt_callback_task_create_t , 5) ompt_event_macro (ompt_callback_task_schedule, ompt_callback_task_schedule_t , 6) ompt_event_macro (ompt_callback_implicit_task, ompt_callback_implicit_task_t , 7) ompt_event_macro (ompt_callback_target, ompt_callback_target_t , 8) ompt_event_macro (ompt_callback_target_data_op, ompt_callback_target_data_op_t , 9) ompt_event_macro (ompt_callback_target_submit, ompt_callback_target_submit_t , 10) ompt_event_macro (ompt_callback_control_tool, ompt_callback_control_tool_t , 11) ompt_event_macro (ompt_callback_device_initialize, ompt_callback_device_initialize_t , 12) ompt_event_macro (ompt_callback_device_finalize, ompt_callback_device_finalize_t , 13) ompt_event_macro (ompt_callback_device_load, ompt_callback_device_load_t , 14) ompt_event_macro (ompt_callback_device_unload, ompt_callback_device_unload_t , 15) ompt_event_macro (ompt_callback_sync_region_wait, ompt_callback_sync_region_t , 16) ompt_event_macro (ompt_callback_mutex_released, ompt_callback_mutex_t , 17) ompt_event_macro (ompt_callback_task_dependences, ompt_callback_task_dependences_t , 18) ompt_event_macro (ompt_callback_task_dependence, ompt_callback_task_dependence_t , 19) ompt_event_macro (ompt_callback_work, ompt_callback_work_t , 20) ompt_event_macro (ompt_callback_master, ompt_callback_master_t , 21) ompt_event_macro (ompt_callback_target_map, ompt_callback_target_map_t , 22) ompt_event_macro (ompt_callback_sync_region, ompt_callback_sync_region_t , 23) ompt_event_macro (ompt_callback_lock_init, ompt_callback_mutex_acquire_t , 24) ompt_event_macro (ompt_callback_lock_destroy, ompt_callback_mutex_t , 25) ompt_event_macro (ompt_callback_mutex_acquire, ompt_callback_mutex_acquire_t , 26) ompt_event_macro (ompt_callback_mutex_acquired, ompt_callback_mutex_t , 27) ompt_event_macro (ompt_callback_nest_lock, ompt_callback_nest_lock_t , 28) ompt_event_macro (ompt_callback_flush, ompt_callback_flush_t , 29) ompt_event_macro (ompt_callback_cancel, ompt_callback_cancel_t , 30) ompt_event_macro (ompt_callback_reduction, ompt_callback_sync_region_t , 31) ompt_event_macro (ompt_callback_dispatch, ompt_callback_dispatch_t , 32) | |||
466 | ||||
467 | #undef ompt_event_macro | |||
468 | ||||
469 | default: | |||
470 | return ompt_get_callback_failure0; | |||
471 | } | |||
472 | } | |||
473 | ||||
474 | /***************************************************************************** | |||
475 | * parallel regions | |||
476 | ****************************************************************************/ | |||
477 | ||||
478 | OMPT_API_ROUTINEstatic int ompt_get_parallel_info(int ancestor_level, | |||
479 | ompt_data_t **parallel_data, | |||
480 | int *team_size) { | |||
481 | return __ompt_get_parallel_info_internal(ancestor_level, parallel_data, | |||
482 | team_size); | |||
483 | } | |||
484 | ||||
485 | OMPT_API_ROUTINEstatic omp_state_t ompt_get_state(omp_wait_id_t *wait_id) { | |||
486 | omp_state_t thread_state = __ompt_get_state_internal(wait_id); | |||
487 | ||||
488 | if (thread_state == omp_state_undefined) { | |||
489 | thread_state = omp_state_work_serial; | |||
490 | } | |||
491 | ||||
492 | return thread_state; | |||
493 | } | |||
494 | ||||
495 | /***************************************************************************** | |||
496 | * tasks | |||
497 | ****************************************************************************/ | |||
498 | ||||
499 | OMPT_API_ROUTINEstatic ompt_data_t *ompt_get_thread_data(void) { | |||
500 | return __ompt_get_thread_data_internal(); | |||
501 | } | |||
502 | ||||
503 | OMPT_API_ROUTINEstatic int ompt_get_task_info(int ancestor_level, int *type, | |||
504 | ompt_data_t **task_data, | |||
505 | omp_frame_t **task_frame, | |||
506 | ompt_data_t **parallel_data, | |||
507 | int *thread_num) { | |||
508 | return __ompt_get_task_info_internal(ancestor_level, type, task_data, | |||
| ||||
509 | task_frame, parallel_data, thread_num); | |||
510 | } | |||
511 | ||||
512 | OMPT_API_ROUTINEstatic int ompt_get_task_memory(void **addr, size_t *size, | |||
513 | int block) { | |||
514 | // stub | |||
515 | return 0; | |||
516 | } | |||
517 | ||||
518 | /***************************************************************************** | |||
519 | * num_procs | |||
520 | ****************************************************************************/ | |||
521 | ||||
522 | OMPT_API_ROUTINEstatic int ompt_get_num_procs(void) { | |||
523 | // copied from kmp_ftn_entry.h (but modified: OMPT can only be called when | |||
524 | // runtime is initialized) | |||
525 | return __kmp_avail_proc; | |||
526 | } | |||
527 | ||||
528 | /***************************************************************************** | |||
529 | * places | |||
530 | ****************************************************************************/ | |||
531 | ||||
532 | OMPT_API_ROUTINEstatic int ompt_get_num_places(void) { | |||
533 | // copied from kmp_ftn_entry.h (but modified) | |||
534 | #if !KMP_AFFINITY_SUPPORTED1 | |||
535 | return 0; | |||
536 | #else | |||
537 | if (!KMP_AFFINITY_CAPABLE()(__kmp_affin_mask_size > 0)) | |||
538 | return 0; | |||
539 | return __kmp_affinity_num_masks; | |||
540 | #endif | |||
541 | } | |||
542 | ||||
543 | OMPT_API_ROUTINEstatic int ompt_get_place_proc_ids(int place_num, int ids_size, | |||
544 | int *ids) { | |||
545 | // copied from kmp_ftn_entry.h (but modified) | |||
546 | #if !KMP_AFFINITY_SUPPORTED1 | |||
547 | return 0; | |||
548 | #else | |||
549 | int i, count; | |||
550 | int tmp_ids[ids_size]; | |||
551 | if (!KMP_AFFINITY_CAPABLE()(__kmp_affin_mask_size > 0)) | |||
552 | return 0; | |||
553 | if (place_num < 0 || place_num >= (int)__kmp_affinity_num_masks) | |||
554 | return 0; | |||
555 | /* TODO: Is this safe for asynchronous call from signal handler during runtime | |||
556 | * shutdown? */ | |||
557 | kmp_affin_mask_t *mask = KMP_CPU_INDEX(__kmp_affinity_masks, place_num)__kmp_affinity_dispatch->index_mask_array(__kmp_affinity_masks , place_num); | |||
558 | count = 0; | |||
559 | KMP_CPU_SET_ITERATE(i, mask)for (i = (mask)->begin(); (int)i != (mask)->end(); i = ( mask)->next(i)) { | |||
560 | if ((!KMP_CPU_ISSET(i, __kmp_affin_fullMask)(__kmp_affin_fullMask)->is_set(i)) || | |||
561 | (!KMP_CPU_ISSET(i, mask)(mask)->is_set(i))) { | |||
562 | continue; | |||
563 | } | |||
564 | if (count < ids_size) | |||
565 | tmp_ids[count] = i; | |||
566 | count++; | |||
567 | } | |||
568 | if (ids_size >= count) { | |||
569 | for (i = 0; i < count; i++) { | |||
570 | ids[i] = tmp_ids[i]; | |||
571 | } | |||
572 | } | |||
573 | return count; | |||
574 | #endif | |||
575 | } | |||
576 | ||||
577 | OMPT_API_ROUTINEstatic int ompt_get_place_num(void) { | |||
578 | // copied from kmp_ftn_entry.h (but modified) | |||
579 | #if !KMP_AFFINITY_SUPPORTED1 | |||
580 | return -1; | |||
581 | #else | |||
582 | if (__kmp_get_gtid()__kmp_get_global_thread_id() < 0) | |||
583 | return -1; | |||
584 | ||||
585 | int gtid; | |||
586 | kmp_info_t *thread; | |||
587 | if (!KMP_AFFINITY_CAPABLE()(__kmp_affin_mask_size > 0)) | |||
588 | return -1; | |||
589 | gtid = __kmp_entry_gtid()__kmp_get_global_thread_id_reg(); | |||
590 | thread = __kmp_thread_from_gtid(gtid); | |||
591 | if (thread == NULL__null || thread->th.th_current_place < 0) | |||
592 | return -1; | |||
593 | return thread->th.th_current_place; | |||
594 | #endif | |||
595 | } | |||
596 | ||||
597 | OMPT_API_ROUTINEstatic int ompt_get_partition_place_nums(int place_nums_size, | |||
598 | int *place_nums) { | |||
599 | // copied from kmp_ftn_entry.h (but modified) | |||
600 | #if !KMP_AFFINITY_SUPPORTED1 | |||
601 | return 0; | |||
602 | #else | |||
603 | if (__kmp_get_gtid()__kmp_get_global_thread_id() < 0) | |||
604 | return 0; | |||
605 | ||||
606 | int i, gtid, place_num, first_place, last_place, start, end; | |||
607 | kmp_info_t *thread; | |||
608 | if (!KMP_AFFINITY_CAPABLE()(__kmp_affin_mask_size > 0)) | |||
609 | return 0; | |||
610 | gtid = __kmp_entry_gtid()__kmp_get_global_thread_id_reg(); | |||
611 | thread = __kmp_thread_from_gtid(gtid); | |||
612 | if (thread == NULL__null) | |||
613 | return 0; | |||
614 | first_place = thread->th.th_first_place; | |||
615 | last_place = thread->th.th_last_place; | |||
616 | if (first_place < 0 || last_place < 0) | |||
617 | return 0; | |||
618 | if (first_place <= last_place) { | |||
619 | start = first_place; | |||
620 | end = last_place; | |||
621 | } else { | |||
622 | start = last_place; | |||
623 | end = first_place; | |||
624 | } | |||
625 | if (end - start <= place_nums_size) | |||
626 | for (i = 0, place_num = start; place_num <= end; ++place_num, ++i) { | |||
627 | place_nums[i] = place_num; | |||
628 | } | |||
629 | return end - start + 1; | |||
630 | #endif | |||
631 | } | |||
632 | ||||
633 | /***************************************************************************** | |||
634 | * places | |||
635 | ****************************************************************************/ | |||
636 | ||||
637 | OMPT_API_ROUTINEstatic int ompt_get_proc_id(void) { | |||
638 | if (__kmp_get_gtid()__kmp_get_global_thread_id() < 0) | |||
639 | return -1; | |||
640 | #if KMP_OS_LINUX1 | |||
641 | return sched_getcpu(); | |||
642 | #elif KMP_OS_WINDOWS0 | |||
643 | PROCESSOR_NUMBER pn; | |||
644 | GetCurrentProcessorNumberEx(&pn); | |||
645 | return 64 * pn.Group + pn.Number; | |||
646 | #else | |||
647 | return -1; | |||
648 | #endif | |||
649 | } | |||
650 | ||||
651 | /***************************************************************************** | |||
652 | * compatability | |||
653 | ****************************************************************************/ | |||
654 | ||||
655 | /* | |||
656 | * Currently unused function | |||
657 | OMPT_API_ROUTINE int ompt_get_ompt_version() { return OMPT_VERSION; } | |||
658 | */ | |||
659 | ||||
660 | /***************************************************************************** | |||
661 | * application-facing API | |||
662 | ****************************************************************************/ | |||
663 | ||||
664 | /*---------------------------------------------------------------------------- | |||
665 | | control | |||
666 | ---------------------------------------------------------------------------*/ | |||
667 | ||||
668 | int __kmp_control_tool(uint64_t command, uint64_t modifier, void *arg) { | |||
669 | ||||
670 | if (ompt_enabled.enabled) { | |||
671 | if (ompt_enabled.ompt_callback_control_tool) { | |||
672 | return ompt_callbacks.ompt_callback(ompt_callback_control_tool)ompt_callback_control_tool_callback( | |||
673 | command, modifier, arg, OMPT_LOAD_RETURN_ADDRESS(__kmp_entry_gtid())__ompt_load_return_address(__kmp_get_global_thread_id_reg())); | |||
674 | } else { | |||
675 | return -1; | |||
676 | } | |||
677 | } else { | |||
678 | return -2; | |||
679 | } | |||
680 | } | |||
681 | ||||
682 | /***************************************************************************** | |||
683 | * misc | |||
684 | ****************************************************************************/ | |||
685 | ||||
686 | OMPT_API_ROUTINEstatic uint64_t ompt_get_unique_id(void) { | |||
687 | return __ompt_get_unique_id_internal(); | |||
688 | } | |||
689 | ||||
690 | OMPT_API_ROUTINEstatic void ompt_finalize_tool(void) { | |||
691 | // stub | |||
692 | } | |||
693 | ||||
694 | /***************************************************************************** | |||
695 | * Target | |||
696 | ****************************************************************************/ | |||
697 | ||||
698 | OMPT_API_ROUTINEstatic int ompt_get_target_info(uint64_t *device_num, | |||
699 | ompt_id_t *target_id, | |||
700 | ompt_id_t *host_op_id) { | |||
701 | return 0; // thread is not in a target region | |||
702 | } | |||
703 | ||||
704 | OMPT_API_ROUTINEstatic int ompt_get_num_devices(void) { | |||
705 | return 1; // only one device (the current device) is available | |||
706 | } | |||
707 | ||||
708 | /***************************************************************************** | |||
709 | * API inquiry for tool | |||
710 | ****************************************************************************/ | |||
711 | ||||
712 | static ompt_interface_fn_t ompt_fn_lookup(const char *s) { | |||
713 | ||||
714 | #define ompt_interface_fn(fn)fn_t fn_f = fn; if (strcmp(s, "fn") == 0) return (ompt_interface_fn_t )fn_f; \ | |||
715 | fn##_t fn##_f = fn; \ | |||
716 | if (strcmp(s, #fn) == 0) \ | |||
717 | return (ompt_interface_fn_t)fn##_f; | |||
718 | ||||
719 | FOREACH_OMPT_INQUIRY_FN(ompt_interface_fn)ompt_enumerate_states_t ompt_enumerate_states_f = ompt_enumerate_states ; if (strcmp(s, "ompt_enumerate_states") == 0) return (ompt_interface_fn_t )ompt_enumerate_states_f; ompt_enumerate_mutex_impls_t ompt_enumerate_mutex_impls_f = ompt_enumerate_mutex_impls; if (strcmp(s, "ompt_enumerate_mutex_impls" ) == 0) return (ompt_interface_fn_t)ompt_enumerate_mutex_impls_f ; ompt_set_callback_t ompt_set_callback_f = ompt_set_callback ; if (strcmp(s, "ompt_set_callback") == 0) return (ompt_interface_fn_t )ompt_set_callback_f; ompt_get_callback_t ompt_get_callback_f = ompt_get_callback; if (strcmp(s, "ompt_get_callback") == 0 ) return (ompt_interface_fn_t)ompt_get_callback_f; ompt_get_state_t ompt_get_state_f = ompt_get_state; if (strcmp(s, "ompt_get_state" ) == 0) return (ompt_interface_fn_t)ompt_get_state_f; ompt_get_parallel_info_t ompt_get_parallel_info_f = ompt_get_parallel_info; if (strcmp (s, "ompt_get_parallel_info") == 0) return (ompt_interface_fn_t )ompt_get_parallel_info_f; ompt_get_task_info_t ompt_get_task_info_f = ompt_get_task_info; if (strcmp(s, "ompt_get_task_info") == 0) return (ompt_interface_fn_t)ompt_get_task_info_f; ompt_get_task_memory_t ompt_get_task_memory_f = ompt_get_task_memory; if (strcmp(s, "ompt_get_task_memory") == 0) return (ompt_interface_fn_t)ompt_get_task_memory_f ; ompt_get_thread_data_t ompt_get_thread_data_f = ompt_get_thread_data ; if (strcmp(s, "ompt_get_thread_data") == 0) return (ompt_interface_fn_t )ompt_get_thread_data_f; ompt_get_unique_id_t ompt_get_unique_id_f = ompt_get_unique_id; if (strcmp(s, "ompt_get_unique_id") == 0) return (ompt_interface_fn_t)ompt_get_unique_id_f; ompt_finalize_tool_t ompt_finalize_tool_f = ompt_finalize_tool; if (strcmp(s, "ompt_finalize_tool" ) == 0) return (ompt_interface_fn_t)ompt_finalize_tool_f; ompt_get_num_procs_t ompt_get_num_procs_f = ompt_get_num_procs; if (strcmp(s, "ompt_get_num_procs" ) == 0) return (ompt_interface_fn_t)ompt_get_num_procs_f; ompt_get_num_places_t ompt_get_num_places_f = ompt_get_num_places; if (strcmp(s, "ompt_get_num_places" ) == 0) return (ompt_interface_fn_t)ompt_get_num_places_f; ompt_get_place_proc_ids_t ompt_get_place_proc_ids_f = ompt_get_place_proc_ids; if (strcmp (s, "ompt_get_place_proc_ids") == 0) return (ompt_interface_fn_t )ompt_get_place_proc_ids_f; ompt_get_place_num_t ompt_get_place_num_f = ompt_get_place_num; if (strcmp(s, "ompt_get_place_num") == 0) return (ompt_interface_fn_t)ompt_get_place_num_f; ompt_get_partition_place_nums_t ompt_get_partition_place_nums_f = ompt_get_partition_place_nums ; if (strcmp(s, "ompt_get_partition_place_nums") == 0) return (ompt_interface_fn_t)ompt_get_partition_place_nums_f; ompt_get_proc_id_t ompt_get_proc_id_f = ompt_get_proc_id; if (strcmp(s, "ompt_get_proc_id" ) == 0) return (ompt_interface_fn_t)ompt_get_proc_id_f; ompt_get_target_info_t ompt_get_target_info_f = ompt_get_target_info; if (strcmp(s, "ompt_get_target_info") == 0) return (ompt_interface_fn_t)ompt_get_target_info_f ; ompt_get_num_devices_t ompt_get_num_devices_f = ompt_get_num_devices ; if (strcmp(s, "ompt_get_num_devices") == 0) return (ompt_interface_fn_t )ompt_get_num_devices_f; | |||
720 | ||||
721 | return (ompt_interface_fn_t)0; | |||
722 | } |
1 | /* | |||
2 | * ompt-specific.cpp -- OMPT internal functions | |||
3 | */ | |||
4 | ||||
5 | //===----------------------------------------------------------------------===// | |||
6 | // | |||
7 | // The LLVM Compiler Infrastructure | |||
8 | // | |||
9 | // This file is dual licensed under the MIT and the University of Illinois Open | |||
10 | // Source Licenses. See LICENSE.txt for details. | |||
11 | // | |||
12 | //===----------------------------------------------------------------------===// | |||
13 | ||||
14 | //****************************************************************************** | |||
15 | // include files | |||
16 | //****************************************************************************** | |||
17 | ||||
18 | #include "kmp.h" | |||
19 | #include "ompt-specific.h" | |||
20 | ||||
21 | #if KMP_OS_UNIX1 | |||
22 | #include <dlfcn.h> | |||
23 | #endif | |||
24 | ||||
25 | #if KMP_OS_WINDOWS0 | |||
26 | #define THREAD_LOCAL__thread __declspec(thread) | |||
27 | #else | |||
28 | #define THREAD_LOCAL__thread __thread | |||
29 | #endif | |||
30 | ||||
31 | #define OMPT_WEAK_ATTRIBUTE__attribute__((weak)) KMP_WEAK_ATTRIBUTE__attribute__((weak)) | |||
32 | ||||
33 | //****************************************************************************** | |||
34 | // macros | |||
35 | //****************************************************************************** | |||
36 | ||||
37 | #define LWT_FROM_TEAM(team)(team)->t.ompt_serialized_team_info (team)->t.ompt_serialized_team_info | |||
38 | ||||
39 | #define OMPT_THREAD_ID_BITS16 16 | |||
40 | ||||
41 | //****************************************************************************** | |||
42 | // private operations | |||
43 | //****************************************************************************** | |||
44 | ||||
45 | //---------------------------------------------------------- | |||
46 | // traverse the team and task hierarchy | |||
47 | // note: __ompt_get_teaminfo and __ompt_get_task_info_object | |||
48 | // traverse the hierarchy similarly and need to be | |||
49 | // kept consistent | |||
50 | //---------------------------------------------------------- | |||
51 | ||||
52 | ompt_team_info_t *__ompt_get_teaminfo(int depth, int *size) { | |||
53 | kmp_info_t *thr = ompt_get_thread(); | |||
54 | ||||
55 | if (thr) { | |||
56 | kmp_team *team = thr->th.th_team; | |||
57 | if (team == NULL__null) | |||
58 | return NULL__null; | |||
59 | ||||
60 | ompt_lw_taskteam_t *next_lwt = LWT_FROM_TEAM(team)(team)->t.ompt_serialized_team_info, *lwt = NULL__null; | |||
61 | ||||
62 | while (depth > 0) { | |||
63 | // next lightweight team (if any) | |||
64 | if (lwt) | |||
65 | lwt = lwt->parent; | |||
66 | ||||
67 | // next heavyweight team (if any) after | |||
68 | // lightweight teams are exhausted | |||
69 | if (!lwt && team) { | |||
70 | if (next_lwt) { | |||
71 | lwt = next_lwt; | |||
72 | next_lwt = NULL__null; | |||
73 | } else { | |||
74 | team = team->t.t_parent; | |||
75 | if (team) { | |||
76 | next_lwt = LWT_FROM_TEAM(team)(team)->t.ompt_serialized_team_info; | |||
77 | } | |||
78 | } | |||
79 | } | |||
80 | ||||
81 | depth--; | |||
82 | } | |||
83 | ||||
84 | if (lwt) { | |||
85 | // lightweight teams have one task | |||
86 | if (size) | |||
87 | *size = 1; | |||
88 | ||||
89 | // return team info for lightweight team | |||
90 | return &lwt->ompt_team_info; | |||
91 | } else if (team) { | |||
92 | // extract size from heavyweight team | |||
93 | if (size) | |||
94 | *size = team->t.t_nproc; | |||
95 | ||||
96 | // return team info for heavyweight team | |||
97 | return &team->t.ompt_team_info; | |||
98 | } | |||
99 | } | |||
100 | ||||
101 | return NULL__null; | |||
102 | } | |||
103 | ||||
104 | ompt_task_info_t *__ompt_get_task_info_object(int depth) { | |||
105 | ompt_task_info_t *info = NULL__null; | |||
106 | kmp_info_t *thr = ompt_get_thread(); | |||
107 | ||||
108 | if (thr) { | |||
109 | kmp_taskdata_t *taskdata = thr->th.th_current_task; | |||
110 | ompt_lw_taskteam_t *lwt = NULL__null, | |||
111 | *next_lwt = LWT_FROM_TEAM(taskdata->td_team)(taskdata->td_team)->t.ompt_serialized_team_info; | |||
112 | ||||
113 | while (depth > 0) { | |||
114 | // next lightweight team (if any) | |||
115 | if (lwt) | |||
116 | lwt = lwt->parent; | |||
117 | ||||
118 | // next heavyweight team (if any) after | |||
119 | // lightweight teams are exhausted | |||
120 | if (!lwt && taskdata) { | |||
121 | if (next_lwt) { | |||
122 | lwt = next_lwt; | |||
123 | next_lwt = NULL__null; | |||
124 | } else { | |||
125 | taskdata = taskdata->td_parent; | |||
126 | if (taskdata) { | |||
127 | next_lwt = LWT_FROM_TEAM(taskdata->td_team)(taskdata->td_team)->t.ompt_serialized_team_info; | |||
128 | } | |||
129 | } | |||
130 | } | |||
131 | depth--; | |||
132 | } | |||
133 | ||||
134 | if (lwt) { | |||
135 | info = &lwt->ompt_task_info; | |||
136 | } else if (taskdata) { | |||
137 | info = &taskdata->ompt_task_info; | |||
138 | } | |||
139 | } | |||
140 | ||||
141 | return info; | |||
142 | } | |||
143 | ||||
144 | ompt_task_info_t *__ompt_get_scheduling_taskinfo(int depth) { | |||
145 | ompt_task_info_t *info = NULL__null; | |||
146 | kmp_info_t *thr = ompt_get_thread(); | |||
147 | ||||
148 | if (thr) { | |||
149 | kmp_taskdata_t *taskdata = thr->th.th_current_task; | |||
150 | ||||
151 | ompt_lw_taskteam_t *lwt = NULL__null, | |||
152 | *next_lwt = LWT_FROM_TEAM(taskdata->td_team)(taskdata->td_team)->t.ompt_serialized_team_info; | |||
153 | ||||
154 | while (depth > 0) { | |||
155 | // next lightweight team (if any) | |||
156 | if (lwt) | |||
157 | lwt = lwt->parent; | |||
158 | ||||
159 | // next heavyweight team (if any) after | |||
160 | // lightweight teams are exhausted | |||
161 | if (!lwt && taskdata) { | |||
162 | // first try scheduling parent (for explicit task scheduling) | |||
163 | if (taskdata->ompt_task_info.scheduling_parent) { | |||
164 | taskdata = taskdata->ompt_task_info.scheduling_parent; | |||
165 | } else if (next_lwt) { | |||
166 | lwt = next_lwt; | |||
167 | next_lwt = NULL__null; | |||
168 | } else { | |||
169 | // then go for implicit tasks | |||
170 | taskdata = taskdata->td_parent; | |||
171 | if (taskdata) { | |||
172 | next_lwt = LWT_FROM_TEAM(taskdata->td_team)(taskdata->td_team)->t.ompt_serialized_team_info; | |||
173 | } | |||
174 | } | |||
175 | } | |||
176 | depth--; | |||
177 | } | |||
178 | ||||
179 | if (lwt) { | |||
180 | info = &lwt->ompt_task_info; | |||
181 | } else if (taskdata) { | |||
182 | info = &taskdata->ompt_task_info; | |||
183 | } | |||
184 | } | |||
185 | ||||
186 | return info; | |||
187 | } | |||
188 | ||||
189 | //****************************************************************************** | |||
190 | // interface operations | |||
191 | //****************************************************************************** | |||
192 | ||||
193 | //---------------------------------------------------------- | |||
194 | // thread support | |||
195 | //---------------------------------------------------------- | |||
196 | ||||
197 | ompt_data_t *__ompt_get_thread_data_internal() { | |||
198 | if (__kmp_get_gtid()__kmp_get_global_thread_id() >= 0) { | |||
199 | kmp_info_t *thread = ompt_get_thread(); | |||
200 | if (thread == NULL__null) | |||
201 | return NULL__null; | |||
202 | return &(thread->th.ompt_thread_info.thread_data); | |||
203 | } | |||
204 | return NULL__null; | |||
205 | } | |||
206 | ||||
207 | //---------------------------------------------------------- | |||
208 | // state support | |||
209 | //---------------------------------------------------------- | |||
210 | ||||
211 | void __ompt_thread_assign_wait_id(void *variable) { | |||
212 | kmp_info_t *ti = ompt_get_thread(); | |||
213 | ||||
214 | ti->th.ompt_thread_info.wait_id = (omp_wait_id_t)variable; | |||
215 | } | |||
216 | ||||
217 | omp_state_t __ompt_get_state_internal(omp_wait_id_t *omp_wait_id) { | |||
218 | kmp_info_t *ti = ompt_get_thread(); | |||
219 | ||||
220 | if (ti) { | |||
221 | if (omp_wait_id) | |||
222 | *omp_wait_id = ti->th.ompt_thread_info.wait_id; | |||
223 | return ti->th.ompt_thread_info.state; | |||
224 | } | |||
225 | return omp_state_undefined; | |||
226 | } | |||
227 | ||||
228 | //---------------------------------------------------------- | |||
229 | // parallel region support | |||
230 | //---------------------------------------------------------- | |||
231 | ||||
232 | int __ompt_get_parallel_info_internal(int ancestor_level, | |||
233 | ompt_data_t **parallel_data, | |||
234 | int *team_size) { | |||
235 | if (__kmp_get_gtid()__kmp_get_global_thread_id() >= 0) { | |||
236 | ompt_team_info_t *info; | |||
237 | if (team_size) { | |||
238 | info = __ompt_get_teaminfo(ancestor_level, team_size); | |||
239 | } else { | |||
240 | info = __ompt_get_teaminfo(ancestor_level, NULL__null); | |||
241 | } | |||
242 | if (parallel_data) { | |||
243 | *parallel_data = info ? &(info->parallel_data) : NULL__null; | |||
244 | } | |||
245 | return info ? 2 : 0; | |||
246 | } else { | |||
247 | return 0; | |||
248 | } | |||
249 | } | |||
250 | ||||
251 | //---------------------------------------------------------- | |||
252 | // lightweight task team support | |||
253 | //---------------------------------------------------------- | |||
254 | ||||
255 | void __ompt_lw_taskteam_init(ompt_lw_taskteam_t *lwt, kmp_info_t *thr, int gtid, | |||
256 | ompt_data_t *ompt_pid, void *codeptr) { | |||
257 | // initialize parallel_data with input, return address to parallel_data on | |||
258 | // exit | |||
259 | lwt->ompt_team_info.parallel_data = *ompt_pid; | |||
260 | lwt->ompt_team_info.master_return_address = codeptr; | |||
261 | lwt->ompt_task_info.task_data.value = 0; | |||
262 | lwt->ompt_task_info.frame.enter_frame = NULL__null; | |||
263 | lwt->ompt_task_info.frame.exit_frame = NULL__null; | |||
264 | lwt->ompt_task_info.scheduling_parent = NULL__null; | |||
265 | lwt->ompt_task_info.deps = NULL__null; | |||
266 | lwt->ompt_task_info.ndeps = 0; | |||
267 | lwt->heap = 0; | |||
268 | lwt->parent = 0; | |||
269 | } | |||
270 | ||||
271 | void __ompt_lw_taskteam_link(ompt_lw_taskteam_t *lwt, kmp_info_t *thr, | |||
272 | int on_heap) { | |||
273 | ompt_lw_taskteam_t *link_lwt = lwt; | |||
274 | if (thr->th.th_team->t.t_serialized > | |||
275 | 1) { // we already have a team, so link the new team and swap values | |||
276 | if (on_heap) { // the lw_taskteam cannot stay on stack, allocate it on heap | |||
277 | link_lwt = | |||
278 | (ompt_lw_taskteam_t *)__kmp_allocate(sizeof(ompt_lw_taskteam_t))___kmp_allocate((sizeof(ompt_lw_taskteam_t)), "/build/llvm-toolchain-snapshot-8~svn345461/projects/openmp/runtime/src/ompt-specific.cpp" , 278); | |||
279 | } | |||
280 | link_lwt->heap = on_heap; | |||
281 | ||||
282 | // would be swap in the (on_stack) case. | |||
283 | ompt_team_info_t tmp_team = lwt->ompt_team_info; | |||
284 | link_lwt->ompt_team_info = *OMPT_CUR_TEAM_INFO(thr)(&(thr->th.th_team->t.ompt_team_info)); | |||
285 | *OMPT_CUR_TEAM_INFO(thr)(&(thr->th.th_team->t.ompt_team_info)) = tmp_team; | |||
286 | ||||
287 | ompt_task_info_t tmp_task = lwt->ompt_task_info; | |||
288 | link_lwt->ompt_task_info = *OMPT_CUR_TASK_INFO(thr)(&(thr->th.th_current_task->ompt_task_info)); | |||
289 | *OMPT_CUR_TASK_INFO(thr)(&(thr->th.th_current_task->ompt_task_info)) = tmp_task; | |||
290 | ||||
291 | // link the taskteam into the list of taskteams: | |||
292 | ompt_lw_taskteam_t *my_parent = | |||
293 | thr->th.th_team->t.ompt_serialized_team_info; | |||
294 | link_lwt->parent = my_parent; | |||
295 | thr->th.th_team->t.ompt_serialized_team_info = link_lwt; | |||
296 | } else { | |||
297 | // this is the first serialized team, so we just store the values in the | |||
298 | // team and drop the taskteam-object | |||
299 | *OMPT_CUR_TEAM_INFO(thr)(&(thr->th.th_team->t.ompt_team_info)) = lwt->ompt_team_info; | |||
300 | *OMPT_CUR_TASK_INFO(thr)(&(thr->th.th_current_task->ompt_task_info)) = lwt->ompt_task_info; | |||
301 | } | |||
302 | } | |||
303 | ||||
304 | void __ompt_lw_taskteam_unlink(kmp_info_t *thr) { | |||
305 | ompt_lw_taskteam_t *lwtask = thr->th.th_team->t.ompt_serialized_team_info; | |||
306 | if (lwtask) { | |||
307 | thr->th.th_team->t.ompt_serialized_team_info = lwtask->parent; | |||
308 | ||||
309 | ompt_team_info_t tmp_team = lwtask->ompt_team_info; | |||
310 | lwtask->ompt_team_info = *OMPT_CUR_TEAM_INFO(thr)(&(thr->th.th_team->t.ompt_team_info)); | |||
311 | *OMPT_CUR_TEAM_INFO(thr)(&(thr->th.th_team->t.ompt_team_info)) = tmp_team; | |||
312 | ||||
313 | ompt_task_info_t tmp_task = lwtask->ompt_task_info; | |||
314 | lwtask->ompt_task_info = *OMPT_CUR_TASK_INFO(thr)(&(thr->th.th_current_task->ompt_task_info)); | |||
315 | *OMPT_CUR_TASK_INFO(thr)(&(thr->th.th_current_task->ompt_task_info)) = tmp_task; | |||
316 | ||||
317 | if (lwtask->heap) { | |||
318 | __kmp_free(lwtask)___kmp_free((lwtask), "/build/llvm-toolchain-snapshot-8~svn345461/projects/openmp/runtime/src/ompt-specific.cpp" , 318); | |||
319 | lwtask = NULL__null; | |||
320 | } | |||
321 | } | |||
322 | // return lwtask; | |||
323 | } | |||
324 | ||||
325 | //---------------------------------------------------------- | |||
326 | // task support | |||
327 | //---------------------------------------------------------- | |||
328 | ||||
329 | int __ompt_get_task_info_internal(int ancestor_level, int *type, | |||
330 | ompt_data_t **task_data, | |||
331 | omp_frame_t **task_frame, | |||
332 | ompt_data_t **parallel_data, | |||
333 | int *thread_num) { | |||
334 | if (__kmp_get_gtid()__kmp_get_global_thread_id() < 0) | |||
335 | return 0; | |||
336 | ||||
337 | if (ancestor_level < 0) | |||
338 | return 0; | |||
339 | ||||
340 | // copied from __ompt_get_scheduling_taskinfo | |||
341 | ompt_task_info_t *info = NULL__null; | |||
342 | ompt_team_info_t *team_info = NULL__null; | |||
343 | kmp_info_t *thr = ompt_get_thread(); | |||
344 | int level = ancestor_level; | |||
345 | ||||
346 | if (thr) { | |||
347 | kmp_taskdata_t *taskdata = thr->th.th_current_task; | |||
348 | if (taskdata == NULL__null) | |||
349 | return 0; | |||
350 | kmp_team *team = thr->th.th_team, *prev_team = NULL__null; | |||
351 | if (team == NULL__null) | |||
352 | return 0; | |||
353 | ompt_lw_taskteam_t *lwt = NULL__null, | |||
354 | *next_lwt = LWT_FROM_TEAM(taskdata->td_team)(taskdata->td_team)->t.ompt_serialized_team_info, | |||
355 | *prev_lwt = NULL__null; | |||
356 | ||||
357 | while (ancestor_level > 0) { | |||
358 | // needed for thread_num | |||
359 | prev_team = team; | |||
360 | prev_lwt = lwt; | |||
361 | // next lightweight team (if any) | |||
362 | if (lwt) | |||
363 | lwt = lwt->parent; | |||
364 | ||||
365 | // next heavyweight team (if any) after | |||
366 | // lightweight teams are exhausted | |||
367 | if (!lwt && taskdata) { | |||
368 | // first try scheduling parent (for explicit task scheduling) | |||
369 | if (taskdata->ompt_task_info.scheduling_parent) { | |||
370 | taskdata = taskdata->ompt_task_info.scheduling_parent; | |||
371 | } else if (next_lwt) { | |||
372 | lwt = next_lwt; | |||
373 | next_lwt = NULL__null; | |||
374 | } else { | |||
375 | // then go for implicit tasks | |||
376 | taskdata = taskdata->td_parent; | |||
377 | if (team == NULL__null) | |||
378 | return 0; | |||
379 | team = team->t.t_parent; | |||
380 | if (taskdata) { | |||
381 | next_lwt = LWT_FROM_TEAM(taskdata->td_team)(taskdata->td_team)->t.ompt_serialized_team_info; | |||
382 | } | |||
383 | } | |||
384 | } | |||
385 | ancestor_level--; | |||
386 | } | |||
387 | ||||
388 | if (lwt) { | |||
389 | info = &lwt->ompt_task_info; | |||
390 | team_info = &lwt->ompt_team_info; | |||
391 | if (type) { | |||
392 | *type = ompt_task_implicit; | |||
393 | } | |||
394 | } else if (taskdata) { | |||
395 | info = &taskdata->ompt_task_info; | |||
396 | team_info = &team->t.ompt_team_info; | |||
397 | if (type) { | |||
398 | if (taskdata->td_parent) { | |||
399 | *type = (taskdata->td_flags.tasktype ? ompt_task_explicit | |||
400 | : ompt_task_implicit) | | |||
401 | TASK_TYPE_DETAILS_FORMAT(taskdata)((taskdata->td_flags.task_serial || taskdata->td_flags. tasking_ser) ? ompt_task_undeferred : 0x0) | ((!(taskdata-> td_flags.tiedness)) ? ompt_task_untied : 0x0) | (taskdata-> td_flags.final ? ompt_task_final : 0x0) | (taskdata->td_flags .merged_if0 ? ompt_task_mergeable : 0x0); | |||
402 | } else { | |||
403 | *type = ompt_task_initial; | |||
404 | } | |||
405 | } | |||
406 | } | |||
407 | if (task_data) { | |||
408 | *task_data = info ? &info->task_data : NULL__null; | |||
409 | } | |||
410 | if (task_frame) { | |||
411 | // OpenMP spec asks for the scheduling task to be returned. | |||
412 | *task_frame = info ? &info->frame : NULL__null; | |||
413 | } | |||
414 | if (parallel_data) { | |||
415 | *parallel_data = team_info ? &(team_info->parallel_data) : NULL__null; | |||
416 | } | |||
417 | if (thread_num) { | |||
418 | if (level == 0) | |||
419 | *thread_num = __kmp_get_tid()(__kmp_tid_from_gtid(__kmp_get_global_thread_id())); | |||
420 | else if (prev_lwt) | |||
421 | *thread_num = 0; | |||
422 | else | |||
423 | *thread_num = prev_team->t.t_master_tid; | |||
| ||||
424 | // *thread_num = team->t.t_master_tid; | |||
425 | } | |||
426 | return info ? 2 : 0; | |||
427 | } | |||
428 | return 0; | |||
429 | } | |||
430 | ||||
431 | //---------------------------------------------------------- | |||
432 | // team support | |||
433 | //---------------------------------------------------------- | |||
434 | ||||
435 | void __ompt_team_assign_id(kmp_team_t *team, ompt_data_t ompt_pid) { | |||
436 | team->t.ompt_team_info.parallel_data = ompt_pid; | |||
437 | } | |||
438 | ||||
439 | //---------------------------------------------------------- | |||
440 | // misc | |||
441 | //---------------------------------------------------------- | |||
442 | ||||
443 | static uint64_t __ompt_get_unique_id_internal() { | |||
444 | static uint64_t thread = 1; | |||
445 | static THREAD_LOCAL__thread uint64_t ID = 0; | |||
446 | if (ID == 0) { | |||
447 | uint64_t new_thread = KMP_TEST_THEN_INC64((kmp_int64 *)&thread)__sync_fetch_and_add((volatile kmp_int64 *)((kmp_int64 *)& thread), 1LL); | |||
448 | ID = new_thread << (sizeof(uint64_t) * 8 - OMPT_THREAD_ID_BITS16); | |||
449 | } | |||
450 | return ++ID; | |||
451 | } |