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 defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)
25: *result = malloc(mem);
26: #elif defined(PETSC_HAVE_MEMALIGN)
27: *result = memalign(PETSC_MEMALIGN,mem);
28: #else
29: {
30: int *ptr,shift;
31: /*
32: malloc space for two extra chunks and shift ptr 1 + enough to get it PetscScalar aligned
33: */
34: ptr = (int*)malloc(mem + 2*PETSC_MEMALIGN);
35: if (ptr) {
36: 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 = 0;
43: }
44: }
45: #endif
46: if (!*result) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_MEM,"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 (!(defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !defined(PETSC_HAVE_MEMALIGN))
55: int shift;
57: if (!ptr) return(0);
58: /*
59: Previous int tells us how many ints the pointer has been shifted from
60: the original address provided by the system malloc().
61: */
62: shift = *(((int*)ptr)-1) - SHIFT_CLASSID;
63: if (shift > PETSC_MEMALIGN-1) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap");
64: if (shift < 0) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap");
65: ptr = (void*)(((int*)ptr) - shift);
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: /*
78: We never use the system free directly because on many machines it
79: does not return an error code.
80: */
83: PetscErrorCode PetscFreeDefault(void *ptr,int line,char *func,char *file) 84: {
85: #if defined(PETSC_HAVE_FREE_RETURN_INT)
86: int err = free(ptr);
87: if (err) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"System free returned error %d\n",err);
88: #else
89: free(ptr);
90: #endif
91: return 0;
92: }
94: PetscErrorCode (*PetscTrMalloc)(size_t,int,const char[],const char[],void**) = PetscMallocAlign;
95: PetscErrorCode (*PetscTrFree)(void*,int,const char[],const char[]) = PetscFreeAlign;
97: PetscBool petscsetmallocvisited = PETSC_FALSE;
101: /*@C
102: PetscMallocSet - Sets the routines used to do mallocs and frees.
103: This routine MUST be called before PetscInitialize() and may be
104: called only once.
106: Not Collective
108: Input Parameters:
109: + malloc - the malloc routine
110: - free - the free routine
112: Level: developer
114: Concepts: malloc
115: Concepts: memory^allocation
117: @*/
118: PetscErrorCodePetscMallocSet(PetscErrorCode (*imalloc)(size_t,int,const char[],const char[],void**),119: PetscErrorCode (*ifree)(void*,int,const char[],const char[]))120: {
122: if (petscsetmallocvisited && (imalloc != PetscTrMalloc || ifree != PetscTrFree)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"cannot call multiple times");
123: PetscTrMalloc = imalloc;
124: PetscTrFree = ifree;
125: petscsetmallocvisited = PETSC_TRUE;
126: return(0);
127: }
131: /*@C
132: PetscMallocClear - Resets the routines used to do mallocs and frees to the
133: defaults.
135: Not Collective
137: Level: developer
139: Notes:
140: In general one should never run a PETSc program with different malloc() and
141: free() settings for different parts; this is because one NEVER wants to
142: free() an address that was malloced by a different memory management system
144: @*/
145: PetscErrorCodePetscMallocClear(void)146: {
148: PetscTrMalloc = PetscMallocAlign;
149: PetscTrFree = PetscFreeAlign;
150: petscsetmallocvisited = PETSC_FALSE;
151: return(0);
152: }
156: PetscErrorCode PetscMemoryTrace(const char label[])157: {
158: PetscErrorCode ierr;
159: PetscLogDouble mem,mal;
160: static PetscLogDouble oldmem = 0,oldmal = 0;
163: PetscMemoryGetCurrentUsage(&mem);
164: PetscMallocGetCurrentUsage(&mal);
166: 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);
167: oldmem = mem;
168: oldmal = mal;
169: return(0);
170: }