1 /* 2 * Copyright (C) by Argonne National Laboratory 3 * See COPYRIGHT in top-level directory 4 */ 5 6 #ifndef MPIR_MEM_H_INCLUDED 7 #define MPIR_MEM_H_INCLUDED 8 9 #include "mpichconf.h" 10 11 /* Make sure that we have the definitions for the malloc routines and size_t */ 12 #include <stdio.h> 13 #include <stdlib.h> 14 /* strdup is often declared in string.h, so if we plan to redefine strdup, 15 we need to include string first. That is done below, only in the 16 case where we redefine strdup */ 17 18 #if defined(__cplusplus) 19 extern "C" { 20 #endif 21 22 #include "mpl.h" 23 24 /* Define attribute as empty if it has no definition */ 25 #ifndef ATTRIBUTE 26 #define ATTRIBUTE(a) 27 #endif 28 29 #if defined (MPL_USE_DBG_LOGGING) 30 extern MPL_dbg_class MPIR_DBG_STRING; 31 #endif /* MPL_USE_DBG_LOGGING */ 32 33 /* ------------------------------------------------------------------------- */ 34 /* mpir_mem.h */ 35 /* ------------------------------------------------------------------------- */ 36 /* Memory allocation */ 37 /* style: allow:malloc:2 sig:0 */ 38 /* style: allow:free:2 sig:0 */ 39 /* style: allow:strdup:2 sig:0 */ 40 /* style: allow:calloc:2 sig:0 */ 41 /* style: allow:realloc:1 sig:0 */ 42 /* style: allow:alloca:1 sig:0 */ 43 /* style: define:__strdup:1 sig:0 */ 44 /* style: define:strdup:1 sig:0 */ 45 /* style: allow:fprintf:5 sig:0 *//* For handle debugging ONLY */ 46 /* style: allow:snprintf:1 sig:0 */ 47 48 /*D 49 Memory - Memory Management Routines 50 51 Rules for memory management: 52 53 MPICH explicity prohibits the appearence of 'malloc', 'free', 54 'calloc', 'realloc', or 'strdup' in any code implementing a device or 55 MPI call (of course, users may use any of these calls in their code). 56 Instead, you must use 'MPL_malloc' etc.; if these are defined 57 as 'malloc', that is allowed, but an explicit use of 'malloc' instead of 58 'MPL_malloc' in the source code is not allowed. This restriction is 59 made to simplify the use of portable tools to test for memory leaks, 60 overwrites, and other consistency checks. 61 62 Most memory should be allocated at the time that 'MPID_Init' is 63 called and released with 'MPID_Finalize' is called. If at all possible, 64 no other routine should fail because memory could not be allocated 65 (for example, because the user has allocated large arrays after 'MPI_Init'). 66 67 The implementation of the MPI routines will strive to avoid memory allocation 68 as well; however, operations such as 'MPI_Type_index' that create a new 69 data type that reflects data that must be copied from an array of arbitrary 70 size will have to allocate memory (and can fail; note that there is an 71 MPI error class for out-of-memory). 72 73 Question: 74 Do we want to have an aligned allocation routine? E.g., one that 75 aligns memory on a cache-line. 76 D*/ 77 78 /* Define the string copy and duplication functions */ 79 /* ------------------------------------------------------------------------- */ 80 81 #define MPIR_Memcpy(dst, src, len) \ 82 do { \ 83 CHECK_MEMCPY((dst),(src),(len)); \ 84 memcpy((dst), (src), (len)); \ 85 } while (0) 86 87 /* Memory allocation macros. See document. */ 88 89 /* Standard macro for generating error codes. We set the error to be 90 * recoverable by default, but this can be changed. */ 91 #ifdef HAVE_ERROR_CHECKING 92 #define MPIR_CHKMEM_SETERR(rc_,nbytes_,name_) \ 93 rc_=MPIR_Err_create_code(MPI_SUCCESS, \ 94 MPIR_ERR_RECOVERABLE, __func__, __LINE__, \ 95 MPI_ERR_OTHER, "**nomem2", "**nomem2 %d %s", nbytes_, name_) 96 #else /* HAVE_ERROR_CHECKING */ 97 #define MPIR_CHKMEM_SETERR(rc_,nbytes_,name_) rc_=MPI_ERR_OTHER 98 #endif /* HAVE_ERROR_CHECKING */ 99 100 /* CHKPMEM_REGISTER is used for memory allocated within another routine */ 101 102 /* Memory used and freed within the current scope (alloca if feasible) */ 103 /* Configure with --enable-alloca to set USE_ALLOCA */ 104 #if defined(HAVE_ALLOCA) && defined(USE_ALLOCA) 105 #ifdef HAVE_ALLOCA_H 106 #include <alloca.h> 107 #endif /* HAVE_ALLOCA_H */ 108 /* Define decl with a dummy definition to allow us to put a semi-colon 109 after the macro without causing the declaration block to end (restriction 110 imposed by C) */ 111 #define MPIR_CHKLMEM_DECL(n_) int dummy_ ATTRIBUTE((unused)) 112 #define MPIR_CHKLMEM_FREEALL() 113 #define MPIR_CHKLMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,class_,stmt_) \ 114 { \ 115 pointer_ = (type_)alloca(nbytes_); \ 116 if (!(pointer_) && (nbytes_ > 0)) { \ 117 MPIR_CHKMEM_SETERR(rc_,nbytes_,name_); \ 118 stmt_; \ 119 } \ 120 } 121 #else /* defined(HAVE_ALLOCA) && defined(USE_ALLOCA) */ 122 #define MPIR_CHKLMEM_DECL(n_) \ 123 void *(mpiu_chklmem_stk_[n_]) = { NULL }; \ 124 int mpiu_chklmem_stk_sp_=0; \ 125 MPIR_AssertDeclValue(const int mpiu_chklmem_stk_sz_,n_) 126 127 #define MPIR_CHKLMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,class_,stmt_) \ 128 { \ 129 pointer_ = (type_)MPL_malloc(nbytes_,class_); \ 130 if (pointer_) { \ 131 MPIR_Assert(mpiu_chklmem_stk_sp_<mpiu_chklmem_stk_sz_); \ 132 mpiu_chklmem_stk_[mpiu_chklmem_stk_sp_++] = (void *) pointer_; \ 133 } else if (nbytes_ > 0) { \ 134 MPIR_CHKMEM_SETERR(rc_,nbytes_,name_); \ 135 stmt_; \ 136 } \ 137 } 138 #define MPIR_CHKLMEM_FREEALL() \ 139 do { \ 140 while (mpiu_chklmem_stk_sp_ > 0) { \ 141 MPL_free(mpiu_chklmem_stk_[--mpiu_chklmem_stk_sp_]); \ 142 } \ 143 } while (0) 144 #endif /* defined(HAVE_ALLOCA) && defined(USE_ALLOCA) */ 145 #define MPIR_CHKLMEM_MALLOC(pointer_,type_,nbytes_,rc_,name_,class_) \ 146 MPIR_CHKLMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_,class_) 147 #define MPIR_CHKLMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_,class_) \ 148 MPIR_CHKLMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,class_,goto fn_fail) 149 150 /* Persistent memory that we may want to recover if something goes wrong */ 151 #define MPIR_CHKPMEM_DECL(n_) \ 152 void *(mpiu_chkpmem_stk_[n_]) = { NULL }; \ 153 int mpiu_chkpmem_stk_sp_=0; \ 154 MPIR_AssertDeclValue(const int mpiu_chkpmem_stk_sz_,n_) 155 #define MPIR_CHKPMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,class_,stmt_) \ 156 { \ 157 pointer_ = (type_)MPL_malloc(nbytes_,class_); \ 158 if (pointer_) { \ 159 MPIR_Assert(mpiu_chkpmem_stk_sp_<mpiu_chkpmem_stk_sz_); \ 160 mpiu_chkpmem_stk_[mpiu_chkpmem_stk_sp_++] = pointer_; \ 161 } else if (nbytes_ > 0) { \ 162 MPIR_CHKMEM_SETERR(rc_,nbytes_,name_); \ 163 stmt_; \ 164 } \ 165 } 166 #define MPIR_CHKPMEM_REGISTER(pointer_) \ 167 { \ 168 MPIR_Assert(mpiu_chkpmem_stk_sp_<mpiu_chkpmem_stk_sz_); \ 169 mpiu_chkpmem_stk_[mpiu_chkpmem_stk_sp_++] = pointer_; \ 170 } 171 #define MPIR_CHKPMEM_REAP() \ 172 { \ 173 while (mpiu_chkpmem_stk_sp_ > 0) { \ 174 MPL_free(mpiu_chkpmem_stk_[--mpiu_chkpmem_stk_sp_]); \ 175 } \ 176 } 177 #define MPIR_CHKPMEM_COMMIT() \ 178 mpiu_chkpmem_stk_sp_ = 0 179 #define MPIR_CHKPMEM_MALLOC(pointer_,type_,nbytes_,rc_,name_,class_) \ 180 MPIR_CHKPMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_,class_) 181 #define MPIR_CHKPMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_,class_) \ 182 MPIR_CHKPMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,class_,goto fn_fail) 183 184 /* now the CALLOC version for zeroed memory */ 185 #define MPIR_CHKPMEM_CALLOC(pointer_,type_,nbytes_,rc_,name_,class_) \ 186 MPIR_CHKPMEM_CALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_,class_) 187 #define MPIR_CHKPMEM_CALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_,class_) \ 188 MPIR_CHKPMEM_CALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,class_,goto fn_fail) 189 #define MPIR_CHKPMEM_CALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,class_,stmt_) \ 190 do { \ 191 pointer_ = (type_)MPL_calloc(1, (nbytes_), (class_)); \ 192 if (pointer_) { \ 193 MPIR_Assert(mpiu_chkpmem_stk_sp_<mpiu_chkpmem_stk_sz_); \ 194 mpiu_chkpmem_stk_[mpiu_chkpmem_stk_sp_++] = pointer_; \ 195 } \ 196 else if (nbytes_ > 0) { \ 197 MPIR_CHKMEM_SETERR(rc_,nbytes_,name_); \ 198 stmt_; \ 199 } \ 200 } while (0) 201 202 /* A special version for routines that only allocate one item */ 203 #define MPIR_CHKPMEM_MALLOC1(pointer_,type_,nbytes_,rc_,name_,class_,stmt_) \ 204 { \ 205 pointer_ = (type_)MPL_malloc(nbytes_,class_); \ 206 if (!(pointer_) && (nbytes_ > 0)) { \ 207 MPIR_CHKMEM_SETERR(rc_,nbytes_,name_); \ 208 stmt_; \ 209 } \ 210 } 211 212 /* Provides a easy way to use realloc safely and avoid the temptation to use 213 * realloc unsafely (direct ptr assignment). Zero-size reallocs returning NULL 214 * are handled and are not considered an error. */ 215 #define MPIR_REALLOC_ORJUMP(ptr_,size_,class_,rc_) \ 216 do { \ 217 void *realloc_tmp_ = MPL_realloc((ptr_), (size_), (class_)); \ 218 if (size_ != 0) \ 219 MPIR_ERR_CHKANDJUMP2(!realloc_tmp_,rc_,MPI_ERR_OTHER,"**nomem2","**nomem2 %d %s",(size_),MPL_QUOTE(ptr_)); \ 220 (ptr_) = realloc_tmp_; \ 221 } while (0) 222 223 #if defined(HAVE_STRNCASECMP) 224 #define MPIR_Strncasecmp strncasecmp 225 #elif defined(HAVE_STRNICMP) 226 #define MPIR_Strncasecmp strnicmp 227 #else 228 /* FIXME: Provide a fallback function ? */ 229 #error "No function defined for case-insensitive strncmp" 230 #endif 231 232 /* Evaluates to a boolean expression, true if the given byte ranges overlap, 233 * false otherwise. That is, true iff [a_,a_+a_len_) overlaps with [b_,b_+b_len_) */ 234 #define MPIR_MEM_RANGES_OVERLAP(a_,a_len_,b_,b_len_) \ 235 (((char *)(a_) >= (char *)(b_) && ((char *)(a_) < ((char *)(b_) + (b_len_)))) || \ 236 ((char *)(b_) >= (char *)(a_) && ((char *)(b_) < ((char *)(a_) + (a_len_))))) 237 #if (!defined(NDEBUG) && defined(HAVE_ERROR_CHECKING)) 238 239 /* May be used to perform sanity and range checking on memcpy and mempcy-like 240 function calls. This macro will bail out much like an MPIR_Assert if any of 241 the checks fail. */ 242 #define CHECK_MEMCPY(dst_,src_,len_) \ 243 do { \ 244 if (len_ != 0) { \ 245 MPL_VG_CHECK_MEM_IS_ADDRESSABLE((dst_),(len_)); \ 246 MPL_VG_CHECK_MEM_IS_ADDRESSABLE((src_),(len_)); \ 247 if (MPIR_MEM_RANGES_OVERLAP((dst_),(len_),(src_),(len_))) { \ 248 MPIR_Assert_fmt_msg(FALSE,("memcpy argument memory ranges overlap, dst_=%p src_=%p len_=%ld\n", \ 249 (dst_), (src_), (long)(len_))); \ 250 } \ 251 } \ 252 } while (0) 253 #else 254 #define CHECK_MEMCPY(dst_,src_,len_) do {} while (0) 255 #endif 256 257 /* valgrind macros are now provided by MPL (via mpl.h included in mpiimpl.h) */ 258 259 /* ------------------------------------------------------------------------- */ 260 /* end of mpir_mem.h */ 261 /* ------------------------------------------------------------------------- */ 262 263 #if defined(__cplusplus) 264 } 265 #endif 266 #endif /* MPIR_MEM_H_INCLUDED */ 267