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