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

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

 62: int PetscFreeAlign(void *ptr,int line,char *func,char *file,char *dir)
 63: {
 64:   int 0;

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

 77: #if defined(PETSC_HAVE_FREE_RETURN_INT)
 78:   free(ptr);
 79:   if (ierr) {
 80:     return PetscError(line,func,file,dir,1,1,"System free returned error %dn",ierr);
 81:   }
 82: #else 
 83:   free(ptr);
 84: #endif
 85:   return ierr;
 86: }

 88: /*
 89:         We never use the system free directly because on many machines it 
 90:     does not return an error code.
 91: */
 92: int PetscFreeDefault(void *ptr,int line,char *func,char *file,char *dir)
 93: {
 94: #if defined(PETSC_HAVE_FREE_RETURN_INT)
 95:   int free(ptr);
 96:   if (ierr) {
 97:     return PetscError(line,func,file,dir,1,1,"System free returned error %dn",ierr);
 98:   }
 99: #else 
100:   free(ptr);
101: #endif
102:   return 0;
103: }

105: int  (*PetscTrMalloc)(int,int,char*,char*,char*,void**)  = PetscMallocAlign;
106: int  (*PetscTrFree)(void *,int,char*,char *,char*)       = PetscFreeAlign;

108: PetscTruth petscsetmallocvisited = PETSC_FALSE;

110: /*@C
111:    PetscSetMalloc - Sets the routines used to do mallocs and frees.
112:    This routine MUST be called before PetscInitialize() and may be
113:    called only once.

115:    Not Collective

117:    Input Parameters:
118: +  malloc - the malloc routine
119: -  free - the free routine

121:    Level: developer

123:    Concepts: malloc
124:    Concepts: memory^allocation 

126: @*/
127: int PetscSetMalloc(int (*imalloc)(int,int,char*,char*,char*,void**),
128:                    int (*ifree)(void*,int,char*,char*,char*))
129: {
131:   if (petscsetmallocvisited) SETERRQ(PETSC_ERR_SUP,"cannot call multiple times");
132:   PetscTrMalloc               = imalloc;
133:   PetscTrFree                 = ifree;
134:   petscsetmallocvisited       = PETSC_TRUE;
135:   return(0);
136: }

138: /*@C
139:    PetscClearMalloc - Resets the routines used to do mallocs and frees to the 
140:         defaults.

142:    Not Collective

144:    Level: developer

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

151: @*/
152: int PetscClearMalloc(void)
153: {
155:   PetscTrMalloc         = PetscMallocAlign;
156:   PetscTrFree           = PetscFreeAlign;
157:   petscsetmallocvisited = PETSC_FALSE;
158:   return(0);
159: }