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