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