xref: /petsc/src/sys/memory/mal.c (revision 08401ef684002a709c6d3db98a0c9f54a8bcf1ec)
1e5c89e4eSSatish Balay /*
2e5c89e4eSSatish Balay     Code that allows a user to dictate what malloc() PETSc uses.
3e5c89e4eSSatish Balay */
4c6db04a5SJed Brown #include <petscsys.h>             /*I   "petscsys.h"   I*/
5ba282f50SJed Brown #include <stdarg.h>
6e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H)
7e5c89e4eSSatish Balay #include <malloc.h>
8e5c89e4eSSatish Balay #endif
9de1d6c17SHong Zhang #if defined(PETSC_HAVE_MEMKIND)
10ca8c994eSHong Zhang #include <errno.h>
11de1d6c17SHong Zhang #include <memkind.h>
12e3acc61dSHong Zhang typedef enum {PETSC_MK_DEFAULT=0,PETSC_MK_HBW_PREFERRED=1} PetscMemkindType;
13e3acc61dSHong Zhang PetscMemkindType currentmktype = PETSC_MK_HBW_PREFERRED;
14e3acc61dSHong Zhang PetscMemkindType previousmktype = PETSC_MK_HBW_PREFERRED;
15de1d6c17SHong Zhang #endif
16e5c89e4eSSatish Balay /*
17e5c89e4eSSatish Balay         We want to make sure that all mallocs of double or complex numbers are complex aligned.
18e5c89e4eSSatish Balay     1) on systems with memalign() we call that routine to get an aligned memory location
19e5c89e4eSSatish Balay     2) on systems without memalign() we
20e5c89e4eSSatish Balay        - allocate one sizeof(PetscScalar) extra space
21e5c89e4eSSatish Balay        - we shift the pointer up slightly if needed to get PetscScalar aligned
220700a824SBarry Smith        - if shifted we store at ptr[-1] the amount of shift (plus a classid)
23e5c89e4eSSatish Balay */
240700a824SBarry Smith #define SHIFT_CLASSID 456123
25e5c89e4eSSatish Balay 
26071fcb05SBarry Smith PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t mem,PetscBool clear,int line,const char func[],const char file[],void **result)
27e5c89e4eSSatish Balay {
28f0ba7cfcSLisandro Dalcin   if (!mem) {*result = NULL; return 0;}
297f18b027SJacob Faibussowitsch #if PetscDefined(HAVE_MEMKIND)
30fc2a7144SHong Zhang   {
317f18b027SJacob Faibussowitsch     int err;
327f18b027SJacob Faibussowitsch 
337f18b027SJacob Faibussowitsch     err = memkind_posix_memalign(currentmktype ? MEMKIND_HBW_PREFERRED : MEMKIND_DEFAULT,result,PETSC_MEMALIGN,mem);
347f18b027SJacob Faibussowitsch     PetscCheck(err != EINVAL,PETSC_COMM_SELF,PETSC_ERR_MEM,"Memkind: invalid 3rd or 4th argument of memkind_posix_memalign()");
357f18b027SJacob Faibussowitsch     if (err == ENOMEM) PetscInfo(NULL,"Memkind: fail to request HBW memory %.0f, falling back to normal memory\n",(PetscLogDouble)mem);
367f18b027SJacob Faibussowitsch     PetscCheck(*result,PETSC_COMM_SELF,line,func,file,PETSC_ERR_MEM,PETSC_ERROR_INITIAL,"Memory requested %.0f",(PetscLogDouble)mem);
379566063dSJacob Faibussowitsch     if (clear) PetscCall(PetscMemzero(*result,mem));
38fc2a7144SHong Zhang   }
397f18b027SJacob Faibussowitsch #else /* PetscDefined(HAVE_MEMKIND) */
407f18b027SJacob Faibussowitsch #  if PetscDefined(HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)
417f18b027SJacob Faibussowitsch   if (clear) *result = calloc(1+mem/sizeof(int),sizeof(int));
427f18b027SJacob Faibussowitsch   else       *result = malloc(mem);
437f18b027SJacob Faibussowitsch 
447f18b027SJacob Faibussowitsch   PetscCheck(*result,PETSC_COMM_SELF,line,func,file,PETSC_ERR_MEM,PETSC_ERROR_INITIAL,"Memory requested %.0f",(PetscLogDouble)mem);
459566063dSJacob Faibussowitsch   if (PetscLogMemory) PetscCall(PetscMemzero(*result,mem));
46071fcb05SBarry Smith 
477f18b027SJacob Faibussowitsch #  elif PetscDefined(HAVE_MEMALIGN)
48e5c89e4eSSatish Balay   *result = memalign(PETSC_MEMALIGN,mem);
497f18b027SJacob Faibussowitsch   PetscCheck(*result,PETSC_COMM_SELF,line,func,file,PETSC_ERR_MEM,PETSC_ERROR_INITIAL,"Memory requested %.0f",(PetscLogDouble)mem);
507f18b027SJacob Faibussowitsch   if (clear || PetscLogMemory) PetscCall(PetscMemzero(*result,mem));
517f18b027SJacob Faibussowitsch #  else /* PetscDefined(HAVE_DOUBLE_ALIGN_MALLOC) || PetscDefined(HAVE_MEMALIGN) */
52e5c89e4eSSatish Balay   {
5366c772faSBarry Smith     int *ptr,shift;
54e5c89e4eSSatish Balay     /*
55e5c89e4eSSatish Balay       malloc space for two extra chunks and shift ptr 1 + enough to get it PetscScalar aligned
56e5c89e4eSSatish Balay     */
57071fcb05SBarry Smith     if (clear) {
58071fcb05SBarry Smith       ptr = (int*)calloc(1+(mem + 2*PETSC_MEMALIGN)/sizeof(int),sizeof(int));
59071fcb05SBarry Smith     } else {
60071fcb05SBarry Smith       ptr = (int*)malloc(mem + 2*PETSC_MEMALIGN);
61071fcb05SBarry Smith     }
627f18b027SJacob Faibussowitsch     PetscCheck(ptr,PETSC_COMM_SELF,line,func,file,PETSC_ERR_MEM,PETSC_ERROR_INITIAL,"Memory requested %.0f",(PetscLogDouble)mem);
6366c772faSBarry Smith     shift        = (int)(((PETSC_UINTPTR_T) ptr) % PETSC_MEMALIGN);
64e5c89e4eSSatish Balay     shift        = (2*PETSC_MEMALIGN - shift)/sizeof(int);
650700a824SBarry Smith     ptr[shift-1] = shift + SHIFT_CLASSID;
66e5c89e4eSSatish Balay     ptr         += shift;
67e5c89e4eSSatish Balay     *result      = (void*)ptr;
689566063dSJacob Faibussowitsch     if (PetscLogMemory) PetscCall(PetscMemzero(*result,mem));
69e5c89e4eSSatish Balay   }
707f18b027SJacob Faibussowitsch #  endif /* PetscDefined(HAVE_DOUBLE_ALIGN_MALLOC) || PetscDefined(HAVE_MEMALIGN) */
717f18b027SJacob Faibussowitsch #endif /* PetscDefined(HAVE_MEMKIND) */
72e5c89e4eSSatish Balay   return 0;
73e5c89e4eSSatish Balay }
74e5c89e4eSSatish Balay 
7595c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *ptr,int line,const char func[],const char file[])
76e5c89e4eSSatish Balay {
77f0ba7cfcSLisandro Dalcin   if (!ptr) return 0;
787f18b027SJacob Faibussowitsch #if PetscDefined(HAVE_MEMKIND)
79fc2a7144SHong Zhang   memkind_free(0,ptr); /* specify the kind to 0 so that memkind will look up for the right type */
807f18b027SJacob Faibussowitsch #else /* PetscDefined(HAVE_MEMKIND) */
817f18b027SJacob Faibussowitsch #  if (!(PetscDefined(HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !PetscDefined(HAVE_MEMALIGN))
82f0ba7cfcSLisandro Dalcin   {
83e5c89e4eSSatish Balay     /*
84e5c89e4eSSatish Balay       Previous int tells us how many ints the pointer has been shifted from
85e5c89e4eSSatish Balay       the original address provided by the system malloc().
86e5c89e4eSSatish Balay     */
877f18b027SJacob Faibussowitsch     const int shift = *(((int*)ptr)-1) - SHIFT_CLASSID;
887f18b027SJacob Faibussowitsch 
897f18b027SJacob Faibussowitsch     PetscCheck(shift <= PETSC_MEMALIGN-1,PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap");
907f18b027SJacob Faibussowitsch     PetscCheck(shift >= 0,PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap");
91e5c89e4eSSatish Balay     ptr = (void*)(((int*)ptr) - shift);
92e5c89e4eSSatish Balay   }
93f0ba7cfcSLisandro Dalcin #  endif
94e5c89e4eSSatish Balay 
957f18b027SJacob Faibussowitsch #  if PetscDefined(HAVE_FREE_RETURN_INT)
96e5c89e4eSSatish Balay   int err = free(ptr);
977f18b027SJacob Faibussowitsch   PetscCheck(!err,PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"System free returned error %d\n",err);
98e5c89e4eSSatish Balay #  else
99e5c89e4eSSatish Balay   free(ptr);
100e5c89e4eSSatish Balay #  endif
101fc2a7144SHong Zhang #endif
102e5c89e4eSSatish Balay   return 0;
103e5c89e4eSSatish Balay }
104e5c89e4eSSatish Balay 
10595c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t mem, int line, const char func[], const char file[], void **result)
1063221ece2SMatthew G. Knepley {
107c22f1541SToby Isaac   if (!mem) {
1087f18b027SJacob Faibussowitsch     PetscCall(PetscFreeAlign(*result, line, func, file));
109c22f1541SToby Isaac     *result = NULL;
110c22f1541SToby Isaac     return 0;
111c22f1541SToby Isaac   }
1127f18b027SJacob Faibussowitsch #if PetscDefined(HAVE_MEMKIND)
1137f18b027SJacob Faibussowitsch   *result = memkind_realloc(currentmktype ? MEMKIND_HBW_PREFERRED : MEMKIND_DEFAULT,*result,mem);
114fc2a7144SHong Zhang #else
1157f18b027SJacob Faibussowitsch #  if (!(PetscDefined(HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !PetscDefined(HAVE_MEMALIGN))
1163221ece2SMatthew G. Knepley   {
1173221ece2SMatthew G. Knepley     /*
1183221ece2SMatthew G. Knepley       Previous int tells us how many ints the pointer has been shifted from
1193221ece2SMatthew G. Knepley       the original address provided by the system malloc().
1203221ece2SMatthew G. Knepley     */
1213221ece2SMatthew G. Knepley     int shift = *(((int*)*result)-1) - SHIFT_CLASSID;
1227f18b027SJacob Faibussowitsch     PetscCheck(shift <= PETSC_MEMALIGN-1,PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap");
1237f18b027SJacob Faibussowitsch     PetscCheck(shift >= 0,PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap");
1243221ece2SMatthew G. Knepley     *result = (void*)(((int*)*result) - shift);
1253221ece2SMatthew G. Knepley   }
1263221ece2SMatthew G. Knepley #  endif
1273221ece2SMatthew G. Knepley 
1287f18b027SJacob Faibussowitsch #  if (PetscDefined(HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) || PetscDefined(HAVE_MEMALIGN)
12941605b92SBarry Smith   *result = realloc(*result, mem);
1303221ece2SMatthew G. Knepley #  else
1313221ece2SMatthew G. Knepley   {
1323221ece2SMatthew G. Knepley     /*
1333221ece2SMatthew G. Knepley       malloc space for two extra chunks and shift ptr 1 + enough to get it PetscScalar aligned
1343221ece2SMatthew G. Knepley     */
1353221ece2SMatthew G. Knepley     int *ptr = (int*)realloc(*result,mem + 2*PETSC_MEMALIGN);
1363221ece2SMatthew G. Knepley     if (ptr) {
1373221ece2SMatthew G. Knepley       int shift    = (int)(((PETSC_UINTPTR_T) ptr) % PETSC_MEMALIGN);
1383221ece2SMatthew G. Knepley       shift        = (2*PETSC_MEMALIGN - shift)/sizeof(int);
1393221ece2SMatthew G. Knepley       ptr[shift-1] = shift + SHIFT_CLASSID;
1403221ece2SMatthew G. Knepley       ptr         += shift;
1413221ece2SMatthew G. Knepley       *result      = (void*)ptr;
1423221ece2SMatthew G. Knepley     } else {
1433221ece2SMatthew G. Knepley       *result      = NULL;
1443221ece2SMatthew G. Knepley     }
1453221ece2SMatthew G. Knepley   }
1463221ece2SMatthew G. Knepley #  endif
147fc2a7144SHong Zhang #endif
1487f18b027SJacob Faibussowitsch   PetscCheck(*result,PETSC_COMM_SELF,line,func,file,PETSC_ERR_MEM,PETSC_ERROR_INITIAL,"Memory requested %.0f",(PetscLogDouble)mem);
1497f18b027SJacob Faibussowitsch #if PetscDefined(HAVE_MEMALIGN)
150c22f1541SToby Isaac   /* There are no standard guarantees that realloc() maintains the alignment of memalign(), so I think we have to
151c22f1541SToby Isaac    * realloc and, if the alignment is wrong, malloc/copy/free. */
152c22f1541SToby Isaac   if (((size_t) (*result)) % PETSC_MEMALIGN) {
153c22f1541SToby Isaac     void *newResult;
1547f18b027SJacob Faibussowitsch #  if PetscDefined(HAVE_MEMKIND)
155fc2a7144SHong Zhang     {
1562da392ccSBarry Smith       int err;
1577f18b027SJacob Faibussowitsch       err = memkind_posix_memalign(currentmktype ? MEMKIND_HBW_PREFERRED : MEMKIND_DEFAULT,&newResult,PETSC_MEMALIGN,mem);
1587f18b027SJacob Faibussowitsch       PetscCheck(err != EINVAL,PETSC_COMM_SELF,PETSC_ERR_MEM,"Memkind: invalid 3rd or 4th argument of memkind_posix_memalign()");
1597f18b027SJacob Faibussowitsch       if (err == ENOMEM) PetscInfo(NULL,"Memkind: fail to request HBW memory %.0f, falling back to normal memory\n",(PetscLogDouble)mem);
160fc2a7144SHong Zhang     }
161fc2a7144SHong Zhang #  else
162c22f1541SToby Isaac     newResult = memalign(PETSC_MEMALIGN,mem);
163fc2a7144SHong Zhang #  endif
1647f18b027SJacob Faibussowitsch     PetscCheck(newResult,PETSC_COMM_SELF,line,func,file,PETSC_ERR_MEM,PETSC_ERROR_INITIAL,"Memory requested %.0f",(PetscLogDouble)mem);
1657f18b027SJacob Faibussowitsch     PetscCall(PetscMemcpy(newResult,*result,mem));
1667f18b027SJacob Faibussowitsch #  if PetscDefined(HAVE_FREE_RETURN_INT)
167c22f1541SToby Isaac     {
168c22f1541SToby Isaac       int err = free(*result);
1697f18b027SJacob Faibussowitsch       PetscCheck(!err,PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"System free returned error %d\n",err);
170c22f1541SToby Isaac     }
171c22f1541SToby Isaac #  else
172de1d6c17SHong Zhang #    if defined(PETSC_HAVE_MEMKIND)
173de1d6c17SHong Zhang     memkind_free(0,*result);
174de1d6c17SHong Zhang #    else
175c22f1541SToby Isaac     free(*result);
176c22f1541SToby Isaac #    endif
177de1d6c17SHong Zhang #  endif
178c22f1541SToby Isaac     *result = newResult;
179c22f1541SToby Isaac   }
180c22f1541SToby Isaac #endif
1813221ece2SMatthew G. Knepley   return 0;
1823221ece2SMatthew G. Knepley }
1833221ece2SMatthew G. Knepley 
184071fcb05SBarry Smith PetscErrorCode (*PetscTrMalloc)(size_t,PetscBool,int,const char[],const char[],void**) = PetscMallocAlign;
185efca3c55SSatish Balay PetscErrorCode (*PetscTrFree)(void*,int,const char[],const char[])                     = PetscFreeAlign;
1863221ece2SMatthew G. Knepley PetscErrorCode (*PetscTrRealloc)(size_t,int,const char[],const char[],void**)          = PetscReallocAlign;
187e5c89e4eSSatish Balay 
18895c0884eSLisandro Dalcin PETSC_INTERN PetscBool petscsetmallocvisited;
189ace3abfcSBarry Smith PetscBool petscsetmallocvisited = PETSC_FALSE;
190e5c89e4eSSatish Balay 
191e5c89e4eSSatish Balay /*@C
1921d1a0024SBarry Smith    PetscMallocSet - Sets the routines used to do mallocs and frees.
193e5c89e4eSSatish Balay    This routine MUST be called before PetscInitialize() and may be
194e5c89e4eSSatish Balay    called only once.
195e5c89e4eSSatish Balay 
196e5c89e4eSSatish Balay    Not Collective
197e5c89e4eSSatish Balay 
198e5c89e4eSSatish Balay    Input Parameters:
19992f119d6SBarry Smith + imalloc - the routine that provides the malloc (also provides calloc(), which is used depends on the second argument)
20092f119d6SBarry Smith . ifree - the routine that provides the free
20192f119d6SBarry Smith - iralloc - the routine that provides the realloc
202e5c89e4eSSatish Balay 
203e5c89e4eSSatish Balay    Level: developer
204e5c89e4eSSatish Balay 
205e5c89e4eSSatish Balay @*/
206071fcb05SBarry Smith PetscErrorCode PetscMallocSet(PetscErrorCode (*imalloc)(size_t,PetscBool,int,const char[],const char[],void**),
20792f119d6SBarry Smith                               PetscErrorCode (*ifree)(void*,int,const char[],const char[]),
20892f119d6SBarry Smith                               PetscErrorCode (*iralloc)(size_t, int, const char[], const char[], void **))
209e5c89e4eSSatish Balay {
210e5c89e4eSSatish Balay   PetscFunctionBegin;
211*08401ef6SPierre Jolivet   PetscCheck(!petscsetmallocvisited || !(imalloc != PetscTrMalloc || ifree != PetscTrFree),PETSC_COMM_SELF,PETSC_ERR_SUP,"cannot call multiple times");
212e5c89e4eSSatish Balay   PetscTrMalloc         = imalloc;
213e5c89e4eSSatish Balay   PetscTrFree           = ifree;
21492f119d6SBarry Smith   PetscTrRealloc        = iralloc;
215e5c89e4eSSatish Balay   petscsetmallocvisited = PETSC_TRUE;
216e5c89e4eSSatish Balay   PetscFunctionReturn(0);
217e5c89e4eSSatish Balay }
218e5c89e4eSSatish Balay 
219e5c89e4eSSatish Balay /*@C
22092f119d6SBarry Smith    PetscMallocClear - Resets the routines used to do mallocs and frees to the defaults.
221e5c89e4eSSatish Balay 
222e5c89e4eSSatish Balay    Not Collective
223e5c89e4eSSatish Balay 
224e5c89e4eSSatish Balay    Level: developer
225e5c89e4eSSatish Balay 
226e5c89e4eSSatish Balay    Notes:
227e5c89e4eSSatish Balay     In general one should never run a PETSc program with different malloc() and
228e5c89e4eSSatish Balay     free() settings for different parts; this is because one NEVER wants to
229e5c89e4eSSatish Balay     free() an address that was malloced by a different memory management system
230e5c89e4eSSatish Balay 
23192f119d6SBarry Smith     Called in PetscFinalize() so that if PetscInitialize() is called again it starts with a fresh slate of allocation information
23292f119d6SBarry Smith 
233e5c89e4eSSatish Balay @*/
2347087cfbeSBarry Smith PetscErrorCode PetscMallocClear(void)
235e5c89e4eSSatish Balay {
236e5c89e4eSSatish Balay   PetscFunctionBegin;
237e5c89e4eSSatish Balay   PetscTrMalloc         = PetscMallocAlign;
238e5c89e4eSSatish Balay   PetscTrFree           = PetscFreeAlign;
23992f119d6SBarry Smith   PetscTrRealloc        = PetscReallocAlign;
240e5c89e4eSSatish Balay   petscsetmallocvisited = PETSC_FALSE;
241e5c89e4eSSatish Balay   PetscFunctionReturn(0);
242e5c89e4eSSatish Balay }
243b44d5720SBarry Smith 
244b44d5720SBarry Smith PetscErrorCode PetscMemoryTrace(const char label[])
245b44d5720SBarry Smith {
246b44d5720SBarry Smith   PetscLogDouble        mem,mal;
247b44d5720SBarry Smith   static PetscLogDouble oldmem = 0,oldmal = 0;
248b44d5720SBarry Smith 
249b44d5720SBarry Smith   PetscFunctionBegin;
2509566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetCurrentUsage(&mem));
2519566063dSJacob Faibussowitsch   PetscCall(PetscMallocGetCurrentUsage(&mal));
252b44d5720SBarry Smith 
2539566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD,"%s High water  %8.3f MB increase %8.3f MB Current %8.3f MB increase %8.3f MB\n",label,mem*1e-6,(mem - oldmem)*1e-6,mal*1e-6,(mal - oldmal)*1e-6));
254b44d5720SBarry Smith   oldmem = mem;
255b44d5720SBarry Smith   oldmal = mal;
256b44d5720SBarry Smith   PetscFunctionReturn(0);
257b44d5720SBarry Smith }
25813850c04SHong Zhang 
259071fcb05SBarry Smith static PetscErrorCode (*PetscTrMallocOld)(size_t,PetscBool,int,const char[],const char[],void**) = PetscMallocAlign;
26092f119d6SBarry Smith static PetscErrorCode (*PetscTrReallocOld)(size_t,int,const char[],const char[],void**)          = PetscReallocAlign;
26150a41461SHong Zhang static PetscErrorCode (*PetscTrFreeOld)(void*,int,const char[],const char[])                     = PetscFreeAlign;
262de1d6c17SHong Zhang 
263de1d6c17SHong Zhang /*@C
264de1d6c17SHong Zhang    PetscMallocSetDRAM - Set PetscMalloc to use DRAM.
265de1d6c17SHong Zhang      If memkind is available, change the memkind type. Otherwise, switch the
266de1d6c17SHong Zhang      current malloc and free routines to the PetscMallocAlign and
267de1d6c17SHong Zhang      PetscFreeAlign (PETSc default).
268de1d6c17SHong Zhang 
269de1d6c17SHong Zhang    Not Collective
270de1d6c17SHong Zhang 
271de1d6c17SHong Zhang    Level: developer
272de1d6c17SHong Zhang 
273de1d6c17SHong Zhang    Notes:
274de1d6c17SHong Zhang      This provides a way to do the allocation on DRAM temporarily. One
275de1d6c17SHong Zhang      can switch back to the previous choice by calling PetscMallocReset().
276de1d6c17SHong Zhang 
277de1d6c17SHong Zhang .seealso: PetscMallocReset()
278de1d6c17SHong Zhang @*/
27913850c04SHong Zhang PetscErrorCode PetscMallocSetDRAM(void)
28013850c04SHong Zhang {
28113850c04SHong Zhang   PetscFunctionBegin;
282de1d6c17SHong Zhang   if (PetscTrMalloc == PetscMallocAlign) {
283de1d6c17SHong Zhang #if defined(PETSC_HAVE_MEMKIND)
284de1d6c17SHong Zhang     previousmktype = currentmktype;
285de1d6c17SHong Zhang     currentmktype  = PETSC_MK_DEFAULT;
286de1d6c17SHong Zhang #endif
287de1d6c17SHong Zhang   } else {
28813850c04SHong Zhang     /* Save the previous choice */
28913850c04SHong Zhang     PetscTrMallocOld  = PetscTrMalloc;
29092f119d6SBarry Smith     PetscTrReallocOld = PetscTrRealloc;
29113850c04SHong Zhang     PetscTrFreeOld    = PetscTrFree;
29213850c04SHong Zhang     PetscTrMalloc     = PetscMallocAlign;
29313850c04SHong Zhang     PetscTrFree       = PetscFreeAlign;
29492f119d6SBarry Smith     PetscTrRealloc    = PetscReallocAlign;
295de1d6c17SHong Zhang   }
29613850c04SHong Zhang   PetscFunctionReturn(0);
29713850c04SHong Zhang }
29813850c04SHong Zhang 
299de1d6c17SHong Zhang /*@C
300de1d6c17SHong Zhang    PetscMallocResetDRAM - Reset the changes made by PetscMallocSetDRAM
301de1d6c17SHong Zhang 
302de1d6c17SHong Zhang    Not Collective
303de1d6c17SHong Zhang 
304de1d6c17SHong Zhang    Level: developer
305de1d6c17SHong Zhang 
306de1d6c17SHong Zhang .seealso: PetscMallocSetDRAM()
307de1d6c17SHong Zhang @*/
30813850c04SHong Zhang PetscErrorCode PetscMallocResetDRAM(void)
30913850c04SHong Zhang {
31013850c04SHong Zhang   PetscFunctionBegin;
311de1d6c17SHong Zhang   if (PetscTrMalloc == PetscMallocAlign) {
312de1d6c17SHong Zhang #if defined(PETSC_HAVE_MEMKIND)
313de1d6c17SHong Zhang     currentmktype = previousmktype;
314de1d6c17SHong Zhang #endif
315de1d6c17SHong Zhang   } else {
31613850c04SHong Zhang     /* Reset to the previous choice */
31713850c04SHong Zhang     PetscTrMalloc  = PetscTrMallocOld;
31892f119d6SBarry Smith     PetscTrRealloc = PetscTrReallocOld;
31913850c04SHong Zhang     PetscTrFree    = PetscTrFreeOld;
320de1d6c17SHong Zhang   }
32113850c04SHong Zhang   PetscFunctionReturn(0);
32213850c04SHong Zhang }
323ba282f50SJed Brown 
324ba282f50SJed Brown static PetscBool petscmalloccoalesce =
325ba282f50SJed Brown #if defined(PETSC_USE_MALLOC_COALESCED)
326ba282f50SJed Brown   PETSC_TRUE;
327ba282f50SJed Brown #else
328ba282f50SJed Brown   PETSC_FALSE;
329ba282f50SJed Brown #endif
330ba282f50SJed Brown 
331ba282f50SJed Brown /*@C
332ba282f50SJed Brown    PetscMallocSetCoalesce - Use coalesced malloc when allocating groups of objects
333ba282f50SJed Brown 
334ba282f50SJed Brown    Not Collective
335ba282f50SJed Brown 
336ba282f50SJed Brown    Input Parameters:
337ba282f50SJed Brown .  coalesce - PETSC_TRUE to use coalesced malloc for multi-object allocation.
338ba282f50SJed Brown 
339ba282f50SJed Brown    Options Database Keys:
340ba282f50SJed Brown .  -malloc_coalesce - turn coalesced malloc on or off
341ba282f50SJed Brown 
342ba282f50SJed Brown    Note:
343ba282f50SJed Brown    PETSc uses coalesced malloc by default for optimized builds and not for debugging builds.  This default can be changed via the command-line option -malloc_coalesce or by calling this function.
34492f119d6SBarry Smith    This function can only be called immediately after PetscInitialize()
345ba282f50SJed Brown 
346ba282f50SJed Brown    Level: developer
347ba282f50SJed Brown 
348ba282f50SJed Brown .seealso: PetscMallocA()
349ba282f50SJed Brown @*/
350ba282f50SJed Brown PetscErrorCode PetscMallocSetCoalesce(PetscBool coalesce)
351ba282f50SJed Brown {
352ba282f50SJed Brown   PetscFunctionBegin;
353ba282f50SJed Brown   petscmalloccoalesce = coalesce;
354ba282f50SJed Brown   PetscFunctionReturn(0);
355ba282f50SJed Brown }
356ba282f50SJed Brown 
357ba282f50SJed Brown /*@C
358ba282f50SJed Brown    PetscMallocA - Allocate and optionally clear one or more objects, possibly using coalesced malloc
359ba282f50SJed Brown 
360ba282f50SJed Brown    Not Collective
361ba282f50SJed Brown 
362ba282f50SJed Brown    Input Parameters:
363ba282f50SJed Brown +  n - number of objects to allocate (at least 1)
36489407d75SBarry Smith .  clear - use calloc() to allocate space initialized to zero
365ba282f50SJed Brown .  lineno - line number to attribute allocation (typically __LINE__)
366ba282f50SJed Brown .  function - function to attribute allocation (typically PETSC_FUNCTION_NAME)
367ba282f50SJed Brown .  filename - file name to attribute allocation (typically __FILE__)
368ba282f50SJed Brown -  bytes0 - first of n object sizes
369ba282f50SJed Brown 
370ba282f50SJed Brown    Output Parameters:
371ba282f50SJed Brown .  ptr0 - first of n pointers to allocate
372ba282f50SJed Brown 
373ba282f50SJed Brown    Notes:
374ba282f50SJed Brown    This function is not normally called directly by users, but rather via the macros PetscMalloc1(), PetscMalloc2(), or PetscCalloc1(), etc.
375ba282f50SJed Brown 
376ba282f50SJed Brown    Level: developer
377ba282f50SJed Brown 
378ba282f50SJed Brown .seealso: PetscMallocAlign(), PetscMallocSet(), PetscMalloc1(), PetscMalloc2(), PetscMalloc3(), PetscMalloc4(), PetscMalloc5(), PetscMalloc6(), PetscMalloc7(), PetscCalloc1(), PetscCalloc2(), PetscCalloc3(), PetscCalloc4(), PetscCalloc5(), PetscCalloc6(), PetscCalloc7(), PetscFreeA()
379ba282f50SJed Brown @*/
380ba282f50SJed Brown PetscErrorCode PetscMallocA(int n,PetscBool clear,int lineno,const char *function,const char *filename,size_t bytes0,void *ptr0,...)
381ba282f50SJed Brown {
382ba282f50SJed Brown   va_list        Argp;
383ba282f50SJed Brown   size_t         bytes[8],sumbytes;
384ba282f50SJed Brown   void           **ptr[8];
385ba282f50SJed Brown   int            i;
386ba282f50SJed Brown 
387ba282f50SJed Brown   PetscFunctionBegin;
3887f18b027SJacob Faibussowitsch   PetscCheck(n <= 8,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Attempt to allocate %d objects but only 8 supported",n);
389ba282f50SJed Brown   bytes[0] = bytes0;
390ba282f50SJed Brown   ptr[0] = (void**)ptr0;
391ba282f50SJed Brown   sumbytes = (bytes0 + PETSC_MEMALIGN-1) & ~(PETSC_MEMALIGN-1);
392ba282f50SJed Brown   va_start(Argp,ptr0);
393ba282f50SJed Brown   for (i=1; i<n; i++) {
394ba282f50SJed Brown     bytes[i] = va_arg(Argp,size_t);
395ba282f50SJed Brown     ptr[i] = va_arg(Argp,void**);
396ba282f50SJed Brown     sumbytes += (bytes[i] + PETSC_MEMALIGN-1) & ~(PETSC_MEMALIGN-1);
397ba282f50SJed Brown   }
398ba282f50SJed Brown   va_end(Argp);
399ba282f50SJed Brown   if (petscmalloccoalesce) {
400ba282f50SJed Brown     char *p;
4019566063dSJacob Faibussowitsch     PetscCall((*PetscTrMalloc)(sumbytes,clear,lineno,function,filename,(void**)&p));
402ba282f50SJed Brown     for (i=0; i<n; i++) {
403ba282f50SJed Brown       *ptr[i] = bytes[i] ? p : NULL;
404ba282f50SJed Brown       p = (char*)PetscAddrAlign(p + bytes[i]);
405ba282f50SJed Brown     }
406ba282f50SJed Brown   } else {
407ba282f50SJed Brown     for (i=0; i<n; i++) {
4089566063dSJacob Faibussowitsch       PetscCall((*PetscTrMalloc)(bytes[i],clear,lineno,function,filename,(void**)ptr[i]));
409ba282f50SJed Brown     }
410ba282f50SJed Brown   }
411ba282f50SJed Brown   PetscFunctionReturn(0);
412ba282f50SJed Brown }
413ba282f50SJed Brown 
414ba282f50SJed Brown /*@C
415ba282f50SJed Brown    PetscFreeA - Free one or more objects, possibly allocated using coalesced malloc
416ba282f50SJed Brown 
417ba282f50SJed Brown    Not Collective
418ba282f50SJed Brown 
419ba282f50SJed Brown    Input Parameters:
420ba282f50SJed Brown +  n - number of objects to free (at least 1)
421ba282f50SJed Brown .  lineno - line number to attribute deallocation (typically __LINE__)
422ba282f50SJed Brown .  function - function to attribute deallocation (typically PETSC_FUNCTION_NAME)
423ba282f50SJed Brown .  filename - file name to attribute deallocation (typically __FILE__)
424ba282f50SJed Brown -  ptr0 ... - first of n pointers to free
425ba282f50SJed Brown 
426ba282f50SJed Brown    Note:
427071fcb05SBarry Smith    This function is not normally called directly by users, but rather via the macros PetscFree(), PetscFree2(), etc.
428ba282f50SJed Brown 
429a5b23f4aSJose E. Roman    The pointers are zeroed to prevent users from accidentally reusing space that has been freed.
43089407d75SBarry Smith 
431ba282f50SJed Brown    Level: developer
432ba282f50SJed Brown 
433ba282f50SJed Brown .seealso: PetscMallocAlign(), PetscMallocSet(), PetscMallocA(), PetscFree1(), PetscFree2(), PetscFree3(), PetscFree4(), PetscFree5(), PetscFree6(), PetscFree7()
434ba282f50SJed Brown @*/
435ba282f50SJed Brown PetscErrorCode PetscFreeA(int n,int lineno,const char *function,const char *filename,void *ptr0,...)
436ba282f50SJed Brown {
437ba282f50SJed Brown   va_list   Argp;
438ba282f50SJed Brown   void    **ptr[8];
439ba282f50SJed Brown   int       i;
440ba282f50SJed Brown 
441ba282f50SJed Brown   PetscFunctionBegin;
4427f18b027SJacob Faibussowitsch   PetscCheck(n <= 8,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Attempt to allocate %d objects but only up to 8 supported",n);
443ba282f50SJed Brown   ptr[0] = (void**)ptr0;
444ba282f50SJed Brown   va_start(Argp,ptr0);
445ba282f50SJed Brown   for (i=1; i<n; i++) {
446ba282f50SJed Brown     ptr[i] = va_arg(Argp,void**);
447ba282f50SJed Brown   }
448ba282f50SJed Brown   va_end(Argp);
449ba282f50SJed Brown   if (petscmalloccoalesce) {
450ba282f50SJed Brown     for (i=0; i<n; i++) {       /* Find first nonempty allocation */
451ba282f50SJed Brown       if (*ptr[i]) break;
452ba282f50SJed Brown     }
453ba282f50SJed Brown     while (--n > i) {
454ba282f50SJed Brown       *ptr[n] = NULL;
455ba282f50SJed Brown     }
4569566063dSJacob Faibussowitsch     PetscCall((*PetscTrFree)(*ptr[n],lineno,function,filename));
457ba282f50SJed Brown     *ptr[n] = NULL;
458ba282f50SJed Brown   } else {
459ba282f50SJed Brown     while (--n >= 0) {
4609566063dSJacob Faibussowitsch       PetscCall((*PetscTrFree)(*ptr[n],lineno,function,filename));
461ba282f50SJed Brown       *ptr[n] = NULL;
462ba282f50SJed Brown     }
463ba282f50SJed Brown   }
464ba282f50SJed Brown   PetscFunctionReturn(0);
465ba282f50SJed Brown }
466