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