xref: /petsc/src/sys/memory/mal.c (revision efca3c55b02548817e185e5069a2acfe20fa4458)
17d0a6c19SBarry Smith 
2e5c89e4eSSatish Balay /*
3e5c89e4eSSatish Balay     Code that allows a user to dictate what malloc() PETSc uses.
4e5c89e4eSSatish Balay */
5c6db04a5SJed Brown #include <petscsys.h>             /*I   "petscsys.h"   I*/
6e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H)
7e5c89e4eSSatish Balay #include <malloc.h>
8e5c89e4eSSatish Balay #endif
9e5c89e4eSSatish Balay 
10e5c89e4eSSatish Balay /*
11e5c89e4eSSatish Balay         We want to make sure that all mallocs of double or complex numbers are complex aligned.
12e5c89e4eSSatish Balay     1) on systems with memalign() we call that routine to get an aligned memory location
13e5c89e4eSSatish Balay     2) on systems without memalign() we
14e5c89e4eSSatish Balay        - allocate one sizeof(PetscScalar) extra space
15e5c89e4eSSatish Balay        - we shift the pointer up slightly if needed to get PetscScalar aligned
160700a824SBarry Smith        - if shifted we store at ptr[-1] the amount of shift (plus a classid)
17e5c89e4eSSatish Balay */
180700a824SBarry Smith #define SHIFT_CLASSID 456123
19e5c89e4eSSatish Balay 
20e5c89e4eSSatish Balay #undef __FUNCT__
21e5c89e4eSSatish Balay #define __FUNCT__ "PetscMallocAlign"
22*efca3c55SSatish Balay PetscErrorCode  PetscMallocAlign(size_t mem,int line,const char func[],const char file[],void **result)
23e5c89e4eSSatish Balay {
24e5c89e4eSSatish Balay #if defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)
25e5c89e4eSSatish Balay   *result = malloc(mem);
26e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_MEMALIGN)
27e5c89e4eSSatish Balay   *result = memalign(PETSC_MEMALIGN,mem);
28e5c89e4eSSatish Balay #else
29e5c89e4eSSatish Balay   {
30e5c89e4eSSatish Balay     int *ptr,shift;
31e5c89e4eSSatish Balay     /*
32e5c89e4eSSatish Balay       malloc space for two extra chunks and shift ptr 1 + enough to get it PetscScalar aligned
33e5c89e4eSSatish Balay     */
34e5c89e4eSSatish Balay     ptr = (int*)malloc(mem + 2*PETSC_MEMALIGN);
35e5c89e4eSSatish Balay     if (ptr) {
36c82284b1SJed Brown       shift        = (int)(((PETSC_UINTPTR_T) ptr) % PETSC_MEMALIGN);
37e5c89e4eSSatish Balay       shift        = (2*PETSC_MEMALIGN - shift)/sizeof(int);
380700a824SBarry Smith       ptr[shift-1] = shift + SHIFT_CLASSID;
39e5c89e4eSSatish Balay       ptr         += shift;
40e5c89e4eSSatish Balay       *result      = (void*)ptr;
41e5c89e4eSSatish Balay     } else {
42e5c89e4eSSatish Balay       *result      = 0;
43e5c89e4eSSatish Balay     }
44e5c89e4eSSatish Balay   }
45e5c89e4eSSatish Balay #endif
46e32f2f54SBarry Smith   if (!*result) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_MEM,"Memory requested %.0f",(PetscLogDouble)mem);
47e5c89e4eSSatish Balay   return 0;
48e5c89e4eSSatish Balay }
49e5c89e4eSSatish Balay 
50e5c89e4eSSatish Balay #undef __FUNCT__
51e5c89e4eSSatish Balay #define __FUNCT__ "PetscFreeAlign"
52*efca3c55SSatish Balay PetscErrorCode  PetscFreeAlign(void *ptr,int line,const char func[],const char file[])
53e5c89e4eSSatish Balay {
54e5c89e4eSSatish Balay #if (!(defined(PETSC_HAVE_DOUBLE_ALIGN_MALLOC) && (PETSC_MEMALIGN == 8)) && !defined(PETSC_HAVE_MEMALIGN))
55e5c89e4eSSatish Balay   int shift;
56e5c89e4eSSatish Balay   /*
57e5c89e4eSSatish Balay        Previous int tells us how many ints the pointer has been shifted from
58e5c89e4eSSatish Balay     the original address provided by the system malloc().
59e5c89e4eSSatish Balay   */
600700a824SBarry Smith   shift = *(((int*)ptr)-1) - SHIFT_CLASSID;
61*efca3c55SSatish Balay   if (shift > PETSC_MEMALIGN-1) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap");
62*efca3c55SSatish Balay   if (shift < 0) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"Likely memory corruption in heap");
63e5c89e4eSSatish Balay   ptr = (void*)(((int*)ptr) - shift);
64e5c89e4eSSatish Balay #endif
65e5c89e4eSSatish Balay 
66e5c89e4eSSatish Balay #if defined(PETSC_HAVE_FREE_RETURN_INT)
67e5c89e4eSSatish Balay   int err = free(ptr);
68*efca3c55SSatish Balay   if (err) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"System free returned error %d\n",err);
69e5c89e4eSSatish Balay #else
70e5c89e4eSSatish Balay   free(ptr);
71e5c89e4eSSatish Balay #endif
72e5c89e4eSSatish Balay   return 0;
73e5c89e4eSSatish Balay }
74e5c89e4eSSatish Balay 
75e5c89e4eSSatish Balay /*
76e5c89e4eSSatish Balay         We never use the system free directly because on many machines it
77e5c89e4eSSatish Balay     does not return an error code.
78e5c89e4eSSatish Balay */
79e5c89e4eSSatish Balay #undef __FUNCT__
80e5c89e4eSSatish Balay #define __FUNCT__ "PetscFreeDefault"
81*efca3c55SSatish Balay PetscErrorCode  PetscFreeDefault(void *ptr,int line,char *func,char *file)
82e5c89e4eSSatish Balay {
83e5c89e4eSSatish Balay #if defined(PETSC_HAVE_FREE_RETURN_INT)
84e5c89e4eSSatish Balay   int err = free(ptr);
85*efca3c55SSatish Balay   if (err) return PetscError(PETSC_COMM_SELF,line,func,file,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL,"System free returned error %d\n",err);
86e5c89e4eSSatish Balay #else
87e5c89e4eSSatish Balay   free(ptr);
88e5c89e4eSSatish Balay #endif
89e5c89e4eSSatish Balay   return 0;
90e5c89e4eSSatish Balay }
91e5c89e4eSSatish Balay 
92*efca3c55SSatish Balay PetscErrorCode (*PetscTrMalloc)(size_t,int,const char[],const char[],void**) = PetscMallocAlign;
93*efca3c55SSatish Balay PetscErrorCode (*PetscTrFree)(void*,int,const char[],const char[])           = PetscFreeAlign;
94e5c89e4eSSatish Balay 
95ace3abfcSBarry Smith PetscBool petscsetmallocvisited = PETSC_FALSE;
96e5c89e4eSSatish Balay 
97e5c89e4eSSatish Balay #undef __FUNCT__
981d1a0024SBarry Smith #define __FUNCT__ "PetscMallocSet"
99e5c89e4eSSatish Balay /*@C
1001d1a0024SBarry Smith    PetscMallocSet - Sets the routines used to do mallocs and frees.
101e5c89e4eSSatish Balay    This routine MUST be called before PetscInitialize() and may be
102e5c89e4eSSatish Balay    called only once.
103e5c89e4eSSatish Balay 
104e5c89e4eSSatish Balay    Not Collective
105e5c89e4eSSatish Balay 
106e5c89e4eSSatish Balay    Input Parameters:
107e5c89e4eSSatish Balay +  malloc - the malloc routine
108e5c89e4eSSatish Balay -  free - the free routine
109e5c89e4eSSatish Balay 
110e5c89e4eSSatish Balay    Level: developer
111e5c89e4eSSatish Balay 
112e5c89e4eSSatish Balay    Concepts: malloc
113e5c89e4eSSatish Balay    Concepts: memory^allocation
114e5c89e4eSSatish Balay 
115e5c89e4eSSatish Balay @*/
116*efca3c55SSatish Balay PetscErrorCode  PetscMallocSet(PetscErrorCode (*imalloc)(size_t,int,const char[],const char[],void**),
117*efca3c55SSatish Balay                                               PetscErrorCode (*ifree)(void*,int,const char[],const char[]))
118e5c89e4eSSatish Balay {
119e5c89e4eSSatish Balay   PetscFunctionBegin;
120e32f2f54SBarry Smith   if (petscsetmallocvisited && (imalloc != PetscTrMalloc || ifree != PetscTrFree)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"cannot call multiple times");
121e5c89e4eSSatish Balay   PetscTrMalloc         = imalloc;
122e5c89e4eSSatish Balay   PetscTrFree           = ifree;
123e5c89e4eSSatish Balay   petscsetmallocvisited = PETSC_TRUE;
124e5c89e4eSSatish Balay   PetscFunctionReturn(0);
125e5c89e4eSSatish Balay }
126e5c89e4eSSatish Balay 
127e5c89e4eSSatish Balay #undef __FUNCT__
1281d1a0024SBarry Smith #define __FUNCT__ "PetscMallocClear"
129e5c89e4eSSatish Balay /*@C
1301d1a0024SBarry Smith    PetscMallocClear - Resets the routines used to do mallocs and frees to the
131e5c89e4eSSatish Balay         defaults.
132e5c89e4eSSatish Balay 
133e5c89e4eSSatish Balay    Not Collective
134e5c89e4eSSatish Balay 
135e5c89e4eSSatish Balay    Level: developer
136e5c89e4eSSatish Balay 
137e5c89e4eSSatish Balay    Notes:
138e5c89e4eSSatish Balay     In general one should never run a PETSc program with different malloc() and
139e5c89e4eSSatish Balay     free() settings for different parts; this is because one NEVER wants to
140e5c89e4eSSatish Balay     free() an address that was malloced by a different memory management system
141e5c89e4eSSatish Balay 
142e5c89e4eSSatish Balay @*/
1437087cfbeSBarry Smith PetscErrorCode  PetscMallocClear(void)
144e5c89e4eSSatish Balay {
145e5c89e4eSSatish Balay   PetscFunctionBegin;
146e5c89e4eSSatish Balay   PetscTrMalloc         = PetscMallocAlign;
147e5c89e4eSSatish Balay   PetscTrFree           = PetscFreeAlign;
148e5c89e4eSSatish Balay   petscsetmallocvisited = PETSC_FALSE;
149e5c89e4eSSatish Balay   PetscFunctionReturn(0);
150e5c89e4eSSatish Balay }
151