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 Previous int tells us how many ints the pointer has been shifted from 58 the original address provided by the system malloc(). 59 */ 60 shift = *(((int*)ptr)-1) - SHIFT_CLASSID; 61 if (shift > PETSC_MEMALIGN-1) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap"); 62 if (shift < 0) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap"); 63 ptr = (void*)(((int*)ptr) - shift); 64 #endif 65 66 #if defined(PETSC_HAVE_FREE_RETURN_INT) 67 int err = free(ptr); 68 if (err) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"System free returned error %d\n",err); 69 #else 70 free(ptr); 71 #endif 72 return 0; 73 } 74 75 /* 76 We never use the system free directly because on many machines it 77 does not return an error code. 78 */ 79 #undef __FUNCT__ 80 #define __FUNCT__ "PetscFreeDefault" 81 PetscErrorCode PetscFreeDefault(void *ptr,int line,char *func,char *file) 82 { 83 #if defined(PETSC_HAVE_FREE_RETURN_INT) 84 int err = free(ptr); 85 if (err) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"System free returned error %d\n",err); 86 #else 87 free(ptr); 88 #endif 89 return 0; 90 } 91 92 PetscErrorCode (*PetscTrMalloc)(size_t,int,const char[],const char[],void**) = PetscMallocAlign; 93 PetscErrorCode (*PetscTrFree)(void*,int,const char[],const char[]) = PetscFreeAlign; 94 95 PetscBool petscsetmallocvisited = PETSC_FALSE; 96 97 #undef __FUNCT__ 98 #define __FUNCT__ "PetscMallocSet" 99 /*@C 100 PetscMallocSet - Sets the routines used to do mallocs and frees. 101 This routine MUST be called before PetscInitialize() and may be 102 called only once. 103 104 Not Collective 105 106 Input Parameters: 107 + malloc - the malloc routine 108 - free - the free routine 109 110 Level: developer 111 112 Concepts: malloc 113 Concepts: memory^allocation 114 115 @*/ 116 PetscErrorCode PetscMallocSet(PetscErrorCode (*imalloc)(size_t,int,const char[],const char[],void**), 117 PetscErrorCode (*ifree)(void*,int,const char[],const char[])) 118 { 119 PetscFunctionBegin; 120 if (petscsetmallocvisited && (imalloc != PetscTrMalloc || ifree != PetscTrFree)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"cannot call multiple times"); 121 PetscTrMalloc = imalloc; 122 PetscTrFree = ifree; 123 petscsetmallocvisited = PETSC_TRUE; 124 PetscFunctionReturn(0); 125 } 126 127 #undef __FUNCT__ 128 #define __FUNCT__ "PetscMallocClear" 129 /*@C 130 PetscMallocClear - Resets the routines used to do mallocs and frees to the 131 defaults. 132 133 Not Collective 134 135 Level: developer 136 137 Notes: 138 In general one should never run a PETSc program with different malloc() and 139 free() settings for different parts; this is because one NEVER wants to 140 free() an address that was malloced by a different memory management system 141 142 @*/ 143 PetscErrorCode PetscMallocClear(void) 144 { 145 PetscFunctionBegin; 146 PetscTrMalloc = PetscMallocAlign; 147 PetscTrFree = PetscFreeAlign; 148 petscsetmallocvisited = PETSC_FALSE; 149 PetscFunctionReturn(0); 150 } 151