/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
* (C) 2001 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
*/
#ifndef SIMPLE_PMIUTIL_H_INCLUDED
#define SIMPLE_PMIUTIL_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 <alloca.h>
#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_<pmi2u_chklmem_stk_sz_); \
pmi2u_chklmem_stk_[pmi2u_chklmem_stk_sp_++] = pointer_; \
} else { \
PMI2U_CHKMEM_SETERR(rc_,nbytes_,name_); \
stmt_; \
} \
} while (0)
#define PMI2U_CHKLMEM_FREEALL() \
while (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_<pmi2u_chklbigmem_stk_sz_); \
pmi2u_chklbigmem_stk_[pmi2u_chklbigmem_stk_sp_++] = pointer_; \
} else { \
PMI2U_CHKMEM_SETERR(rc_,nbytes_,name_); \
stmt_; \
} \
} while (0)
#define PMI2U_CHKLBIGMEM_FREEALL() \
while (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_<pmi2u_chkpmem_stk_sz_); \
pmi2u_chkpmem_stk_[pmi2u_chkpmem_stk_sp_++] = pointer_; \
} else { \
PMI2U_CHKMEM_SETERR(rc_,nbytes_,name_); \
stmt_; \
} \
} while (0)
#define PMI2U_CHKPMEM_REGISTER(pointer_) do { \
PMI2U_Assert(pmi2u_chkpmem_stk_sp_<pmi2u_chkpmem_stk_sz_); \
pmi2u_chkpmem_stk_[pmi2u_chkpmem_stk_sp_++] = pointer_; \
} while (0)
#define PMI2U_CHKPMEM_REAP() \
while (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_PMIUTIL_H_INCLUDED */