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