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