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