Actual source code: mal.c

petsc-3.5.2 2014-09-08
Report Typos and Errors
  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

 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

 22: PetscErrorCode  PetscMallocAlign(size_t mem,int line,const char func[],const char file[],void **result)
 23: {
 24: #if defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)
 25:   *result = malloc(mem);
 26: #elif defined(PETSC_HAVE_MEMALIGN)
 27:   *result = memalign(PETSC_MEMALIGN,mem);
 28: #else
 29:   {
 30:     int *ptr,shift;
 31:     /*
 32:       malloc space for two extra chunks and shift ptr 1 + enough to get it PetscScalar aligned
 33:     */
 34:     ptr = (int*)malloc(mem + 2*PETSC_MEMALIGN);
 35:     if (ptr) {
 36:       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      = 0;
 43:     }
 44:   }
 45: #endif
 46:   if (!*result) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_MEM,"Memory requested %.0f",(PetscLogDouble)mem);
 47:   return 0;
 48: }

 52: PetscErrorCode  PetscFreeAlign(void *ptr,int line,const char func[],const char file[])
 53: {
 54: #if (!(defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !defined(PETSC_HAVE_MEMALIGN))
 55:   int shift;

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

 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: }

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

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

 97: PetscBool petscsetmallocvisited = PETSC_FALSE;

101: /*@C
102:    PetscMallocSet - Sets the routines used to do mallocs and frees.
103:    This routine MUST be called before PetscInitialize() and may be
104:    called only once.

106:    Not Collective

108:    Input Parameters:
109: +  malloc - the malloc routine
110: -  free - the free routine

112:    Level: developer

114:    Concepts: malloc
115:    Concepts: memory^allocation

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

131: /*@C
132:    PetscMallocClear - Resets the routines used to do mallocs and frees to the
133:         defaults.

135:    Not Collective

137:    Level: developer

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

144: @*/
145: PetscErrorCode  PetscMallocClear(void)
146: {
148:   PetscTrMalloc         = PetscMallocAlign;
149:   PetscTrFree           = PetscFreeAlign;
150:   petscsetmallocvisited = PETSC_FALSE;
151:   return(0);
152: }

156: PetscErrorCode PetscMemoryTrace(const char label[])
157: {
158:   PetscErrorCode        ierr;
159:   PetscLogDouble        mem,mal;
160:   static PetscLogDouble oldmem = 0,oldmal = 0;

163:   PetscMemoryGetCurrentUsage(&mem);
164:   PetscMallocGetCurrentUsage(&mal);

166:   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);
167:   oldmem = mem;
168:   oldmal = mal;
169:   return(0);
170: }