Path: blob/main/contrib/llvm-project/openmp/runtime/src/kmp_error.cpp
35258 views
/*1* kmp_error.cpp -- KPTS functions for error checking at runtime2*/34//===----------------------------------------------------------------------===//5//6// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.7// See https://llvm.org/LICENSE.txt for license information.8// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception9//10//===----------------------------------------------------------------------===//1112#include "kmp.h"13#include "kmp_error.h"14#include "kmp_i18n.h"15#include "kmp_str.h"1617/* ------------------------------------------------------------------------ */1819#define MIN_STACK 1002021static char const *cons_text_c[] = {22"(none)",23"\"parallel\"",24"work-sharing", /* this is not called "for"25because of lowering of26"sections" pragmas */27"\"ordered\" work-sharing", /* this is not called "for ordered" because of28lowering of "sections" pragmas */29"\"sections\"",30"work-sharing", /* this is not called "single" because of lowering of31"sections" pragmas */32"\"critical\"",33"\"ordered\"", /* in PARALLEL */34"\"ordered\"", /* in PDO */35"\"master\"",36"\"reduce\"",37"\"barrier\"",38"\"masked\""};3940#define get_src(ident) ((ident) == NULL ? NULL : (ident)->psource)4142#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], \46get_src((p)->stack_data[tos].ident)4748static int const cons_text_c_num = sizeof(cons_text_c) / sizeof(char const *);4950/* --------------- START OF STATIC LOCAL ROUTINES ------------------------- */5152static void __kmp_check_null_func(void) { /* nothing to do */53}5455static void __kmp_expand_cons_stack(int gtid, struct cons_header *p) {56int i;57struct cons_data *d;5859/* TODO for monitor perhaps? */60if (gtid < 0)61__kmp_check_null_func();6263KE_TRACE(10, ("expand cons_stack (%d %d)\n", gtid, __kmp_get_gtid()));6465d = p->stack_data;6667p->stack_size = (p->stack_size * 2) + 100;6869/* TODO free the old data */70p->stack_data = (struct cons_data *)__kmp_allocate(sizeof(struct cons_data) *71(p->stack_size + 1));7273for (i = p->stack_top; i >= 0; --i)74p->stack_data[i] = d[i];7576/* NOTE: we do not free the old stack_data */77}7879// NOTE: Function returns allocated memory, caller must free it!80static char *__kmp_pragma(int ct, ident_t const *ident) {81char const *cons = NULL; // Construct name.82char *file = NULL; // File name.83char *func = NULL; // Function (routine) name.84char *line = NULL; // Line number.85kmp_str_buf_t buffer;86kmp_msg_t prgm;87__kmp_str_buf_init(&buffer);88if (0 < ct && ct < cons_text_c_num) {89cons = cons_text_c[ct];90} else {91KMP_DEBUG_ASSERT(0);92}93if (ident != NULL && ident->psource != NULL) {94char *tail = NULL;95__kmp_str_buf_print(&buffer, "%s",96ident->psource); // Copy source to buffer.97// Split string in buffer to file, func, and line.98tail = 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}104prgm = __kmp_msg_format(kmp_i18n_fmt_Pragma, cons, file, func, line);105__kmp_str_buf_free(&buffer);106return prgm.str;107} // __kmp_pragma108109/* ----------------- END OF STATIC LOCAL ROUTINES ------------------------- */110111void __kmp_error_construct(kmp_i18n_id_t id, // Message identifier.112enum cons_type ct, // Construct type.113ident_t const *ident // Construct ident.114) {115char *construct = __kmp_pragma(ct, ident);116__kmp_fatal(__kmp_msg_format(id, construct), __kmp_msg_null);117KMP_INTERNAL_FREE(construct);118}119120void __kmp_error_construct2(kmp_i18n_id_t id, // Message identifier.121enum cons_type ct, // First construct type.122ident_t const *ident, // First construct ident.123struct cons_data const *cons // Second construct.124) {125char *construct1 = __kmp_pragma(ct, ident);126char *construct2 = __kmp_pragma(cons->type, cons->ident);127__kmp_fatal(__kmp_msg_format(id, construct1, construct2), __kmp_msg_null);128KMP_INTERNAL_FREE(construct1);129KMP_INTERNAL_FREE(construct2);130}131132struct cons_header *__kmp_allocate_cons_stack(int gtid) {133struct cons_header *p;134135/* TODO for monitor perhaps? */136if (gtid < 0) {137__kmp_check_null_func();138}139KE_TRACE(10, ("allocate cons_stack (%d)\n", gtid));140p = (struct cons_header *)__kmp_allocate(sizeof(struct cons_header));141p->p_top = p->w_top = p->s_top = 0;142p->stack_data = (struct cons_data *)__kmp_allocate(sizeof(struct cons_data) *143(MIN_STACK + 1));144p->stack_size = MIN_STACK;145p->stack_top = 0;146p->stack_data[0].type = ct_none;147p->stack_data[0].prev = 0;148p->stack_data[0].ident = NULL;149return p;150}151152void __kmp_free_cons_stack(void *ptr) {153struct cons_header *p = (struct cons_header *)ptr;154if (p != NULL) {155if (p->stack_data != NULL) {156__kmp_free(p->stack_data);157p->stack_data = NULL;158}159__kmp_free(p);160}161}162163#if KMP_DEBUG164static void dump_cons_stack(int gtid, struct cons_header *p) {165int i;166int tos = p->stack_top;167kmp_str_buf_t buffer;168__kmp_str_buf_init(&buffer);169__kmp_str_buf_print(170&buffer,171"+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-\n");172__kmp_str_buf_print(&buffer,173"Begin construct stack with %d items for thread %d\n",174tos, gtid);175__kmp_str_buf_print(&buffer, " stack_top=%d { P=%d, W=%d, S=%d }\n", tos,176p->p_top, p->w_top, p->s_top);177for (i = tos; i > 0; i--) {178struct cons_data *c = &(p->stack_data[i]);179__kmp_str_buf_print(180&buffer, " stack_data[%2d] = { %s (%s) %d %p }\n", i,181cons_text_c[c->type], get_src(c->ident), c->prev, c->name);182}183__kmp_str_buf_print(&buffer, "End construct stack for thread %d\n", gtid);184__kmp_str_buf_print(185&buffer,186"+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-\n");187__kmp_debug_printf("%s", buffer.str);188__kmp_str_buf_free(&buffer);189}190#endif191192void __kmp_push_parallel(int gtid, ident_t const *ident) {193int tos;194struct cons_header *p = __kmp_threads[gtid]->th.th_cons;195196KMP_DEBUG_ASSERT(__kmp_threads[gtid]->th.th_cons);197KE_TRACE(10, ("__kmp_push_parallel (%d %d)\n", gtid, __kmp_get_gtid()));198KE_TRACE(100, (PUSH_MSG(ct_parallel, ident)));199if (p->stack_top >= p->stack_size) {200__kmp_expand_cons_stack(gtid, p);201}202tos = ++p->stack_top;203p->stack_data[tos].type = ct_parallel;204p->stack_data[tos].prev = p->p_top;205p->stack_data[tos].ident = ident;206p->stack_data[tos].name = NULL;207p->p_top = tos;208KE_DUMP(1000, dump_cons_stack(gtid, p));209}210211void __kmp_check_workshare(int gtid, enum cons_type ct, ident_t const *ident) {212struct cons_header *p = __kmp_threads[gtid]->th.th_cons;213214KMP_DEBUG_ASSERT(__kmp_threads[gtid]->th.th_cons);215KE_TRACE(10, ("__kmp_check_workshare (%d %d)\n", gtid, __kmp_get_gtid()));216217if (p->stack_top >= p->stack_size) {218__kmp_expand_cons_stack(gtid, p);219}220if (p->w_top > p->p_top) {221// We are already in a WORKSHARE construct for this PARALLEL region.222__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,223&p->stack_data[p->w_top]);224}225if (p->s_top > p->p_top) {226// We are already in a SYNC construct for this PARALLEL region.227__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,228&p->stack_data[p->s_top]);229}230}231232void __kmp_push_workshare(int gtid, enum cons_type ct, ident_t const *ident) {233int tos;234struct cons_header *p = __kmp_threads[gtid]->th.th_cons;235KE_TRACE(10, ("__kmp_push_workshare (%d %d)\n", gtid, __kmp_get_gtid()));236__kmp_check_workshare(gtid, ct, ident);237KE_TRACE(100, (PUSH_MSG(ct, ident)));238tos = ++p->stack_top;239p->stack_data[tos].type = ct;240p->stack_data[tos].prev = p->w_top;241p->stack_data[tos].ident = ident;242p->stack_data[tos].name = NULL;243p->w_top = tos;244KE_DUMP(1000, dump_cons_stack(gtid, p));245}246247void248#if KMP_USE_DYNAMIC_LOCK249__kmp_check_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck, kmp_uint32 seq )250#else251__kmp_check_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck )252#endif253{254struct cons_header *p = __kmp_threads[gtid]->th.th_cons;255256KE_TRACE(10, ("__kmp_check_sync (gtid=%d)\n", __kmp_get_gtid()));257258if (p->stack_top >= p->stack_size)259__kmp_expand_cons_stack(gtid, p);260261if (ct == ct_ordered_in_parallel || ct == ct_ordered_in_pdo) {262if (p->w_top <= p->p_top) {263/* we are not in a worksharing construct */264#ifdef BUILD_PARALLEL_ORDERED265/* do not report error messages for PARALLEL ORDERED */266KMP_ASSERT(ct == ct_ordered_in_parallel);267#else268__kmp_error_construct(kmp_i18n_msg_CnsBoundToWorksharing, ct, ident);269#endif /* BUILD_PARALLEL_ORDERED */270} else {271/* inside a WORKSHARING construct for this PARALLEL region */272if (!IS_CONS_TYPE_ORDERED(p->stack_data[p->w_top].type)) {273__kmp_error_construct2(kmp_i18n_msg_CnsNoOrderedClause, ct, ident,274&p->stack_data[p->w_top]);275}276}277if (p->s_top > p->p_top && p->s_top > p->w_top) {278/* inside a sync construct which is inside a worksharing construct */279int index = p->s_top;280enum cons_type stack_type;281282stack_type = p->stack_data[index].type;283284if (stack_type == ct_critical ||285((stack_type == ct_ordered_in_parallel ||286stack_type == ct_ordered_in_pdo) &&287/* C doesn't allow named ordered; ordered in ordered gets error */288p->stack_data[index].ident != NULL &&289(p->stack_data[index].ident->flags & KMP_IDENT_KMPC))) {290/* we are in ORDERED which is inside an ORDERED or CRITICAL construct */291__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,292&p->stack_data[index]);293}294}295} else if (ct == ct_critical) {296#if KMP_USE_DYNAMIC_LOCK297if (lck != NULL &&298__kmp_get_user_lock_owner(lck, seq) ==299gtid) { /* this thread already has lock for this critical section */300#else301if (lck != NULL &&302__kmp_get_user_lock_owner(lck) ==303gtid) { /* this thread already has lock for this critical section */304#endif305int index = p->s_top;306struct cons_data cons = {NULL, ct_critical, 0, NULL};307/* walk up construct stack and try to find critical with matching name */308while (index != 0 && p->stack_data[index].name != lck) {309index = p->stack_data[index].prev;310}311if (index != 0) {312/* found match on the stack (may not always because of interleaved313* critical for Fortran) */314cons = p->stack_data[index];315}316/* we are in CRITICAL which is inside a CRITICAL construct of same name */317__kmp_error_construct2(kmp_i18n_msg_CnsNestingSameName, ct, ident, &cons);318}319} else if (ct == ct_master || ct == ct_masked || ct == ct_reduce) {320if (p->w_top > p->p_top) {321/* inside a WORKSHARING construct for this PARALLEL region */322__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,323&p->stack_data[p->w_top]);324}325if (ct == ct_reduce && p->s_top > p->p_top) {326/* inside a another SYNC construct for this PARALLEL region */327__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,328&p->stack_data[p->s_top]);329}330}331}332333void334#if KMP_USE_DYNAMIC_LOCK335__kmp_push_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck, kmp_uint32 seq )336#else337__kmp_push_sync( int gtid, enum cons_type ct, ident_t const * ident, kmp_user_lock_p lck )338#endif339{340int tos;341struct cons_header *p = __kmp_threads[gtid]->th.th_cons;342343KMP_ASSERT(gtid == __kmp_get_gtid());344KE_TRACE(10, ("__kmp_push_sync (gtid=%d)\n", gtid));345#if KMP_USE_DYNAMIC_LOCK346__kmp_check_sync(gtid, ct, ident, lck, seq);347#else348__kmp_check_sync(gtid, ct, ident, lck);349#endif350KE_TRACE(100, (PUSH_MSG(ct, ident)));351tos = ++p->stack_top;352p->stack_data[tos].type = ct;353p->stack_data[tos].prev = p->s_top;354p->stack_data[tos].ident = ident;355p->stack_data[tos].name = lck;356p->s_top = tos;357KE_DUMP(1000, dump_cons_stack(gtid, p));358}359360/* ------------------------------------------------------------------------ */361362void __kmp_pop_parallel(int gtid, ident_t const *ident) {363int tos;364struct cons_header *p = __kmp_threads[gtid]->th.th_cons;365tos = p->stack_top;366KE_TRACE(10, ("__kmp_pop_parallel (%d %d)\n", gtid, __kmp_get_gtid()));367if (tos == 0 || p->p_top == 0) {368__kmp_error_construct(kmp_i18n_msg_CnsDetectedEnd, ct_parallel, ident);369}370if (tos != p->p_top || p->stack_data[tos].type != ct_parallel) {371__kmp_error_construct2(kmp_i18n_msg_CnsExpectedEnd, ct_parallel, ident,372&p->stack_data[tos]);373}374KE_TRACE(100, (POP_MSG(p)));375p->p_top = p->stack_data[tos].prev;376p->stack_data[tos].type = ct_none;377p->stack_data[tos].ident = NULL;378p->stack_top = tos - 1;379KE_DUMP(1000, dump_cons_stack(gtid, p));380}381382enum cons_type __kmp_pop_workshare(int gtid, enum cons_type ct,383ident_t const *ident) {384int tos;385struct cons_header *p = __kmp_threads[gtid]->th.th_cons;386387tos = p->stack_top;388KE_TRACE(10, ("__kmp_pop_workshare (%d %d)\n", gtid, __kmp_get_gtid()));389if (tos == 0 || p->w_top == 0) {390__kmp_error_construct(kmp_i18n_msg_CnsDetectedEnd, ct, ident);391}392393if (tos != p->w_top ||394(p->stack_data[tos].type != ct &&395// below is the exception to the rule that construct types must match396!(p->stack_data[tos].type == ct_pdo_ordered && ct == ct_pdo))) {397__kmp_check_null_func();398__kmp_error_construct2(kmp_i18n_msg_CnsExpectedEnd, ct, ident,399&p->stack_data[tos]);400}401KE_TRACE(100, (POP_MSG(p)));402p->w_top = p->stack_data[tos].prev;403p->stack_data[tos].type = ct_none;404p->stack_data[tos].ident = NULL;405p->stack_top = tos - 1;406KE_DUMP(1000, dump_cons_stack(gtid, p));407return p->stack_data[p->w_top].type;408}409410void __kmp_pop_sync(int gtid, enum cons_type ct, ident_t const *ident) {411int tos;412struct cons_header *p = __kmp_threads[gtid]->th.th_cons;413tos = p->stack_top;414KE_TRACE(10, ("__kmp_pop_sync (%d %d)\n", gtid, __kmp_get_gtid()));415if (tos == 0 || p->s_top == 0) {416__kmp_error_construct(kmp_i18n_msg_CnsDetectedEnd, ct, ident);417}418if (tos != p->s_top || p->stack_data[tos].type != ct) {419__kmp_check_null_func();420__kmp_error_construct2(kmp_i18n_msg_CnsExpectedEnd, ct, ident,421&p->stack_data[tos]);422}423KE_TRACE(100, (POP_MSG(p)));424p->s_top = p->stack_data[tos].prev;425p->stack_data[tos].type = ct_none;426p->stack_data[tos].ident = NULL;427p->stack_top = tos - 1;428KE_DUMP(1000, dump_cons_stack(gtid, p));429}430431/* ------------------------------------------------------------------------ */432433void __kmp_check_barrier(int gtid, enum cons_type ct, ident_t const *ident) {434struct cons_header *p = __kmp_threads[gtid]->th.th_cons;435KE_TRACE(10, ("__kmp_check_barrier (loc: %p, gtid: %d %d)\n", ident, gtid,436__kmp_get_gtid()));437if (ident != 0) {438__kmp_check_null_func();439}440if (p->w_top > p->p_top) {441/* we are already in a WORKSHARING construct for this PARALLEL region */442__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,443&p->stack_data[p->w_top]);444}445if (p->s_top > p->p_top) {446/* we are already in a SYNC construct for this PARALLEL region */447__kmp_error_construct2(kmp_i18n_msg_CnsInvalidNesting, ct, ident,448&p->stack_data[p->s_top]);449}450}451452453