doc: Add serial to list of ci file reserved words
[charm.git] / src / conv-core / memory-isomalloc.c
1 /******************************************************************************
2
3 A migratable memory allocator.
4
5 FIXME: isomalloc is threadsafe, so the isomallocs *don't* need to
6 be wrapped in CmiMemLock.  (Doesn't hurt, tho')
7
8 *****************************************************************************/
9
10 #define CMK_ISOMALLOC_EXCLUDE_FORTRAN_CALLS   0
11
12 #if ! CMK_MEMORY_BUILD_OS
13 /* Use Gnumalloc as meta-meta malloc fallbacks (mm_*) */
14 #include "memory-gnu.c"
15 #endif
16
17 #include "memory-isomalloc.h"
18
19 /*The current allocation arena */
20 CpvStaticDeclare(CmiIsomallocBlockList *,isomalloc_blocklist);
21 CpvStaticDeclare(CmiIsomallocBlockList *,pushed_blocklist);
22
23 #define ISOMALLOC_PUSH \
24         CmiIsomallocBlockList *pushed_blocklist=CpvAccess(isomalloc_blocklist);\
25         CpvAccess(isomalloc_blocklist)=NULL;\
26         rank_holding_CmiMemLock=CmiMyRank();\
27
28 #define ISOMALLOC_POP \
29         CpvAccess(isomalloc_blocklist)=pushed_blocklist;\
30         rank_holding_CmiMemLock=-1;\
31
32 /* temporarily disable/enable isomalloc. Note the following two fucntions
33  * must be used in pair, and no suspend of thread is allowed in between
34  * */
35 void CmiDisableIsomalloc()
36 {
37         CpvAccess(pushed_blocklist)=CpvAccess(isomalloc_blocklist);
38         CpvAccess(isomalloc_blocklist)=NULL;
39         rank_holding_CmiMemLock=CmiMyRank();
40 }
41
42 void CmiEnableIsomalloc()
43 {
44         CpvAccess(isomalloc_blocklist)=CpvAccess(pushed_blocklist);
45         rank_holding_CmiMemLock=-1;
46 }
47
48 #if CMK_HAS_TLS_VARIABLES
49 /**
50  * make sure isomalloc is only called in pthreads that is spawned by Charm++.
51  * It is not safe to call isomalloc in system spawned pthreads for example
52  * mpich pthreads, or aio pthreads.
53  * Use the following TLS variable to distinguish those pthreads.
54  * when set to 1, the current pthreads is allowed to call isomalloc.
55  */
56 static __thread int isomalloc_thread = 0;
57 #else
58 #if BIGSIM_OUT_OF_CORE && BIGSIM_OOC_PREFETCH
59 #error TLS support is required for bigsim out-of-core prefetch optimization
60 #endif
61 #endif
62
63 static int meta_inited = 0;
64
65 static void meta_init(char **argv)
66 {
67    CmiMemoryIs_flag|=CMI_MEMORY_IS_ISOMALLOC;
68    CpvInitialize(CmiIsomallocBlockList *,isomalloc_blocklist);
69    CpvInitialize(CmiIsomallocBlockList *,pushed_blocklist);
70 #if CMK_HAS_TLS_VARIABLES
71    isomalloc_thread = 1;         /* isomalloc is allowed in this pthread */
72 #endif
73    CmiNodeAllBarrier();
74    meta_inited = 1;
75 }
76
77 static void *meta_malloc(size_t size)
78 {
79         void *ret=NULL;
80 #if CMK_HAS_TLS_VARIABLES
81         int _isomalloc_thread = isomalloc_thread;
82         if (CmiThreadIs(CMI_THREAD_IS_TLS)) _isomalloc_thread = 1;
83 #endif
84         if (meta_inited && CpvInitialized(isomalloc_blocklist) && CpvAccess(isomalloc_blocklist)
85 #if CMK_HAS_TLS_VARIABLES
86              && _isomalloc_thread
87 #endif
88            )
89         { /*Isomalloc a new block and link it in*/
90                 ISOMALLOC_PUSH /*Disable isomalloc while inside isomalloc*/
91 #if CMK_ISOMALLOC_EXCLUDE_FORTRAN_CALLS
92                 if (CmiIsFortranLibraryCall()==1) {
93                   ret=mm_malloc(size);
94                 }
95                 else
96 #endif
97                 ret=CmiIsomallocBlockListMalloc(pushed_blocklist,size);
98                 ISOMALLOC_POP
99         }
100         else /*Just use regular malloc*/
101                 ret=mm_malloc(size);
102         return ret;
103 }
104
105 static void meta_free(void *mem)
106 {       
107         if (CmiIsomallocInRange(mem)) 
108         { /*Unlink this slot and isofree*/
109                 ISOMALLOC_PUSH
110                 CmiIsomallocBlockListFree(mem);
111                 ISOMALLOC_POP
112         }
113         else /*Just use regular malloc*/
114                 mm_free(mem);
115 }
116
117 static void *meta_calloc(size_t nelem, size_t size)
118 {
119         void *ret=meta_malloc(nelem*size);
120         if (ret != NULL) memset(ret,0,nelem*size);
121         return ret;
122 }
123
124 static void meta_cfree(void *mem)
125 {
126         meta_free(mem);
127 }
128
129 static void *meta_realloc(void *oldBuffer, size_t newSize)
130 {
131         void *newBuffer;
132         /*Just forget it for regular malloc's:*/
133         if (!CmiIsomallocInRange(oldBuffer))
134                 return mm_realloc(oldBuffer,newSize);
135         
136         newBuffer = meta_malloc(newSize);
137         if ( newBuffer && oldBuffer ) {
138                 /*Must preserve old buffer contents, so we need the size of the
139                   buffer.  SILLY HACK: muck with internals of blocklist header.*/
140                 size_t size=CmiIsomallocLength(((CmiIsomallocBlockList *)oldBuffer)-1)-
141                         sizeof(CmiIsomallocBlockList);
142                 if (size>newSize) size=newSize;
143                 if (size > 0)
144                         memcpy(newBuffer, oldBuffer, size);
145         }
146         if (oldBuffer)
147                 meta_free(oldBuffer);
148         return newBuffer;
149 }
150
151 static void *meta_memalign(size_t align, size_t size)
152 {
153         void *ret=NULL;
154         if (CpvInitialized(isomalloc_blocklist) && CpvAccess(isomalloc_blocklist)) 
155         { /*Isomalloc a new block and link it in*/
156                 ISOMALLOC_PUSH /*Disable isomalloc while inside isomalloc*/
157 #if CMK_ISOMALLOC_EXCLUDE_FORTRAN_CALLS
158                 if (CmiIsFortranLibraryCall()==1) {
159                   ret=mm_memalign(align, size);
160                 }
161                 else
162 #endif
163                   ret=CmiIsomallocBlockListMallocAlign(pushed_blocklist,align,size);
164                 ISOMALLOC_POP
165         }
166         else /*Just use regular memalign*/
167                 ret=mm_memalign(align, size);
168         return ret;
169 }
170
171 static void *meta_valloc(size_t size)
172 {
173         return meta_malloc(size);
174 }
175
176 #define CMK_MEMORY_HAS_NOMIGRATE
177 /*Allocate non-migratable memory:*/
178 void *malloc_nomigrate(size_t size) { 
179   void *result;
180   CmiMemLock();
181   result = mm_malloc(size);
182   CmiMemUnlock();
183   return result;
184 }
185
186 void free_nomigrate(void *mem)
187 {
188   CmiMemLock();
189   mm_free(mem);
190   CmiMemUnlock();
191 }
192
193 #define CMK_MEMORY_HAS_ISOMALLOC
194
195 /*Make this blockList "active"-- the recipient of incoming
196 mallocs.  Returns the old blocklist.*/
197 CmiIsomallocBlockList *CmiIsomallocBlockListActivate(CmiIsomallocBlockList *l)
198 {
199         register CmiIsomallocBlockList **s=&CpvAccess(isomalloc_blocklist);
200         CmiIsomallocBlockList *ret=*s;
201         *s=l;
202         return ret;
203 }
204
205 CmiIsomallocBlockList *CmiIsomallocBlockListCurrent(){
206         return CpvAccess(isomalloc_blocklist);
207 }
208
209
210
211