1 /*
2  * kmp_gsupport.cpp
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 #include "kmp.h"
15 #include "kmp_atomic.h"
16 
17 #if OMPT_SUPPORT
18 #include "ompt-specific.h"
19 #endif
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif // __cplusplus
24 
25 #define MKLOC(loc, routine)                                                    \
26   static ident_t(loc) = {0, KMP_IDENT_KMPC, 0, 0, ";unknown;unknown;0;0;;"};
27 
28 #include "kmp_ftn_os.h"
29 
30 void xexpand(KMP_API_NAME_GOMP_BARRIER)(void) {
31   int gtid = __kmp_entry_gtid();
32   MKLOC(loc, "GOMP_barrier");
33   KA_TRACE(20, ("GOMP_barrier: T#%d\n", gtid));
34 #if OMPT_SUPPORT && OMPT_TRACE
35   ompt_frame_t *ompt_frame;
36   if (ompt_enabled) {
37     ompt_frame = __ompt_get_task_frame_internal(0);
38     ompt_frame->reenter_runtime_frame = __builtin_frame_address(1);
39   }
40 #endif
41   __kmpc_barrier(&loc, gtid);
42 }
43 
44 // Mutual exclusion
45 
46 // The symbol that icc/ifort generates for unnamed for unnamed critical sections
47 // - .gomp_critical_user_ - is defined using .comm in any objects reference it.
48 // We can't reference it directly here in C code, as the symbol contains a ".".
49 //
50 // The RTL contains an assembly language definition of .gomp_critical_user_
51 // with another symbol __kmp_unnamed_critical_addr initialized with it's
52 // address.
53 extern kmp_critical_name *__kmp_unnamed_critical_addr;
54 
55 void xexpand(KMP_API_NAME_GOMP_CRITICAL_START)(void) {
56   int gtid = __kmp_entry_gtid();
57   MKLOC(loc, "GOMP_critical_start");
58   KA_TRACE(20, ("GOMP_critical_start: T#%d\n", gtid));
59   __kmpc_critical(&loc, gtid, __kmp_unnamed_critical_addr);
60 }
61 
62 void xexpand(KMP_API_NAME_GOMP_CRITICAL_END)(void) {
63   int gtid = __kmp_get_gtid();
64   MKLOC(loc, "GOMP_critical_end");
65   KA_TRACE(20, ("GOMP_critical_end: T#%d\n", gtid));
66   __kmpc_end_critical(&loc, gtid, __kmp_unnamed_critical_addr);
67 }
68 
69 void xexpand(KMP_API_NAME_GOMP_CRITICAL_NAME_START)(void **pptr) {
70   int gtid = __kmp_entry_gtid();
71   MKLOC(loc, "GOMP_critical_name_start");
72   KA_TRACE(20, ("GOMP_critical_name_start: T#%d\n", gtid));
73   __kmpc_critical(&loc, gtid, (kmp_critical_name *)pptr);
74 }
75 
76 void xexpand(KMP_API_NAME_GOMP_CRITICAL_NAME_END)(void **pptr) {
77   int gtid = __kmp_get_gtid();
78   MKLOC(loc, "GOMP_critical_name_end");
79   KA_TRACE(20, ("GOMP_critical_name_end: T#%d\n", gtid));
80   __kmpc_end_critical(&loc, gtid, (kmp_critical_name *)pptr);
81 }
82 
83 // The Gnu codegen tries to use locked operations to perform atomic updates
84 // inline.  If it can't, then it calls GOMP_atomic_start() before performing
85 // the update and GOMP_atomic_end() afterward, regardless of the data type.
86 void xexpand(KMP_API_NAME_GOMP_ATOMIC_START)(void) {
87   int gtid = __kmp_entry_gtid();
88   KA_TRACE(20, ("GOMP_atomic_start: T#%d\n", gtid));
89 
90 #if OMPT_SUPPORT
91   __ompt_thread_assign_wait_id(0);
92 #endif
93 
94   __kmp_acquire_atomic_lock(&__kmp_atomic_lock, gtid);
95 }
96 
97 void xexpand(KMP_API_NAME_GOMP_ATOMIC_END)(void) {
98   int gtid = __kmp_get_gtid();
99   KA_TRACE(20, ("GOMP_atomic_start: T#%d\n", gtid));
100   __kmp_release_atomic_lock(&__kmp_atomic_lock, gtid);
101 }
102 
103 int xexpand(KMP_API_NAME_GOMP_SINGLE_START)(void) {
104   int gtid = __kmp_entry_gtid();
105   MKLOC(loc, "GOMP_single_start");
106   KA_TRACE(20, ("GOMP_single_start: T#%d\n", gtid));
107 
108   if (!TCR_4(__kmp_init_parallel))
109     __kmp_parallel_initialize();
110 
111   // 3rd parameter == FALSE prevents kmp_enter_single from pushing a
112   // workshare when USE_CHECKS is defined.  We need to avoid the push,
113   // as there is no corresponding GOMP_single_end() call.
114   return __kmp_enter_single(gtid, &loc, FALSE);
115 }
116 
117 void *xexpand(KMP_API_NAME_GOMP_SINGLE_COPY_START)(void) {
118   void *retval;
119   int gtid = __kmp_entry_gtid();
120   MKLOC(loc, "GOMP_single_copy_start");
121   KA_TRACE(20, ("GOMP_single_copy_start: T#%d\n", gtid));
122 
123   if (!TCR_4(__kmp_init_parallel))
124     __kmp_parallel_initialize();
125 
126   // If this is the first thread to enter, return NULL.  The generated code will
127   // then call GOMP_single_copy_end() for this thread only, with the
128   // copyprivate data pointer as an argument.
129   if (__kmp_enter_single(gtid, &loc, FALSE))
130     return NULL;
131 
132   // Wait for the first thread to set the copyprivate data pointer,
133   // and for all other threads to reach this point.
134   __kmp_barrier(bs_plain_barrier, gtid, FALSE, 0, NULL, NULL);
135 
136   // Retrieve the value of the copyprivate data point, and wait for all
137   // threads to do likewise, then return.
138   retval = __kmp_team_from_gtid(gtid)->t.t_copypriv_data;
139   __kmp_barrier(bs_plain_barrier, gtid, FALSE, 0, NULL, NULL);
140   return retval;
141 }
142 
143 void xexpand(KMP_API_NAME_GOMP_SINGLE_COPY_END)(void *data) {
144   int gtid = __kmp_get_gtid();
145   KA_TRACE(20, ("GOMP_single_copy_end: T#%d\n", gtid));
146 
147   // Set the copyprivate data pointer fo the team, then hit the barrier so that
148   // the other threads will continue on and read it.  Hit another barrier before
149   // continuing, so that the know that the copyprivate data pointer has been
150   // propagated to all threads before trying to reuse the t_copypriv_data field.
151   __kmp_team_from_gtid(gtid)->t.t_copypriv_data = data;
152   __kmp_barrier(bs_plain_barrier, gtid, FALSE, 0, NULL, NULL);
153   __kmp_barrier(bs_plain_barrier, gtid, FALSE, 0, NULL, NULL);
154 }
155 
156 void xexpand(KMP_API_NAME_GOMP_ORDERED_START)(void) {
157   int gtid = __kmp_entry_gtid();
158   MKLOC(loc, "GOMP_ordered_start");
159   KA_TRACE(20, ("GOMP_ordered_start: T#%d\n", gtid));
160   __kmpc_ordered(&loc, gtid);
161 }
162 
163 void xexpand(KMP_API_NAME_GOMP_ORDERED_END)(void) {
164   int gtid = __kmp_get_gtid();
165   MKLOC(loc, "GOMP_ordered_end");
166   KA_TRACE(20, ("GOMP_ordered_start: T#%d\n", gtid));
167   __kmpc_end_ordered(&loc, gtid);
168 }
169 
170 // Dispatch macro defs
171 //
172 // They come in two flavors: 64-bit unsigned, and either 32-bit signed
173 // (IA-32 architecture) or 64-bit signed (Intel(R) 64).
174 
175 #if KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_MIPS
176 #define KMP_DISPATCH_INIT __kmp_aux_dispatch_init_4
177 #define KMP_DISPATCH_FINI_CHUNK __kmp_aux_dispatch_fini_chunk_4
178 #define KMP_DISPATCH_NEXT __kmpc_dispatch_next_4
179 #else
180 #define KMP_DISPATCH_INIT __kmp_aux_dispatch_init_8
181 #define KMP_DISPATCH_FINI_CHUNK __kmp_aux_dispatch_fini_chunk_8
182 #define KMP_DISPATCH_NEXT __kmpc_dispatch_next_8
183 #endif /* KMP_ARCH_X86 */
184 
185 #define KMP_DISPATCH_INIT_ULL __kmp_aux_dispatch_init_8u
186 #define KMP_DISPATCH_FINI_CHUNK_ULL __kmp_aux_dispatch_fini_chunk_8u
187 #define KMP_DISPATCH_NEXT_ULL __kmpc_dispatch_next_8u
188 
189 // The parallel contruct
190 
191 #ifndef KMP_DEBUG
192 static
193 #endif /* KMP_DEBUG */
194     void
195     __kmp_GOMP_microtask_wrapper(int *gtid, int *npr, void (*task)(void *),
196                                  void *data) {
197 #if OMPT_SUPPORT
198   kmp_info_t *thr;
199   ompt_frame_t *ompt_frame;
200   ompt_state_t enclosing_state;
201 
202   if (ompt_enabled) {
203     // get pointer to thread data structure
204     thr = __kmp_threads[*gtid];
205 
206     // save enclosing task state; set current state for task
207     enclosing_state = thr->th.ompt_thread_info.state;
208     thr->th.ompt_thread_info.state = ompt_state_work_parallel;
209 
210     // set task frame
211     ompt_frame = __ompt_get_task_frame_internal(0);
212     ompt_frame->exit_runtime_frame = __builtin_frame_address(0);
213   }
214 #endif
215 
216   task(data);
217 
218 #if OMPT_SUPPORT
219   if (ompt_enabled) {
220     // clear task frame
221     ompt_frame->exit_runtime_frame = NULL;
222 
223     // restore enclosing state
224     thr->th.ompt_thread_info.state = enclosing_state;
225   }
226 #endif
227 }
228 
229 #ifndef KMP_DEBUG
230 static
231 #endif /* KMP_DEBUG */
232     void
233     __kmp_GOMP_parallel_microtask_wrapper(int *gtid, int *npr,
234                                           void (*task)(void *), void *data,
235                                           unsigned num_threads, ident_t *loc,
236                                           enum sched_type schedule, long start,
237                                           long end, long incr,
238                                           long chunk_size) {
239   // Intialize the loop worksharing construct.
240   KMP_DISPATCH_INIT(loc, *gtid, schedule, start, end, incr, chunk_size,
241                     schedule != kmp_sch_static);
242 
243 #if OMPT_SUPPORT
244   kmp_info_t *thr;
245   ompt_frame_t *ompt_frame;
246   ompt_state_t enclosing_state;
247 
248   if (ompt_enabled) {
249     thr = __kmp_threads[*gtid];
250     // save enclosing task state; set current state for task
251     enclosing_state = thr->th.ompt_thread_info.state;
252     thr->th.ompt_thread_info.state = ompt_state_work_parallel;
253 
254     // set task frame
255     ompt_frame = __ompt_get_task_frame_internal(0);
256     ompt_frame->exit_runtime_frame = __builtin_frame_address(0);
257   }
258 #endif
259 
260   // Now invoke the microtask.
261   task(data);
262 
263 #if OMPT_SUPPORT
264   if (ompt_enabled) {
265     // clear task frame
266     ompt_frame->exit_runtime_frame = NULL;
267 
268     // reset enclosing state
269     thr->th.ompt_thread_info.state = enclosing_state;
270   }
271 #endif
272 }
273 
274 #ifndef KMP_DEBUG
275 static
276 #endif /* KMP_DEBUG */
277     void
278     __kmp_GOMP_fork_call(ident_t *loc, int gtid, void (*unwrapped_task)(void *),
279                          microtask_t wrapper, int argc, ...) {
280   int rc;
281   kmp_info_t *thr = __kmp_threads[gtid];
282   kmp_team_t *team = thr->th.th_team;
283   int tid = __kmp_tid_from_gtid(gtid);
284 
285   va_list ap;
286   va_start(ap, argc);
287 
288   rc = __kmp_fork_call(loc, gtid, fork_context_gnu, argc,
289 #if OMPT_SUPPORT
290                        VOLATILE_CAST(void *) unwrapped_task,
291 #endif
292                        wrapper, __kmp_invoke_task_func,
293 #if (KMP_ARCH_X86_64 || KMP_ARCH_ARM || KMP_ARCH_AARCH64) && KMP_OS_LINUX
294                        &ap
295 #else
296                        ap
297 #endif
298                        );
299 
300   va_end(ap);
301 
302   if (rc) {
303     __kmp_run_before_invoked_task(gtid, tid, thr, team);
304   }
305 
306 #if OMPT_SUPPORT
307   if (ompt_enabled) {
308 #if OMPT_TRACE
309     ompt_team_info_t *team_info = __ompt_get_teaminfo(0, NULL);
310     ompt_task_info_t *task_info = __ompt_get_taskinfo(0);
311 
312     // implicit task callback
313     if (ompt_callbacks.ompt_callback(ompt_event_implicit_task_begin)) {
314       ompt_callbacks.ompt_callback(ompt_event_implicit_task_begin)(
315           team_info->parallel_id, task_info->task_id);
316     }
317 #endif
318     thr->th.ompt_thread_info.state = ompt_state_work_parallel;
319   }
320 #endif
321 }
322 
323 static void __kmp_GOMP_serialized_parallel(ident_t *loc, kmp_int32 gtid,
324                                            void (*task)(void *)) {
325 #if OMPT_SUPPORT
326   ompt_parallel_id_t ompt_parallel_id;
327   if (ompt_enabled) {
328     ompt_task_info_t *task_info = __ompt_get_taskinfo(0);
329 
330     ompt_parallel_id = __ompt_parallel_id_new(gtid);
331 
332     // parallel region callback
333     if (ompt_callbacks.ompt_callback(ompt_event_parallel_begin)) {
334       int team_size = 1;
335       ompt_callbacks.ompt_callback(ompt_event_parallel_begin)(
336           task_info->task_id, &task_info->frame, ompt_parallel_id, team_size,
337           (void *)task, OMPT_INVOKER(fork_context_gnu));
338     }
339   }
340 #endif
341 
342   __kmp_serialized_parallel(loc, gtid);
343 
344 #if OMPT_SUPPORT
345   if (ompt_enabled) {
346     kmp_info_t *thr = __kmp_threads[gtid];
347 
348     ompt_task_id_t my_ompt_task_id = __ompt_task_id_new(gtid);
349 
350     // set up lightweight task
351     ompt_lw_taskteam_t *lwt =
352         (ompt_lw_taskteam_t *)__kmp_allocate(sizeof(ompt_lw_taskteam_t));
353     __ompt_lw_taskteam_init(lwt, thr, gtid, (void *)task, ompt_parallel_id);
354     lwt->ompt_task_info.task_id = my_ompt_task_id;
355     __ompt_lw_taskteam_link(lwt, thr);
356 
357 #if OMPT_TRACE
358     // implicit task callback
359     if (ompt_callbacks.ompt_callback(ompt_event_implicit_task_begin)) {
360       ompt_callbacks.ompt_callback(ompt_event_implicit_task_begin)(
361           ompt_parallel_id, my_ompt_task_id);
362     }
363     thr->th.ompt_thread_info.state = ompt_state_work_parallel;
364 #endif
365   }
366 #endif
367 }
368 
369 void xexpand(KMP_API_NAME_GOMP_PARALLEL_START)(void (*task)(void *), void *data,
370                                                unsigned num_threads) {
371   int gtid = __kmp_entry_gtid();
372 
373 #if OMPT_SUPPORT
374   ompt_frame_t *parent_frame, *frame;
375 
376   if (ompt_enabled) {
377     parent_frame = __ompt_get_task_frame_internal(0);
378     parent_frame->reenter_runtime_frame = __builtin_frame_address(1);
379   }
380 #endif
381 
382   MKLOC(loc, "GOMP_parallel_start");
383   KA_TRACE(20, ("GOMP_parallel_start: T#%d\n", gtid));
384 
385   if (__kmpc_ok_to_fork(&loc) && (num_threads != 1)) {
386     if (num_threads != 0) {
387       __kmp_push_num_threads(&loc, gtid, num_threads);
388     }
389     __kmp_GOMP_fork_call(&loc, gtid, task,
390                          (microtask_t)__kmp_GOMP_microtask_wrapper, 2, task,
391                          data);
392   } else {
393     __kmp_GOMP_serialized_parallel(&loc, gtid, task);
394   }
395 
396 #if OMPT_SUPPORT
397   if (ompt_enabled) {
398     frame = __ompt_get_task_frame_internal(0);
399     frame->exit_runtime_frame = __builtin_frame_address(1);
400   }
401 #endif
402 }
403 
404 void xexpand(KMP_API_NAME_GOMP_PARALLEL_END)(void) {
405   int gtid = __kmp_get_gtid();
406   kmp_info_t *thr;
407 
408   thr = __kmp_threads[gtid];
409 
410   MKLOC(loc, "GOMP_parallel_end");
411   KA_TRACE(20, ("GOMP_parallel_end: T#%d\n", gtid));
412 
413 #if OMPT_SUPPORT
414   ompt_parallel_id_t parallel_id;
415   ompt_task_id_t serialized_task_id;
416   ompt_frame_t *ompt_frame = NULL;
417 
418   if (ompt_enabled) {
419     ompt_team_info_t *team_info = __ompt_get_teaminfo(0, NULL);
420     parallel_id = team_info->parallel_id;
421 
422     ompt_task_info_t *task_info = __ompt_get_taskinfo(0);
423     serialized_task_id = task_info->task_id;
424 
425     // unlink if necessary. no-op if there is not a lightweight task.
426     ompt_lw_taskteam_t *lwt = __ompt_lw_taskteam_unlink(thr);
427     // GOMP allocates/frees lwt since it can't be kept on the stack
428     if (lwt) {
429       __kmp_free(lwt);
430     }
431   }
432 #endif
433 
434   if (!thr->th.th_team->t.t_serialized) {
435     __kmp_run_after_invoked_task(gtid, __kmp_tid_from_gtid(gtid), thr,
436                                  thr->th.th_team);
437 
438 #if OMPT_SUPPORT
439     if (ompt_enabled) {
440       // Implicit task is finished here, in the barrier we might schedule
441       // deferred tasks,
442       // these don't see the implicit task on the stack
443       ompt_frame = __ompt_get_task_frame_internal(0);
444       ompt_frame->exit_runtime_frame = NULL;
445     }
446 #endif
447 
448     __kmp_join_call(&loc, gtid
449 #if OMPT_SUPPORT
450                     ,
451                     fork_context_gnu
452 #endif
453                     );
454   } else {
455 #if OMPT_SUPPORT && OMPT_TRACE
456     if (ompt_enabled &&
457         ompt_callbacks.ompt_callback(ompt_event_implicit_task_end)) {
458       ompt_callbacks.ompt_callback(ompt_event_implicit_task_end)(
459           parallel_id, serialized_task_id);
460     }
461 #endif
462 
463     __kmpc_end_serialized_parallel(&loc, gtid);
464 
465 #if OMPT_SUPPORT
466     if (ompt_enabled) {
467       // Record that we re-entered the runtime system in the frame that
468       // created the parallel region.
469       ompt_task_info_t *parent_task_info = __ompt_get_taskinfo(0);
470 
471       if (ompt_callbacks.ompt_callback(ompt_event_parallel_end)) {
472         ompt_callbacks.ompt_callback(ompt_event_parallel_end)(
473             parallel_id, parent_task_info->task_id,
474             OMPT_INVOKER(fork_context_gnu));
475       }
476 
477       parent_task_info->frame.reenter_runtime_frame = NULL;
478 
479       thr->th.ompt_thread_info.state =
480           (((thr->th.th_team)->t.t_serialized) ? ompt_state_work_serial
481                                                : ompt_state_work_parallel);
482     }
483 #endif
484   }
485 }
486 
487 // Loop worksharing constructs
488 
489 // The Gnu codegen passes in an exclusive upper bound for the overall range,
490 // but the libguide dispatch code expects an inclusive upper bound, hence the
491 // "end - incr" 5th argument to KMP_DISPATCH_INIT (and the " ub - str" 11th
492 // argument to __kmp_GOMP_fork_call).
493 //
494 // Conversely, KMP_DISPATCH_NEXT returns and inclusive upper bound in *p_ub,
495 // but the Gnu codegen expects an excluside upper bound, so the adjustment
496 // "*p_ub += stride" compenstates for the discrepancy.
497 //
498 // Correction: the gnu codegen always adjusts the upper bound by +-1, not the
499 // stride value.  We adjust the dispatch parameters accordingly (by +-1), but
500 // we still adjust p_ub by the actual stride value.
501 //
502 // The "runtime" versions do not take a chunk_sz parameter.
503 //
504 // The profile lib cannot support construct checking of unordered loops that
505 // are predetermined by the compiler to be statically scheduled, as the gcc
506 // codegen will not always emit calls to GOMP_loop_static_next() to get the
507 // next iteration.  Instead, it emits inline code to call omp_get_thread_num()
508 // num and calculate the iteration space using the result.  It doesn't do this
509 // with ordered static loop, so they can be checked.
510 
511 #define LOOP_START(func, schedule)                                             \
512   int func(long lb, long ub, long str, long chunk_sz, long *p_lb,              \
513            long *p_ub) {                                                       \
514     int status;                                                                \
515     long stride;                                                               \
516     int gtid = __kmp_entry_gtid();                                             \
517     MKLOC(loc, #func);                                                         \
518     KA_TRACE(20,                                                               \
519              (#func ": T#%d, lb 0x%lx, ub 0x%lx, str 0x%lx, chunk_sz 0x%lx\n", \
520               gtid, lb, ub, str, chunk_sz));                                   \
521                                                                                \
522     if ((str > 0) ? (lb < ub) : (lb > ub)) {                                   \
523       KMP_DISPATCH_INIT(&loc, gtid, (schedule), lb,                            \
524                         (str > 0) ? (ub - 1) : (ub + 1), str, chunk_sz,        \
525                         (schedule) != kmp_sch_static);                         \
526       status = KMP_DISPATCH_NEXT(&loc, gtid, NULL, (kmp_int *)p_lb,            \
527                                  (kmp_int *)p_ub, (kmp_int *)&stride);         \
528       if (status) {                                                            \
529         KMP_DEBUG_ASSERT(stride == str);                                       \
530         *p_ub += (str > 0) ? 1 : -1;                                           \
531       }                                                                        \
532     } else {                                                                   \
533       status = 0;                                                              \
534     }                                                                          \
535                                                                                \
536     KA_TRACE(20,                                                               \
537              (#func " exit: T#%d, *p_lb 0x%lx, *p_ub 0x%lx, returning %d\n",   \
538               gtid, *p_lb, *p_ub, status));                                    \
539     return status;                                                             \
540   }
541 
542 #define LOOP_RUNTIME_START(func, schedule)                                     \
543   int func(long lb, long ub, long str, long *p_lb, long *p_ub) {               \
544     int status;                                                                \
545     long stride;                                                               \
546     long chunk_sz = 0;                                                         \
547     int gtid = __kmp_entry_gtid();                                             \
548     MKLOC(loc, #func);                                                         \
549     KA_TRACE(20,                                                               \
550              (#func ": T#%d, lb 0x%lx, ub 0x%lx, str 0x%lx, chunk_sz %d\n",    \
551               gtid, lb, ub, str, chunk_sz));                                   \
552                                                                                \
553     if ((str > 0) ? (lb < ub) : (lb > ub)) {                                   \
554       KMP_DISPATCH_INIT(&loc, gtid, (schedule), lb,                            \
555                         (str > 0) ? (ub - 1) : (ub + 1), str, chunk_sz, TRUE); \
556       status = KMP_DISPATCH_NEXT(&loc, gtid, NULL, (kmp_int *)p_lb,            \
557                                  (kmp_int *)p_ub, (kmp_int *)&stride);         \
558       if (status) {                                                            \
559         KMP_DEBUG_ASSERT(stride == str);                                       \
560         *p_ub += (str > 0) ? 1 : -1;                                           \
561       }                                                                        \
562     } else {                                                                   \
563       status = 0;                                                              \
564     }                                                                          \
565                                                                                \
566     KA_TRACE(20,                                                               \
567              (#func " exit: T#%d, *p_lb 0x%lx, *p_ub 0x%lx, returning %d\n",   \
568               gtid, *p_lb, *p_ub, status));                                    \
569     return status;                                                             \
570   }
571 
572 #define LOOP_NEXT(func, fini_code)                                             \
573   int func(long *p_lb, long *p_ub) {                                           \
574     int status;                                                                \
575     long stride;                                                               \
576     int gtid = __kmp_get_gtid();                                               \
577     MKLOC(loc, #func);                                                         \
578     KA_TRACE(20, (#func ": T#%d\n", gtid));                                    \
579                                                                                \
580     fini_code status = KMP_DISPATCH_NEXT(&loc, gtid, NULL, (kmp_int *)p_lb,    \
581                                          (kmp_int *)p_ub, (kmp_int *)&stride); \
582     if (status) {                                                              \
583       *p_ub += (stride > 0) ? 1 : -1;                                          \
584     }                                                                          \
585                                                                                \
586     KA_TRACE(20,                                                               \
587              (#func " exit: T#%d, *p_lb 0x%lx, *p_ub 0x%lx, stride 0x%lx, "    \
588                     "returning %d\n",                                          \
589               gtid, *p_lb, *p_ub, stride, status));                            \
590     return status;                                                             \
591   }
592 
593 LOOP_START(xexpand(KMP_API_NAME_GOMP_LOOP_STATIC_START), kmp_sch_static)
594 LOOP_NEXT(xexpand(KMP_API_NAME_GOMP_LOOP_STATIC_NEXT), {})
595 LOOP_START(xexpand(KMP_API_NAME_GOMP_LOOP_DYNAMIC_START),
596            kmp_sch_dynamic_chunked)
597 LOOP_NEXT(xexpand(KMP_API_NAME_GOMP_LOOP_DYNAMIC_NEXT), {})
598 LOOP_START(xexpand(KMP_API_NAME_GOMP_LOOP_GUIDED_START), kmp_sch_guided_chunked)
599 LOOP_NEXT(xexpand(KMP_API_NAME_GOMP_LOOP_GUIDED_NEXT), {})
600 LOOP_RUNTIME_START(xexpand(KMP_API_NAME_GOMP_LOOP_RUNTIME_START),
601                    kmp_sch_runtime)
602 LOOP_NEXT(xexpand(KMP_API_NAME_GOMP_LOOP_RUNTIME_NEXT), {})
603 
604 LOOP_START(xexpand(KMP_API_NAME_GOMP_LOOP_ORDERED_STATIC_START), kmp_ord_static)
605 LOOP_NEXT(xexpand(KMP_API_NAME_GOMP_LOOP_ORDERED_STATIC_NEXT),
606           { KMP_DISPATCH_FINI_CHUNK(&loc, gtid); })
607 LOOP_START(xexpand(KMP_API_NAME_GOMP_LOOP_ORDERED_DYNAMIC_START),
608            kmp_ord_dynamic_chunked)
609 LOOP_NEXT(xexpand(KMP_API_NAME_GOMP_LOOP_ORDERED_DYNAMIC_NEXT),
610           { KMP_DISPATCH_FINI_CHUNK(&loc, gtid); })
611 LOOP_START(xexpand(KMP_API_NAME_GOMP_LOOP_ORDERED_GUIDED_START),
612            kmp_ord_guided_chunked)
613 LOOP_NEXT(xexpand(KMP_API_NAME_GOMP_LOOP_ORDERED_GUIDED_NEXT),
614           { KMP_DISPATCH_FINI_CHUNK(&loc, gtid); })
615 LOOP_RUNTIME_START(xexpand(KMP_API_NAME_GOMP_LOOP_ORDERED_RUNTIME_START),
616                    kmp_ord_runtime)
617 LOOP_NEXT(xexpand(KMP_API_NAME_GOMP_LOOP_ORDERED_RUNTIME_NEXT),
618           { KMP_DISPATCH_FINI_CHUNK(&loc, gtid); })
619 
620 void xexpand(KMP_API_NAME_GOMP_LOOP_END)(void) {
621   int gtid = __kmp_get_gtid();
622   KA_TRACE(20, ("GOMP_loop_end: T#%d\n", gtid))
623 
624   __kmp_barrier(bs_plain_barrier, gtid, FALSE, 0, NULL, NULL);
625 
626   KA_TRACE(20, ("GOMP_loop_end exit: T#%d\n", gtid))
627 }
628 
629 void xexpand(KMP_API_NAME_GOMP_LOOP_END_NOWAIT)(void) {
630   KA_TRACE(20, ("GOMP_loop_end_nowait: T#%d\n", __kmp_get_gtid()))
631 }
632 
633 // Unsigned long long loop worksharing constructs
634 //
635 // These are new with gcc 4.4
636 
637 #define LOOP_START_ULL(func, schedule)                                         \
638   int func(int up, unsigned long long lb, unsigned long long ub,               \
639            unsigned long long str, unsigned long long chunk_sz,                \
640            unsigned long long *p_lb, unsigned long long *p_ub) {               \
641     int status;                                                                \
642     long long str2 = up ? ((long long)str) : -((long long)str);                \
643     long long stride;                                                          \
644     int gtid = __kmp_entry_gtid();                                             \
645     MKLOC(loc, #func);                                                         \
646                                                                                \
647     KA_TRACE(                                                                  \
648         20,                                                                    \
649         (#func                                                                 \
650          ": T#%d, up %d, lb 0x%llx, ub 0x%llx, str 0x%llx, chunk_sz 0x%llx\n", \
651          gtid, up, lb, ub, str, chunk_sz));                                    \
652                                                                                \
653     if ((str > 0) ? (lb < ub) : (lb > ub)) {                                   \
654       KMP_DISPATCH_INIT_ULL(&loc, gtid, (schedule), lb,                        \
655                             (str2 > 0) ? (ub - 1) : (ub + 1), str2, chunk_sz,  \
656                             (schedule) != kmp_sch_static);                     \
657       status =                                                                 \
658           KMP_DISPATCH_NEXT_ULL(&loc, gtid, NULL, (kmp_uint64 *)p_lb,          \
659                                 (kmp_uint64 *)p_ub, (kmp_int64 *)&stride);     \
660       if (status) {                                                            \
661         KMP_DEBUG_ASSERT(stride == str2);                                      \
662         *p_ub += (str > 0) ? 1 : -1;                                           \
663       }                                                                        \
664     } else {                                                                   \
665       status = 0;                                                              \
666     }                                                                          \
667                                                                                \
668     KA_TRACE(20,                                                               \
669              (#func " exit: T#%d, *p_lb 0x%llx, *p_ub 0x%llx, returning %d\n", \
670               gtid, *p_lb, *p_ub, status));                                    \
671     return status;                                                             \
672   }
673 
674 #define LOOP_RUNTIME_START_ULL(func, schedule)                                 \
675   int func(int up, unsigned long long lb, unsigned long long ub,               \
676            unsigned long long str, unsigned long long *p_lb,                   \
677            unsigned long long *p_ub) {                                         \
678     int status;                                                                \
679     long long str2 = up ? ((long long)str) : -((long long)str);                \
680     unsigned long long stride;                                                 \
681     unsigned long long chunk_sz = 0;                                           \
682     int gtid = __kmp_entry_gtid();                                             \
683     MKLOC(loc, #func);                                                         \
684                                                                                \
685     KA_TRACE(                                                                  \
686         20,                                                                    \
687         (#func                                                                 \
688          ": T#%d, up %d, lb 0x%llx, ub 0x%llx, str 0x%llx, chunk_sz 0x%llx\n", \
689          gtid, up, lb, ub, str, chunk_sz));                                    \
690                                                                                \
691     if ((str > 0) ? (lb < ub) : (lb > ub)) {                                   \
692       KMP_DISPATCH_INIT_ULL(&loc, gtid, (schedule), lb,                        \
693                             (str2 > 0) ? (ub - 1) : (ub + 1), str2, chunk_sz,  \
694                             TRUE);                                             \
695       status =                                                                 \
696           KMP_DISPATCH_NEXT_ULL(&loc, gtid, NULL, (kmp_uint64 *)p_lb,          \
697                                 (kmp_uint64 *)p_ub, (kmp_int64 *)&stride);     \
698       if (status) {                                                            \
699         KMP_DEBUG_ASSERT((long long)stride == str2);                           \
700         *p_ub += (str > 0) ? 1 : -1;                                           \
701       }                                                                        \
702     } else {                                                                   \
703       status = 0;                                                              \
704     }                                                                          \
705                                                                                \
706     KA_TRACE(20,                                                               \
707              (#func " exit: T#%d, *p_lb 0x%llx, *p_ub 0x%llx, returning %d\n", \
708               gtid, *p_lb, *p_ub, status));                                    \
709     return status;                                                             \
710   }
711 
712 #define LOOP_NEXT_ULL(func, fini_code)                                         \
713   int func(unsigned long long *p_lb, unsigned long long *p_ub) {               \
714     int status;                                                                \
715     long long stride;                                                          \
716     int gtid = __kmp_get_gtid();                                               \
717     MKLOC(loc, #func);                                                         \
718     KA_TRACE(20, (#func ": T#%d\n", gtid));                                    \
719                                                                                \
720     fini_code status =                                                         \
721         KMP_DISPATCH_NEXT_ULL(&loc, gtid, NULL, (kmp_uint64 *)p_lb,            \
722                               (kmp_uint64 *)p_ub, (kmp_int64 *)&stride);       \
723     if (status) {                                                              \
724       *p_ub += (stride > 0) ? 1 : -1;                                          \
725     }                                                                          \
726                                                                                \
727     KA_TRACE(20,                                                               \
728              (#func " exit: T#%d, *p_lb 0x%llx, *p_ub 0x%llx, stride 0x%llx, " \
729                     "returning %d\n",                                          \
730               gtid, *p_lb, *p_ub, stride, status));                            \
731     return status;                                                             \
732   }
733 
734 LOOP_START_ULL(xexpand(KMP_API_NAME_GOMP_LOOP_ULL_STATIC_START), kmp_sch_static)
735 LOOP_NEXT_ULL(xexpand(KMP_API_NAME_GOMP_LOOP_ULL_STATIC_NEXT), {})
736 LOOP_START_ULL(xexpand(KMP_API_NAME_GOMP_LOOP_ULL_DYNAMIC_START),
737                kmp_sch_dynamic_chunked)
738 LOOP_NEXT_ULL(xexpand(KMP_API_NAME_GOMP_LOOP_ULL_DYNAMIC_NEXT), {})
739 LOOP_START_ULL(xexpand(KMP_API_NAME_GOMP_LOOP_ULL_GUIDED_START),
740                kmp_sch_guided_chunked)
741 LOOP_NEXT_ULL(xexpand(KMP_API_NAME_GOMP_LOOP_ULL_GUIDED_NEXT), {})
742 LOOP_RUNTIME_START_ULL(xexpand(KMP_API_NAME_GOMP_LOOP_ULL_RUNTIME_START),
743                        kmp_sch_runtime)
744 LOOP_NEXT_ULL(xexpand(KMP_API_NAME_GOMP_LOOP_ULL_RUNTIME_NEXT), {})
745 
746 LOOP_START_ULL(xexpand(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_STATIC_START),
747                kmp_ord_static)
748 LOOP_NEXT_ULL(xexpand(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_STATIC_NEXT),
749               { KMP_DISPATCH_FINI_CHUNK_ULL(&loc, gtid); })
750 LOOP_START_ULL(xexpand(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_DYNAMIC_START),
751                kmp_ord_dynamic_chunked)
752 LOOP_NEXT_ULL(xexpand(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_DYNAMIC_NEXT),
753               { KMP_DISPATCH_FINI_CHUNK_ULL(&loc, gtid); })
754 LOOP_START_ULL(xexpand(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_GUIDED_START),
755                kmp_ord_guided_chunked)
756 LOOP_NEXT_ULL(xexpand(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_GUIDED_NEXT),
757               { KMP_DISPATCH_FINI_CHUNK_ULL(&loc, gtid); })
758 LOOP_RUNTIME_START_ULL(
759     xexpand(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_RUNTIME_START), kmp_ord_runtime)
760 LOOP_NEXT_ULL(xexpand(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_RUNTIME_NEXT),
761               { KMP_DISPATCH_FINI_CHUNK_ULL(&loc, gtid); })
762 
763 // Combined parallel / loop worksharing constructs
764 //
765 // There are no ull versions (yet).
766 
767 #define PARALLEL_LOOP_START(func, schedule, ompt_pre, ompt_post)               \
768   void func(void (*task)(void *), void *data, unsigned num_threads, long lb,   \
769             long ub, long str, long chunk_sz) {                                \
770     int gtid = __kmp_entry_gtid();                                             \
771     MKLOC(loc, #func);                                                         \
772     KA_TRACE(20,                                                               \
773              (#func ": T#%d, lb 0x%lx, ub 0x%lx, str 0x%lx, chunk_sz 0x%lx\n", \
774               gtid, lb, ub, str, chunk_sz));                                   \
775                                                                                \
776     ompt_pre();                                                                \
777                                                                                \
778     if (__kmpc_ok_to_fork(&loc) && (num_threads != 1)) {                       \
779       if (num_threads != 0) {                                                  \
780         __kmp_push_num_threads(&loc, gtid, num_threads);                       \
781       }                                                                        \
782       __kmp_GOMP_fork_call(&loc, gtid, task,                                   \
783                            (microtask_t)__kmp_GOMP_parallel_microtask_wrapper, \
784                            9, task, data, num_threads, &loc, (schedule), lb,   \
785                            (str > 0) ? (ub - 1) : (ub + 1), str, chunk_sz);    \
786     } else {                                                                   \
787       __kmp_GOMP_serialized_parallel(&loc, gtid, task);                        \
788     }                                                                          \
789                                                                                \
790     KMP_DISPATCH_INIT(&loc, gtid, (schedule), lb,                              \
791                       (str > 0) ? (ub - 1) : (ub + 1), str, chunk_sz,          \
792                       (schedule) != kmp_sch_static);                           \
793                                                                                \
794     ompt_post();                                                               \
795                                                                                \
796     KA_TRACE(20, (#func " exit: T#%d\n", gtid));                               \
797   }
798 
799 #if OMPT_SUPPORT
800 
801 #define OMPT_LOOP_PRE()                                                        \
802   ompt_frame_t *parent_frame;                                                  \
803   if (ompt_enabled) {                                                          \
804     parent_frame = __ompt_get_task_frame_internal(0);                          \
805     parent_frame->reenter_runtime_frame = __builtin_frame_address(1);          \
806   }
807 
808 #define OMPT_LOOP_POST()                                                       \
809   if (ompt_enabled) {                                                          \
810     parent_frame->reenter_runtime_frame = NULL;                                \
811   }
812 
813 #else
814 
815 #define OMPT_LOOP_PRE()
816 
817 #define OMPT_LOOP_POST()
818 
819 #endif
820 
821 PARALLEL_LOOP_START(xexpand(KMP_API_NAME_GOMP_PARALLEL_LOOP_STATIC_START),
822                     kmp_sch_static, OMPT_LOOP_PRE, OMPT_LOOP_POST)
823 PARALLEL_LOOP_START(xexpand(KMP_API_NAME_GOMP_PARALLEL_LOOP_DYNAMIC_START),
824                     kmp_sch_dynamic_chunked, OMPT_LOOP_PRE, OMPT_LOOP_POST)
825 PARALLEL_LOOP_START(xexpand(KMP_API_NAME_GOMP_PARALLEL_LOOP_GUIDED_START),
826                     kmp_sch_guided_chunked, OMPT_LOOP_PRE, OMPT_LOOP_POST)
827 PARALLEL_LOOP_START(xexpand(KMP_API_NAME_GOMP_PARALLEL_LOOP_RUNTIME_START),
828                     kmp_sch_runtime, OMPT_LOOP_PRE, OMPT_LOOP_POST)
829 
830 // Tasking constructs
831 
832 void xexpand(KMP_API_NAME_GOMP_TASK)(void (*func)(void *), void *data,
833                                      void (*copy_func)(void *, void *),
834                                      long arg_size, long arg_align,
835                                      bool if_cond, unsigned gomp_flags
836 #if OMP_40_ENABLED
837                                      ,
838                                      void **depend
839 #endif
840                                      ) {
841   MKLOC(loc, "GOMP_task");
842   int gtid = __kmp_entry_gtid();
843   kmp_int32 flags = 0;
844   kmp_tasking_flags_t *input_flags = (kmp_tasking_flags_t *)&flags;
845 
846   KA_TRACE(20, ("GOMP_task: T#%d\n", gtid));
847 
848   // The low-order bit is the "untied" flag
849   if (!(gomp_flags & 1)) {
850     input_flags->tiedness = 1;
851   }
852   // The second low-order bit is the "final" flag
853   if (gomp_flags & 2) {
854     input_flags->final = 1;
855   }
856   input_flags->native = 1;
857   // __kmp_task_alloc() sets up all other flags
858 
859   if (!if_cond) {
860     arg_size = 0;
861   }
862 
863   kmp_task_t *task = __kmp_task_alloc(
864       &loc, gtid, input_flags, sizeof(kmp_task_t),
865       arg_size ? arg_size + arg_align - 1 : 0, (kmp_routine_entry_t)func);
866 
867   if (arg_size > 0) {
868     if (arg_align > 0) {
869       task->shareds = (void *)((((size_t)task->shareds) + arg_align - 1) /
870                                arg_align * arg_align);
871     }
872     // else error??
873 
874     if (copy_func) {
875       (*copy_func)(task->shareds, data);
876     } else {
877       KMP_MEMCPY(task->shareds, data, arg_size);
878     }
879   }
880 
881   if (if_cond) {
882 #if OMP_40_ENABLED
883     if (gomp_flags & 8) {
884       KMP_ASSERT(depend);
885       const size_t ndeps = (kmp_intptr_t)depend[0];
886       const size_t nout = (kmp_intptr_t)depend[1];
887       kmp_depend_info_t dep_list[ndeps];
888 
889       for (size_t i = 0U; i < ndeps; i++) {
890         dep_list[i].base_addr = (kmp_intptr_t)depend[2U + i];
891         dep_list[i].len = 0U;
892         dep_list[i].flags.in = 1;
893         dep_list[i].flags.out = (i < nout);
894       }
895       __kmpc_omp_task_with_deps(&loc, gtid, task, ndeps, dep_list, 0, NULL);
896     } else
897 #endif
898       __kmpc_omp_task(&loc, gtid, task);
899   } else {
900 #if OMPT_SUPPORT
901     ompt_thread_info_t oldInfo;
902     kmp_info_t *thread;
903     kmp_taskdata_t *taskdata;
904     if (ompt_enabled) {
905       // Store the threads states and restore them after the task
906       thread = __kmp_threads[gtid];
907       taskdata = KMP_TASK_TO_TASKDATA(task);
908       oldInfo = thread->th.ompt_thread_info;
909       thread->th.ompt_thread_info.wait_id = 0;
910       thread->th.ompt_thread_info.state = ompt_state_work_parallel;
911       taskdata->ompt_task_info.frame.exit_runtime_frame =
912           __builtin_frame_address(0);
913     }
914 #endif
915 
916     __kmpc_omp_task_begin_if0(&loc, gtid, task);
917     func(data);
918     __kmpc_omp_task_complete_if0(&loc, gtid, task);
919 
920 #if OMPT_SUPPORT
921     if (ompt_enabled) {
922       thread->th.ompt_thread_info = oldInfo;
923       taskdata->ompt_task_info.frame.exit_runtime_frame = NULL;
924     }
925 #endif
926   }
927 
928   KA_TRACE(20, ("GOMP_task exit: T#%d\n", gtid));
929 }
930 
931 void xexpand(KMP_API_NAME_GOMP_TASKWAIT)(void) {
932   MKLOC(loc, "GOMP_taskwait");
933   int gtid = __kmp_entry_gtid();
934 
935   KA_TRACE(20, ("GOMP_taskwait: T#%d\n", gtid));
936 
937   __kmpc_omp_taskwait(&loc, gtid);
938 
939   KA_TRACE(20, ("GOMP_taskwait exit: T#%d\n", gtid));
940 }
941 
942 // Sections worksharing constructs
943 //
944 // For the sections construct, we initialize a dynamically scheduled loop
945 // worksharing construct with lb 1 and stride 1, and use the iteration #'s
946 // that its returns as sections ids.
947 //
948 // There are no special entry points for ordered sections, so we always use
949 // the dynamically scheduled workshare, even if the sections aren't ordered.
950 
951 unsigned xexpand(KMP_API_NAME_GOMP_SECTIONS_START)(unsigned count) {
952   int status;
953   kmp_int lb, ub, stride;
954   int gtid = __kmp_entry_gtid();
955   MKLOC(loc, "GOMP_sections_start");
956   KA_TRACE(20, ("GOMP_sections_start: T#%d\n", gtid));
957 
958   KMP_DISPATCH_INIT(&loc, gtid, kmp_nm_dynamic_chunked, 1, count, 1, 1, TRUE);
959 
960   status = KMP_DISPATCH_NEXT(&loc, gtid, NULL, &lb, &ub, &stride);
961   if (status) {
962     KMP_DEBUG_ASSERT(stride == 1);
963     KMP_DEBUG_ASSERT(lb > 0);
964     KMP_ASSERT(lb == ub);
965   } else {
966     lb = 0;
967   }
968 
969   KA_TRACE(20, ("GOMP_sections_start exit: T#%d returning %u\n", gtid,
970                 (unsigned)lb));
971   return (unsigned)lb;
972 }
973 
974 unsigned xexpand(KMP_API_NAME_GOMP_SECTIONS_NEXT)(void) {
975   int status;
976   kmp_int lb, ub, stride;
977   int gtid = __kmp_get_gtid();
978   MKLOC(loc, "GOMP_sections_next");
979   KA_TRACE(20, ("GOMP_sections_next: T#%d\n", gtid));
980 
981   status = KMP_DISPATCH_NEXT(&loc, gtid, NULL, &lb, &ub, &stride);
982   if (status) {
983     KMP_DEBUG_ASSERT(stride == 1);
984     KMP_DEBUG_ASSERT(lb > 0);
985     KMP_ASSERT(lb == ub);
986   } else {
987     lb = 0;
988   }
989 
990   KA_TRACE(
991       20, ("GOMP_sections_next exit: T#%d returning %u\n", gtid, (unsigned)lb));
992   return (unsigned)lb;
993 }
994 
995 void xexpand(KMP_API_NAME_GOMP_PARALLEL_SECTIONS_START)(void (*task)(void *),
996                                                         void *data,
997                                                         unsigned num_threads,
998                                                         unsigned count) {
999   int gtid = __kmp_entry_gtid();
1000 
1001 #if OMPT_SUPPORT
1002   ompt_frame_t *parent_frame;
1003 
1004   if (ompt_enabled) {
1005     parent_frame = __ompt_get_task_frame_internal(0);
1006     parent_frame->reenter_runtime_frame = __builtin_frame_address(1);
1007   }
1008 #endif
1009 
1010   MKLOC(loc, "GOMP_parallel_sections_start");
1011   KA_TRACE(20, ("GOMP_parallel_sections_start: T#%d\n", gtid));
1012 
1013   if (__kmpc_ok_to_fork(&loc) && (num_threads != 1)) {
1014     if (num_threads != 0) {
1015       __kmp_push_num_threads(&loc, gtid, num_threads);
1016     }
1017     __kmp_GOMP_fork_call(&loc, gtid, task,
1018                          (microtask_t)__kmp_GOMP_parallel_microtask_wrapper, 9,
1019                          task, data, num_threads, &loc, kmp_nm_dynamic_chunked,
1020                          (kmp_int)1, (kmp_int)count, (kmp_int)1, (kmp_int)1);
1021   } else {
1022     __kmp_GOMP_serialized_parallel(&loc, gtid, task);
1023   }
1024 
1025 #if OMPT_SUPPORT
1026   if (ompt_enabled) {
1027     parent_frame->reenter_runtime_frame = NULL;
1028   }
1029 #endif
1030 
1031   KMP_DISPATCH_INIT(&loc, gtid, kmp_nm_dynamic_chunked, 1, count, 1, 1, TRUE);
1032 
1033   KA_TRACE(20, ("GOMP_parallel_sections_start exit: T#%d\n", gtid));
1034 }
1035 
1036 void xexpand(KMP_API_NAME_GOMP_SECTIONS_END)(void) {
1037   int gtid = __kmp_get_gtid();
1038   KA_TRACE(20, ("GOMP_sections_end: T#%d\n", gtid))
1039 
1040   __kmp_barrier(bs_plain_barrier, gtid, FALSE, 0, NULL, NULL);
1041 
1042   KA_TRACE(20, ("GOMP_sections_end exit: T#%d\n", gtid))
1043 }
1044 
1045 void xexpand(KMP_API_NAME_GOMP_SECTIONS_END_NOWAIT)(void) {
1046   KA_TRACE(20, ("GOMP_sections_end_nowait: T#%d\n", __kmp_get_gtid()))
1047 }
1048 
1049 // libgomp has an empty function for GOMP_taskyield as of 2013-10-10
1050 void xexpand(KMP_API_NAME_GOMP_TASKYIELD)(void) {
1051   KA_TRACE(20, ("GOMP_taskyield: T#%d\n", __kmp_get_gtid()))
1052   return;
1053 }
1054 
1055 #if OMP_40_ENABLED // these are new GOMP_4.0 entry points
1056 
1057 void xexpand(KMP_API_NAME_GOMP_PARALLEL)(void (*task)(void *), void *data,
1058                                          unsigned num_threads,
1059                                          unsigned int flags) {
1060   int gtid = __kmp_entry_gtid();
1061   MKLOC(loc, "GOMP_parallel");
1062   KA_TRACE(20, ("GOMP_parallel: T#%d\n", gtid));
1063 
1064 #if OMPT_SUPPORT
1065   ompt_task_info_t *parent_task_info, *task_info;
1066   if (ompt_enabled) {
1067     parent_task_info = __ompt_get_taskinfo(0);
1068     parent_task_info->frame.reenter_runtime_frame = __builtin_frame_address(1);
1069   }
1070 #endif
1071   if (__kmpc_ok_to_fork(&loc) && (num_threads != 1)) {
1072     if (num_threads != 0) {
1073       __kmp_push_num_threads(&loc, gtid, num_threads);
1074     }
1075     if (flags != 0) {
1076       __kmp_push_proc_bind(&loc, gtid, (kmp_proc_bind_t)flags);
1077     }
1078     __kmp_GOMP_fork_call(&loc, gtid, task,
1079                          (microtask_t)__kmp_GOMP_microtask_wrapper, 2, task,
1080                          data);
1081   } else {
1082     __kmp_GOMP_serialized_parallel(&loc, gtid, task);
1083   }
1084 #if OMPT_SUPPORT
1085   if (ompt_enabled) {
1086     task_info = __ompt_get_taskinfo(0);
1087     task_info->frame.exit_runtime_frame = __builtin_frame_address(0);
1088   }
1089 #endif
1090   task(data);
1091   xexpand(KMP_API_NAME_GOMP_PARALLEL_END)();
1092 #if OMPT_SUPPORT
1093   if (ompt_enabled) {
1094     task_info->frame.exit_runtime_frame = NULL;
1095     parent_task_info->frame.reenter_runtime_frame = NULL;
1096   }
1097 #endif
1098 }
1099 
1100 void xexpand(KMP_API_NAME_GOMP_PARALLEL_SECTIONS)(void (*task)(void *),
1101                                                   void *data,
1102                                                   unsigned num_threads,
1103                                                   unsigned count,
1104                                                   unsigned flags) {
1105   int gtid = __kmp_entry_gtid();
1106   MKLOC(loc, "GOMP_parallel_sections");
1107   KA_TRACE(20, ("GOMP_parallel_sections: T#%d\n", gtid));
1108 
1109   if (__kmpc_ok_to_fork(&loc) && (num_threads != 1)) {
1110     if (num_threads != 0) {
1111       __kmp_push_num_threads(&loc, gtid, num_threads);
1112     }
1113     if (flags != 0) {
1114       __kmp_push_proc_bind(&loc, gtid, (kmp_proc_bind_t)flags);
1115     }
1116     __kmp_GOMP_fork_call(&loc, gtid, task,
1117                          (microtask_t)__kmp_GOMP_parallel_microtask_wrapper, 9,
1118                          task, data, num_threads, &loc, kmp_nm_dynamic_chunked,
1119                          (kmp_int)1, (kmp_int)count, (kmp_int)1, (kmp_int)1);
1120   } else {
1121     __kmp_GOMP_serialized_parallel(&loc, gtid, task);
1122   }
1123 
1124   KMP_DISPATCH_INIT(&loc, gtid, kmp_nm_dynamic_chunked, 1, count, 1, 1, TRUE);
1125 
1126   task(data);
1127   xexpand(KMP_API_NAME_GOMP_PARALLEL_END)();
1128   KA_TRACE(20, ("GOMP_parallel_sections exit: T#%d\n", gtid));
1129 }
1130 
1131 #define PARALLEL_LOOP(func, schedule, ompt_pre, ompt_post)                     \
1132   void func(void (*task)(void *), void *data, unsigned num_threads, long lb,   \
1133             long ub, long str, long chunk_sz, unsigned flags) {                \
1134     int gtid = __kmp_entry_gtid();                                             \
1135     MKLOC(loc, #func);                                                         \
1136     KA_TRACE(20,                                                               \
1137              (#func ": T#%d, lb 0x%lx, ub 0x%lx, str 0x%lx, chunk_sz 0x%lx\n", \
1138               gtid, lb, ub, str, chunk_sz));                                   \
1139                                                                                \
1140     ompt_pre();                                                                \
1141     if (__kmpc_ok_to_fork(&loc) && (num_threads != 1)) {                       \
1142       if (num_threads != 0) {                                                  \
1143         __kmp_push_num_threads(&loc, gtid, num_threads);                       \
1144       }                                                                        \
1145       if (flags != 0) {                                                        \
1146         __kmp_push_proc_bind(&loc, gtid, (kmp_proc_bind_t)flags);              \
1147       }                                                                        \
1148       __kmp_GOMP_fork_call(&loc, gtid, task,                                   \
1149                            (microtask_t)__kmp_GOMP_parallel_microtask_wrapper, \
1150                            9, task, data, num_threads, &loc, (schedule), lb,   \
1151                            (str > 0) ? (ub - 1) : (ub + 1), str, chunk_sz);    \
1152     } else {                                                                   \
1153       __kmp_GOMP_serialized_parallel(&loc, gtid, task);                        \
1154     }                                                                          \
1155                                                                                \
1156     KMP_DISPATCH_INIT(&loc, gtid, (schedule), lb,                              \
1157                       (str > 0) ? (ub - 1) : (ub + 1), str, chunk_sz,          \
1158                       (schedule) != kmp_sch_static);                           \
1159     task(data);                                                                \
1160     xexpand(KMP_API_NAME_GOMP_PARALLEL_END)();                                 \
1161     ompt_post();                                                               \
1162                                                                                \
1163     KA_TRACE(20, (#func " exit: T#%d\n", gtid));                               \
1164   }
1165 
1166 PARALLEL_LOOP(xexpand(KMP_API_NAME_GOMP_PARALLEL_LOOP_STATIC), kmp_sch_static,
1167               OMPT_LOOP_PRE, OMPT_LOOP_POST)
1168 PARALLEL_LOOP(xexpand(KMP_API_NAME_GOMP_PARALLEL_LOOP_DYNAMIC),
1169               kmp_sch_dynamic_chunked, OMPT_LOOP_PRE, OMPT_LOOP_POST)
1170 PARALLEL_LOOP(xexpand(KMP_API_NAME_GOMP_PARALLEL_LOOP_GUIDED),
1171               kmp_sch_guided_chunked, OMPT_LOOP_PRE, OMPT_LOOP_POST)
1172 PARALLEL_LOOP(xexpand(KMP_API_NAME_GOMP_PARALLEL_LOOP_RUNTIME), kmp_sch_runtime,
1173               OMPT_LOOP_PRE, OMPT_LOOP_POST)
1174 
1175 void xexpand(KMP_API_NAME_GOMP_TASKGROUP_START)(void) {
1176   int gtid = __kmp_entry_gtid();
1177   MKLOC(loc, "GOMP_taskgroup_start");
1178   KA_TRACE(20, ("GOMP_taskgroup_start: T#%d\n", gtid));
1179 
1180   __kmpc_taskgroup(&loc, gtid);
1181 
1182   return;
1183 }
1184 
1185 void xexpand(KMP_API_NAME_GOMP_TASKGROUP_END)(void) {
1186   int gtid = __kmp_get_gtid();
1187   MKLOC(loc, "GOMP_taskgroup_end");
1188   KA_TRACE(20, ("GOMP_taskgroup_end: T#%d\n", gtid));
1189 
1190   __kmpc_end_taskgroup(&loc, gtid);
1191 
1192   return;
1193 }
1194 
1195 #ifndef KMP_DEBUG
1196 static
1197 #endif /* KMP_DEBUG */
1198     kmp_int32
1199     __kmp_gomp_to_omp_cancellation_kind(int gomp_kind) {
1200   kmp_int32 cncl_kind = 0;
1201   switch (gomp_kind) {
1202   case 1:
1203     cncl_kind = cancel_parallel;
1204     break;
1205   case 2:
1206     cncl_kind = cancel_loop;
1207     break;
1208   case 4:
1209     cncl_kind = cancel_sections;
1210     break;
1211   case 8:
1212     cncl_kind = cancel_taskgroup;
1213     break;
1214   }
1215   return cncl_kind;
1216 }
1217 
1218 bool xexpand(KMP_API_NAME_GOMP_CANCELLATION_POINT)(int which) {
1219   if (__kmp_omp_cancellation) {
1220     KMP_FATAL(NoGompCancellation);
1221   }
1222   int gtid = __kmp_get_gtid();
1223   MKLOC(loc, "GOMP_cancellation_point");
1224   KA_TRACE(20, ("GOMP_cancellation_point: T#%d\n", gtid));
1225 
1226   kmp_int32 cncl_kind = __kmp_gomp_to_omp_cancellation_kind(which);
1227 
1228   return __kmpc_cancellationpoint(&loc, gtid, cncl_kind);
1229 }
1230 
1231 bool xexpand(KMP_API_NAME_GOMP_BARRIER_CANCEL)(void) {
1232   if (__kmp_omp_cancellation) {
1233     KMP_FATAL(NoGompCancellation);
1234   }
1235   KMP_FATAL(NoGompCancellation);
1236   int gtid = __kmp_get_gtid();
1237   MKLOC(loc, "GOMP_barrier_cancel");
1238   KA_TRACE(20, ("GOMP_barrier_cancel: T#%d\n", gtid));
1239 
1240   return __kmpc_cancel_barrier(&loc, gtid);
1241 }
1242 
1243 bool xexpand(KMP_API_NAME_GOMP_CANCEL)(int which, bool do_cancel) {
1244   if (__kmp_omp_cancellation) {
1245     KMP_FATAL(NoGompCancellation);
1246   } else {
1247     return FALSE;
1248   }
1249 
1250   int gtid = __kmp_get_gtid();
1251   MKLOC(loc, "GOMP_cancel");
1252   KA_TRACE(20, ("GOMP_cancel: T#%d\n", gtid));
1253 
1254   kmp_int32 cncl_kind = __kmp_gomp_to_omp_cancellation_kind(which);
1255 
1256   if (do_cancel == FALSE) {
1257     return xexpand(KMP_API_NAME_GOMP_CANCELLATION_POINT)(which);
1258   } else {
1259     return __kmpc_cancel(&loc, gtid, cncl_kind);
1260   }
1261 }
1262 
1263 bool xexpand(KMP_API_NAME_GOMP_SECTIONS_END_CANCEL)(void) {
1264   if (__kmp_omp_cancellation) {
1265     KMP_FATAL(NoGompCancellation);
1266   }
1267   int gtid = __kmp_get_gtid();
1268   MKLOC(loc, "GOMP_sections_end_cancel");
1269   KA_TRACE(20, ("GOMP_sections_end_cancel: T#%d\n", gtid));
1270 
1271   return __kmpc_cancel_barrier(&loc, gtid);
1272 }
1273 
1274 bool xexpand(KMP_API_NAME_GOMP_LOOP_END_CANCEL)(void) {
1275   if (__kmp_omp_cancellation) {
1276     KMP_FATAL(NoGompCancellation);
1277   }
1278   int gtid = __kmp_get_gtid();
1279   MKLOC(loc, "GOMP_loop_end_cancel");
1280   KA_TRACE(20, ("GOMP_loop_end_cancel: T#%d\n", gtid));
1281 
1282   return __kmpc_cancel_barrier(&loc, gtid);
1283 }
1284 
1285 // All target functions are empty as of 2014-05-29
1286 void xexpand(KMP_API_NAME_GOMP_TARGET)(int device, void (*fn)(void *),
1287                                        const void *openmp_target, size_t mapnum,
1288                                        void **hostaddrs, size_t *sizes,
1289                                        unsigned char *kinds) {
1290   return;
1291 }
1292 
1293 void xexpand(KMP_API_NAME_GOMP_TARGET_DATA)(int device,
1294                                             const void *openmp_target,
1295                                             size_t mapnum, void **hostaddrs,
1296                                             size_t *sizes,
1297                                             unsigned char *kinds) {
1298   return;
1299 }
1300 
1301 void xexpand(KMP_API_NAME_GOMP_TARGET_END_DATA)(void) { return; }
1302 
1303 void xexpand(KMP_API_NAME_GOMP_TARGET_UPDATE)(int device,
1304                                               const void *openmp_target,
1305                                               size_t mapnum, void **hostaddrs,
1306                                               size_t *sizes,
1307                                               unsigned char *kinds) {
1308   return;
1309 }
1310 
1311 void xexpand(KMP_API_NAME_GOMP_TEAMS)(unsigned int num_teams,
1312                                       unsigned int thread_limit) {
1313   return;
1314 }
1315 #endif // OMP_40_ENABLED
1316 
1317 /* The following sections of code create aliases for the GOMP_* functions, then
1318    create versioned symbols using the assembler directive .symver. This is only
1319    pertinent for ELF .so library xaliasify and xversionify are defined in
1320    kmp_ftn_os.h  */
1321 
1322 #ifdef KMP_USE_VERSION_SYMBOLS
1323 
1324 // GOMP_1.0 aliases
1325 xaliasify(KMP_API_NAME_GOMP_ATOMIC_END, 10);
1326 xaliasify(KMP_API_NAME_GOMP_ATOMIC_START, 10);
1327 xaliasify(KMP_API_NAME_GOMP_BARRIER, 10);
1328 xaliasify(KMP_API_NAME_GOMP_CRITICAL_END, 10);
1329 xaliasify(KMP_API_NAME_GOMP_CRITICAL_NAME_END, 10);
1330 xaliasify(KMP_API_NAME_GOMP_CRITICAL_NAME_START, 10);
1331 xaliasify(KMP_API_NAME_GOMP_CRITICAL_START, 10);
1332 xaliasify(KMP_API_NAME_GOMP_LOOP_DYNAMIC_NEXT, 10);
1333 xaliasify(KMP_API_NAME_GOMP_LOOP_DYNAMIC_START, 10);
1334 xaliasify(KMP_API_NAME_GOMP_LOOP_END, 10);
1335 xaliasify(KMP_API_NAME_GOMP_LOOP_END_NOWAIT, 10);
1336 xaliasify(KMP_API_NAME_GOMP_LOOP_GUIDED_NEXT, 10);
1337 xaliasify(KMP_API_NAME_GOMP_LOOP_GUIDED_START, 10);
1338 xaliasify(KMP_API_NAME_GOMP_LOOP_ORDERED_DYNAMIC_NEXT, 10);
1339 xaliasify(KMP_API_NAME_GOMP_LOOP_ORDERED_DYNAMIC_START, 10);
1340 xaliasify(KMP_API_NAME_GOMP_LOOP_ORDERED_GUIDED_NEXT, 10);
1341 xaliasify(KMP_API_NAME_GOMP_LOOP_ORDERED_GUIDED_START, 10);
1342 xaliasify(KMP_API_NAME_GOMP_LOOP_ORDERED_RUNTIME_NEXT, 10);
1343 xaliasify(KMP_API_NAME_GOMP_LOOP_ORDERED_RUNTIME_START, 10);
1344 xaliasify(KMP_API_NAME_GOMP_LOOP_ORDERED_STATIC_NEXT, 10);
1345 xaliasify(KMP_API_NAME_GOMP_LOOP_ORDERED_STATIC_START, 10);
1346 xaliasify(KMP_API_NAME_GOMP_LOOP_RUNTIME_NEXT, 10);
1347 xaliasify(KMP_API_NAME_GOMP_LOOP_RUNTIME_START, 10);
1348 xaliasify(KMP_API_NAME_GOMP_LOOP_STATIC_NEXT, 10);
1349 xaliasify(KMP_API_NAME_GOMP_LOOP_STATIC_START, 10);
1350 xaliasify(KMP_API_NAME_GOMP_ORDERED_END, 10);
1351 xaliasify(KMP_API_NAME_GOMP_ORDERED_START, 10);
1352 xaliasify(KMP_API_NAME_GOMP_PARALLEL_END, 10);
1353 xaliasify(KMP_API_NAME_GOMP_PARALLEL_LOOP_DYNAMIC_START, 10);
1354 xaliasify(KMP_API_NAME_GOMP_PARALLEL_LOOP_GUIDED_START, 10);
1355 xaliasify(KMP_API_NAME_GOMP_PARALLEL_LOOP_RUNTIME_START, 10);
1356 xaliasify(KMP_API_NAME_GOMP_PARALLEL_LOOP_STATIC_START, 10);
1357 xaliasify(KMP_API_NAME_GOMP_PARALLEL_SECTIONS_START, 10);
1358 xaliasify(KMP_API_NAME_GOMP_PARALLEL_START, 10);
1359 xaliasify(KMP_API_NAME_GOMP_SECTIONS_END, 10);
1360 xaliasify(KMP_API_NAME_GOMP_SECTIONS_END_NOWAIT, 10);
1361 xaliasify(KMP_API_NAME_GOMP_SECTIONS_NEXT, 10);
1362 xaliasify(KMP_API_NAME_GOMP_SECTIONS_START, 10);
1363 xaliasify(KMP_API_NAME_GOMP_SINGLE_COPY_END, 10);
1364 xaliasify(KMP_API_NAME_GOMP_SINGLE_COPY_START, 10);
1365 xaliasify(KMP_API_NAME_GOMP_SINGLE_START, 10);
1366 
1367 // GOMP_2.0 aliases
1368 xaliasify(KMP_API_NAME_GOMP_TASK, 20);
1369 xaliasify(KMP_API_NAME_GOMP_TASKWAIT, 20);
1370 xaliasify(KMP_API_NAME_GOMP_LOOP_ULL_DYNAMIC_NEXT, 20);
1371 xaliasify(KMP_API_NAME_GOMP_LOOP_ULL_DYNAMIC_START, 20);
1372 xaliasify(KMP_API_NAME_GOMP_LOOP_ULL_GUIDED_NEXT, 20);
1373 xaliasify(KMP_API_NAME_GOMP_LOOP_ULL_GUIDED_START, 20);
1374 xaliasify(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_DYNAMIC_NEXT, 20);
1375 xaliasify(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_DYNAMIC_START, 20);
1376 xaliasify(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_GUIDED_NEXT, 20);
1377 xaliasify(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_GUIDED_START, 20);
1378 xaliasify(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_RUNTIME_NEXT, 20);
1379 xaliasify(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_RUNTIME_START, 20);
1380 xaliasify(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_STATIC_NEXT, 20);
1381 xaliasify(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_STATIC_START, 20);
1382 xaliasify(KMP_API_NAME_GOMP_LOOP_ULL_RUNTIME_NEXT, 20);
1383 xaliasify(KMP_API_NAME_GOMP_LOOP_ULL_RUNTIME_START, 20);
1384 xaliasify(KMP_API_NAME_GOMP_LOOP_ULL_STATIC_NEXT, 20);
1385 xaliasify(KMP_API_NAME_GOMP_LOOP_ULL_STATIC_START, 20);
1386 
1387 // GOMP_3.0 aliases
1388 xaliasify(KMP_API_NAME_GOMP_TASKYIELD, 30);
1389 
1390 // GOMP_4.0 aliases
1391 // The GOMP_parallel* entry points below aren't OpenMP 4.0 related.
1392 #if OMP_40_ENABLED
1393 xaliasify(KMP_API_NAME_GOMP_PARALLEL, 40);
1394 xaliasify(KMP_API_NAME_GOMP_PARALLEL_SECTIONS, 40);
1395 xaliasify(KMP_API_NAME_GOMP_PARALLEL_LOOP_DYNAMIC, 40);
1396 xaliasify(KMP_API_NAME_GOMP_PARALLEL_LOOP_GUIDED, 40);
1397 xaliasify(KMP_API_NAME_GOMP_PARALLEL_LOOP_RUNTIME, 40);
1398 xaliasify(KMP_API_NAME_GOMP_PARALLEL_LOOP_STATIC, 40);
1399 xaliasify(KMP_API_NAME_GOMP_TASKGROUP_START, 40);
1400 xaliasify(KMP_API_NAME_GOMP_TASKGROUP_END, 40);
1401 xaliasify(KMP_API_NAME_GOMP_BARRIER_CANCEL, 40);
1402 xaliasify(KMP_API_NAME_GOMP_CANCEL, 40);
1403 xaliasify(KMP_API_NAME_GOMP_CANCELLATION_POINT, 40);
1404 xaliasify(KMP_API_NAME_GOMP_LOOP_END_CANCEL, 40);
1405 xaliasify(KMP_API_NAME_GOMP_SECTIONS_END_CANCEL, 40);
1406 xaliasify(KMP_API_NAME_GOMP_TARGET, 40);
1407 xaliasify(KMP_API_NAME_GOMP_TARGET_DATA, 40);
1408 xaliasify(KMP_API_NAME_GOMP_TARGET_END_DATA, 40);
1409 xaliasify(KMP_API_NAME_GOMP_TARGET_UPDATE, 40);
1410 xaliasify(KMP_API_NAME_GOMP_TEAMS, 40);
1411 #endif
1412 
1413 // GOMP_1.0 versioned symbols
1414 xversionify(KMP_API_NAME_GOMP_ATOMIC_END, 10, "GOMP_1.0");
1415 xversionify(KMP_API_NAME_GOMP_ATOMIC_START, 10, "GOMP_1.0");
1416 xversionify(KMP_API_NAME_GOMP_BARRIER, 10, "GOMP_1.0");
1417 xversionify(KMP_API_NAME_GOMP_CRITICAL_END, 10, "GOMP_1.0");
1418 xversionify(KMP_API_NAME_GOMP_CRITICAL_NAME_END, 10, "GOMP_1.0");
1419 xversionify(KMP_API_NAME_GOMP_CRITICAL_NAME_START, 10, "GOMP_1.0");
1420 xversionify(KMP_API_NAME_GOMP_CRITICAL_START, 10, "GOMP_1.0");
1421 xversionify(KMP_API_NAME_GOMP_LOOP_DYNAMIC_NEXT, 10, "GOMP_1.0");
1422 xversionify(KMP_API_NAME_GOMP_LOOP_DYNAMIC_START, 10, "GOMP_1.0");
1423 xversionify(KMP_API_NAME_GOMP_LOOP_END, 10, "GOMP_1.0");
1424 xversionify(KMP_API_NAME_GOMP_LOOP_END_NOWAIT, 10, "GOMP_1.0");
1425 xversionify(KMP_API_NAME_GOMP_LOOP_GUIDED_NEXT, 10, "GOMP_1.0");
1426 xversionify(KMP_API_NAME_GOMP_LOOP_GUIDED_START, 10, "GOMP_1.0");
1427 xversionify(KMP_API_NAME_GOMP_LOOP_ORDERED_DYNAMIC_NEXT, 10, "GOMP_1.0");
1428 xversionify(KMP_API_NAME_GOMP_LOOP_ORDERED_DYNAMIC_START, 10, "GOMP_1.0");
1429 xversionify(KMP_API_NAME_GOMP_LOOP_ORDERED_GUIDED_NEXT, 10, "GOMP_1.0");
1430 xversionify(KMP_API_NAME_GOMP_LOOP_ORDERED_GUIDED_START, 10, "GOMP_1.0");
1431 xversionify(KMP_API_NAME_GOMP_LOOP_ORDERED_RUNTIME_NEXT, 10, "GOMP_1.0");
1432 xversionify(KMP_API_NAME_GOMP_LOOP_ORDERED_RUNTIME_START, 10, "GOMP_1.0");
1433 xversionify(KMP_API_NAME_GOMP_LOOP_ORDERED_STATIC_NEXT, 10, "GOMP_1.0");
1434 xversionify(KMP_API_NAME_GOMP_LOOP_ORDERED_STATIC_START, 10, "GOMP_1.0");
1435 xversionify(KMP_API_NAME_GOMP_LOOP_RUNTIME_NEXT, 10, "GOMP_1.0");
1436 xversionify(KMP_API_NAME_GOMP_LOOP_RUNTIME_START, 10, "GOMP_1.0");
1437 xversionify(KMP_API_NAME_GOMP_LOOP_STATIC_NEXT, 10, "GOMP_1.0");
1438 xversionify(KMP_API_NAME_GOMP_LOOP_STATIC_START, 10, "GOMP_1.0");
1439 xversionify(KMP_API_NAME_GOMP_ORDERED_END, 10, "GOMP_1.0");
1440 xversionify(KMP_API_NAME_GOMP_ORDERED_START, 10, "GOMP_1.0");
1441 xversionify(KMP_API_NAME_GOMP_PARALLEL_END, 10, "GOMP_1.0");
1442 xversionify(KMP_API_NAME_GOMP_PARALLEL_LOOP_DYNAMIC_START, 10, "GOMP_1.0");
1443 xversionify(KMP_API_NAME_GOMP_PARALLEL_LOOP_GUIDED_START, 10, "GOMP_1.0");
1444 xversionify(KMP_API_NAME_GOMP_PARALLEL_LOOP_RUNTIME_START, 10, "GOMP_1.0");
1445 xversionify(KMP_API_NAME_GOMP_PARALLEL_LOOP_STATIC_START, 10, "GOMP_1.0");
1446 xversionify(KMP_API_NAME_GOMP_PARALLEL_SECTIONS_START, 10, "GOMP_1.0");
1447 xversionify(KMP_API_NAME_GOMP_PARALLEL_START, 10, "GOMP_1.0");
1448 xversionify(KMP_API_NAME_GOMP_SECTIONS_END, 10, "GOMP_1.0");
1449 xversionify(KMP_API_NAME_GOMP_SECTIONS_END_NOWAIT, 10, "GOMP_1.0");
1450 xversionify(KMP_API_NAME_GOMP_SECTIONS_NEXT, 10, "GOMP_1.0");
1451 xversionify(KMP_API_NAME_GOMP_SECTIONS_START, 10, "GOMP_1.0");
1452 xversionify(KMP_API_NAME_GOMP_SINGLE_COPY_END, 10, "GOMP_1.0");
1453 xversionify(KMP_API_NAME_GOMP_SINGLE_COPY_START, 10, "GOMP_1.0");
1454 xversionify(KMP_API_NAME_GOMP_SINGLE_START, 10, "GOMP_1.0");
1455 
1456 // GOMP_2.0 versioned symbols
1457 xversionify(KMP_API_NAME_GOMP_TASK, 20, "GOMP_2.0");
1458 xversionify(KMP_API_NAME_GOMP_TASKWAIT, 20, "GOMP_2.0");
1459 xversionify(KMP_API_NAME_GOMP_LOOP_ULL_DYNAMIC_NEXT, 20, "GOMP_2.0");
1460 xversionify(KMP_API_NAME_GOMP_LOOP_ULL_DYNAMIC_START, 20, "GOMP_2.0");
1461 xversionify(KMP_API_NAME_GOMP_LOOP_ULL_GUIDED_NEXT, 20, "GOMP_2.0");
1462 xversionify(KMP_API_NAME_GOMP_LOOP_ULL_GUIDED_START, 20, "GOMP_2.0");
1463 xversionify(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_DYNAMIC_NEXT, 20, "GOMP_2.0");
1464 xversionify(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_DYNAMIC_START, 20, "GOMP_2.0");
1465 xversionify(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_GUIDED_NEXT, 20, "GOMP_2.0");
1466 xversionify(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_GUIDED_START, 20, "GOMP_2.0");
1467 xversionify(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_RUNTIME_NEXT, 20, "GOMP_2.0");
1468 xversionify(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_RUNTIME_START, 20, "GOMP_2.0");
1469 xversionify(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_STATIC_NEXT, 20, "GOMP_2.0");
1470 xversionify(KMP_API_NAME_GOMP_LOOP_ULL_ORDERED_STATIC_START, 20, "GOMP_2.0");
1471 xversionify(KMP_API_NAME_GOMP_LOOP_ULL_RUNTIME_NEXT, 20, "GOMP_2.0");
1472 xversionify(KMP_API_NAME_GOMP_LOOP_ULL_RUNTIME_START, 20, "GOMP_2.0");
1473 xversionify(KMP_API_NAME_GOMP_LOOP_ULL_STATIC_NEXT, 20, "GOMP_2.0");
1474 xversionify(KMP_API_NAME_GOMP_LOOP_ULL_STATIC_START, 20, "GOMP_2.0");
1475 
1476 // GOMP_3.0 versioned symbols
1477 xversionify(KMP_API_NAME_GOMP_TASKYIELD, 30, "GOMP_3.0");
1478 
1479 // GOMP_4.0 versioned symbols
1480 #if OMP_40_ENABLED
1481 xversionify(KMP_API_NAME_GOMP_PARALLEL, 40, "GOMP_4.0");
1482 xversionify(KMP_API_NAME_GOMP_PARALLEL_SECTIONS, 40, "GOMP_4.0");
1483 xversionify(KMP_API_NAME_GOMP_PARALLEL_LOOP_DYNAMIC, 40, "GOMP_4.0");
1484 xversionify(KMP_API_NAME_GOMP_PARALLEL_LOOP_GUIDED, 40, "GOMP_4.0");
1485 xversionify(KMP_API_NAME_GOMP_PARALLEL_LOOP_RUNTIME, 40, "GOMP_4.0");
1486 xversionify(KMP_API_NAME_GOMP_PARALLEL_LOOP_STATIC, 40, "GOMP_4.0");
1487 xversionify(KMP_API_NAME_GOMP_TASKGROUP_START, 40, "GOMP_4.0");
1488 xversionify(KMP_API_NAME_GOMP_TASKGROUP_END, 40, "GOMP_4.0");
1489 xversionify(KMP_API_NAME_GOMP_BARRIER_CANCEL, 40, "GOMP_4.0");
1490 xversionify(KMP_API_NAME_GOMP_CANCEL, 40, "GOMP_4.0");
1491 xversionify(KMP_API_NAME_GOMP_CANCELLATION_POINT, 40, "GOMP_4.0");
1492 xversionify(KMP_API_NAME_GOMP_LOOP_END_CANCEL, 40, "GOMP_4.0");
1493 xversionify(KMP_API_NAME_GOMP_SECTIONS_END_CANCEL, 40, "GOMP_4.0");
1494 xversionify(KMP_API_NAME_GOMP_TARGET, 40, "GOMP_4.0");
1495 xversionify(KMP_API_NAME_GOMP_TARGET_DATA, 40, "GOMP_4.0");
1496 xversionify(KMP_API_NAME_GOMP_TARGET_END_DATA, 40, "GOMP_4.0");
1497 xversionify(KMP_API_NAME_GOMP_TARGET_UPDATE, 40, "GOMP_4.0");
1498 xversionify(KMP_API_NAME_GOMP_TEAMS, 40, "GOMP_4.0");
1499 #endif
1500 
1501 #endif // KMP_USE_VERSION_SYMBOLS
1502 
1503 #ifdef __cplusplus
1504 } // extern "C"
1505 #endif // __cplusplus
1506