1#if USE_ITT_BUILD
2/*
3 * kmp_itt.h -- ITT Notify interface.
4 */
5
6//===----------------------------------------------------------------------===//
7//
8// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
9// See https://llvm.org/LICENSE.txt for license information.
10// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef KMP_ITT_H
15#define KMP_ITT_H
16
17#include "kmp_lock.h"
18
19#define INTEL_ITTNOTIFY_API_PRIVATE
20#include "ittnotify.h"
21#include "legacy/ittnotify.h"
22
23#if KMP_DEBUG
24#define __kmp_inline // Turn off inlining in debug mode.
25#else
26#define __kmp_inline static inline
27#endif
28
29#if USE_ITT_NOTIFY
30extern kmp_int32 __kmp_itt_prepare_delay;
31#ifdef __cplusplus
32extern "C" void __kmp_itt_fini_ittlib(void);
33#else
34extern void __kmp_itt_fini_ittlib(void);
35#endif
36#endif
37
38// Simplify the handling of an argument that is only required when USE_ITT_BUILD
39// is enabled.
40#define USE_ITT_BUILD_ARG(x) , x
41
42void __kmp_itt_initialize();
43void __kmp_itt_destroy();
44void __kmp_itt_reset();
45
46// -----------------------------------------------------------------------------
47// New stuff for reporting high-level constructs.
48
49// Note the naming convention:
50//     __kmp_itt_xxxing() function should be called before action, while
51//     __kmp_itt_xxxed()  function should be called after action.
52
53// --- Parallel region reporting ---
54__kmp_inline void
55__kmp_itt_region_forking(int gtid, int team_size,
56                         int barriers); // Primary only, before forking threads.
57__kmp_inline void
58__kmp_itt_region_joined(int gtid); // Primary only, after joining threads.
59// (*) Note: A thread may execute tasks after this point, though.
60
61// --- Frame reporting ---
62// region=0: no regions, region=1: parallel, region=2: serialized parallel
63__kmp_inline void __kmp_itt_frame_submit(int gtid, __itt_timestamp begin,
64                                         __itt_timestamp end, int imbalance,
65                                         ident_t *loc, int team_size,
66                                         int region = 0);
67
68// --- Metadata reporting ---
69// begin/end - begin/end timestamps of a barrier frame, imbalance - aggregated
70// wait time value, reduction -if this is a reduction barrier
71__kmp_inline void __kmp_itt_metadata_imbalance(int gtid, kmp_uint64 begin,
72                                               kmp_uint64 end,
73                                               kmp_uint64 imbalance,
74                                               kmp_uint64 reduction);
75// sched_type: 0 - static, 1 - dynamic, 2 - guided, 3 - custom (all others);
76// iterations - loop trip count, chunk - chunk size
77__kmp_inline void __kmp_itt_metadata_loop(ident_t *loc, kmp_uint64 sched_type,
78                                          kmp_uint64 iterations,
79                                          kmp_uint64 chunk);
80__kmp_inline void __kmp_itt_metadata_single(ident_t *loc);
81
82// --- Barrier reporting ---
83__kmp_inline void *__kmp_itt_barrier_object(int gtid, int bt, int set_name = 0,
84                                            int delta = 0);
85__kmp_inline void __kmp_itt_barrier_starting(int gtid, void *object);
86__kmp_inline void __kmp_itt_barrier_middle(int gtid, void *object);
87__kmp_inline void __kmp_itt_barrier_finished(int gtid, void *object);
88
89// --- Taskwait reporting ---
90__kmp_inline void *__kmp_itt_taskwait_object(int gtid);
91__kmp_inline void __kmp_itt_taskwait_starting(int gtid, void *object);
92__kmp_inline void __kmp_itt_taskwait_finished(int gtid, void *object);
93#define KMP_ITT_TASKWAIT_STARTING(obj)                                         \
94  if (UNLIKELY(__itt_sync_create_ptr)) {                                       \
95    obj = __kmp_itt_taskwait_object(gtid);                                     \
96    if (obj != NULL) {                                                         \
97      __kmp_itt_taskwait_starting(gtid, obj);                                  \
98    }                                                                          \
99  }
100#define KMP_ITT_TASKWAIT_FINISHED(obj)                                         \
101  if (UNLIKELY(obj != NULL))                                                   \
102    __kmp_itt_taskwait_finished(gtid, obj);
103
104// --- Task reporting ---
105__kmp_inline void __kmp_itt_task_starting(void *object);
106__kmp_inline void __kmp_itt_task_finished(void *object);
107
108// --- Lock reporting ---
109#if KMP_USE_DYNAMIC_LOCK
110__kmp_inline void __kmp_itt_lock_creating(kmp_user_lock_p lock,
111                                          const ident_t *);
112#else
113__kmp_inline void __kmp_itt_lock_creating(kmp_user_lock_p lock);
114#endif
115__kmp_inline void __kmp_itt_lock_acquiring(kmp_user_lock_p lock);
116__kmp_inline void __kmp_itt_lock_acquired(kmp_user_lock_p lock);
117__kmp_inline void __kmp_itt_lock_releasing(kmp_user_lock_p lock);
118__kmp_inline void __kmp_itt_lock_cancelled(kmp_user_lock_p lock);
119__kmp_inline void __kmp_itt_lock_destroyed(kmp_user_lock_p lock);
120
121// --- Critical reporting ---
122#if KMP_USE_DYNAMIC_LOCK
123__kmp_inline void __kmp_itt_critical_creating(kmp_user_lock_p lock,
124                                              const ident_t *);
125#else
126__kmp_inline void __kmp_itt_critical_creating(kmp_user_lock_p lock);
127#endif
128__kmp_inline void __kmp_itt_critical_acquiring(kmp_user_lock_p lock);
129__kmp_inline void __kmp_itt_critical_acquired(kmp_user_lock_p lock);
130__kmp_inline void __kmp_itt_critical_releasing(kmp_user_lock_p lock);
131__kmp_inline void __kmp_itt_critical_destroyed(kmp_user_lock_p lock);
132
133// --- Single reporting ---
134__kmp_inline void __kmp_itt_single_start(int gtid);
135__kmp_inline void __kmp_itt_single_end(int gtid);
136
137// --- Ordered reporting ---
138__kmp_inline void __kmp_itt_ordered_init(int gtid);
139__kmp_inline void __kmp_itt_ordered_prep(int gtid);
140__kmp_inline void __kmp_itt_ordered_start(int gtid);
141__kmp_inline void __kmp_itt_ordered_end(int gtid);
142
143// --- Threads reporting ---
144__kmp_inline void __kmp_itt_thread_ignore();
145__kmp_inline void __kmp_itt_thread_name(int gtid);
146
147// --- System objects ---
148__kmp_inline void __kmp_itt_system_object_created(void *object,
149                                                  char const *name);
150
151// --- Stack stitching ---
152__kmp_inline __itt_caller __kmp_itt_stack_caller_create(void);
153__kmp_inline void __kmp_itt_stack_caller_destroy(__itt_caller);
154__kmp_inline void __kmp_itt_stack_callee_enter(__itt_caller);
155__kmp_inline void __kmp_itt_stack_callee_leave(__itt_caller);
156
157// -----------------------------------------------------------------------------
158// Old stuff for reporting low-level internal synchronization.
159
160#if USE_ITT_NOTIFY
161
162/* Support for SSC marks, which are used by SDE
163   http://software.intel.com/en-us/articles/intel-software-development-emulator
164   to mark points in instruction traces that represent spin-loops and are
165   therefore uninteresting when collecting traces for architecture simulation.
166 */
167#ifndef INCLUDE_SSC_MARKS
168#define INCLUDE_SSC_MARKS (KMP_OS_LINUX && KMP_ARCH_X86_64)
169#endif
170
171/* Linux 64 only for now */
172#if (INCLUDE_SSC_MARKS && KMP_OS_LINUX && KMP_ARCH_X86_64)
173// Portable (at least for gcc and icc) code to insert the necessary instructions
174// to set %ebx and execute the unlikely no-op.
175#if defined(__INTEL_COMPILER)
176#define INSERT_SSC_MARK(tag) __SSC_MARK(tag)
177#else
178#define INSERT_SSC_MARK(tag)                                                   \
179  __asm__ __volatile__("movl %0, %%ebx; .byte 0x64, 0x67, 0x90 " ::"i"(tag)    \
180                       : "%ebx")
181#endif
182#else
183#define INSERT_SSC_MARK(tag) ((void)0)
184#endif
185
186/* Markers for the start and end of regions that represent polling and are
187   therefore uninteresting to architectural simulations 0x4376 and 0x4377 are
188   arbitrary numbers that should be unique in the space of SSC tags, but there
189   is no central issuing authority rather randomness is expected to work. */
190#define SSC_MARK_SPIN_START() INSERT_SSC_MARK(0x4376)
191#define SSC_MARK_SPIN_END() INSERT_SSC_MARK(0x4377)
192
193// Markers for architecture simulation.
194// FORKING      : Before the primary thread forks.
195// JOINING      : At the start of the join.
196// INVOKING     : Before the threads invoke microtasks.
197// DISPATCH_INIT: At the start of dynamically scheduled loop.
198// DISPATCH_NEXT: After claming next iteration of dynamically scheduled loop.
199#define SSC_MARK_FORKING() INSERT_SSC_MARK(0xd693)
200#define SSC_MARK_JOINING() INSERT_SSC_MARK(0xd694)
201#define SSC_MARK_INVOKING() INSERT_SSC_MARK(0xd695)
202#define SSC_MARK_DISPATCH_INIT() INSERT_SSC_MARK(0xd696)
203#define SSC_MARK_DISPATCH_NEXT() INSERT_SSC_MARK(0xd697)
204
205// The object is an address that associates a specific set of the prepare,
206// acquire, release, and cancel operations.
207
208/* Sync prepare indicates a thread is going to start waiting for another thread
209   to send a release event.  This operation should be done just before the
210   thread begins checking for the existence of the release event */
211
212/* Sync cancel indicates a thread is cancelling a wait on another thread and
213   continuing execution without waiting for the other thread to release it */
214
215/* Sync acquired indicates a thread has received a release event from another
216   thread and has stopped waiting.  This operation must occur only after the
217   release event is received. */
218
219/* Sync release indicates a thread is going to send a release event to another
220   thread so it will stop waiting and continue execution. This operation must
221   just happen before the release event. */
222
223#define KMP_FSYNC_PREPARE(obj) __itt_fsync_prepare((void *)(obj))
224#define KMP_FSYNC_CANCEL(obj) __itt_fsync_cancel((void *)(obj))
225#define KMP_FSYNC_ACQUIRED(obj) __itt_fsync_acquired((void *)(obj))
226#define KMP_FSYNC_RELEASING(obj) __itt_fsync_releasing((void *)(obj))
227
228/* In case of waiting in a spin loop, ITT wants KMP_FSYNC_PREPARE() to be called
229   with a delay (and not called at all if waiting time is small). So, in spin
230   loops, do not use KMP_FSYNC_PREPARE(), but use KMP_FSYNC_SPIN_INIT() (before
231   spin loop), KMP_FSYNC_SPIN_PREPARE() (whithin the spin loop), and
232   KMP_FSYNC_SPIN_ACQUIRED(). See KMP_WAIT() for example. */
233
234#undef KMP_FSYNC_SPIN_INIT
235#define KMP_FSYNC_SPIN_INIT(obj, spin)                                         \
236  int sync_iters = 0;                                                          \
237  if (__itt_fsync_prepare_ptr) {                                               \
238    if (obj == NULL) {                                                         \
239      obj = spin;                                                              \
240    } /* if */                                                                 \
241  } /* if */                                                                   \
242  SSC_MARK_SPIN_START()
243
244#undef KMP_FSYNC_SPIN_PREPARE
245#define KMP_FSYNC_SPIN_PREPARE(obj)                                            \
246  do {                                                                         \
247    if (__itt_fsync_prepare_ptr && sync_iters < __kmp_itt_prepare_delay) {     \
248      ++sync_iters;                                                            \
249      if (sync_iters >= __kmp_itt_prepare_delay) {                             \
250        KMP_FSYNC_PREPARE((void *)obj);                                        \
251      } /* if */                                                               \
252    } /* if */                                                                 \
253  } while (0)
254#undef KMP_FSYNC_SPIN_ACQUIRED
255#define KMP_FSYNC_SPIN_ACQUIRED(obj)                                           \
256  do {                                                                         \
257    SSC_MARK_SPIN_END();                                                       \
258    if (sync_iters >= __kmp_itt_prepare_delay) {                               \
259      KMP_FSYNC_ACQUIRED((void *)obj);                                         \
260    } /* if */                                                                 \
261  } while (0)
262
263/* ITT will not report objects created within KMP_ITT_IGNORE(), e. g.:
264       KMP_ITT_IGNORE(
265           ptr = malloc( size );
266       );
267*/
268#define KMP_ITT_IGNORE(statement)                                              \
269  do {                                                                         \
270    __itt_state_t __itt_state_;                                                \
271    if (__itt_state_get_ptr) {                                                 \
272      __itt_state_ = __itt_state_get();                                        \
273      __itt_obj_mode_set(__itt_obj_prop_ignore, __itt_obj_state_set);          \
274    } /* if */                                                                 \
275    { statement }                                                              \
276    if (__itt_state_get_ptr) {                                                 \
277      __itt_state_set(__itt_state_);                                           \
278    } /* if */                                                                 \
279  } while (0)
280
281// Maximum number of frame domains to use (maps to
282// different OpenMP regions in the user source code).
283const int KMP_MAX_FRAME_DOMAINS = 997;
284typedef struct kmp_itthash_entry {
285  ident_t *loc;
286  int team_size;
287  __itt_domain *d;
288  struct kmp_itthash_entry *next_in_bucket;
289} kmp_itthash_entry_t;
290typedef struct kmp_itthash {
291  kmp_itthash_entry_t *buckets[KMP_MAX_FRAME_DOMAINS];
292  int count; // just a heuristic to limit number of entries
293} kmp_itthash_t;
294extern kmp_itthash_t __kmp_itt_region_domains;
295extern kmp_itthash_t __kmp_itt_barrier_domains;
296extern __itt_domain *metadata_domain;
297extern __itt_string_handle *string_handle_imbl;
298extern __itt_string_handle *string_handle_loop;
299extern __itt_string_handle *string_handle_sngl;
300
301#else
302
303// Null definitions of the synchronization tracing functions.
304#define KMP_FSYNC_PREPARE(obj) ((void)0)
305#define KMP_FSYNC_CANCEL(obj) ((void)0)
306#define KMP_FSYNC_ACQUIRED(obj) ((void)0)
307#define KMP_FSYNC_RELEASING(obj) ((void)0)
308
309#define KMP_FSYNC_SPIN_INIT(obj, spin) ((void)0)
310#define KMP_FSYNC_SPIN_PREPARE(obj) ((void)0)
311#define KMP_FSYNC_SPIN_ACQUIRED(obj) ((void)0)
312
313#define KMP_ITT_IGNORE(stmt)                                                   \
314  do {                                                                         \
315    stmt                                                                       \
316  } while (0)
317
318#endif // USE_ITT_NOTIFY
319
320#if !KMP_DEBUG
321// In release mode include definitions of inline functions.
322#include "kmp_itt.inl"
323#endif
324
325#endif // KMP_ITT_H
326
327#else /* USE_ITT_BUILD */
328
329// Null definitions of the synchronization tracing functions.
330// If USE_ITT_BULID is not enabled, USE_ITT_NOTIFY cannot be either.
331// By defining these we avoid unpleasant ifdef tests in many places.
332#define KMP_FSYNC_PREPARE(obj) ((void)0)
333#define KMP_FSYNC_CANCEL(obj) ((void)0)
334#define KMP_FSYNC_ACQUIRED(obj) ((void)0)
335#define KMP_FSYNC_RELEASING(obj) ((void)0)
336
337#define KMP_FSYNC_SPIN_INIT(obj, spin) ((void)0)
338#define KMP_FSYNC_SPIN_PREPARE(obj) ((void)0)
339#define KMP_FSYNC_SPIN_ACQUIRED(obj) ((void)0)
340
341#define KMP_ITT_IGNORE(stmt)                                                   \
342  do {                                                                         \
343    stmt                                                                       \
344  } while (0)
345
346#define USE_ITT_BUILD_ARG(x)
347
348#endif /* USE_ITT_BUILD */
349