1 /******************************************************************************
3 A migratable memory allocator.
5 NOTE: isomalloc is threadsafe, so the isomallocs are not wrapped in CmiMemLock.
7 *****************************************************************************/
9 #define CMK_ISOMALLOC_EXCLUDE_FORTRAN_CALLS 0
11 #if ! CMK_MEMORY_BUILD_OS
12 /* Use Gnumalloc as meta-meta malloc fallbacks (mm_*) */
13 #include "memory-gnu.c"
16 #include "memory-isomalloc.h"
18 /*The current allocation arena */
19 CpvStaticDeclare(CmiIsomallocBlockList
*,isomalloc_blocklist
);
20 CpvStaticDeclare(CmiIsomallocBlockList
*,pushed_blocklist
);
22 #define ISOMALLOC_PUSH \
23 CmiIsomallocBlockList *pushed_blocklist=CpvAccess(isomalloc_blocklist);\
24 CpvAccess(isomalloc_blocklist)=NULL;\
26 #define ISOMALLOC_POP \
27 CpvAccess(isomalloc_blocklist)=pushed_blocklist;\
29 /* temporarily disable/enable isomalloc. Note the following two fucntions
30 * must be used in pair, and no suspend of thread is allowed in between
32 void CmiDisableIsomalloc()
34 CpvAccess(pushed_blocklist
)=CpvAccess(isomalloc_blocklist
);
35 CpvAccess(isomalloc_blocklist
)=NULL
;
38 void CmiEnableIsomalloc()
40 CpvAccess(isomalloc_blocklist
)=CpvAccess(pushed_blocklist
);
43 #if CMK_HAS_TLS_VARIABLES
45 * make sure isomalloc is only called in pthreads that is spawned by Charm++.
46 * It is not safe to call isomalloc in system spawned pthreads for example
47 * mpich pthreads, or aio pthreads.
48 * Use the following TLS variable to distinguish those pthreads.
49 * when set to 1, the current pthreads is allowed to call isomalloc.
51 static __thread
int isomalloc_thread
= 0;
53 #if BIGSIM_OUT_OF_CORE && BIGSIM_OOC_PREFETCH
54 #error TLS support is required for bigsim out-of-core prefetch optimization
58 static int meta_inited
= 0;
60 extern int _sync_iso_warned
;
62 static void meta_init(char **argv
)
64 CmiMemoryIs_flag
|=CMI_MEMORY_IS_ISOMALLOC
;
65 CpvInitialize(CmiIsomallocBlockList
*,isomalloc_blocklist
);
66 CpvInitialize(CmiIsomallocBlockList
*,pushed_blocklist
);
67 #if CMK_HAS_TLS_VARIABLES
68 isomalloc_thread
= 1; /* isomalloc is allowed in this pthread */
70 if (CmiMyRank()==0) meta_inited
= 1;
73 if (_sync_iso
== 0 && _sync_iso_warned
== 0) {
75 printf("Warning> Using Isomalloc in SMP mode, you may need to run with '+isomalloc_sync'.\n");
80 static void *meta_malloc(size_t size
)
83 #if CMK_HAS_TLS_VARIABLES
84 int _isomalloc_thread
= isomalloc_thread
;
85 if (CmiThreadIs(CMI_THREAD_IS_TLS
)) _isomalloc_thread
= 1;
87 if (meta_inited
&& CpvInitialized(isomalloc_blocklist
) && CpvAccess(isomalloc_blocklist
)
88 #if CMK_HAS_TLS_VARIABLES
92 { /*Isomalloc a new block and link it in*/
93 ISOMALLOC_PUSH
/*Disable isomalloc while inside isomalloc*/
94 #if CMK_ISOMALLOC_EXCLUDE_FORTRAN_CALLS
95 if (CmiIsFortranLibraryCall()==1) {
100 ret
=CmiIsomallocBlockListMalloc(pushed_blocklist
,size
);
103 else /*Just use regular malloc*/
108 static void meta_free(void *mem
)
110 if (mem
!= NULL
&& CmiIsomallocInRange(mem
))
111 { /*Unlink this slot and isofree*/
113 CmiIsomallocBlockListFree(mem
);
116 else /*Just use regular malloc*/
120 static void *meta_calloc(size_t nelem
, size_t size
)
122 void *ret
=meta_malloc(nelem
*size
);
123 if (ret
!= NULL
) memset(ret
,0,nelem
*size
);
127 static void meta_cfree(void *mem
)
132 static void *meta_realloc(void *oldBuffer
, size_t newSize
)
135 /*Just forget it for regular malloc's:*/
136 if (!CmiIsomallocInRange(oldBuffer
))
137 return mm_realloc(oldBuffer
,newSize
);
139 newBuffer
= meta_malloc(newSize
);
140 if ( newBuffer
&& oldBuffer
) {
141 /*Must preserve old buffer contents, so we need the size of the
142 buffer. SILLY HACK: muck with internals of blocklist header.*/
143 size_t size
=CmiIsomallocLength(((CmiIsomallocBlockList
*)oldBuffer
)-1)-
144 sizeof(CmiIsomallocBlockList
);
145 if (size
>newSize
) size
=newSize
;
147 memcpy(newBuffer
, oldBuffer
, size
);
150 meta_free(oldBuffer
);
154 static void *meta_memalign(size_t align
, size_t size
)
157 if (CpvInitialized(isomalloc_blocklist
) && CpvAccess(isomalloc_blocklist
))
158 { /*Isomalloc a new block and link it in*/
159 ISOMALLOC_PUSH
/*Disable isomalloc while inside isomalloc*/
160 #if CMK_ISOMALLOC_EXCLUDE_FORTRAN_CALLS
161 if (CmiIsFortranLibraryCall()==1) {
162 ret
=mm_memalign(align
, size
);
166 ret
=CmiIsomallocBlockListMallocAlign(pushed_blocklist
,align
,size
);
169 else /*Just use regular memalign*/
170 ret
=mm_memalign(align
, size
);
174 static void *meta_valloc(size_t size
)
176 return meta_malloc(size
);
179 #define CMK_MEMORY_HAS_NOMIGRATE
180 /*Allocate non-migratable memory:*/
181 void *malloc_nomigrate(size_t size
) {
184 result
= mm_malloc(size
);
189 void free_nomigrate(void *mem
)
196 #define CMK_MEMORY_HAS_ISOMALLOC
198 /*Make this blockList "active"-- the recipient of incoming
199 mallocs. Returns the old blocklist.*/
200 CmiIsomallocBlockList
*CmiIsomallocBlockListActivate(CmiIsomallocBlockList
*l
)
202 CmiIsomallocBlockList
**s
=&CpvAccess(isomalloc_blocklist
);
203 CmiIsomallocBlockList
*ret
=*s
;
208 CmiIsomallocBlockList
*CmiIsomallocBlockListCurrent(){
209 return CpvAccess(isomalloc_blocklist
);