17cc577a4SJonathan Peyton /*
2de4749b7SJonathan Peyton  * kmp_error.cpp -- KPTS functions for error checking at runtime
37cc577a4SJonathan Peyton  */
47cc577a4SJonathan Peyton 
57cc577a4SJonathan Peyton //===----------------------------------------------------------------------===//
67cc577a4SJonathan Peyton //
757b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
857b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
957b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
107cc577a4SJonathan Peyton //
117cc577a4SJonathan Peyton //===----------------------------------------------------------------------===//
127cc577a4SJonathan Peyton 
137cc577a4SJonathan Peyton #include "kmp.h"
143041982dSJonathan Peyton #include "kmp_error.h"
157cc577a4SJonathan Peyton #include "kmp_i18n.h"
167cc577a4SJonathan Peyton #include "kmp_str.h"
177cc577a4SJonathan Peyton 
187cc577a4SJonathan Peyton /* ------------------------------------------------------------------------ */
197cc577a4SJonathan Peyton 
207cc577a4SJonathan Peyton #define MIN_STACK 100
217cc577a4SJonathan Peyton 
227cc577a4SJonathan Peyton static char const *cons_text_c[] = {
23*309b00a4SShilei Tian     "(none)",
24*309b00a4SShilei Tian     "\"parallel\"",
25*309b00a4SShilei Tian     "work-sharing", /* this is not called "for"
263041982dSJonathan Peyton                        because of lowering of
273041982dSJonathan Peyton                        "sections" pragmas */
283041982dSJonathan Peyton     "\"ordered\" work-sharing", /* this is not called "for ordered" because of
293041982dSJonathan Peyton                                    lowering of "sections" pragmas */
307cc577a4SJonathan Peyton     "\"sections\"",
313041982dSJonathan Peyton     "work-sharing", /* this is not called "single" because of lowering of
323041982dSJonathan Peyton                        "sections" pragmas */
33*309b00a4SShilei Tian     "\"critical\"",
34*309b00a4SShilei Tian     "\"ordered\"", /* in PARALLEL */
357cc577a4SJonathan Peyton     "\"ordered\"", /* in PDO */
36*309b00a4SShilei Tian     "\"master\"",
37*309b00a4SShilei Tian     "\"reduce\"",
38*309b00a4SShilei Tian     "\"barrier\""};
397cc577a4SJonathan Peyton 
407cc577a4SJonathan Peyton #define get_src(ident) ((ident) == NULL ? NULL : (ident)->psource)
417cc577a4SJonathan Peyton 
427cc577a4SJonathan Peyton #define PUSH_MSG(ct, ident)                                                    \
437cc577a4SJonathan Peyton   "\tpushing on stack: %s (%s)\n", cons_text_c[(ct)], get_src((ident))
447cc577a4SJonathan Peyton #define POP_MSG(p)                                                             \
453041982dSJonathan Peyton   "\tpopping off stack: %s (%s)\n", cons_text_c[(p)->stack_data[tos].type],    \
467cc577a4SJonathan Peyton       get_src((p)->stack_data[tos].ident)
477cc577a4SJonathan Peyton 
487cc577a4SJonathan Peyton static int const cons_text_c_num = sizeof(cons_text_c) / sizeof(char const *);
497cc577a4SJonathan Peyton 
507cc577a4SJonathan Peyton /* --------------- START OF STATIC LOCAL ROUTINES ------------------------- */
517cc577a4SJonathan Peyton 
523041982dSJonathan Peyton static void __kmp_check_null_func(void) { /* nothing to do */
537cc577a4SJonathan Peyton }
547cc577a4SJonathan Peyton 
553041982dSJonathan Peyton static void __kmp_expand_cons_stack(int gtid, struct cons_header *p) {
567cc577a4SJonathan Peyton   int i;
577cc577a4SJonathan Peyton   struct cons_data *d;
587cc577a4SJonathan Peyton 
597cc577a4SJonathan Peyton   /* TODO for monitor perhaps? */
607cc577a4SJonathan Peyton   if (gtid < 0)
617cc577a4SJonathan Peyton     __kmp_check_null_func();
627cc577a4SJonathan Peyton 
637cc577a4SJonathan Peyton   KE_TRACE(10, ("expand cons_stack (%d %d)\n", gtid, __kmp_get_gtid()));
647cc577a4SJonathan Peyton 
657cc577a4SJonathan Peyton   d = p->stack_data;
667cc577a4SJonathan Peyton 
677cc577a4SJonathan Peyton   p->stack_size = (p->stack_size * 2) + 100;
687cc577a4SJonathan Peyton 
697cc577a4SJonathan Peyton   /* TODO free the old data */
703041982dSJonathan Peyton   p->stack_data = (struct cons_data *)__kmp_allocate(sizeof(struct cons_data) *
713041982dSJonathan Peyton                                                      (p->stack_size + 1));
727cc577a4SJonathan Peyton 
737cc577a4SJonathan Peyton   for (i = p->stack_top; i >= 0; --i)
747cc577a4SJonathan Peyton     p->stack_data[i] = d[i];
757cc577a4SJonathan Peyton 
767cc577a4SJonathan Peyton   /* NOTE: we do not free the old stack_data */
777cc577a4SJonathan Peyton }
787cc577a4SJonathan Peyton 
797cc577a4SJonathan Peyton // NOTE: Function returns allocated memory, caller must free it!
80aeb40adaSJonas Hahnfeld static char *__kmp_pragma(int ct, ident_t const *ident) {
817cc577a4SJonathan Peyton   char const *cons = NULL; // Construct name.
827cc577a4SJonathan Peyton   char *file = NULL; // File name.
837cc577a4SJonathan Peyton   char *func = NULL; // Function (routine) name.
847cc577a4SJonathan Peyton   char *line = NULL; // Line number.
857cc577a4SJonathan Peyton   kmp_str_buf_t buffer;
867cc577a4SJonathan Peyton   kmp_msg_t prgm;
877cc577a4SJonathan Peyton   __kmp_str_buf_init(&buffer);
887cc577a4SJonathan Peyton   if (0 < ct && ct < cons_text_c_num) {
897cc577a4SJonathan Peyton     cons = cons_text_c[ct];
907cc577a4SJonathan Peyton   } else {
917cc577a4SJonathan Peyton     KMP_DEBUG_ASSERT(0);
92bd3a7633SJonathan Peyton   }
937cc577a4SJonathan Peyton   if (ident != NULL && ident->psource != NULL) {
947cc577a4SJonathan Peyton     char *tail = NULL;
953041982dSJonathan Peyton     __kmp_str_buf_print(&buffer, "%s",
963041982dSJonathan Peyton                         ident->psource); // Copy source to buffer.
977cc577a4SJonathan Peyton     // Split string in buffer to file, func, and line.
987cc577a4SJonathan Peyton     tail = buffer.str;
997cc577a4SJonathan Peyton     __kmp_str_split(tail, ';', NULL, &tail);
1007cc577a4SJonathan Peyton     __kmp_str_split(tail, ';', &file, &tail);
1017cc577a4SJonathan Peyton     __kmp_str_split(tail, ';', &func, &tail);
1027cc577a4SJonathan Peyton     __kmp_str_split(tail, ';', &line, &tail);
103bd3a7633SJonathan Peyton   }
1047cc577a4SJonathan Peyton   prgm = __kmp_msg_format(kmp_i18n_fmt_Pragma, cons, file, func, line);
1057cc577a4SJonathan Peyton   __kmp_str_buf_free(&buffer);
1067cc577a4SJonathan Peyton   return prgm.str;
1077cc577a4SJonathan Peyton } // __kmp_pragma
1087cc577a4SJonathan Peyton 
1097cc577a4SJonathan Peyton /* ----------------- END OF STATIC LOCAL ROUTINES ------------------------- */
1107cc577a4SJonathan Peyton 
1113041982dSJonathan Peyton void __kmp_error_construct(kmp_i18n_id_t id, // Message identifier.
1127cc577a4SJonathan Peyton                            enum cons_type ct, // Construct type.
1137cc577a4SJonathan Peyton                            ident_t const *ident // Construct ident.
1147cc577a4SJonathan Peyton ) {
115aeb40adaSJonas Hahnfeld   char *construct = __kmp_pragma(ct, ident);
1166a393f75SJonathan Peyton   __kmp_fatal(__kmp_msg_format(id, construct), __kmp_msg_null);
117aeb40adaSJonas Hahnfeld   KMP_INTERNAL_FREE(construct);
1187cc577a4SJonathan Peyton }
1197cc577a4SJonathan Peyton 
1203041982dSJonathan Peyton void __kmp_error_construct2(kmp_i18n_id_t id, // Message identifier.
1217cc577a4SJonathan Peyton                             enum cons_type ct, // First construct type.
1227cc577a4SJonathan Peyton                             ident_t const *ident, // First construct ident.
1237cc577a4SJonathan Peyton                             struct cons_data const *cons // Second construct.
1247cc577a4SJonathan Peyton ) {
125aeb40adaSJonas Hahnfeld   char *construct1 = __kmp_pragma(ct, ident);
126aeb40adaSJonas Hahnfeld   char *construct2 = __kmp_pragma(cons->type, cons->ident);
1276a393f75SJonathan Peyton   __kmp_fatal(__kmp_msg_format(id, construct1, construct2), __kmp_msg_null);
128aeb40adaSJonas Hahnfeld   KMP_INTERNAL_FREE(construct1);
129aeb40adaSJonas Hahnfeld   KMP_INTERNAL_FREE(construct2);
1307cc577a4SJonathan Peyton }
1317cc577a4SJonathan Peyton 
1323041982dSJonathan Peyton struct cons_header *__kmp_allocate_cons_stack(int gtid) {
1337cc577a4SJonathan Peyton   struct cons_header *p;
1347cc577a4SJonathan Peyton 
1357cc577a4SJonathan Peyton   /* TODO for monitor perhaps? */
1367cc577a4SJonathan Peyton   if (gtid < 0) {
1377cc577a4SJonathan Peyton     __kmp_check_null_func();
138bd3a7633SJonathan Peyton   }
1397cc577a4SJonathan Peyton   KE_TRACE(10, ("allocate cons_stack (%d)\n", gtid));
1407cc577a4SJonathan Peyton   p = (struct cons_header *)__kmp_allocate(sizeof(struct cons_header));
1417cc577a4SJonathan Peyton   p->p_top = p->w_top = p->s_top = 0;
1423041982dSJonathan Peyton   p->stack_data = (struct cons_data *)__kmp_allocate(sizeof(struct cons_data) *
1433041982dSJonathan Peyton                                                      (MIN_STACK + 1));
1447cc577a4SJonathan Peyton   p->stack_size = MIN_STACK;
1457cc577a4SJonathan Peyton   p->stack_top = 0;
1467cc577a4SJonathan Peyton   p->stack_data[0].type = ct_none;
1477cc577a4SJonathan Peyton   p->stack_data[0].prev = 0;
1487cc577a4SJonathan Peyton   p->stack_data[0].ident = NULL;
1497cc577a4SJonathan Peyton   return p;
1507cc577a4SJonathan Peyton }
1517cc577a4SJonathan Peyton 
1523041982dSJonathan Peyton void __kmp_free_cons_stack(void *ptr) {
1537cc577a4SJonathan Peyton   struct cons_header *p = (struct cons_header *)ptr;
1547cc577a4SJonathan Peyton   if (p != NULL) {
1557cc577a4SJonathan Peyton     if (p->stack_data != NULL) {
1567cc577a4SJonathan Peyton       __kmp_free(p->stack_data);
1577cc577a4SJonathan Peyton       p->stack_data = NULL;
158bd3a7633SJonathan Peyton     }
1597cc577a4SJonathan Peyton     __kmp_free(p);
160bd3a7633SJonathan Peyton   }
1617cc577a4SJonathan Peyton }
1627cc577a4SJonathan Peyton 
1637cc577a4SJonathan Peyton #if KMP_DEBUG
1643041982dSJonathan Peyton static void dump_cons_stack(int gtid, struct cons_header *p) {
1657cc577a4SJonathan Peyton   int i;
1667cc577a4SJonathan Peyton   int tos = p->stack_top;
1677cc577a4SJonathan Peyton   kmp_str_buf_t buffer;
1687cc577a4SJonathan Peyton   __kmp_str_buf_init(&buffer);
1693041982dSJonathan Peyton   __kmp_str_buf_print(
1703041982dSJonathan Peyton       &buffer,
1713041982dSJonathan Peyton       "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-\n");
1723041982dSJonathan Peyton   __kmp_str_buf_print(&buffer,
1733041982dSJonathan Peyton                       "Begin construct stack with %d items for thread %d\n",
1743041982dSJonathan Peyton                       tos, gtid);
1753041982dSJonathan Peyton   __kmp_str_buf_print(&buffer, "     stack_top=%d { P=%d, W=%d, S=%d }\n", tos,
1763041982dSJonathan Peyton                       p->p_top, p->w_top, p->s_top);
1777cc577a4SJonathan Peyton   for (i = tos; i > 0; i--) {
1787cc577a4SJonathan Peyton     struct cons_data *c = &(p->stack_data[i]);
1793041982dSJonathan Peyton     __kmp_str_buf_print(
1803041982dSJonathan Peyton         &buffer, "        stack_data[%2d] = { %s (%s) %d %p }\n", i,
1813041982dSJonathan Peyton         cons_text_c[c->type], get_src(c->ident), c->prev, c->name);
182bd3a7633SJonathan Peyton   }
1837cc577a4SJonathan Peyton   __kmp_str_buf_print(&buffer, "End construct stack for thread %d\n", gtid);
1843041982dSJonathan Peyton   __kmp_str_buf_print(
1853041982dSJonathan Peyton       &buffer,
1863041982dSJonathan Peyton       "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-\n");
1877cc577a4SJonathan Peyton   __kmp_debug_printf("%s", buffer.str);
1887cc577a4SJonathan Peyton   __kmp_str_buf_free(&buffer);
1897cc577a4SJonathan Peyton }
1907cc577a4SJonathan Peyton #endif
1917cc577a4SJonathan Peyton 
1923041982dSJonathan Peyton void __kmp_push_parallel(int gtid, ident_t const *ident) {
1937cc577a4SJonathan Peyton   int tos;
1947cc577a4SJonathan Peyton   struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
1957cc577a4SJonathan Peyton 
1967cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(__kmp_threads[gtid]->th.th_cons);
1977cc577a4SJonathan Peyton   KE_TRACE(10, ("__kmp_push_parallel (%d %d)\n", gtid, __kmp_get_gtid()));
1987cc577a4SJonathan Peyton   KE_TRACE(100, (PUSH_MSG(ct_parallel, ident)));
1997cc577a4SJonathan Peyton   if (p->stack_top >= p->stack_size) {
2007cc577a4SJonathan Peyton     __kmp_expand_cons_stack(gtid, p);
201bd3a7633SJonathan Peyton   }
2027cc577a4SJonathan Peyton   tos = ++p->stack_top;
2037cc577a4SJonathan Peyton   p->stack_data[tos].type = ct_parallel;
2047cc577a4SJonathan Peyton   p->stack_data[tos].prev = p->p_top;
2057cc577a4SJonathan Peyton   p->stack_data[tos].ident = ident;
2067cc577a4SJonathan Peyton   p->stack_data[tos].name = NULL;
2077cc577a4SJonathan Peyton   p->p_top = tos;
2087cc577a4SJonathan Peyton   KE_DUMP(1000, dump_cons_stack(gtid, p));
2097cc577a4SJonathan Peyton }
2107cc577a4SJonathan Peyton 
2113041982dSJonathan Peyton void __kmp_check_workshare(int gtid, enum cons_type ct, ident_t const *ident) {
2127cc577a4SJonathan Peyton   struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
2137cc577a4SJonathan Peyton 
2147cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(__kmp_threads[gtid]->th.th_cons);
2157cc577a4SJonathan Peyton   KE_TRACE(10, ("__kmp_check_workshare (%d %d)\n", gtid, __kmp_get_gtid()));
2167cc577a4SJonathan Peyton 
2177cc577a4SJonathan Peyton   if (p->stack_top >= p->stack_size) {
2187cc577a4SJonathan Peyton     __kmp_expand_cons_stack(gtid, p);
219bd3a7633SJonathan Peyton   }
22044b476c1SJonathan Peyton   if (p->w_top > p->p_top) {
2217cc577a4SJonathan Peyton     // We are already in a WORKSHARE construct for this PARALLEL region.
2223041982dSJonathan Peyton     __kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
2233041982dSJonathan Peyton                            &p->stack_data[p->w_top]);
224bd3a7633SJonathan Peyton   }
2257cc577a4SJonathan Peyton   if (p->s_top > p->p_top) {
2267cc577a4SJonathan Peyton     // We are already in a SYNC construct for this PARALLEL region.
2273041982dSJonathan Peyton     __kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
2283041982dSJonathan Peyton                            &p->stack_data[p->s_top]);
229bd3a7633SJonathan Peyton   }
2307cc577a4SJonathan Peyton }
2317cc577a4SJonathan Peyton 
2323041982dSJonathan Peyton void __kmp_push_workshare(int gtid, enum cons_type ct, ident_t const *ident) {
2337cc577a4SJonathan Peyton   int tos;
2347cc577a4SJonathan Peyton   struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
2357cc577a4SJonathan Peyton   KE_TRACE(10, ("__kmp_push_workshare (%d %d)\n", gtid, __kmp_get_gtid()));
2367cc577a4SJonathan Peyton   __kmp_check_workshare(gtid, ct, ident);
2377cc577a4SJonathan Peyton   KE_TRACE(100, (PUSH_MSG(ct, ident)));
2387cc577a4SJonathan Peyton   tos = ++p->stack_top;
2397cc577a4SJonathan Peyton   p->stack_data[tos].type = ct;
2407cc577a4SJonathan Peyton   p->stack_data[tos].prev = p->w_top;
2417cc577a4SJonathan Peyton   p->stack_data[tos].ident = ident;
2427cc577a4SJonathan Peyton   p->stack_data[tos].name = NULL;
2437cc577a4SJonathan Peyton   p->w_top = tos;
2447cc577a4SJonathan Peyton   KE_DUMP(1000, dump_cons_stack(gtid, p));
2457cc577a4SJonathan Peyton }
2467cc577a4SJonathan Peyton 
2477cc577a4SJonathan Peyton void
2487cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
2497cc577a4SJonathan Peyton __kmp_check_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck, kmp_uint32 seq )
2507cc577a4SJonathan Peyton #else
2517cc577a4SJonathan Peyton __kmp_check_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck )
2527cc577a4SJonathan Peyton #endif
2537cc577a4SJonathan Peyton {
2547cc577a4SJonathan Peyton   struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
2557cc577a4SJonathan Peyton 
2567cc577a4SJonathan Peyton   KE_TRACE(10, ("__kmp_check_sync (gtid=%d)\n", __kmp_get_gtid()));
2577cc577a4SJonathan Peyton 
2587cc577a4SJonathan Peyton   if (p->stack_top >= p->stack_size)
2597cc577a4SJonathan Peyton     __kmp_expand_cons_stack(gtid, p);
2607cc577a4SJonathan Peyton 
26144b476c1SJonathan Peyton   if (ct == ct_ordered_in_parallel || ct == ct_ordered_in_pdo) {
2627cc577a4SJonathan Peyton     if (p->w_top <= p->p_top) {
2637cc577a4SJonathan Peyton /* we are not in a worksharing construct */
2647cc577a4SJonathan Peyton #ifdef BUILD_PARALLEL_ORDERED
2657cc577a4SJonathan Peyton       /* do not report error messages for PARALLEL ORDERED */
2667cc577a4SJonathan Peyton       KMP_ASSERT(ct == ct_ordered_in_parallel);
2677cc577a4SJonathan Peyton #else
2687cc577a4SJonathan Peyton       __kmp_error_construct(kmp_i18n_msg_CnsBoundToWorksharing, ct, ident);
2697cc577a4SJonathan Peyton #endif /* BUILD_PARALLEL_ORDERED */
2707cc577a4SJonathan Peyton     } else {
2717cc577a4SJonathan Peyton       /* inside a WORKSHARING construct for this PARALLEL region */
2727cc577a4SJonathan Peyton       if (!IS_CONS_TYPE_ORDERED(p->stack_data[p->w_top].type)) {
2733041982dSJonathan Peyton         __kmp_error_construct2(kmp_i18n_msg_CnsNoOrderedClause, ct, ident,
2743041982dSJonathan Peyton                                &p->stack_data[p->w_top]);
2757cc577a4SJonathan Peyton       }
2767cc577a4SJonathan Peyton     }
2777cc577a4SJonathan Peyton     if (p->s_top > p->p_top && p->s_top > p->w_top) {
2787cc577a4SJonathan Peyton       /* inside a sync construct which is inside a worksharing construct */
2797cc577a4SJonathan Peyton       int index = p->s_top;
2807cc577a4SJonathan Peyton       enum cons_type stack_type;
2817cc577a4SJonathan Peyton 
2827cc577a4SJonathan Peyton       stack_type = p->stack_data[index].type;
2837cc577a4SJonathan Peyton 
2847cc577a4SJonathan Peyton       if (stack_type == ct_critical ||
2857cc577a4SJonathan Peyton           ((stack_type == ct_ordered_in_parallel ||
28644b476c1SJonathan Peyton             stack_type == ct_ordered_in_pdo) &&
28744b476c1SJonathan Peyton            /* C doesn't allow named ordered; ordered in ordered gets error */
2887cc577a4SJonathan Peyton            p->stack_data[index].ident != NULL &&
2897cc577a4SJonathan Peyton            (p->stack_data[index].ident->flags & KMP_IDENT_KMPC))) {
2907cc577a4SJonathan Peyton         /* we are in ORDERED which is inside an ORDERED or CRITICAL construct */
2913041982dSJonathan Peyton         __kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
2923041982dSJonathan Peyton                                &p->stack_data[index]);
2937cc577a4SJonathan Peyton       }
2947cc577a4SJonathan Peyton     }
2957cc577a4SJonathan Peyton   } else if (ct == ct_critical) {
2967cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
2973041982dSJonathan Peyton     if (lck != NULL &&
2983041982dSJonathan Peyton         __kmp_get_user_lock_owner(lck, seq) ==
2993041982dSJonathan Peyton             gtid) { /* this thread already has lock for this critical section */
3007cc577a4SJonathan Peyton #else
3013041982dSJonathan Peyton     if (lck != NULL &&
3023041982dSJonathan Peyton         __kmp_get_user_lock_owner(lck) ==
3033041982dSJonathan Peyton             gtid) { /* this thread already has lock for this critical section */
3047cc577a4SJonathan Peyton #endif
3057cc577a4SJonathan Peyton       int index = p->s_top;
3067cc577a4SJonathan Peyton       struct cons_data cons = {NULL, ct_critical, 0, NULL};
3077cc577a4SJonathan Peyton       /* walk up construct stack and try to find critical with matching name */
3087cc577a4SJonathan Peyton       while (index != 0 && p->stack_data[index].name != lck) {
3097cc577a4SJonathan Peyton         index = p->stack_data[index].prev;
3107cc577a4SJonathan Peyton       }
3117cc577a4SJonathan Peyton       if (index != 0) {
3123041982dSJonathan Peyton         /* found match on the stack (may not always because of interleaved
3133041982dSJonathan Peyton          * critical for Fortran) */
3147cc577a4SJonathan Peyton         cons = p->stack_data[index];
3157cc577a4SJonathan Peyton       }
3163041982dSJonathan Peyton       /* we are in CRITICAL which is inside a CRITICAL construct of same name */
3177cc577a4SJonathan Peyton       __kmp_error_construct2(kmp_i18n_msg_CnsNestingSameName, ct, ident, &cons);
3187cc577a4SJonathan Peyton     }
3197cc577a4SJonathan Peyton   } else if (ct == ct_master || ct == ct_reduce) {
3207cc577a4SJonathan Peyton     if (p->w_top > p->p_top) {
3217cc577a4SJonathan Peyton       /* inside a WORKSHARING construct for this PARALLEL region */
3223041982dSJonathan Peyton       __kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
3233041982dSJonathan Peyton                              &p->stack_data[p->w_top]);
3247cc577a4SJonathan Peyton     }
3257cc577a4SJonathan Peyton     if (ct == ct_reduce && p->s_top > p->p_top) {
3267cc577a4SJonathan Peyton       /* inside a another SYNC construct for this PARALLEL region */
3273041982dSJonathan Peyton       __kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
3283041982dSJonathan Peyton                              &p->stack_data[p->s_top]);
329bd3a7633SJonathan Peyton     }
330bd3a7633SJonathan Peyton   }
3317cc577a4SJonathan Peyton }
3327cc577a4SJonathan Peyton 
3337cc577a4SJonathan Peyton void
3347cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
3357cc577a4SJonathan Peyton __kmp_push_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck, kmp_uint32 seq )
3367cc577a4SJonathan Peyton #else
3377cc577a4SJonathan Peyton __kmp_push_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck )
3387cc577a4SJonathan Peyton #endif
3397cc577a4SJonathan Peyton {
3407cc577a4SJonathan Peyton   int tos;
3417cc577a4SJonathan Peyton   struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
3427cc577a4SJonathan Peyton 
3437cc577a4SJonathan Peyton   KMP_ASSERT(gtid == __kmp_get_gtid());
3447cc577a4SJonathan Peyton   KE_TRACE(10, ("__kmp_push_sync (gtid=%d)\n", gtid));
3457cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
3467cc577a4SJonathan Peyton   __kmp_check_sync(gtid, ct, ident, lck, seq);
3477cc577a4SJonathan Peyton #else
3487cc577a4SJonathan Peyton   __kmp_check_sync(gtid, ct, ident, lck);
3497cc577a4SJonathan Peyton #endif
3507cc577a4SJonathan Peyton   KE_TRACE(100, (PUSH_MSG(ct, ident)));
3517cc577a4SJonathan Peyton   tos = ++p->stack_top;
3527cc577a4SJonathan Peyton   p->stack_data[tos].type = ct;
3537cc577a4SJonathan Peyton   p->stack_data[tos].prev = p->s_top;
3547cc577a4SJonathan Peyton   p->stack_data[tos].ident = ident;
3557cc577a4SJonathan Peyton   p->stack_data[tos].name = lck;
3567cc577a4SJonathan Peyton   p->s_top = tos;
3577cc577a4SJonathan Peyton   KE_DUMP(1000, dump_cons_stack(gtid, p));
3587cc577a4SJonathan Peyton }
3597cc577a4SJonathan Peyton 
3607cc577a4SJonathan Peyton /* ------------------------------------------------------------------------ */
3617cc577a4SJonathan Peyton 
3623041982dSJonathan Peyton void __kmp_pop_parallel(int gtid, ident_t const *ident) {
3637cc577a4SJonathan Peyton   int tos;
3647cc577a4SJonathan Peyton   struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
3657cc577a4SJonathan Peyton   tos = p->stack_top;
3667cc577a4SJonathan Peyton   KE_TRACE(10, ("__kmp_pop_parallel (%d %d)\n", gtid, __kmp_get_gtid()));
3677cc577a4SJonathan Peyton   if (tos == 0 || p->p_top == 0) {
3687cc577a4SJonathan Peyton     __kmp_error_construct(kmp_i18n_msg_CnsDetectedEnd, ct_parallel, ident);
3697cc577a4SJonathan Peyton   }
3707cc577a4SJonathan Peyton   if (tos != p->p_top || p->stack_data[tos].type != ct_parallel) {
3713041982dSJonathan Peyton     __kmp_error_construct2(kmp_i18n_msg_CnsExpectedEnd, ct_parallel, ident,
3723041982dSJonathan Peyton                            &p->stack_data[tos]);
3737cc577a4SJonathan Peyton   }
3747cc577a4SJonathan Peyton   KE_TRACE(100, (POP_MSG(p)));
3757cc577a4SJonathan Peyton   p->p_top = p->stack_data[tos].prev;
3767cc577a4SJonathan Peyton   p->stack_data[tos].type = ct_none;
3777cc577a4SJonathan Peyton   p->stack_data[tos].ident = NULL;
3787cc577a4SJonathan Peyton   p->stack_top = tos - 1;
3797cc577a4SJonathan Peyton   KE_DUMP(1000, dump_cons_stack(gtid, p));
3807cc577a4SJonathan Peyton }
3817cc577a4SJonathan Peyton 
3823041982dSJonathan Peyton enum cons_type __kmp_pop_workshare(int gtid, enum cons_type ct,
3833041982dSJonathan Peyton                                    ident_t const *ident) {
3847cc577a4SJonathan Peyton   int tos;
3857cc577a4SJonathan Peyton   struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
3867cc577a4SJonathan Peyton 
3877cc577a4SJonathan Peyton   tos = p->stack_top;
3887cc577a4SJonathan Peyton   KE_TRACE(10, ("__kmp_pop_workshare (%d %d)\n", gtid, __kmp_get_gtid()));
3897cc577a4SJonathan Peyton   if (tos == 0 || p->w_top == 0) {
3907cc577a4SJonathan Peyton     __kmp_error_construct(kmp_i18n_msg_CnsDetectedEnd, ct, ident);
3917cc577a4SJonathan Peyton   }
3927cc577a4SJonathan Peyton 
3937cc577a4SJonathan Peyton   if (tos != p->w_top ||
3947cc577a4SJonathan Peyton       (p->stack_data[tos].type != ct &&
39544b476c1SJonathan Peyton        // below is the exception to the rule that construct types must match
39644b476c1SJonathan Peyton        !(p->stack_data[tos].type == ct_pdo_ordered && ct == ct_pdo))) {
3977cc577a4SJonathan Peyton     __kmp_check_null_func();
3983041982dSJonathan Peyton     __kmp_error_construct2(kmp_i18n_msg_CnsExpectedEnd, ct, ident,
3993041982dSJonathan Peyton                            &p->stack_data[tos]);
4007cc577a4SJonathan Peyton   }
4017cc577a4SJonathan Peyton   KE_TRACE(100, (POP_MSG(p)));
4027cc577a4SJonathan Peyton   p->w_top = p->stack_data[tos].prev;
4037cc577a4SJonathan Peyton   p->stack_data[tos].type = ct_none;
4047cc577a4SJonathan Peyton   p->stack_data[tos].ident = NULL;
4057cc577a4SJonathan Peyton   p->stack_top = tos - 1;
4067cc577a4SJonathan Peyton   KE_DUMP(1000, dump_cons_stack(gtid, p));
4077cc577a4SJonathan Peyton   return p->stack_data[p->w_top].type;
4087cc577a4SJonathan Peyton }
4097cc577a4SJonathan Peyton 
4103041982dSJonathan Peyton void __kmp_pop_sync(int gtid, enum cons_type ct, ident_t const *ident) {
4117cc577a4SJonathan Peyton   int tos;
4127cc577a4SJonathan Peyton   struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
4137cc577a4SJonathan Peyton   tos = p->stack_top;
4147cc577a4SJonathan Peyton   KE_TRACE(10, ("__kmp_pop_sync (%d %d)\n", gtid, __kmp_get_gtid()));
4157cc577a4SJonathan Peyton   if (tos == 0 || p->s_top == 0) {
4167cc577a4SJonathan Peyton     __kmp_error_construct(kmp_i18n_msg_CnsDetectedEnd, ct, ident);
417bd3a7633SJonathan Peyton   }
4187cc577a4SJonathan Peyton   if (tos != p->s_top || p->stack_data[tos].type != ct) {
4197cc577a4SJonathan Peyton     __kmp_check_null_func();
4203041982dSJonathan Peyton     __kmp_error_construct2(kmp_i18n_msg_CnsExpectedEnd, ct, ident,
4213041982dSJonathan Peyton                            &p->stack_data[tos]);
422bd3a7633SJonathan Peyton   }
4237cc577a4SJonathan Peyton   KE_TRACE(100, (POP_MSG(p)));
4247cc577a4SJonathan Peyton   p->s_top = p->stack_data[tos].prev;
4257cc577a4SJonathan Peyton   p->stack_data[tos].type = ct_none;
4267cc577a4SJonathan Peyton   p->stack_data[tos].ident = NULL;
4277cc577a4SJonathan Peyton   p->stack_top = tos - 1;
4287cc577a4SJonathan Peyton   KE_DUMP(1000, dump_cons_stack(gtid, p));
4297cc577a4SJonathan Peyton }
4307cc577a4SJonathan Peyton 
4317cc577a4SJonathan Peyton /* ------------------------------------------------------------------------ */
4327cc577a4SJonathan Peyton 
4333041982dSJonathan Peyton void __kmp_check_barrier(int gtid, enum cons_type ct, ident_t const *ident) {
4347cc577a4SJonathan Peyton   struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
4353041982dSJonathan Peyton   KE_TRACE(10, ("__kmp_check_barrier (loc: %p, gtid: %d %d)\n", ident, gtid,
4363041982dSJonathan Peyton                 __kmp_get_gtid()));
4377cc577a4SJonathan Peyton   if (ident != 0) {
4387cc577a4SJonathan Peyton     __kmp_check_null_func();
4397cc577a4SJonathan Peyton   }
4407cc577a4SJonathan Peyton   if (p->w_top > p->p_top) {
4417cc577a4SJonathan Peyton     /* we are already in a WORKSHARING construct for this PARALLEL region */
4423041982dSJonathan Peyton     __kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
4433041982dSJonathan Peyton                            &p->stack_data[p->w_top]);
4447cc577a4SJonathan Peyton   }
4457cc577a4SJonathan Peyton   if (p->s_top > p->p_top) {
4467cc577a4SJonathan Peyton     /* we are already in a SYNC construct for this PARALLEL region */
4473041982dSJonathan Peyton     __kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
4483041982dSJonathan Peyton                            &p->stack_data[p->s_top]);
4497cc577a4SJonathan Peyton   }
4507cc577a4SJonathan Peyton }
451