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