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