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 defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8) 25 *result = malloc(mem); 26 #elif defined(PETSC_HAVE_MEMALIGN) 27 *result = memalign(PETSC_MEMALIGN,mem); 28 #else 29 { 30 int *ptr,shift; 31 /* 32 malloc space for two extra chunks and shift ptr 1 + enough to get it PetscScalar aligned 33 */ 34 ptr = (int*)malloc(mem + 2*PETSC_MEMALIGN); 35 if (ptr) { 36 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 = 0; 43 } 44 } 45 #endif 46 if (!*result) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_MEM,"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 (!(defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !defined(PETSC_HAVE_MEMALIGN)) 55 int shift; 56 57 if (!ptr) PetscFunctionReturn(0); 58 /* 59 Previous int tells us how many ints the pointer has been shifted from 60 the original address provided by the system malloc(). 61 */ 62 shift = *(((int*)ptr)-1) - SHIFT_CLASSID; 63 if (shift > PETSC_MEMALIGN-1) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap"); 64 if (shift < 0) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap"); 65 ptr = (void*)(((int*)ptr) - shift); 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 /* 78 We never use the system free directly because on many machines it 79 does not return an error code. 80 */ 81 #undef __FUNCT__ 82 #define __FUNCT__ "PetscFreeDefault" 83 PetscErrorCode PetscFreeDefault(void *ptr,int line,char *func,char *file) 84 { 85 #if defined(PETSC_HAVE_FREE_RETURN_INT) 86 int err = free(ptr); 87 if (err) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"System free returned error %d\n",err); 88 #else 89 free(ptr); 90 #endif 91 return 0; 92 } 93 94 PetscErrorCode (*PetscTrMalloc)(size_t,int,const char[],const char[],void**) = PetscMallocAlign; 95 PetscErrorCode (*PetscTrFree)(void*,int,const char[],const char[]) = PetscFreeAlign; 96 97 PetscBool petscsetmallocvisited = PETSC_FALSE; 98 99 #undef __FUNCT__ 100 #define __FUNCT__ "PetscMallocSet" 101 /*@C 102 PetscMallocSet - Sets the routines used to do mallocs and frees. 103 This routine MUST be called before PetscInitialize() and may be 104 called only once. 105 106 Not Collective 107 108 Input Parameters: 109 + malloc - the malloc routine 110 - free - the free routine 111 112 Level: developer 113 114 Concepts: malloc 115 Concepts: memory^allocation 116 117 @*/ 118 PetscErrorCode PetscMallocSet(PetscErrorCode (*imalloc)(size_t,int,const char[],const char[],void**), 119 PetscErrorCode (*ifree)(void*,int,const char[],const char[])) 120 { 121 PetscFunctionBegin; 122 if (petscsetmallocvisited && (imalloc != PetscTrMalloc || ifree != PetscTrFree)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"cannot call multiple times"); 123 PetscTrMalloc = imalloc; 124 PetscTrFree = ifree; 125 petscsetmallocvisited = PETSC_TRUE; 126 PetscFunctionReturn(0); 127 } 128 129 #undef __FUNCT__ 130 #define __FUNCT__ "PetscMallocClear" 131 /*@C 132 PetscMallocClear - Resets the routines used to do mallocs and frees to the 133 defaults. 134 135 Not Collective 136 137 Level: developer 138 139 Notes: 140 In general one should never run a PETSc program with different malloc() and 141 free() settings for different parts; this is because one NEVER wants to 142 free() an address that was malloced by a different memory management system 143 144 @*/ 145 PetscErrorCode PetscMallocClear(void) 146 { 147 PetscFunctionBegin; 148 PetscTrMalloc = PetscMallocAlign; 149 PetscTrFree = PetscFreeAlign; 150 petscsetmallocvisited = PETSC_FALSE; 151 PetscFunctionReturn(0); 152 } 153 154 #undef __FUNCT__ 155 #define __FUNCT__ "PetscMemoryTrace" 156 PetscErrorCode PetscMemoryTrace(const char label[]) 157 { 158 PetscErrorCode ierr; 159 PetscLogDouble mem,mal; 160 static PetscLogDouble oldmem = 0,oldmal = 0; 161 162 PetscFunctionBegin; 163 ierr = PetscMemoryGetCurrentUsage(&mem);CHKERRQ(ierr); 164 ierr = PetscMallocGetCurrentUsage(&mal);CHKERRQ(ierr); 165 166 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); 167 oldmem = mem; 168 oldmal = mal; 169 PetscFunctionReturn(0); 170 } 171