Actual source code: mal.c

  1: /*$Id: mal.c,v 1.57 2001/08/07 03:02:00 balay Exp $*/
  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: int PetscMallocAlign(size_t mem,int line,const char func[],const char file[],const char dir[],void** result)
 38: {
 39:   if (mem == 0) 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 %lu",(long)mem);
 63:   return 0;
 64: }

 68: int PetscFreeAlign(void *ptr,int line,const char func[],const char file[],const char dir[])
 69: {
 70:   int 0;

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

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

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

113: int  (*PetscTrMalloc)(size_t,int,const char[],const char[],const char[],void**) = PetscMallocAlign;
114: int  (*PetscTrFree)(void *,int,const char[],const char[],const char[])          = PetscFreeAlign;

116: PetscTruth petscsetmallocvisited = PETSC_FALSE;

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

125:    Not Collective

127:    Input Parameters:
128: +  malloc - the malloc routine
129: -  free - the free routine

131:    Level: developer

133:    Concepts: malloc
134:    Concepts: memory^allocation 

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

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

154:    Not Collective

156:    Level: developer

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

163: @*/
164: int PetscClearMalloc(void)
165: {
167:   PetscTrMalloc         = PetscMallocAlign;
168:   PetscTrFree           = PetscFreeAlign;
169:   petscsetmallocvisited = PETSC_FALSE;
170:   return(0);
171: }