/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ /* * (C) 2001 by Argonne National Laboratory. * See COPYRIGHT in top-level directory. */ #ifndef SIMPLE_PMI_UTIL_H_INCLUDED #define SIMPLE_PMI_UTIL_H_INCLUDED #include "mpichconf.h" /* maximum sizes for arrays */ #define PMI2U_MAXLINE 1024 #define PMI2U_IDSIZE 32 /* prototypes for PMIU routines */ void PMI2U_Set_rank( int PMI_rank ); void PMI2U_SetServer( void ); void PMI2U_printf( int print_flag, const char *fmt, ... ); int PMI2U_readline( int fd, char *buf, int max ); int PMI2U_writeline( int fd, char *buf ); int PMI2U_parse_keyvals( char *st ); void PMI2U_dump_keyvals( void ); char *PMI2U_getval( const char *keystr, char *valstr, int vallen ); void PMI2U_chgval( const char *keystr, char *valstr ); #ifdef HAVE__FUNCTION__ #define PMI2U_FUNC __FUNCTION__ #elif defined(HAVE_CAP__FUNC__) #define PMI2U_FUNC __FUNC__ #elif defined(HAVE__FUNC__) #define PMI2U_FUNC __func__ #else #define PMI2U_FUNC __FILE__ #endif extern int PMI2_pmiverbose; /* Set this to true to print PMI debugging info */ #define printf_d(x...) do { if (PMI2_pmiverbose) printf(x); } while (0) /* error reporting macros */ #define PMI2U_ERR_POP(err) do { pmi2_errno = err; printf_d("ERROR: %s (%d)\n", PMI2U_FUNC, __LINE__); goto fn_fail; } while (0) #define PMI2U_ERR_SETANDJUMP(err, class, str) do { \ printf_d("ERROR: "str" in %s (%d)\n", PMI2U_FUNC, __LINE__); \ pmi2_errno = class; \ goto fn_fail; \ } while (0) #define PMI2U_ERR_SETANDJUMP1(err, class, str, str1, arg) do { \ printf_d("ERROR: "str1" in %s (%d)\n", arg, PMI2U_FUNC, __LINE__); \ pmi2_errno = class; \ goto fn_fail; \ } while (0) #define PMI2U_ERR_SETANDJUMP2(err, class, str, str1, arg1, arg2) do { \ printf_d("ERROR: "str1" in %s (%d)\n", arg1, arg2, PMI2U_FUNC, __LINE__); \ pmi2_errno = class; \ goto fn_fail; \ } while (0) #define PMI2U_ERR_SETANDJUMP3(err, class, str, str1, arg1, arg2, arg3) do { \ printf_d("ERROR: "str1" in %s (%d)\n", arg1, arg2, arg3, PMI2U_FUNC, __LINE__); \ pmi2_errno = class; \ goto fn_fail; \ } while (0) #define PMI2U_ERR_SETANDJUMP4(err, class, str, str1, arg1, arg2, arg3, arg4) do { \ printf_d("ERROR: "str1" in %s (%d)\n", arg1, arg2, arg3, arg4, PMI2U_FUNC, __LINE__); \ pmi2_errno = class; \ goto fn_fail; \ } while (0) #define PMI2U_ERR_SETANDJUMP5(err, class, str, str1, arg1, arg2, arg3, arg4, arg5) do { \ printf_d("ERROR: "str1" in %s (%d)\n", arg1, arg2, arg3, arg4, arg5, PMI2U_FUNC, __LINE__); \ pmi2_errno = class; \ goto fn_fail; \ } while (0) #define PMI2U_ERR_SETANDJUMP6(err, class, str, str1, arg1, arg2, arg3, arg4, arg5, arg6) do { \ printf_d("ERROR: "str1" in %s (%d)\n", arg1, arg2, arg3, arg4, arg5, arg6, PMI2U_FUNC, __LINE__); \ pmi2_errno = class; \ goto fn_fail; \ } while (0) #define PMI2U_ERR_CHKANDJUMP(cond, err, class, str) do { \ if (cond) \ PMI2U_ERR_SETANDJUMP(err, class, str); \ } while (0) #define PMI2U_ERR_CHKANDJUMP1(cond, err, class, str, str1, arg) do { \ if (cond) \ PMI2U_ERR_SETANDJUMP1(err, class, str, str1, arg); \ } while (0) #define PMI2U_ERR_CHKANDJUMP2(cond, err, class, str, str1, arg1, arg2) do { \ if (cond) \ PMI2U_ERR_SETANDJUMP2(err, class, str, str1, arg1, arg2); \ } while (0) #define PMI2U_ERR_CHKANDJUMP3(cond, err, class, str, str1, arg1, arg2, arg3) do { \ if (cond) \ PMI2U_ERR_SETANDJUMP3(err, class, str, str1, arg1, arg2, arg3); \ } while (0) #define PMI2U_ERR_CHKANDJUMP4(cond, err, class, str, str1, arg1, arg2, arg3, arg4) do { \ if (cond) \ PMI2U_ERR_SETANDJUMP4(err, class, str, str1, arg1, arg2, arg3, arg4); \ } while (0) #define PMI2U_ERR_CHKANDJUMP5(cond, err, class, str, str1, arg1, arg2, arg3, arg4, arg5) do { \ if (cond) \ PMI2U_ERR_SETANDJUMP5(err, class, str, str1, arg1, arg2, arg3, arg4, arg5); \ } while (0) #define PMI2U_ERR_CHKANDJUMP6(cond, err, class, str, str1, arg1, arg2, arg3, arg4, arg5, arg6) do { \ if (cond) \ PMI2U_ERR_SETANDJUMP6(err, class, str, str1, arg1, arg2, arg3, arg4, arg5, arg6); \ } while (0) #if (!defined(NDEBUG) && defined(HAVE_ERROR_CHECKING)) #define PMI2U_AssertDecl(a_) a_ #define PMI2U_AssertDeclValue(_a, _b) _a = _b #else /* Empty decls not allowed in C */ #define PMI2U_AssertDecl(a_) a_ #define PMI2U_AssertDeclValue(_a, _b) _a ATTRIBUTE((unused)) #endif #ifdef HAVE_ERROR_CHECKING #define PMI2U_CHKMEM_SETERR(rc_, nbytes_, name_) do { \ rc_ = PMI2_ERR_NOMEM; \ printf_d("ERROR: memory allocation of %lu bytes failed for %s in %s (%d)\n", \ (size_t)nbytes_, name_, PMI2U_FUNC, __LINE__); \ } while(0) #else #define PMI2U_CHKMEM_SETERR(rc_, nbytes_, name_) rc_ = PMI2_ERR_NOMEM #endif #if defined(HAVE_ALLOCA) && defined(USE_ALLOCA) #ifdef HAVE_ALLOCA_H #include #endif /* Define decl with a dummy definition to allow us to put a semi-colon after the macro without causing the declaration block to end (restriction imposed by C) */ #define PMI2U_CHKLMEM_DECL(n_) int dummy_ ATTRIBUTE((unused)) #define PMI2U_CHKLMEM_FREEALL() #define PMI2U_CHKLMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,stmt_) do { \ pointer_ = (type_)alloca(nbytes_); \ if (!(pointer_)) { \ PMI2U_CHKMEM_SETERR(rc_,nbytes_,name_); \ stmt_; \ } \ } while(0) #else #define PMI2U_CHKLMEM_DECL(n_) \ void *(pmi2u_chklmem_stk_[n_]) = {0}; \ int pmi2u_chklmem_stk_sp_=0; \ PMI2U_AssertDeclValue(const int pmi2u_chklmem_stk_sz_,n_) #define PMI2U_CHKLMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,stmt_) do { \ pointer_ = (type_)PMI2U_Malloc(nbytes_); \ if (pointer_) { \ PMI2U_Assert(pmi2u_chklmem_stk_sp_ 0) { \ PMI2U_Free( pmi2u_chklmem_stk_[--pmi2u_chklmem_stk_sp_] ); } #endif /* HAVE_ALLOCA */ #define PMI2U_CHKLMEM_MALLOC(pointer_,type_,nbytes_,rc_,name_) \ PMI2U_CHKLMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_) #define PMI2U_CHKLMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_) \ PMI2U_CHKLMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,goto fn_fail) /* In some cases, we need to allocate large amounts of memory. This can be a problem if alloca is used, as the available stack space may be small. This is the same approach for the temporary memory as is used when alloca is not available. */ #define PMI2U_CHKLBIGMEM_DECL(n_) \ void *(pmi2u_chklbigmem_stk_[n_]); \ int pmi2u_chklbigmem_stk_sp_ = 0; \ PMI2U_AssertDeclValue(const int pmi2u_chklbigmem_stk_sz_,n_) #define PMI2U_CHKLBIGMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,stmt_) do { \ pointer_ = (type_)PMI2U_Malloc(nbytes_); \ if (pointer_) { \ PMI2U_Assert(pmi2u_chklbigmem_stk_sp_ 0) { \ PMI2U_Free( pmi2u_chklbigmem_stk_[--pmi2u_chklbigmem_stk_sp_] ); } #define PMI2U_CHKLBIGMEM_MALLOC(pointer_,type_,nbytes_,rc_,name_) \ PMI2U_CHKLBIGMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_) #define PMI2U_CHKLBIGMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_) \ PMI2U_CHKLBIGMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,goto fn_fail) /* Persistent memory that we may want to recover if something goes wrong */ #define PMI2U_CHKPMEM_DECL(n_) \ void *(pmi2u_chkpmem_stk_[n_]) = {0}; \ int pmi2u_chkpmem_stk_sp_=0; \ PMI2U_AssertDeclValue(const int pmi2u_chkpmem_stk_sz_,n_) #define PMI2U_CHKPMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,stmt_) do { \ pointer_ = (type_)PMI2U_Malloc(nbytes_); \ if (pointer_) { \ PMI2U_Assert(pmi2u_chkpmem_stk_sp_ 0) { \ PMI2U_Free( pmi2u_chkpmem_stk_[--pmi2u_chkpmem_stk_sp_] ); } #define PMI2U_CHKPMEM_COMMIT() pmi2u_chkpmem_stk_sp_ = 0 #define PMI2U_CHKPMEM_MALLOC(pointer_,type_,nbytes_,rc_,name_) \ PMI2U_CHKPMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_) #define PMI2U_CHKPMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_) \ PMI2U_CHKPMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,goto fn_fail) /* A special version for routines that only allocate one item */ #define PMI2U_CHKPMEM_MALLOC1(pointer_,type_,nbytes_,rc_,name_,stmt_) do { \ pointer_ = (type_)PMI2U_Malloc(nbytes_); \ if (!(pointer_)) { \ PMI2U_CHKMEM_SETERR(rc_,nbytes_,name_); \ stmt_; \ } \ } while(0) /* Provides a easy way to use realloc safely and avoid the temptation to use * realloc unsafely (direct ptr assignment). Zero-size reallocs returning NULL * are handled and are not considered an error. */ #define PMI2U_REALLOC_OR_FREE_AND_JUMP(ptr_,size_,rc_) do { \ void *realloc_tmp_ = PMI2U_Realloc((ptr_), (size_)); \ if ((size_) && !realloc_tmp_) { \ PMI2U_Free(ptr_); \ PMI2U_ERR_SETANDJUMP2(rc_,PMI2U_CHKMEM_ISFATAL, \ "**nomem2","**nomem2 %d %s",(size_),PMI2U_QUOTE(ptr_)); \ } \ (ptr_) = realloc_tmp_; \ } while (0) /* this version does not free ptr_ */ #define PMI2U_REALLOC_ORJUMP(ptr_,size_,rc_) do { \ void *realloc_tmp_ = PMI2U_Realloc((ptr_), (size_)); \ if (size_) \ PMI2U_ERR_CHKANDJUMP2(!realloc_tmp_,rc_,PMI2U_CHKMEM_ISFATAL,\ \ "**nomem2","**nomem2 %d %s",(size_),PMI2U_QUOTE(ptr_)); \ (ptr_) = realloc_tmp_; \ } while (0) #endif /*SIMPLE_PMI_UTIL_H_INCLUDED*/