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