Actual source code: mal.c

  1: /*
  2:     Code that allows a user to dictate what malloc() PETSc uses.
  3: */
 4:  #include petsc.h
 5:  #include petscsys.h
  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
 12: #include "petscfix.h"


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

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

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

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

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

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

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

113: PetscTruth petscsetmallocvisited = PETSC_FALSE;

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

122:    Not Collective

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

128:    Level: developer

130:    Concepts: malloc
131:    Concepts: memory^allocation 

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

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

151:    Not Collective

153:    Level: developer

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

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