1*b5893f02SDimitry Andric /*
2*b5893f02SDimitry Andric * kmp_error.cpp -- KPTS functions for error checking at runtime
3*b5893f02SDimitry Andric */
4*b5893f02SDimitry Andric
5*b5893f02SDimitry Andric //===----------------------------------------------------------------------===//
6*b5893f02SDimitry Andric //
7*b5893f02SDimitry Andric // The LLVM Compiler Infrastructure
8*b5893f02SDimitry Andric //
9*b5893f02SDimitry Andric // This file is dual licensed under the MIT and the University of Illinois Open
10*b5893f02SDimitry Andric // Source Licenses. See LICENSE.txt for details.
11*b5893f02SDimitry Andric //
12*b5893f02SDimitry Andric //===----------------------------------------------------------------------===//
13*b5893f02SDimitry Andric
14*b5893f02SDimitry Andric #include "kmp.h"
15*b5893f02SDimitry Andric #include "kmp_error.h"
16*b5893f02SDimitry Andric #include "kmp_i18n.h"
17*b5893f02SDimitry Andric #include "kmp_str.h"
18*b5893f02SDimitry Andric
19*b5893f02SDimitry Andric /* ------------------------------------------------------------------------ */
20*b5893f02SDimitry Andric
21*b5893f02SDimitry Andric #define MIN_STACK 100
22*b5893f02SDimitry Andric
23*b5893f02SDimitry Andric static char const *cons_text_c[] = {
24*b5893f02SDimitry Andric "(none)", "\"parallel\"", "work-sharing", /* this is not called "for"
25*b5893f02SDimitry Andric because of lowering of
26*b5893f02SDimitry Andric "sections" pragmas */
27*b5893f02SDimitry Andric "\"ordered\" work-sharing", /* this is not called "for ordered" because of
28*b5893f02SDimitry Andric lowering of "sections" pragmas */
29*b5893f02SDimitry Andric "\"sections\"",
30*b5893f02SDimitry Andric "work-sharing", /* this is not called "single" because of lowering of
31*b5893f02SDimitry Andric "sections" pragmas */
32*b5893f02SDimitry Andric "\"taskq\"", "\"taskq\"", "\"taskq ordered\"", "\"critical\"",
33*b5893f02SDimitry Andric "\"ordered\"", /* in PARALLEL */
34*b5893f02SDimitry Andric "\"ordered\"", /* in PDO */
35*b5893f02SDimitry Andric "\"ordered\"", /* in TASKQ */
36*b5893f02SDimitry Andric "\"master\"", "\"reduce\"", "\"barrier\""};
37*b5893f02SDimitry Andric
38*b5893f02SDimitry Andric #define get_src(ident) ((ident) == NULL ? NULL : (ident)->psource)
39*b5893f02SDimitry Andric
40*b5893f02SDimitry Andric #define PUSH_MSG(ct, ident) \
41*b5893f02SDimitry Andric "\tpushing on stack: %s (%s)\n", cons_text_c[(ct)], get_src((ident))
42*b5893f02SDimitry Andric #define POP_MSG(p) \
43*b5893f02SDimitry Andric "\tpopping off stack: %s (%s)\n", cons_text_c[(p)->stack_data[tos].type], \
44*b5893f02SDimitry Andric get_src((p)->stack_data[tos].ident)
45*b5893f02SDimitry Andric
46*b5893f02SDimitry Andric static int const cons_text_c_num = sizeof(cons_text_c) / sizeof(char const *);
47*b5893f02SDimitry Andric
48*b5893f02SDimitry Andric /* --------------- START OF STATIC LOCAL ROUTINES ------------------------- */
49*b5893f02SDimitry Andric
__kmp_check_null_func(void)50*b5893f02SDimitry Andric static void __kmp_check_null_func(void) { /* nothing to do */
51*b5893f02SDimitry Andric }
52*b5893f02SDimitry Andric
__kmp_expand_cons_stack(int gtid,struct cons_header * p)53*b5893f02SDimitry Andric static void __kmp_expand_cons_stack(int gtid, struct cons_header *p) {
54*b5893f02SDimitry Andric int i;
55*b5893f02SDimitry Andric struct cons_data *d;
56*b5893f02SDimitry Andric
57*b5893f02SDimitry Andric /* TODO for monitor perhaps? */
58*b5893f02SDimitry Andric if (gtid < 0)
59*b5893f02SDimitry Andric __kmp_check_null_func();
60*b5893f02SDimitry Andric
61*b5893f02SDimitry Andric KE_TRACE(10, ("expand cons_stack (%d %d)\n", gtid, __kmp_get_gtid()));
62*b5893f02SDimitry Andric
63*b5893f02SDimitry Andric d = p->stack_data;
64*b5893f02SDimitry Andric
65*b5893f02SDimitry Andric p->stack_size = (p->stack_size * 2) + 100;
66*b5893f02SDimitry Andric
67*b5893f02SDimitry Andric /* TODO free the old data */
68*b5893f02SDimitry Andric p->stack_data = (struct cons_data *)__kmp_allocate(sizeof(struct cons_data) *
69*b5893f02SDimitry Andric (p->stack_size + 1));
70*b5893f02SDimitry Andric
71*b5893f02SDimitry Andric for (i = p->stack_top; i >= 0; --i)
72*b5893f02SDimitry Andric p->stack_data[i] = d[i];
73*b5893f02SDimitry Andric
74*b5893f02SDimitry Andric /* NOTE: we do not free the old stack_data */
75*b5893f02SDimitry Andric }
76*b5893f02SDimitry Andric
77*b5893f02SDimitry Andric // NOTE: Function returns allocated memory, caller must free it!
__kmp_pragma(int ct,ident_t const * ident)78*b5893f02SDimitry Andric static char *__kmp_pragma(int ct, ident_t const *ident) {
79*b5893f02SDimitry Andric char const *cons = NULL; // Construct name.
80*b5893f02SDimitry Andric char *file = NULL; // File name.
81*b5893f02SDimitry Andric char *func = NULL; // Function (routine) name.
82*b5893f02SDimitry Andric char *line = NULL; // Line number.
83*b5893f02SDimitry Andric kmp_str_buf_t buffer;
84*b5893f02SDimitry Andric kmp_msg_t prgm;
85*b5893f02SDimitry Andric __kmp_str_buf_init(&buffer);
86*b5893f02SDimitry Andric if (0 < ct && ct < cons_text_c_num) {
87*b5893f02SDimitry Andric cons = cons_text_c[ct];
88*b5893f02SDimitry Andric } else {
89*b5893f02SDimitry Andric KMP_DEBUG_ASSERT(0);
90*b5893f02SDimitry Andric }
91*b5893f02SDimitry Andric if (ident != NULL && ident->psource != NULL) {
92*b5893f02SDimitry Andric char *tail = NULL;
93*b5893f02SDimitry Andric __kmp_str_buf_print(&buffer, "%s",
94*b5893f02SDimitry Andric ident->psource); // Copy source to buffer.
95*b5893f02SDimitry Andric // Split string in buffer to file, func, and line.
96*b5893f02SDimitry Andric tail = buffer.str;
97*b5893f02SDimitry Andric __kmp_str_split(tail, ';', NULL, &tail);
98*b5893f02SDimitry Andric __kmp_str_split(tail, ';', &file, &tail);
99*b5893f02SDimitry Andric __kmp_str_split(tail, ';', &func, &tail);
100*b5893f02SDimitry Andric __kmp_str_split(tail, ';', &line, &tail);
101*b5893f02SDimitry Andric }
102*b5893f02SDimitry Andric prgm = __kmp_msg_format(kmp_i18n_fmt_Pragma, cons, file, func, line);
103*b5893f02SDimitry Andric __kmp_str_buf_free(&buffer);
104*b5893f02SDimitry Andric return prgm.str;
105*b5893f02SDimitry Andric } // __kmp_pragma
106*b5893f02SDimitry Andric
107*b5893f02SDimitry Andric /* ----------------- END OF STATIC LOCAL ROUTINES ------------------------- */
108*b5893f02SDimitry Andric
__kmp_error_construct(kmp_i18n_id_t id,enum cons_type ct,ident_t const * ident)109*b5893f02SDimitry Andric void __kmp_error_construct(kmp_i18n_id_t id, // Message identifier.
110*b5893f02SDimitry Andric enum cons_type ct, // Construct type.
111*b5893f02SDimitry Andric ident_t const *ident // Construct ident.
112*b5893f02SDimitry Andric ) {
113*b5893f02SDimitry Andric char *construct = __kmp_pragma(ct, ident);
114*b5893f02SDimitry Andric __kmp_fatal(__kmp_msg_format(id, construct), __kmp_msg_null);
115*b5893f02SDimitry Andric KMP_INTERNAL_FREE(construct);
116*b5893f02SDimitry Andric }
117*b5893f02SDimitry Andric
__kmp_error_construct2(kmp_i18n_id_t id,enum cons_type ct,ident_t const * ident,struct cons_data const * cons)118*b5893f02SDimitry Andric void __kmp_error_construct2(kmp_i18n_id_t id, // Message identifier.
119*b5893f02SDimitry Andric enum cons_type ct, // First construct type.
120*b5893f02SDimitry Andric ident_t const *ident, // First construct ident.
121*b5893f02SDimitry Andric struct cons_data const *cons // Second construct.
122*b5893f02SDimitry Andric ) {
123*b5893f02SDimitry Andric char *construct1 = __kmp_pragma(ct, ident);
124*b5893f02SDimitry Andric char *construct2 = __kmp_pragma(cons->type, cons->ident);
125*b5893f02SDimitry Andric __kmp_fatal(__kmp_msg_format(id, construct1, construct2), __kmp_msg_null);
126*b5893f02SDimitry Andric KMP_INTERNAL_FREE(construct1);
127*b5893f02SDimitry Andric KMP_INTERNAL_FREE(construct2);
128*b5893f02SDimitry Andric }
129*b5893f02SDimitry Andric
__kmp_allocate_cons_stack(int gtid)130*b5893f02SDimitry Andric struct cons_header *__kmp_allocate_cons_stack(int gtid) {
131*b5893f02SDimitry Andric struct cons_header *p;
132*b5893f02SDimitry Andric
133*b5893f02SDimitry Andric /* TODO for monitor perhaps? */
134*b5893f02SDimitry Andric if (gtid < 0) {
135*b5893f02SDimitry Andric __kmp_check_null_func();
136*b5893f02SDimitry Andric }
137*b5893f02SDimitry Andric KE_TRACE(10, ("allocate cons_stack (%d)\n", gtid));
138*b5893f02SDimitry Andric p = (struct cons_header *)__kmp_allocate(sizeof(struct cons_header));
139*b5893f02SDimitry Andric p->p_top = p->w_top = p->s_top = 0;
140*b5893f02SDimitry Andric p->stack_data = (struct cons_data *)__kmp_allocate(sizeof(struct cons_data) *
141*b5893f02SDimitry Andric (MIN_STACK + 1));
142*b5893f02SDimitry Andric p->stack_size = MIN_STACK;
143*b5893f02SDimitry Andric p->stack_top = 0;
144*b5893f02SDimitry Andric p->stack_data[0].type = ct_none;
145*b5893f02SDimitry Andric p->stack_data[0].prev = 0;
146*b5893f02SDimitry Andric p->stack_data[0].ident = NULL;
147*b5893f02SDimitry Andric return p;
148*b5893f02SDimitry Andric }
149*b5893f02SDimitry Andric
__kmp_free_cons_stack(void * ptr)150*b5893f02SDimitry Andric void __kmp_free_cons_stack(void *ptr) {
151*b5893f02SDimitry Andric struct cons_header *p = (struct cons_header *)ptr;
152*b5893f02SDimitry Andric if (p != NULL) {
153*b5893f02SDimitry Andric if (p->stack_data != NULL) {
154*b5893f02SDimitry Andric __kmp_free(p->stack_data);
155*b5893f02SDimitry Andric p->stack_data = NULL;
156*b5893f02SDimitry Andric }
157*b5893f02SDimitry Andric __kmp_free(p);
158*b5893f02SDimitry Andric }
159*b5893f02SDimitry Andric }
160*b5893f02SDimitry Andric
161*b5893f02SDimitry Andric #if KMP_DEBUG
dump_cons_stack(int gtid,struct cons_header * p)162*b5893f02SDimitry Andric static void dump_cons_stack(int gtid, struct cons_header *p) {
163*b5893f02SDimitry Andric int i;
164*b5893f02SDimitry Andric int tos = p->stack_top;
165*b5893f02SDimitry Andric kmp_str_buf_t buffer;
166*b5893f02SDimitry Andric __kmp_str_buf_init(&buffer);
167*b5893f02SDimitry Andric __kmp_str_buf_print(
168*b5893f02SDimitry Andric &buffer,
169*b5893f02SDimitry Andric "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-\n");
170*b5893f02SDimitry Andric __kmp_str_buf_print(&buffer,
171*b5893f02SDimitry Andric "Begin construct stack with %d items for thread %d\n",
172*b5893f02SDimitry Andric tos, gtid);
173*b5893f02SDimitry Andric __kmp_str_buf_print(&buffer, " stack_top=%d { P=%d, W=%d, S=%d }\n", tos,
174*b5893f02SDimitry Andric p->p_top, p->w_top, p->s_top);
175*b5893f02SDimitry Andric for (i = tos; i > 0; i--) {
176*b5893f02SDimitry Andric struct cons_data *c = &(p->stack_data[i]);
177*b5893f02SDimitry Andric __kmp_str_buf_print(
178*b5893f02SDimitry Andric &buffer, " stack_data[%2d] = { %s (%s) %d %p }\n", i,
179*b5893f02SDimitry Andric cons_text_c[c->type], get_src(c->ident), c->prev, c->name);
180*b5893f02SDimitry Andric }
181*b5893f02SDimitry Andric __kmp_str_buf_print(&buffer, "End construct stack for thread %d\n", gtid);
182*b5893f02SDimitry Andric __kmp_str_buf_print(
183*b5893f02SDimitry Andric &buffer,
184*b5893f02SDimitry Andric "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-\n");
185*b5893f02SDimitry Andric __kmp_debug_printf("%s", buffer.str);
186*b5893f02SDimitry Andric __kmp_str_buf_free(&buffer);
187*b5893f02SDimitry Andric }
188*b5893f02SDimitry Andric #endif
189*b5893f02SDimitry Andric
__kmp_push_parallel(int gtid,ident_t const * ident)190*b5893f02SDimitry Andric void __kmp_push_parallel(int gtid, ident_t const *ident) {
191*b5893f02SDimitry Andric int tos;
192*b5893f02SDimitry Andric struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
193*b5893f02SDimitry Andric
194*b5893f02SDimitry Andric KMP_DEBUG_ASSERT(__kmp_threads[gtid]->th.th_cons);
195*b5893f02SDimitry Andric KE_TRACE(10, ("__kmp_push_parallel (%d %d)\n", gtid, __kmp_get_gtid()));
196*b5893f02SDimitry Andric KE_TRACE(100, (PUSH_MSG(ct_parallel, ident)));
197*b5893f02SDimitry Andric if (p->stack_top >= p->stack_size) {
198*b5893f02SDimitry Andric __kmp_expand_cons_stack(gtid, p);
199*b5893f02SDimitry Andric }
200*b5893f02SDimitry Andric tos = ++p->stack_top;
201*b5893f02SDimitry Andric p->stack_data[tos].type = ct_parallel;
202*b5893f02SDimitry Andric p->stack_data[tos].prev = p->p_top;
203*b5893f02SDimitry Andric p->stack_data[tos].ident = ident;
204*b5893f02SDimitry Andric p->stack_data[tos].name = NULL;
205*b5893f02SDimitry Andric p->p_top = tos;
206*b5893f02SDimitry Andric KE_DUMP(1000, dump_cons_stack(gtid, p));
207*b5893f02SDimitry Andric }
208*b5893f02SDimitry Andric
__kmp_check_workshare(int gtid,enum cons_type ct,ident_t const * ident)209*b5893f02SDimitry Andric void __kmp_check_workshare(int gtid, enum cons_type ct, ident_t const *ident) {
210*b5893f02SDimitry Andric struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
211*b5893f02SDimitry Andric
212*b5893f02SDimitry Andric KMP_DEBUG_ASSERT(__kmp_threads[gtid]->th.th_cons);
213*b5893f02SDimitry Andric KE_TRACE(10, ("__kmp_check_workshare (%d %d)\n", gtid, __kmp_get_gtid()));
214*b5893f02SDimitry Andric
215*b5893f02SDimitry Andric if (p->stack_top >= p->stack_size) {
216*b5893f02SDimitry Andric __kmp_expand_cons_stack(gtid, p);
217*b5893f02SDimitry Andric }
218*b5893f02SDimitry Andric if (p->w_top > p->p_top &&
219*b5893f02SDimitry Andric !(IS_CONS_TYPE_TASKQ(p->stack_data[p->w_top].type) &&
220*b5893f02SDimitry Andric IS_CONS_TYPE_TASKQ(ct))) {
221*b5893f02SDimitry Andric // We are already in a WORKSHARE construct for this PARALLEL region.
222*b5893f02SDimitry Andric __kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
223*b5893f02SDimitry Andric &p->stack_data[p->w_top]);
224*b5893f02SDimitry Andric }
225*b5893f02SDimitry Andric if (p->s_top > p->p_top) {
226*b5893f02SDimitry Andric // We are already in a SYNC construct for this PARALLEL region.
227*b5893f02SDimitry Andric __kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
228*b5893f02SDimitry Andric &p->stack_data[p->s_top]);
229*b5893f02SDimitry Andric }
230*b5893f02SDimitry Andric }
231*b5893f02SDimitry Andric
__kmp_push_workshare(int gtid,enum cons_type ct,ident_t const * ident)232*b5893f02SDimitry Andric void __kmp_push_workshare(int gtid, enum cons_type ct, ident_t const *ident) {
233*b5893f02SDimitry Andric int tos;
234*b5893f02SDimitry Andric struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
235*b5893f02SDimitry Andric KE_TRACE(10, ("__kmp_push_workshare (%d %d)\n", gtid, __kmp_get_gtid()));
236*b5893f02SDimitry Andric __kmp_check_workshare(gtid, ct, ident);
237*b5893f02SDimitry Andric KE_TRACE(100, (PUSH_MSG(ct, ident)));
238*b5893f02SDimitry Andric tos = ++p->stack_top;
239*b5893f02SDimitry Andric p->stack_data[tos].type = ct;
240*b5893f02SDimitry Andric p->stack_data[tos].prev = p->w_top;
241*b5893f02SDimitry Andric p->stack_data[tos].ident = ident;
242*b5893f02SDimitry Andric p->stack_data[tos].name = NULL;
243*b5893f02SDimitry Andric p->w_top = tos;
244*b5893f02SDimitry Andric KE_DUMP(1000, dump_cons_stack(gtid, p));
245*b5893f02SDimitry Andric }
246*b5893f02SDimitry Andric
247*b5893f02SDimitry Andric void
248*b5893f02SDimitry Andric #if KMP_USE_DYNAMIC_LOCK
__kmp_check_sync(int gtid,enum cons_type ct,ident_t const * ident,kmp_user_lock_p lck,kmp_uint32 seq)249*b5893f02SDimitry Andric __kmp_check_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck, kmp_uint32 seq )
250*b5893f02SDimitry Andric #else
251*b5893f02SDimitry Andric __kmp_check_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck )
252*b5893f02SDimitry Andric #endif
253*b5893f02SDimitry Andric {
254*b5893f02SDimitry Andric struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
255*b5893f02SDimitry Andric
256*b5893f02SDimitry Andric KE_TRACE(10, ("__kmp_check_sync (gtid=%d)\n", __kmp_get_gtid()));
257*b5893f02SDimitry Andric
258*b5893f02SDimitry Andric if (p->stack_top >= p->stack_size)
259*b5893f02SDimitry Andric __kmp_expand_cons_stack(gtid, p);
260*b5893f02SDimitry Andric
261*b5893f02SDimitry Andric if (ct == ct_ordered_in_parallel || ct == ct_ordered_in_pdo ||
262*b5893f02SDimitry Andric ct == ct_ordered_in_taskq) {
263*b5893f02SDimitry Andric if (p->w_top <= p->p_top) {
264*b5893f02SDimitry Andric /* we are not in a worksharing construct */
265*b5893f02SDimitry Andric #ifdef BUILD_PARALLEL_ORDERED
266*b5893f02SDimitry Andric /* do not report error messages for PARALLEL ORDERED */
267*b5893f02SDimitry Andric KMP_ASSERT(ct == ct_ordered_in_parallel);
268*b5893f02SDimitry Andric #else
269*b5893f02SDimitry Andric __kmp_error_construct(kmp_i18n_msg_CnsBoundToWorksharing, ct, ident);
270*b5893f02SDimitry Andric #endif /* BUILD_PARALLEL_ORDERED */
271*b5893f02SDimitry Andric } else {
272*b5893f02SDimitry Andric /* inside a WORKSHARING construct for this PARALLEL region */
273*b5893f02SDimitry Andric if (!IS_CONS_TYPE_ORDERED(p->stack_data[p->w_top].type)) {
274*b5893f02SDimitry Andric if (p->stack_data[p->w_top].type == ct_taskq) {
275*b5893f02SDimitry Andric __kmp_error_construct2(kmp_i18n_msg_CnsNotInTaskConstruct, ct, ident,
276*b5893f02SDimitry Andric &p->stack_data[p->w_top]);
277*b5893f02SDimitry Andric } else {
278*b5893f02SDimitry Andric __kmp_error_construct2(kmp_i18n_msg_CnsNoOrderedClause, ct, ident,
279*b5893f02SDimitry Andric &p->stack_data[p->w_top]);
280*b5893f02SDimitry Andric }
281*b5893f02SDimitry Andric }
282*b5893f02SDimitry Andric }
283*b5893f02SDimitry Andric if (p->s_top > p->p_top && p->s_top > p->w_top) {
284*b5893f02SDimitry Andric /* inside a sync construct which is inside a worksharing construct */
285*b5893f02SDimitry Andric int index = p->s_top;
286*b5893f02SDimitry Andric enum cons_type stack_type;
287*b5893f02SDimitry Andric
288*b5893f02SDimitry Andric stack_type = p->stack_data[index].type;
289*b5893f02SDimitry Andric
290*b5893f02SDimitry Andric if (stack_type == ct_critical ||
291*b5893f02SDimitry Andric ((stack_type == ct_ordered_in_parallel ||
292*b5893f02SDimitry Andric stack_type == ct_ordered_in_pdo ||
293*b5893f02SDimitry Andric stack_type ==
294*b5893f02SDimitry Andric ct_ordered_in_taskq) && /* C doesn't allow named ordered;
295*b5893f02SDimitry Andric ordered in ordered gets error */
296*b5893f02SDimitry Andric p->stack_data[index].ident != NULL &&
297*b5893f02SDimitry Andric (p->stack_data[index].ident->flags & KMP_IDENT_KMPC))) {
298*b5893f02SDimitry Andric /* we are in ORDERED which is inside an ORDERED or CRITICAL construct */
299*b5893f02SDimitry Andric __kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
300*b5893f02SDimitry Andric &p->stack_data[index]);
301*b5893f02SDimitry Andric }
302*b5893f02SDimitry Andric }
303*b5893f02SDimitry Andric } else if (ct == ct_critical) {
304*b5893f02SDimitry Andric #if KMP_USE_DYNAMIC_LOCK
305*b5893f02SDimitry Andric if (lck != NULL &&
306*b5893f02SDimitry Andric __kmp_get_user_lock_owner(lck, seq) ==
307*b5893f02SDimitry Andric gtid) { /* this thread already has lock for this critical section */
308*b5893f02SDimitry Andric #else
309*b5893f02SDimitry Andric if (lck != NULL &&
310*b5893f02SDimitry Andric __kmp_get_user_lock_owner(lck) ==
311*b5893f02SDimitry Andric gtid) { /* this thread already has lock for this critical section */
312*b5893f02SDimitry Andric #endif
313*b5893f02SDimitry Andric int index = p->s_top;
314*b5893f02SDimitry Andric struct cons_data cons = {NULL, ct_critical, 0, NULL};
315*b5893f02SDimitry Andric /* walk up construct stack and try to find critical with matching name */
316*b5893f02SDimitry Andric while (index != 0 && p->stack_data[index].name != lck) {
317*b5893f02SDimitry Andric index = p->stack_data[index].prev;
318*b5893f02SDimitry Andric }
319*b5893f02SDimitry Andric if (index != 0) {
320*b5893f02SDimitry Andric /* found match on the stack (may not always because of interleaved
321*b5893f02SDimitry Andric * critical for Fortran) */
322*b5893f02SDimitry Andric cons = p->stack_data[index];
323*b5893f02SDimitry Andric }
324*b5893f02SDimitry Andric /* we are in CRITICAL which is inside a CRITICAL construct of same name */
325*b5893f02SDimitry Andric __kmp_error_construct2(kmp_i18n_msg_CnsNestingSameName, ct, ident, &cons);
326*b5893f02SDimitry Andric }
327*b5893f02SDimitry Andric } else if (ct == ct_master || ct == ct_reduce) {
328*b5893f02SDimitry Andric if (p->w_top > p->p_top) {
329*b5893f02SDimitry Andric /* inside a WORKSHARING construct for this PARALLEL region */
330*b5893f02SDimitry Andric __kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
331*b5893f02SDimitry Andric &p->stack_data[p->w_top]);
332*b5893f02SDimitry Andric }
333*b5893f02SDimitry Andric if (ct == ct_reduce && p->s_top > p->p_top) {
334*b5893f02SDimitry Andric /* inside a another SYNC construct for this PARALLEL region */
335*b5893f02SDimitry Andric __kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
336*b5893f02SDimitry Andric &p->stack_data[p->s_top]);
337*b5893f02SDimitry Andric }
338*b5893f02SDimitry Andric }
339*b5893f02SDimitry Andric }
340*b5893f02SDimitry Andric
341*b5893f02SDimitry Andric void
342*b5893f02SDimitry Andric #if KMP_USE_DYNAMIC_LOCK
343*b5893f02SDimitry Andric __kmp_push_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck, kmp_uint32 seq )
344*b5893f02SDimitry Andric #else
345*b5893f02SDimitry Andric __kmp_push_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck )
346*b5893f02SDimitry Andric #endif
347*b5893f02SDimitry Andric {
348*b5893f02SDimitry Andric int tos;
349*b5893f02SDimitry Andric struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
350*b5893f02SDimitry Andric
351*b5893f02SDimitry Andric KMP_ASSERT(gtid == __kmp_get_gtid());
352*b5893f02SDimitry Andric KE_TRACE(10, ("__kmp_push_sync (gtid=%d)\n", gtid));
353*b5893f02SDimitry Andric #if KMP_USE_DYNAMIC_LOCK
354*b5893f02SDimitry Andric __kmp_check_sync(gtid, ct, ident, lck, seq);
355*b5893f02SDimitry Andric #else
356*b5893f02SDimitry Andric __kmp_check_sync(gtid, ct, ident, lck);
357*b5893f02SDimitry Andric #endif
358*b5893f02SDimitry Andric KE_TRACE(100, (PUSH_MSG(ct, ident)));
359*b5893f02SDimitry Andric tos = ++p->stack_top;
360*b5893f02SDimitry Andric p->stack_data[tos].type = ct;
361*b5893f02SDimitry Andric p->stack_data[tos].prev = p->s_top;
362*b5893f02SDimitry Andric p->stack_data[tos].ident = ident;
363*b5893f02SDimitry Andric p->stack_data[tos].name = lck;
364*b5893f02SDimitry Andric p->s_top = tos;
365*b5893f02SDimitry Andric KE_DUMP(1000, dump_cons_stack(gtid, p));
366*b5893f02SDimitry Andric }
367*b5893f02SDimitry Andric
368*b5893f02SDimitry Andric /* ------------------------------------------------------------------------ */
369*b5893f02SDimitry Andric
370*b5893f02SDimitry Andric void __kmp_pop_parallel(int gtid, ident_t const *ident) {
371*b5893f02SDimitry Andric int tos;
372*b5893f02SDimitry Andric struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
373*b5893f02SDimitry Andric tos = p->stack_top;
374*b5893f02SDimitry Andric KE_TRACE(10, ("__kmp_pop_parallel (%d %d)\n", gtid, __kmp_get_gtid()));
375*b5893f02SDimitry Andric if (tos == 0 || p->p_top == 0) {
376*b5893f02SDimitry Andric __kmp_error_construct(kmp_i18n_msg_CnsDetectedEnd, ct_parallel, ident);
377*b5893f02SDimitry Andric }
378*b5893f02SDimitry Andric if (tos != p->p_top || p->stack_data[tos].type != ct_parallel) {
379*b5893f02SDimitry Andric __kmp_error_construct2(kmp_i18n_msg_CnsExpectedEnd, ct_parallel, ident,
380*b5893f02SDimitry Andric &p->stack_data[tos]);
381*b5893f02SDimitry Andric }
382*b5893f02SDimitry Andric KE_TRACE(100, (POP_MSG(p)));
383*b5893f02SDimitry Andric p->p_top = p->stack_data[tos].prev;
384*b5893f02SDimitry Andric p->stack_data[tos].type = ct_none;
385*b5893f02SDimitry Andric p->stack_data[tos].ident = NULL;
386*b5893f02SDimitry Andric p->stack_top = tos - 1;
387*b5893f02SDimitry Andric KE_DUMP(1000, dump_cons_stack(gtid, p));
388*b5893f02SDimitry Andric }
389*b5893f02SDimitry Andric
390*b5893f02SDimitry Andric enum cons_type __kmp_pop_workshare(int gtid, enum cons_type ct,
391*b5893f02SDimitry Andric ident_t const *ident) {
392*b5893f02SDimitry Andric int tos;
393*b5893f02SDimitry Andric struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
394*b5893f02SDimitry Andric
395*b5893f02SDimitry Andric tos = p->stack_top;
396*b5893f02SDimitry Andric KE_TRACE(10, ("__kmp_pop_workshare (%d %d)\n", gtid, __kmp_get_gtid()));
397*b5893f02SDimitry Andric if (tos == 0 || p->w_top == 0) {
398*b5893f02SDimitry Andric __kmp_error_construct(kmp_i18n_msg_CnsDetectedEnd, ct, ident);
399*b5893f02SDimitry Andric }
400*b5893f02SDimitry Andric
401*b5893f02SDimitry Andric if (tos != p->w_top ||
402*b5893f02SDimitry Andric (p->stack_data[tos].type != ct &&
403*b5893f02SDimitry Andric // below are two exceptions to the rule that construct types must match
404*b5893f02SDimitry Andric !(p->stack_data[tos].type == ct_pdo_ordered && ct == ct_pdo) &&
405*b5893f02SDimitry Andric !(p->stack_data[tos].type == ct_task_ordered && ct == ct_task))) {
406*b5893f02SDimitry Andric __kmp_check_null_func();
407*b5893f02SDimitry Andric __kmp_error_construct2(kmp_i18n_msg_CnsExpectedEnd, ct, ident,
408*b5893f02SDimitry Andric &p->stack_data[tos]);
409*b5893f02SDimitry Andric }
410*b5893f02SDimitry Andric KE_TRACE(100, (POP_MSG(p)));
411*b5893f02SDimitry Andric p->w_top = p->stack_data[tos].prev;
412*b5893f02SDimitry Andric p->stack_data[tos].type = ct_none;
413*b5893f02SDimitry Andric p->stack_data[tos].ident = NULL;
414*b5893f02SDimitry Andric p->stack_top = tos - 1;
415*b5893f02SDimitry Andric KE_DUMP(1000, dump_cons_stack(gtid, p));
416*b5893f02SDimitry Andric return p->stack_data[p->w_top].type;
417*b5893f02SDimitry Andric }
418*b5893f02SDimitry Andric
419*b5893f02SDimitry Andric void __kmp_pop_sync(int gtid, enum cons_type ct, ident_t const *ident) {
420*b5893f02SDimitry Andric int tos;
421*b5893f02SDimitry Andric struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
422*b5893f02SDimitry Andric tos = p->stack_top;
423*b5893f02SDimitry Andric KE_TRACE(10, ("__kmp_pop_sync (%d %d)\n", gtid, __kmp_get_gtid()));
424*b5893f02SDimitry Andric if (tos == 0 || p->s_top == 0) {
425*b5893f02SDimitry Andric __kmp_error_construct(kmp_i18n_msg_CnsDetectedEnd, ct, ident);
426*b5893f02SDimitry Andric }
427*b5893f02SDimitry Andric if (tos != p->s_top || p->stack_data[tos].type != ct) {
428*b5893f02SDimitry Andric __kmp_check_null_func();
429*b5893f02SDimitry Andric __kmp_error_construct2(kmp_i18n_msg_CnsExpectedEnd, ct, ident,
430*b5893f02SDimitry Andric &p->stack_data[tos]);
431*b5893f02SDimitry Andric }
432*b5893f02SDimitry Andric if (gtid < 0) {
433*b5893f02SDimitry Andric __kmp_check_null_func();
434*b5893f02SDimitry Andric }
435*b5893f02SDimitry Andric KE_TRACE(100, (POP_MSG(p)));
436*b5893f02SDimitry Andric p->s_top = p->stack_data[tos].prev;
437*b5893f02SDimitry Andric p->stack_data[tos].type = ct_none;
438*b5893f02SDimitry Andric p->stack_data[tos].ident = NULL;
439*b5893f02SDimitry Andric p->stack_top = tos - 1;
440*b5893f02SDimitry Andric KE_DUMP(1000, dump_cons_stack(gtid, p));
441*b5893f02SDimitry Andric }
442*b5893f02SDimitry Andric
443*b5893f02SDimitry Andric /* ------------------------------------------------------------------------ */
444*b5893f02SDimitry Andric
445*b5893f02SDimitry Andric void __kmp_check_barrier(int gtid, enum cons_type ct, ident_t const *ident) {
446*b5893f02SDimitry Andric struct cons_header *p = __kmp_threads[gtid]->th.th_cons;
447*b5893f02SDimitry Andric KE_TRACE(10, ("__kmp_check_barrier (loc: %p, gtid: %d %d)\n", ident, gtid,
448*b5893f02SDimitry Andric __kmp_get_gtid()));
449*b5893f02SDimitry Andric if (ident != 0) {
450*b5893f02SDimitry Andric __kmp_check_null_func();
451*b5893f02SDimitry Andric }
452*b5893f02SDimitry Andric if (p->w_top > p->p_top) {
453*b5893f02SDimitry Andric /* we are already in a WORKSHARING construct for this PARALLEL region */
454*b5893f02SDimitry Andric __kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
455*b5893f02SDimitry Andric &p->stack_data[p->w_top]);
456*b5893f02SDimitry Andric }
457*b5893f02SDimitry Andric if (p->s_top > p->p_top) {
458*b5893f02SDimitry Andric /* we are already in a SYNC construct for this PARALLEL region */
459*b5893f02SDimitry Andric __kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,
460*b5893f02SDimitry Andric &p->stack_data[p->s_top]);
461*b5893f02SDimitry Andric }
462*b5893f02SDimitry Andric }
463