1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
2 /*
3  *  (C) 2001 by Argonne National Laboratory.
4  *      See COPYRIGHT in top-level directory.
5  */
6 #ifndef MPIMEM_H_INCLUDED
7 #define MPIMEM_H_INCLUDED
8 
9 /* Make sure that we have the definitions for the malloc routines and size_t */
10 #include <stdio.h>
11 #include <stdlib.h>
12 /* strdup is often declared in string.h, so if we plan to redefine strdup,
13    we need to include string first.  That is done below, only in the
14    case where we redefine strdup */
15 
16 #if defined(__cplusplus)
17 extern "C" {
18 #endif
19 
20 #include "mpichconf.h"
21 #include "mpl.h"
22 
23 /* ensure that we weren't included out of order */
24 #include "mpibase.h"
25 
26 /* ------------------------------------------------------------------------- */
27 /* mpimem.h */
28 /* ------------------------------------------------------------------------- */
29 /* Memory allocation */
30 /* style: allow:malloc:2 sig:0 */
31 /* style: allow:free:2 sig:0 */
32 /* style: allow:strdup:2 sig:0 */
33 /* style: allow:calloc:2 sig:0 */
34 /* style: allow:realloc:1 sig:0 */
35 /* style: allow:alloca:1 sig:0 */
36 /* style: define:__strdup:1 sig:0 */
37 /* style: define:strdup:1 sig:0 */
38 /* style: allow:fprintf:5 sig:0 */   /* For handle debugging ONLY */
39 /* style: allow:snprintf:1 sig:0 */
40 
41 /*D
42   Memory - Memory Management Routines
43 
44   Rules for memory management:
45 
46   MPICH explicity prohibits the appearence of 'malloc', 'free',
47   'calloc', 'realloc', or 'strdup' in any code implementing a device or
48   MPI call (of course, users may use any of these calls in their code).
49   Instead, you must use 'MPIU_Malloc' etc.; if these are defined
50   as 'malloc', that is allowed, but an explicit use of 'malloc' instead of
51   'MPIU_Malloc' in the source code is not allowed.  This restriction is
52   made to simplify the use of portable tools to test for memory leaks,
53   overwrites, and other consistency checks.
54 
55   Most memory should be allocated at the time that 'MPID_Init' is
56   called and released with 'MPID_Finalize' is called.  If at all possible,
57   no other MPID routine should fail because memory could not be allocated
58   (for example, because the user has allocated large arrays after 'MPI_Init').
59 
60   The implementation of the MPI routines will strive to avoid memory allocation
61   as well; however, operations such as 'MPI_Type_index' that create a new
62   data type that reflects data that must be copied from an array of arbitrary
63   size will have to allocate memory (and can fail; note that there is an
64   MPI error class for out-of-memory).
65 
66   Question:
67   Do we want to have an aligned allocation routine?  E.g., one that
68   aligns memory on a cache-line.
69   D*/
70 
71 /* Define the string copy and duplication functions */
72 /* Safer string routines */
73 int MPIU_Strncpy( char *outstr, const char *instr, size_t maxlen );
74 
75 int MPIU_Strnapp( char *, const char *, size_t );
76 char *MPIU_Strdup( const char * );
77 
78 /* ---------------------------------------------------------------------- */
79 /* FIXME - The string routines do not belong in the memory header file  */
80 /* FIXME - The string error code such be MPICH2-usable error codes */
81 #define MPIU_STR_SUCCESS    0
82 #define MPIU_STR_FAIL      -1
83 #define MPIU_STR_NOMEM      1
84 
85 /* FIXME: TRUE/FALSE definitions should either not be used or be
86    used consistently.  These also do not belong in the mpimem header file. */
87 #define MPIU_TRUE  1
88 #define MPIU_FALSE 0
89 
90 /* FIXME: Global types like this need to be discussed and agreed to */
91 typedef int MPIU_BOOL;
92 
93 /* FIXME: These should be scoped to only the routines that need them */
94 #ifdef USE_HUMAN_READABLE_TOKENS
95 
96 #define MPIU_STR_QUOTE_CHAR     '\"'
97 #define MPIU_STR_QUOTE_STR      "\""
98 #define MPIU_STR_DELIM_CHAR     '='
99 #define MPIU_STR_DELIM_STR      "="
100 #define MPIU_STR_ESCAPE_CHAR    '\\'
101 #define MPIU_STR_HIDE_CHAR      '*'
102 #define MPIU_STR_SEPAR_CHAR     ' '
103 #define MPIU_STR_SEPAR_STR      " "
104 
105 #else
106 
107 #define MPIU_STR_QUOTE_CHAR     '\"'
108 #define MPIU_STR_QUOTE_STR      "\""
109 #define MPIU_STR_DELIM_CHAR     '#'
110 #define MPIU_STR_DELIM_STR      "#"
111 #define MPIU_STR_ESCAPE_CHAR    '\\'
112 #define MPIU_STR_HIDE_CHAR      '*'
113 #define MPIU_STR_SEPAR_CHAR     '$'
114 #define MPIU_STR_SEPAR_STR      "$"
115 
116 #endif
117 
118 int MPIU_Str_get_string_arg(const char *str, const char *key, char *val,
119 			    int maxlen);
120 int MPIU_Str_get_binary_arg(const char *str, const char *key, char *buffer,
121 			    int maxlen, int *out_length);
122 int MPIU_Str_get_int_arg(const char *str, const char *key, int *val_ptr);
123 int MPIU_Str_add_string_arg(char **str_ptr, int *maxlen_ptr, const char *key,
124 			    const char *val);
125 int MPIU_Str_add_binary_arg(char **str_ptr, int *maxlen_ptr, const char *key,
126 			    const char *buffer, int length);
127 int MPIU_Str_add_int_arg(char **str_ptr, int *maxlen_ptr, const char *key,
128 			 int val);
129 MPIU_BOOL MPIU_Str_hide_string_arg(char *str, const char *key);
130 int MPIU_Str_add_string(char **str_ptr, int *maxlen_ptr, const char *val);
131 int MPIU_Str_get_string(char **str_ptr, char *val, int maxlen);
132 
133 /* ------------------------------------------------------------------------- */
134 
135 void MPIU_trinit(int);
136 void *MPIU_trmalloc(unsigned int, int, const char []);
137 void MPIU_trfree(void *, int, const char []);
138 int MPIU_trvalid(const char []);
139 void MPIU_trspace(int *, int *);
140 void MPIU_trid(int);
141 void MPIU_trlevel(int);
142 void MPIU_trDebugLevel(int);
143 void *MPIU_trcalloc(unsigned int, unsigned int, int, const char []);
144 void *MPIU_trrealloc(void *, int, int, const char[]);
145 void *MPIU_trstrdup(const char *, int, const char[]);
146 void MPIU_TrSetMaxMem(int);
147 void MPIU_trdump(FILE *, int);
148 
149 #ifdef USE_MEMORY_TRACING
150 /*M
151   MPIU_Malloc - Allocate memory
152 
153   Synopsis:
154 .vb
155   void *MPIU_Malloc( size_t len )
156 .ve
157 
158   Input Parameter:
159 . len - Length of memory to allocate in bytes
160 
161   Return Value:
162   Pointer to allocated memory, or null if memory could not be allocated.
163 
164   Notes:
165   This routine will often be implemented as the simple macro
166 .vb
167   #define MPIU_Malloc(n) malloc(n)
168 .ve
169   However, it can also be defined as
170 .vb
171   #define MPIU_Malloc(n) MPIU_trmalloc(n,__FILE__,__LINE__)
172 .ve
173   where 'MPIU_trmalloc' is a tracing version of 'malloc' that is included with
174   MPICH.
175 
176   Module:
177   Utility
178   M*/
179 #define MPIU_Malloc(a)    MPIU_trmalloc((unsigned)(a),__LINE__,__FILE__)
180 
181 /*M
182   MPIU_Calloc - Allocate memory that is initialized to zero.
183 
184   Synopsis:
185 .vb
186     void *MPIU_Calloc( size_t nelm, size_t elsize )
187 .ve
188 
189   Input Parameters:
190 + nelm - Number of elements to allocate
191 - elsize - Size of each element.
192 
193   Notes:
194   Like 'MPIU_Malloc' and 'MPIU_Free', this will often be implemented as a
195   macro but may use 'MPIU_trcalloc' to provide a tracing version.
196 
197   Module:
198   Utility
199   M*/
200 #define MPIU_Calloc(a,b)  \
201     MPIU_trcalloc((unsigned)(a),(unsigned)(b),__LINE__,__FILE__)
202 
203 /*M
204   MPIU_Free - Free memory
205 
206   Synopsis:
207 .vb
208    void MPIU_Free( void *ptr )
209 .ve
210 
211   Input Parameter:
212 . ptr - Pointer to memory to be freed.  This memory must have been allocated
213   with 'MPIU_Malloc'.
214 
215   Notes:
216   This routine will often be implemented as the simple macro
217 .vb
218   #define MPIU_Free(n) free(n)
219 .ve
220   However, it can also be defined as
221 .vb
222   #define MPIU_Free(n) MPIU_trfree(n,__FILE__,__LINE__)
223 .ve
224   where 'MPIU_trfree' is a tracing version of 'free' that is included with
225   MPICH.
226 
227   Module:
228   Utility
229   M*/
230 #define MPIU_Free(a)      MPIU_trfree(a,__LINE__,__FILE__)
231 
232 #define MPIU_Strdup(a)    MPIU_trstrdup(a,__LINE__,__FILE__)
233 
234 #define MPIU_Realloc(a,b)    MPIU_trrealloc((a),(b),__LINE__,__FILE__)
235 
236 /* Define these as invalid C to catch their use in the code */
237 #define malloc(a)         'Error use MPIU_Malloc' :::
238 #define calloc(a,b)       'Error use MPIU_Calloc' :::
239 #define free(a)           'Error use MPIU_Free'   :::
240 #define realloc(a)        'Error use MPIU_Realloc' :::
241 #if defined(strdup) || defined(__strdup)
242 #undef strdup
243 #endif
244     /* We include string.h first, so that if it contains a definition of
245      strdup, we won't have an obscure failure when a file include string.h
246     later in the compilation process. */
247 #include <string.h>
248 
249     /* The ::: should cause the compiler to choke; the string
250        will give the explanation */
251 #undef strdup /* in case strdup is a macro */
252 #define strdup(a)         'Error use MPIU_Strdup' :::
253 
254 #else /* USE_MEMORY_TRACING */
255 /* No memory tracing; just use native functions */
256 #define MPIU_Malloc(a)    malloc((size_t)(a))
257 #define MPIU_Calloc(a,b)  calloc((size_t)(a),(size_t)(b))
258 #define MPIU_Free(a)      free((void *)(a))
259 #define MPIU_Realloc(a,b)  realloc((void *)(a),(size_t)(b))
260 
261 #ifdef HAVE_STRDUP
262 /* Watch for the case where strdup is defined as a macro by a header include */
263 # if defined(NEEDS_STRDUP_DECL) && !defined(strdup)
264 extern char *strdup( const char * );
265 # endif
266 #define MPIU_Strdup(a)    strdup(a)
267 #else
268 /* Don't define MPIU_Strdup, provide it in safestr.c */
269 #endif /* HAVE_STRDUP */
270 
271 #endif /* USE_MEMORY_TRACING */
272 
273 
274 /* Memory allocation macros. See document. */
275 
276 /* You can redefine this to indicate whether memory allocation errors
277    are fatal.  Recoverable by default */
278 #define MPIU_CHKMEM_ISFATAL MPIR_ERR_RECOVERABLE
279 
280 /* Standard macro for generating error codes.   */
281 #ifdef HAVE_ERROR_CHECKING
282 #define MPIU_CHKMEM_SETERR(rc_,nbytes_,name_) \
283      rc_=MPIR_Err_create_code( MPI_SUCCESS, \
284           MPIU_CHKMEM_ISFATAL, FCNAME, __LINE__, \
285           MPI_ERR_OTHER, "**nomem2", "**nomem2 %d %s", nbytes_, name_ )
286 #else
287 #define MPIU_CHKMEM_SETERR(rc_,nbytes_,name_) rc_=MPI_ERR_OTHER
288 #endif
289 
290     /* CHKPMEM_REGISTER is used for memory allocated within another routine */
291 
292 /* Memory used and freed within the current scopy (alloca if feasible) */
293 /* Configure with --enable-alloca to set USE_ALLOCA */
294 #if defined(HAVE_ALLOCA) && defined(USE_ALLOCA)
295 #ifdef HAVE_ALLOCA_H
296 #include <alloca.h>
297 #endif
298 /* Define decl with a dummy definition to allow us to put a semi-colon
299    after the macro without causing the declaration block to end (restriction
300    imposed by C) */
301 #define MPIU_CHKLMEM_DECL(n_) int dummy_
302 #define MPIU_CHKLMEM_FREEALL()
303 #define MPIU_CHKLMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,stmt_) \
304 {pointer_ = (type_)alloca(nbytes_); \
305     if (!(pointer_) && (nbytes_ > 0)) {	   \
306     MPIU_CHKMEM_SETERR(rc_,nbytes_,name_); \
307     stmt_;\
308 }}
309 #else
310 #define MPIU_CHKLMEM_DECL(n_) \
311  void *(mpiu_chklmem_stk_[n_]) = {0};\
312  int mpiu_chklmem_stk_sp_=0;\
313  MPIU_AssertDeclValue(const int mpiu_chklmem_stk_sz_,n_)
314 
315 #define MPIU_CHKLMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,stmt_) \
316 {pointer_ = (type_)MPIU_Malloc(nbytes_); \
317 if (pointer_) { \
318     MPIU_Assert(mpiu_chklmem_stk_sp_<mpiu_chklmem_stk_sz_);\
319     mpiu_chklmem_stk_[mpiu_chklmem_stk_sp_++] = pointer_;\
320  } else if (nbytes_ > 0) {				 \
321     MPIU_CHKMEM_SETERR(rc_,nbytes_,name_); \
322     stmt_;\
323 }}
324 #define MPIU_CHKLMEM_FREEALL() \
325     do { while (mpiu_chklmem_stk_sp_ > 0) {\
326        MPIU_Free( mpiu_chklmem_stk_[--mpiu_chklmem_stk_sp_] ); } } while(0)
327 #endif /* HAVE_ALLOCA */
328 #define MPIU_CHKLMEM_MALLOC(pointer_,type_,nbytes_,rc_,name_) \
329     MPIU_CHKLMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_)
330 #define MPIU_CHKLMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_) \
331     MPIU_CHKLMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,goto fn_fail)
332 
333 /* In some cases, we need to allocate large amounts of memory. This can
334    be a problem if alloca is used, as the available stack space may be small.
335    This is the same approach for the temporary memory as is used when alloca
336    is not available. */
337 #define MPIU_CHKLBIGMEM_DECL(n_) \
338  void *(mpiu_chklbigmem_stk_[n_]);\
339  int mpiu_chklbigmem_stk_sp_=0;\
340  MPIU_AssertDeclValue(const int mpiu_chklbigmem_stk_sz_,n_)
341 
342 #define MPIU_CHKLBIGMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,stmt_) \
343 {pointer_ = (type_)MPIU_Malloc(nbytes_); \
344 if (pointer_) { \
345     MPIU_Assert(mpiu_chklbigmem_stk_sp_<mpiu_chklbigmem_stk_sz_);\
346     mpiu_chklbigmem_stk_[mpiu_chklbigmem_stk_sp_++] = pointer_;\
347  } else if (nbytes_ > 0) {				       \
348     MPIU_CHKMEM_SETERR(rc_,nbytes_,name_); \
349     stmt_;\
350 }}
351 #define MPIU_CHKLBIGMEM_FREEALL() \
352     { while (mpiu_chklbigmem_stk_sp_ > 0) {\
353        MPIU_Free( mpiu_chklbigmem_stk_[--mpiu_chklbigmem_stk_sp_] ); } }
354 
355 #define MPIU_CHKLBIGMEM_MALLOC(pointer_,type_,nbytes_,rc_,name_) \
356     MPIU_CHKLBIGMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_)
357 #define MPIU_CHKLBIGMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_) \
358     MPIU_CHKLBIGMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,goto fn_fail)
359 
360 /* Persistent memory that we may want to recover if something goes wrong */
361 #define MPIU_CHKPMEM_DECL(n_) \
362  void *(mpiu_chkpmem_stk_[n_]);\
363  int mpiu_chkpmem_stk_sp_=0;\
364  MPIU_AssertDeclValue(const int mpiu_chkpmem_stk_sz_,n_)
365 #define MPIU_CHKPMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,stmt_) \
366 {pointer_ = (type_)MPIU_Malloc(nbytes_); \
367 if (pointer_) { \
368     MPIU_Assert(mpiu_chkpmem_stk_sp_<mpiu_chkpmem_stk_sz_);\
369     mpiu_chkpmem_stk_[mpiu_chkpmem_stk_sp_++] = pointer_;\
370  } else if (nbytes_ > 0) {				 \
371     MPIU_CHKMEM_SETERR(rc_,nbytes_,name_); \
372     stmt_;\
373 }}
374 #define MPIU_CHKPMEM_REGISTER(pointer_) \
375     {MPIU_Assert(mpiu_chkpmem_stk_sp_<mpiu_chkpmem_stk_sz_);\
376     mpiu_chkpmem_stk_[mpiu_chkpmem_stk_sp_++] = pointer_;}
377 #define MPIU_CHKPMEM_REAP() \
378     { while (mpiu_chkpmem_stk_sp_ > 0) {\
379        MPIU_Free( mpiu_chkpmem_stk_[--mpiu_chkpmem_stk_sp_] ); } }
380 #define MPIU_CHKPMEM_COMMIT() \
381     mpiu_chkpmem_stk_sp_ = 0
382 #define MPIU_CHKPMEM_MALLOC(pointer_,type_,nbytes_,rc_,name_) \
383     MPIU_CHKPMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_)
384 #define MPIU_CHKPMEM_MALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_) \
385     MPIU_CHKPMEM_MALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,goto fn_fail)
386 
387 /* now the CALLOC version for zeroed memory */
388 #define MPIU_CHKPMEM_CALLOC(pointer_,type_,nbytes_,rc_,name_) \
389     MPIU_CHKPMEM_CALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_)
390 #define MPIU_CHKPMEM_CALLOC_ORJUMP(pointer_,type_,nbytes_,rc_,name_) \
391     MPIU_CHKPMEM_CALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,goto fn_fail)
392 #define MPIU_CHKPMEM_CALLOC_ORSTMT(pointer_,type_,nbytes_,rc_,name_,stmt_) \
393     do {                                                                   \
394         pointer_ = (type_)MPIU_Calloc(1, (nbytes_));                       \
395         if (pointer_) {                                                    \
396             MPIU_Assert(mpiu_chkpmem_stk_sp_<mpiu_chkpmem_stk_sz_);        \
397             mpiu_chkpmem_stk_[mpiu_chkpmem_stk_sp_++] = pointer_;          \
398         }                                                                  \
399         else if (nbytes_ > 0) {                                            \
400             MPIU_CHKMEM_SETERR(rc_,nbytes_,name_);                         \
401             stmt_;                                                         \
402         }                                                                  \
403     } while (0)
404 
405 /* A special version for routines that only allocate one item */
406 #define MPIU_CHKPMEM_MALLOC1(pointer_,type_,nbytes_,rc_,name_,stmt_) \
407 {pointer_ = (type_)MPIU_Malloc(nbytes_); \
408     if (!(pointer_) && (nbytes_ > 0)) {	   \
409     MPIU_CHKMEM_SETERR(rc_,nbytes_,name_); \
410     stmt_;\
411 }}
412 
413 /* Provides a easy way to use realloc safely and avoid the temptation to use
414  * realloc unsafely (direct ptr assignment).  Zero-size reallocs returning NULL
415  * are handled and are not considered an error. */
416 #define MPIU_REALLOC_OR_FREE_AND_JUMP(ptr_,size_,rc_) do { \
417     void *realloc_tmp_ = MPIU_Realloc((ptr_), (size_)); \
418     if ((size_) && !realloc_tmp_) { \
419         MPIU_Free(ptr_); \
420         MPIU_ERR_SETANDJUMP2(rc_,MPIU_CHKMEM_ISFATAL,"**nomem2","**nomem2 %d %s",(size_),MPIU_QUOTE(ptr_)); \
421     } \
422     (ptr_) = realloc_tmp_; \
423 } while (0)
424 /* this version does not free ptr_ */
425 #define MPIU_REALLOC_ORJUMP(ptr_,size_,rc_) do { \
426     void *realloc_tmp_ = MPIU_Realloc((ptr_), (size_)); \
427     if (size_) \
428         MPIU_ERR_CHKANDJUMP2(!realloc_tmp_,rc_,MPIU_CHKMEM_ISFATAL,"**nomem2","**nomem2 %d %s",(size_),MPIU_QUOTE(ptr_)); \
429     (ptr_) = realloc_tmp_; \
430 } while (0)
431 
432 /* Define attribute as empty if it has no definition */
433 #ifndef ATTRIBUTE
434 #define ATTRIBUTE(a)
435 #endif
436 
437 #if defined(HAVE_STRNCASECMP)
438 #   define MPIU_Strncasecmp strncasecmp
439 #elif defined(HAVE_STRNICMP)
440 #   define MPIU_Strncasecmp strnicmp
441 #else
442 /* FIXME: Provide a fallback function ? */
443 #   error "No function defined for case-insensitive strncmp"
444 #endif
445 
446 #define MPIU_Snprintf MPL_snprintf
447 
448 /* MPIU_Basename(path, basename)
449    This function finds the basename in a path (ala "man 1 basename").
450    *basename will point to an element in path.
451    More formally: This function sets basename to the character just after the last '/' in path.
452 */
453 void MPIU_Basename(char *path, char **basename);
454 
455 /* Evaluates to a boolean expression, true if the given byte ranges overlap,
456  * false otherwise.  That is, true iff [a_,a_+a_len_) overlaps with [b_,b_+b_len_) */
457 #define MPIU_MEM_RANGES_OVERLAP(a_,a_len_,b_,b_len_) \
458     ( ((char *)(a_) >= (char *)(b_) && ((char *)(a_) < ((char *)(b_) + (b_len_)))) ||  \
459       ((char *)(b_) >= (char *)(a_) && ((char *)(b_) < ((char *)(a_) + (a_len_)))) )
460 #if (!defined(NDEBUG) && defined(HAVE_ERROR_CHECKING))
461 
462 #ifndef TRUE
463 #define TRUE 1
464 #endif
465 #ifndef FALSE
466 #define FALSE 0
467 #endif
468 
469 /* May be used to perform sanity and range checking on memcpy and mempcy-like
470    function calls.  This macro will bail out much like an MPIU_Assert if any of
471    the checks fail. */
472 #define MPIU_MEM_CHECK_MEMCPY(dst_,src_,len_)                                                                   \
473     do {                                                                                                        \
474         if (len_) {                                                                                             \
475             MPIU_Assert((dst_) != NULL);                                                                        \
476             MPIU_Assert((src_) != NULL);                                                                        \
477             MPL_VG_CHECK_MEM_IS_ADDRESSABLE((dst_),(len_));                                                     \
478             MPL_VG_CHECK_MEM_IS_ADDRESSABLE((src_),(len_));                                                     \
479             if (MPIU_MEM_RANGES_OVERLAP((dst_),(len_),(src_),(len_))) {                                          \
480                 MPIU_Assert_fmt_msg(FALSE,("memcpy argument memory ranges overlap, dst_=%p src_=%p len_=%ld\n", \
481                                            (dst_), (src_), (long)(len_)));                                      \
482             }                                                                                                   \
483         }                                                                                                       \
484     } while (0)
485 #else
486 #define MPIU_MEM_CHECK_MEMCPY(dst_,src_,len_) do {} while(0)
487 #endif
488 
489 /* valgrind macros are now provided by MPL (via mpl.h included in mpiimpl.h) */
490 
491 /* ------------------------------------------------------------------------- */
492 /* end of mpimem.h */
493 /* ------------------------------------------------------------------------- */
494 
495 #if defined(__cplusplus)
496 }
497 #endif
498 #endif
499