Actual source code: mal.c
petsc-3.7.1 2016-05-15
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 (!mem) { *result = NULL; return 0; }
     25: #if defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)
     26:   *result = malloc(mem);
     27: #elif defined(PETSC_HAVE_MEMALIGN)
     28:   *result = memalign(PETSC_MEMALIGN,mem);
     29: #else
     30:   {
     31:     /*
     32:       malloc space for two extra chunks and shift ptr 1 + enough to get it PetscScalar aligned
     33:     */
     34:     int *ptr = (int*)malloc(mem + 2*PETSC_MEMALIGN);
     35:     if (ptr) {
     36:       int 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      = NULL;
     43:     }
     44:   }
     45: #endif
     46:   if (!*result) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_MEM,PETSC_ERROR_INITIAL,"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 (!ptr) return 0;
     55: #if (!(defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !defined(PETSC_HAVE_MEMALIGN))
     56:   {
     57:     /*
     58:       Previous int tells us how many ints the pointer has been shifted from
     59:       the original address provided by the system malloc().
     60:     */
     61:     int shift = *(((int*)ptr)-1) - SHIFT_CLASSID;
     62:     if (shift > PETSC_MEMALIGN-1) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap");
     63:     if (shift < 0) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap");
     64:     ptr = (void*)(((int*)ptr) - shift);
     65:   }
     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: PetscErrorCode (*PetscTrMalloc)(size_t,int,const char[],const char[],void**) = PetscMallocAlign;
     78: PetscErrorCode (*PetscTrFree)(void*,int,const char[],const char[])           = PetscFreeAlign;

     80: PetscBool petscsetmallocvisited = PETSC_FALSE;

     84: /*@C
     85:    PetscMallocSet - Sets the routines used to do mallocs and frees.
     86:    This routine MUST be called before PetscInitialize() and may be
     87:    called only once.

     89:    Not Collective

     91:    Input Parameters:
     92: +  malloc - the malloc routine
     93: -  free - the free routine

     95:    Level: developer

     97:    Concepts: malloc
     98:    Concepts: memory^allocation

    100: @*/
    101: PetscErrorCode  PetscMallocSet(PetscErrorCode (*imalloc)(size_t,int,const char[],const char[],void**),
    102:                                               PetscErrorCode (*ifree)(void*,int,const char[],const char[]))
    103: {
    105:   if (petscsetmallocvisited && (imalloc != PetscTrMalloc || ifree != PetscTrFree)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"cannot call multiple times");
    106:   PetscTrMalloc         = imalloc;
    107:   PetscTrFree           = ifree;
    108:   petscsetmallocvisited = PETSC_TRUE;
    109:   return(0);
    110: }

    114: /*@C
    115:    PetscMallocClear - Resets the routines used to do mallocs and frees to the
    116:         defaults.

    118:    Not Collective

    120:    Level: developer

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

    127: @*/
    128: PetscErrorCode  PetscMallocClear(void)
    129: {
    131:   PetscTrMalloc         = PetscMallocAlign;
    132:   PetscTrFree           = PetscFreeAlign;
    133:   petscsetmallocvisited = PETSC_FALSE;
    134:   return(0);
    135: }

    139: PetscErrorCode PetscMemoryTrace(const char label[])
    140: {
    141:   PetscErrorCode        ierr;
    142:   PetscLogDouble        mem,mal;
    143:   static PetscLogDouble oldmem = 0,oldmal = 0;

    146:   PetscMemoryGetCurrentUsage(&mem);
    147:   PetscMallocGetCurrentUsage(&mal);

    149:   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);
    150:   oldmem = mem;
    151:   oldmal = mal;
    152:   return(0);
    153: }