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