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