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