Actual source code: mal.c

petsc-3.3-p7 2013-05-11
  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_STDLIB_H)
  7: #include <stdlib.h>
  8: #endif
  9: #if defined(PETSC_HAVE_MALLOC_H)
 10: #include <malloc.h>
 11: #endif

 13: /*
 14:         We want to make sure that all mallocs of double or complex numbers are complex aligned.
 15:     1) on systems with memalign() we call that routine to get an aligned memory location
 16:     2) on systems without memalign() we 
 17:        - allocate one sizeof(PetscScalar) extra space
 18:        - we shift the pointer up slightly if needed to get PetscScalar aligned
 19:        - if shifted we store at ptr[-1] the amount of shift (plus a classid)
 20: */
 21: #define SHIFT_CLASSID 456123

 25: PetscErrorCode  PetscMallocAlign(size_t mem,int line,const char func[],const char file[],const char dir[],void** result)
 26: {
 27: #if defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)
 28:   *result = malloc(mem);
 29: #elif defined(PETSC_HAVE_MEMALIGN)
 30:   *result = memalign(PETSC_MEMALIGN,mem);
 31: #else
 32:   {
 33:     int *ptr,shift;
 34:     /*
 35:       malloc space for two extra chunks and shift ptr 1 + enough to get it PetscScalar aligned
 36:     */
 37:     ptr = (int*)malloc(mem + 2*PETSC_MEMALIGN);
 38:     if (ptr) {
 39:       shift        = (int)(((PETSC_UINTPTR_T) ptr) % PETSC_MEMALIGN);
 40:       shift        = (2*PETSC_MEMALIGN - shift)/sizeof(int);
 41:       ptr[shift-1] = shift + SHIFT_CLASSID ;
 42:       ptr         += shift;
 43:       *result      = (void*)ptr;
 44:     } else {
 45:       *result      = 0;
 46:     }
 47:   }
 48: #endif
 49:   if (!*result)  SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_MEM,"Memory requested %.0f",(PetscLogDouble)mem);
 50:   return 0;
 51: }

 55: PetscErrorCode  PetscFreeAlign(void *ptr,int line,const char func[],const char file[],const char dir[])
 56: {
 57: #if (!(defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !defined(PETSC_HAVE_MEMALIGN))
 58:   int shift;
 59:   /*
 60:        Previous int tells us how many ints the pointer has been shifted from
 61:     the original address provided by the system malloc().
 62:   */
 63:   shift = *(((int*)ptr)-1) - SHIFT_CLASSID;
 64:   if (shift > PETSC_MEMALIGN-1) return PetscError(PETSC_COMM_SELF,line,func,file,dir,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap");
 65:   if (shift < 0) return PetscError(PETSC_COMM_SELF,line,func,file,dir,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap");
 66:   ptr   = (void*)(((int*)ptr) - shift);
 67: #endif

 69: #if defined(PETSC_HAVE_FREE_RETURN_INT)
 70:   int err = free(ptr);
 71:   if (err) {
 72:     return PetscError(PETSC_COMM_SELF,line,func,file,dir,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"System free returned error %d\n",err);
 73:   }
 74: #else 
 75:   free(ptr);
 76: #endif
 77:   return 0;
 78: }

 80: /*
 81:         We never use the system free directly because on many machines it 
 82:     does not return an error code.
 83: */
 86: PetscErrorCode  PetscFreeDefault(void *ptr,int line,char *func,char *file,char *dir)
 87: {
 88: #if defined(PETSC_HAVE_FREE_RETURN_INT)
 89:   int err = free(ptr);
 90:   if (err) {
 91:     return PetscError(PETSC_COMM_SELF,line,func,file,dir,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"System free returned error %d\n",err);
 92:   }
 93: #else 
 94:   free(ptr);
 95: #endif
 96:   return 0;
 97: }

 99: PetscErrorCode   (*PetscTrMalloc)(size_t,int,const char[],const char[],const char[],void**) = PetscMallocAlign;
100: PetscErrorCode   (*PetscTrFree)(void*,int,const char[],const char[],const char[])          = PetscFreeAlign;

102: PetscBool  petscsetmallocvisited = PETSC_FALSE;

106: /*@C
107:    PetscMallocSet - Sets the routines used to do mallocs and frees.
108:    This routine MUST be called before PetscInitialize() and may be
109:    called only once.

111:    Not Collective

113:    Input Parameters:
114: +  malloc - the malloc routine
115: -  free - the free routine

117:    Level: developer

119:    Concepts: malloc
120:    Concepts: memory^allocation 

122: @*/
123: PetscErrorCode  PetscMallocSet(PetscErrorCode (*imalloc)(size_t,int,const char[],const char[],const char[],void**),
124:                                               PetscErrorCode (*ifree)(void*,int,const char[],const char[],const char[]))
125: {
127:   if (petscsetmallocvisited && (imalloc != PetscTrMalloc || ifree != PetscTrFree)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"cannot call multiple times");
128:   PetscTrMalloc               = imalloc;
129:   PetscTrFree                 = ifree;
130:   petscsetmallocvisited       = PETSC_TRUE;
131:   return(0);
132: }

136: /*@C
137:    PetscMallocClear - Resets the routines used to do mallocs and frees to the 
138:         defaults.

140:    Not Collective

142:    Level: developer

144:    Notes:
145:     In general one should never run a PETSc program with different malloc() and 
146:     free() settings for different parts; this is because one NEVER wants to 
147:     free() an address that was malloced by a different memory management system

149: @*/
150: PetscErrorCode  PetscMallocClear(void)
151: {
153:   PetscTrMalloc         = PetscMallocAlign;
154:   PetscTrFree           = PetscFreeAlign;
155:   petscsetmallocvisited = PETSC_FALSE;
156:   return(0);
157: }