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 PetscMallocAlign(size_t mem,int line,const char func[],const char file[],const char dir[],void** result)
38: {
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-1] = shift + SHIFT_COOKIE ;
54: ptr += shift;
55: *result = (void*)ptr;
56: } else {
57: *result = 0;
58: }
59: }
60: #endif
61: if (!*result) SETERRQ1(PETSC_ERR_MEM,"Memory requested %.0f",(PetscLogDouble)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: if (shift < 0) 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 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 (*PetscTrMalloc)(size_t,int,const char[],const char[],const char[],void**) = PetscMallocAlign;
112: PetscErrorCode (*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 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 PetscClearMalloc(void)
163: {
165: PetscTrMalloc = PetscMallocAlign;
166: PetscTrFree = PetscFreeAlign;
167: petscsetmallocvisited = PETSC_FALSE;
168: return(0);
169: }