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_STDLIB_H)
7: #include <stdlib.h>
8: #endif
9: #if defined(PETSC_HAVE_MALLOC_H)
10: #include <malloc.h>
11: #endif
13: /*
14: We want to make sure that all mallocs of double or complex numbers are complex aligned.
15: 1) on systems with memalign() we call that routine to get an aligned memory location
16: 2) on systems without memalign() we
17: - allocate one sizeof(PetscScalar) extra space
18: - we shift the pointer up slightly if needed to get PetscScalar aligned
19: - if shifted we store at ptr[-1] the amount of shift (plus a classid)
20: */
21: #define SHIFT_CLASSID 456123 25: PetscErrorCode PetscMallocAlign(size_t mem,int line,const char func[],const char file[],const char dir[],void** result) 26: {
27: #if defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)
28: *result = malloc(mem);
29: #elif defined(PETSC_HAVE_MEMALIGN)
30: *result = memalign(PETSC_MEMALIGN,mem);
31: #else
32: {
33: int *ptr,shift;
34: /*
35: malloc space for two extra chunks and shift ptr 1 + enough to get it PetscScalar aligned
36: */
37: ptr = (int*)malloc(mem + 2*PETSC_MEMALIGN);
38: if (ptr) {
39: shift = (int)(((PETSC_UINTPTR_T) ptr) % PETSC_MEMALIGN);
40: shift = (2*PETSC_MEMALIGN - shift)/sizeof(int);
41: ptr[shift-1] = shift + SHIFT_CLASSID ;
42: ptr += shift;
43: *result = (void*)ptr;
44: } else {
45: *result = 0;
46: }
47: }
48: #endif
49: if (!*result) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_MEM,"Memory requested %.0f",(PetscLogDouble)mem);
50: return 0;
51: }
55: PetscErrorCode PetscFreeAlign(void *ptr,int line,const char func[],const char file[],const char dir[]) 56: {
57: #if (!(defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !defined(PETSC_HAVE_MEMALIGN))
58: int shift;
59: /*
60: Previous int tells us how many ints the pointer has been shifted from
61: the original address provided by the system malloc().
62: */
63: shift = *(((int*)ptr)-1) - SHIFT_CLASSID;
64: if (shift > PETSC_MEMALIGN-1) return PetscError(PETSC_COMM_SELF,line,func,file,dir,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap");
65: if (shift < 0) return PetscError(PETSC_COMM_SELF,line,func,file,dir,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap");
66: ptr = (void*)(((int*)ptr) - shift);
67: #endif
69: #if defined(PETSC_HAVE_FREE_RETURN_INT)
70: int err = free(ptr);
71: if (err) {
72: return PetscError(PETSC_COMM_SELF,line,func,file,dir,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"System free returned error %d\n",err);
73: }
74: #else
75: free(ptr);
76: #endif
77: return 0;
78: }
80: /*
81: We never use the system free directly because on many machines it
82: does not return an error code.
83: */
86: PetscErrorCode PetscFreeDefault(void *ptr,int line,char *func,char *file,char *dir) 87: {
88: #if defined(PETSC_HAVE_FREE_RETURN_INT)
89: int err = free(ptr);
90: if (err) {
91: return PetscError(PETSC_COMM_SELF,line,func,file,dir,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"System free returned error %d\n",err);
92: }
93: #else
94: free(ptr);
95: #endif
96: return 0;
97: }
99: PetscErrorCode (*PetscTrMalloc)(size_t,int,const char[],const char[],const char[],void**) = PetscMallocAlign;
100: PetscErrorCode (*PetscTrFree)(void*,int,const char[],const char[],const char[]) = PetscFreeAlign;
102: PetscBool petscsetmallocvisited = PETSC_FALSE;
106: /*@C
107: PetscMallocSet - Sets the routines used to do mallocs and frees.
108: This routine MUST be called before PetscInitialize() and may be
109: called only once.
111: Not Collective
113: Input Parameters:
114: + malloc - the malloc routine
115: - free - the free routine
117: Level: developer
119: Concepts: malloc
120: Concepts: memory^allocation
122: @*/
123: PetscErrorCodePetscMallocSet(PetscErrorCode (*imalloc)(size_t,int,const char[],const char[],const char[],void**),124: PetscErrorCode (*ifree)(void*,int,const char[],const char[],const char[]))125: {
127: if (petscsetmallocvisited && (imalloc != PetscTrMalloc || ifree != PetscTrFree)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"cannot call multiple times");
128: PetscTrMalloc = imalloc;
129: PetscTrFree = ifree;
130: petscsetmallocvisited = PETSC_TRUE;
131: return(0);
132: }
136: /*@C
137: PetscMallocClear - Resets the routines used to do mallocs and frees to the
138: defaults.
140: Not Collective
142: Level: developer
144: Notes:
145: In general one should never run a PETSc program with different malloc() and
146: free() settings for different parts; this is because one NEVER wants to
147: free() an address that was malloced by a different memory management system
149: @*/
150: PetscErrorCodePetscMallocClear(void)151: {
153: PetscTrMalloc = PetscMallocAlign;
154: PetscTrFree = PetscFreeAlign;
155: petscsetmallocvisited = PETSC_FALSE;
156: return(0);
157: }