17d0a6c19SBarry Smith 2e5c89e4eSSatish Balay /* 3e5c89e4eSSatish Balay Code that allows a user to dictate what malloc() PETSc uses. 4e5c89e4eSSatish Balay */ 5c6db04a5SJed Brown #include <petscsys.h> /*I "petscsys.h" I*/ 6e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H) 7e5c89e4eSSatish Balay #include <malloc.h> 8e5c89e4eSSatish Balay #endif 9e5c89e4eSSatish Balay 10e5c89e4eSSatish Balay /* 11e5c89e4eSSatish Balay We want to make sure that all mallocs of double or complex numbers are complex aligned. 12e5c89e4eSSatish Balay 1) on systems with memalign() we call that routine to get an aligned memory location 13e5c89e4eSSatish Balay 2) on systems without memalign() we 14e5c89e4eSSatish Balay - allocate one sizeof(PetscScalar) extra space 15e5c89e4eSSatish Balay - we shift the pointer up slightly if needed to get PetscScalar aligned 160700a824SBarry Smith - if shifted we store at ptr[-1] the amount of shift (plus a classid) 17e5c89e4eSSatish Balay */ 180700a824SBarry Smith #define SHIFT_CLASSID 456123 19e5c89e4eSSatish Balay 20e5c89e4eSSatish Balay #undef __FUNCT__ 21e5c89e4eSSatish Balay #define __FUNCT__ "PetscMallocAlign" 22efca3c55SSatish Balay PetscErrorCode PetscMallocAlign(size_t mem,int line,const char func[],const char file[],void **result) 23e5c89e4eSSatish Balay { 24f0ba7cfcSLisandro Dalcin if (!mem) { *result = NULL; return 0; } 25e5c89e4eSSatish Balay #if defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8) 26e5c89e4eSSatish Balay *result = malloc(mem); 27e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_MEMALIGN) 28e5c89e4eSSatish Balay *result = memalign(PETSC_MEMALIGN,mem); 29e5c89e4eSSatish Balay #else 30e5c89e4eSSatish Balay { 31e5c89e4eSSatish Balay /* 32e5c89e4eSSatish Balay malloc space for two extra chunks and shift ptr 1 + enough to get it PetscScalar aligned 33e5c89e4eSSatish Balay */ 34f0ba7cfcSLisandro Dalcin int *ptr = (int*)malloc(mem + 2*PETSC_MEMALIGN); 35e5c89e4eSSatish Balay if (ptr) { 36f0ba7cfcSLisandro Dalcin int shift = (int)(((PETSC_UINTPTR_T) ptr) % PETSC_MEMALIGN); 37e5c89e4eSSatish Balay shift = (2*PETSC_MEMALIGN - shift)/sizeof(int); 380700a824SBarry Smith ptr[shift-1] = shift + SHIFT_CLASSID; 39e5c89e4eSSatish Balay ptr += shift; 40e5c89e4eSSatish Balay *result = (void*)ptr; 41e5c89e4eSSatish Balay } else { 42f0ba7cfcSLisandro Dalcin *result = NULL; 43e5c89e4eSSatish Balay } 44e5c89e4eSSatish Balay } 45e5c89e4eSSatish Balay #endif 46f0ba7cfcSLisandro Dalcin if (!*result) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_MEM,PETSC_ERROR_INITIAL,"Memory requested %.0f",(PetscLogDouble)mem); 47e5c89e4eSSatish Balay return 0; 48e5c89e4eSSatish Balay } 49e5c89e4eSSatish Balay 50e5c89e4eSSatish Balay #undef __FUNCT__ 51e5c89e4eSSatish Balay #define __FUNCT__ "PetscFreeAlign" 52efca3c55SSatish Balay PetscErrorCode PetscFreeAlign(void *ptr,int line,const char func[],const char file[]) 53e5c89e4eSSatish Balay { 54f0ba7cfcSLisandro Dalcin if (!ptr) return 0; 55e5c89e4eSSatish Balay #if (!(defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !defined(PETSC_HAVE_MEMALIGN)) 56f0ba7cfcSLisandro Dalcin { 57e5c89e4eSSatish Balay /* 58e5c89e4eSSatish Balay Previous int tells us how many ints the pointer has been shifted from 59e5c89e4eSSatish Balay the original address provided by the system malloc(). 60e5c89e4eSSatish Balay */ 61f0ba7cfcSLisandro Dalcin int shift = *(((int*)ptr)-1) - SHIFT_CLASSID; 62efca3c55SSatish Balay if (shift > PETSC_MEMALIGN-1) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap"); 63efca3c55SSatish Balay if (shift < 0) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap"); 64e5c89e4eSSatish Balay ptr = (void*)(((int*)ptr) - shift); 65e5c89e4eSSatish Balay } 66f0ba7cfcSLisandro Dalcin #endif 67e5c89e4eSSatish Balay 68e5c89e4eSSatish Balay #if defined(PETSC_HAVE_FREE_RETURN_INT) 69e5c89e4eSSatish Balay int err = free(ptr); 70efca3c55SSatish Balay if (err) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"System free returned error %d\n",err); 71e5c89e4eSSatish Balay #else 72e5c89e4eSSatish Balay free(ptr); 73e5c89e4eSSatish Balay #endif 74e5c89e4eSSatish Balay return 0; 75e5c89e4eSSatish Balay } 76e5c89e4eSSatish Balay 77*3221ece2SMatthew G. Knepley #undef __FUNCT__ 78*3221ece2SMatthew G. Knepley #define __FUNCT__ "PetscReallocAlign" 79*3221ece2SMatthew G. Knepley PetscErrorCode PetscReallocAlign(size_t mem, int line, const char func[], const char file[], void **result) 80*3221ece2SMatthew G. Knepley { 81*3221ece2SMatthew G. Knepley if (!mem) {*result = NULL; return 0;} 82*3221ece2SMatthew G. Knepley #if (!(defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !defined(PETSC_HAVE_MEMALIGN)) 83*3221ece2SMatthew G. Knepley { 84*3221ece2SMatthew G. Knepley /* 85*3221ece2SMatthew G. Knepley Previous int tells us how many ints the pointer has been shifted from 86*3221ece2SMatthew G. Knepley the original address provided by the system malloc(). 87*3221ece2SMatthew G. Knepley */ 88*3221ece2SMatthew G. Knepley int shift = *(((int*)*result)-1) - SHIFT_CLASSID; 89*3221ece2SMatthew G. Knepley if (shift > PETSC_MEMALIGN-1) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap"); 90*3221ece2SMatthew G. Knepley if (shift < 0) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap"); 91*3221ece2SMatthew G. Knepley *result = (void*)(((int*)*result) - shift); 92*3221ece2SMatthew G. Knepley } 93*3221ece2SMatthew G. Knepley #endif 94*3221ece2SMatthew G. Knepley 95*3221ece2SMatthew G. Knepley #if defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8) 96*3221ece2SMatthew G. Knepley *result = realloc(*result, mem); 97*3221ece2SMatthew G. Knepley #else 98*3221ece2SMatthew G. Knepley { 99*3221ece2SMatthew G. Knepley /* 100*3221ece2SMatthew G. Knepley malloc space for two extra chunks and shift ptr 1 + enough to get it PetscScalar aligned 101*3221ece2SMatthew G. Knepley */ 102*3221ece2SMatthew G. Knepley int *ptr = (int *) realloc(*result, mem + 2*PETSC_MEMALIGN); 103*3221ece2SMatthew G. Knepley if (ptr) { 104*3221ece2SMatthew G. Knepley int shift = (int)(((PETSC_UINTPTR_T) ptr) % PETSC_MEMALIGN); 105*3221ece2SMatthew G. Knepley shift = (2*PETSC_MEMALIGN - shift)/sizeof(int); 106*3221ece2SMatthew G. Knepley ptr[shift-1] = shift + SHIFT_CLASSID; 107*3221ece2SMatthew G. Knepley ptr += shift; 108*3221ece2SMatthew G. Knepley *result = (void*)ptr; 109*3221ece2SMatthew G. Knepley } else { 110*3221ece2SMatthew G. Knepley *result = NULL; 111*3221ece2SMatthew G. Knepley } 112*3221ece2SMatthew G. Knepley } 113*3221ece2SMatthew G. Knepley #endif 114*3221ece2SMatthew G. Knepley if (!*result) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_MEM,PETSC_ERROR_INITIAL,"Memory requested %.0f",(PetscLogDouble)mem); 115*3221ece2SMatthew G. Knepley return 0; 116*3221ece2SMatthew G. Knepley } 117*3221ece2SMatthew G. Knepley 118efca3c55SSatish Balay PetscErrorCode (*PetscTrMalloc)(size_t,int,const char[],const char[],void**) = PetscMallocAlign; 119efca3c55SSatish Balay PetscErrorCode (*PetscTrFree)(void*,int,const char[],const char[]) = PetscFreeAlign; 120*3221ece2SMatthew G. Knepley PetscErrorCode (*PetscTrRealloc)(size_t,int,const char[],const char[],void**) = PetscReallocAlign; 121e5c89e4eSSatish Balay 122ace3abfcSBarry Smith PetscBool petscsetmallocvisited = PETSC_FALSE; 123e5c89e4eSSatish Balay 124e5c89e4eSSatish Balay #undef __FUNCT__ 1251d1a0024SBarry Smith #define __FUNCT__ "PetscMallocSet" 126e5c89e4eSSatish Balay /*@C 1271d1a0024SBarry Smith PetscMallocSet - Sets the routines used to do mallocs and frees. 128e5c89e4eSSatish Balay This routine MUST be called before PetscInitialize() and may be 129e5c89e4eSSatish Balay called only once. 130e5c89e4eSSatish Balay 131e5c89e4eSSatish Balay Not Collective 132e5c89e4eSSatish Balay 133e5c89e4eSSatish Balay Input Parameters: 134e5c89e4eSSatish Balay + malloc - the malloc routine 135e5c89e4eSSatish Balay - free - the free routine 136e5c89e4eSSatish Balay 137e5c89e4eSSatish Balay Level: developer 138e5c89e4eSSatish Balay 139e5c89e4eSSatish Balay Concepts: malloc 140e5c89e4eSSatish Balay Concepts: memory^allocation 141e5c89e4eSSatish Balay 142e5c89e4eSSatish Balay @*/ 143efca3c55SSatish Balay PetscErrorCode PetscMallocSet(PetscErrorCode (*imalloc)(size_t,int,const char[],const char[],void**), 144efca3c55SSatish Balay PetscErrorCode (*ifree)(void*,int,const char[],const char[])) 145e5c89e4eSSatish Balay { 146e5c89e4eSSatish Balay PetscFunctionBegin; 147e32f2f54SBarry Smith if (petscsetmallocvisited && (imalloc != PetscTrMalloc || ifree != PetscTrFree)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"cannot call multiple times"); 148e5c89e4eSSatish Balay PetscTrMalloc = imalloc; 149e5c89e4eSSatish Balay PetscTrFree = ifree; 150e5c89e4eSSatish Balay petscsetmallocvisited = PETSC_TRUE; 151e5c89e4eSSatish Balay PetscFunctionReturn(0); 152e5c89e4eSSatish Balay } 153e5c89e4eSSatish Balay 154e5c89e4eSSatish Balay #undef __FUNCT__ 1551d1a0024SBarry Smith #define __FUNCT__ "PetscMallocClear" 156e5c89e4eSSatish Balay /*@C 1571d1a0024SBarry Smith PetscMallocClear - Resets the routines used to do mallocs and frees to the 158e5c89e4eSSatish Balay defaults. 159e5c89e4eSSatish Balay 160e5c89e4eSSatish Balay Not Collective 161e5c89e4eSSatish Balay 162e5c89e4eSSatish Balay Level: developer 163e5c89e4eSSatish Balay 164e5c89e4eSSatish Balay Notes: 165e5c89e4eSSatish Balay In general one should never run a PETSc program with different malloc() and 166e5c89e4eSSatish Balay free() settings for different parts; this is because one NEVER wants to 167e5c89e4eSSatish Balay free() an address that was malloced by a different memory management system 168e5c89e4eSSatish Balay 169e5c89e4eSSatish Balay @*/ 1707087cfbeSBarry Smith PetscErrorCode PetscMallocClear(void) 171e5c89e4eSSatish Balay { 172e5c89e4eSSatish Balay PetscFunctionBegin; 173e5c89e4eSSatish Balay PetscTrMalloc = PetscMallocAlign; 174e5c89e4eSSatish Balay PetscTrFree = PetscFreeAlign; 175e5c89e4eSSatish Balay petscsetmallocvisited = PETSC_FALSE; 176e5c89e4eSSatish Balay PetscFunctionReturn(0); 177e5c89e4eSSatish Balay } 178b44d5720SBarry Smith 179b44d5720SBarry Smith #undef __FUNCT__ 180b44d5720SBarry Smith #define __FUNCT__ "PetscMemoryTrace" 181b44d5720SBarry Smith PetscErrorCode PetscMemoryTrace(const char label[]) 182b44d5720SBarry Smith { 183b44d5720SBarry Smith PetscErrorCode ierr; 184b44d5720SBarry Smith PetscLogDouble mem,mal; 185b44d5720SBarry Smith static PetscLogDouble oldmem = 0,oldmal = 0; 186b44d5720SBarry Smith 187b44d5720SBarry Smith PetscFunctionBegin; 188b44d5720SBarry Smith ierr = PetscMemoryGetCurrentUsage(&mem);CHKERRQ(ierr); 189b44d5720SBarry Smith ierr = PetscMallocGetCurrentUsage(&mal);CHKERRQ(ierr); 190b44d5720SBarry Smith 191b44d5720SBarry Smith ierr = 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);CHKERRQ(ierr); 192b44d5720SBarry Smith oldmem = mem; 193b44d5720SBarry Smith oldmal = mal; 194b44d5720SBarry Smith PetscFunctionReturn(0); 195b44d5720SBarry Smith } 196