Actual source code: mal.c

      1: #define PETSC_DLL
      2: /*
      3:     Code that allows a user to dictate what malloc() PETSc uses.
      4: */
     5:  #include petsc.h
     6:  #include petscsys.h
      7: #if defined(PETSC_HAVE_STDLIB_H)
      8: #include <stdlib.h>
      9: #endif
     10: #if defined(PETSC_HAVE_MALLOC_H)
     11: #include <malloc.h>
     12: #endif
     13: #include "petscfix.h"

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

     26: /* need to use 16 and 8 below instead of sizeof() cause #if cannot handle sizeof() */
     27: #if !defined(PETSC_MEMALIGN)
     28: #  if defined(PETSC_USE_COMPLEX)
     29: #    define PETSC_MEMALIGN 16
     30: #  else
     31: #    define PETSC_MEMALIGN 8
     32: #  endif
     33: #endif

     37: PetscErrorCode PETSC_DLLEXPORT PetscMallocAlign(size_t mem,int line,const char func[],const char file[],const char dir[],void** result)
     38: {
     39:   if (!mem) SETERRQ(PETSC_ERR_MEM_MALLOC_0,"Cannot malloc size zero");
     40: #if defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)
     41:   *result = malloc(mem);
     42: #elif defined(PETSC_HAVE_MEMALIGN)
     43:   *result = memalign(PETSC_MEMALIGN,mem);
     44: #else
     45:   {
     46:     int *ptr,shift;
     47:     /*
     48:       malloc space for two extra chunks and shift ptr 1 + enough to get it PetscScalar aligned
     49:     */
     50:     ptr = (int*)malloc(mem + 2*PETSC_MEMALIGN);
     51:     if (ptr) {
     52:       shift    = (int)(((unsigned long) ptr) % PETSC_MEMALIGN);
     53:       shift    = (2*PETSC_MEMALIGN - shift)/sizeof(int);
     54:       ptr     += shift;
     55:       ptr[-1]  = shift + SHIFT_COOKIE ;
     56:       *result  = (void*)ptr;
     57:     } else {
     58:       *result  = 0;
     59:     }
     60:   }
     61: #endif
     62:   if (!*result)  SETERRQ1(PETSC_ERR_MEM,"Memory requested %.0f",(PetscLogDouble)mem);
     63:   return 0;
     64: }

     68: PetscErrorCode PETSC_DLLEXPORT PetscFreeAlign(void *ptr,int line,const char func[],const char file[],const char dir[])
     69: {
     70: #if (!(defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !defined(PETSC_HAVE_MEMALIGN))
     71:   int shift;
     72:   /*
     73:        Previous int tells us how many ints the pointer has been shifted from
     74:     the original address provided by the system malloc().
     75:   */
     76:   shift = ((int*)ptr)[-1] - SHIFT_COOKIE;
     77:   if (shift > PETSC_MEMALIGN-1) return PetscError(line,func,file,dir,1,1,"Likely memory corruption in heap");
     78:   ptr   = (void*)(((int*)ptr) - shift);
     79: #endif

     81: #if defined(PETSC_HAVE_FREE_RETURN_INT)
     82:   int err = free(ptr);
     83:   if (err) {
     84:     return PetscError(line,func,file,dir,1,1,"System free returned error %d\n",err);
     85:   }
     86: #else
     87:   free(ptr);
     88: #endif
     89:   return 0;
     90: }

     92: /*
     93:         We never use the system free directly because on many machines it
     94:     does not return an error code.
     95: */
     98: PetscErrorCode PETSC_DLLEXPORT PetscFreeDefault(void *ptr,int line,char *func,char *file,char *dir)
     99: {
    100: #if defined(PETSC_HAVE_FREE_RETURN_INT)
    101:   int err = free(ptr);
    102:   if (err) {
    103:     return PetscError(line,func,file,dir,1,1,"System free returned error %d\n",err);
    104:   }
    105: #else
    106:   free(ptr);
    107: #endif
    108:   return 0;
    109: }

    111: PetscErrorCode  PETSC_DLLEXPORT (*PetscTrMalloc)(size_t,int,const char[],const char[],const char[],void**) = PetscMallocAlign;
    112: PetscErrorCode  PETSC_DLLEXPORT (*PetscTrFree)(void*,int,const char[],const char[],const char[])          = PetscFreeAlign;

    114: PetscTruth petscsetmallocvisited = PETSC_FALSE;

    118: /*@C
    119:    PetscSetMalloc - Sets the routines used to do mallocs and frees.
    120:    This routine MUST be called before PetscInitialize() and may be
    121:    called only once.

    123:    Not Collective

    125:    Input Parameters:
    126: +  malloc - the malloc routine
    127: -  free - the free routine

    129:    Level: developer

    131:    Concepts: malloc
    132:    Concepts: memory^allocation

    134: @*/
    135: PetscErrorCode PETSC_DLLEXPORT PetscSetMalloc(PetscErrorCode (*imalloc)(size_t,int,const char[],const char[],const char[],void**),
    136:                                               PetscErrorCode (*ifree)(void*,int,const char[],const char[],const char[]))
    137: {
    139:   if (petscsetmallocvisited && (imalloc != PetscTrMalloc || ifree != PetscTrFree)) SETERRQ(PETSC_ERR_SUP,"cannot call multiple times");
    140:   PetscTrMalloc               = imalloc;
    141:   PetscTrFree                 = ifree;
    142:   petscsetmallocvisited       = PETSC_TRUE;
    143:   return(0);
    144: }

    148: /*@C
    149:    PetscClearMalloc - Resets the routines used to do mallocs and frees to the
    150:         defaults.

    152:    Not Collective

    154:    Level: developer

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

    161: @*/
    162: PetscErrorCode PETSC_DLLEXPORT PetscClearMalloc(void)
    163: {
    165:   PetscTrMalloc         = PetscMallocAlign;
    166:   PetscTrFree           = PetscFreeAlign;
    167:   petscsetmallocvisited = PETSC_FALSE;
    168:   return(0);
    169: }