add allocation modes
[IRC.git] / Robust / src / Runtime / bamboo / multicoremem.c
1 #ifdef MULTICORE
2 #include "runtime_arch.h"
3 #include "multicoreruntime.h"
4
5 #ifdef MULTICORE_GC
6 #include "multicoregarbage.h"
7 #include "multicorehelper.h"
8 #include "multicoremem_helper.h"
9
10 // Only allocate local mem chunks to each core.
11 // If a core has used up its local shared memory, start gc.
12 void * localmalloc_I(int coren,
13                      unsigned int isize,
14                      int * allocsize) {
15   for(block_t localblocknum=0;localblocknum<GCNUMLOCALBLOCK;localblocknum++) {
16     block_t searchblock=BLOCKINDEX2(coren, localblocknum);
17     struct blockrecord * block=&allocationinfo.blocktable[searchblock];
18     if (block->status==BS_FREE) {
19       unsigned INTPTR freespace=block->freespace&~BAMBOO_CACHE_LINE_MASK;
20       if (freespace>=memcheck) {
21         //we have a block
22         //mark block as used
23         block->status=BS_USED;
24         void *blockptr=OFFSET2BASEVA(searchblock)+gcbaseva;
25         unsigned INTPTR usedspace=((block->usedspace-1)&~BAMBOO_CACHE_LINE_MASK)+BAMBOO_CACHE_LINE_SIZE;
26         void *startaddr=blockptr+usedspace;
27         *allocsize=freespace;
28         return startaddr;
29       }
30     }
31   }
32   
33   return NULL;
34
35
36 // Allocate the local shared memory to each core with the highest priority,
37 // if a core has used up its local shared memory, try to allocate the 
38 // shared memory that belong to its neighbours, if also failed, start gc.
39 void * fixedmalloc_I(int coren,
40                      unsigned int memcheck,
41                      int * allocsize) {
42   //try locally first
43   void * mem=localmalloc_I(coren,memcheck,allocsize);
44   if (mem!=NULL)
45     return mem;
46
47   //failed try neighbors...in a round robin fashion
48   
49   int minblockindex=allocationinfo.lowestfreeblock/NUMCORES4GC;
50   unsigned INTPTR threshold=(desiredmem<MINMEMORYCHUNKSIZE)? desiredmem: MINMEMORYCHUNKSIZE;
51   unsigned INTPTR memcheck=requiredmem>threshold?requiredmem:threshold;
52   
53   for(block_t lblock=0;lblock<MAXNEIGHBORALLOC;lblock++) {  
54     for(int i=0;i<NUM_CORES2TEST;i++) {
55       int neighborcore=core2test[corenum][i];
56       if (neighborcore!=-1) {
57         block_t globalblockindex=BLOCKINDEX2(neighborcore, lblock);
58         struct blockrecord * block=&allocationinfo.blocktable[globalblockindex];
59         if (block->status==BS_FREE) {
60           unsigned INTPTR freespace=block->freespace&~BAMBOO_CACHE_LINE_MASK;
61           if (memcheck<=freespace) {
62             //we have a block
63             //mark block as used
64             block->status=BS_USED;
65             void *blockptr=OFFSET2BASEVA(globalblockindex)+gcbaseva;
66             unsigned INTPTR usedspace=((block->usedspace-1)&~BAMBOO_CACHE_LINE_MASK)+BAMBOO_CACHE_LINE_SIZE;
67             *allocsize=usedspace;
68             return blockptr+usedspace;
69           }
70         }
71       }
72     }
73   }
74
75   //no memory
76   return NULL;
77
78
79
80 // Allocate the local shared memory to each core with the highest priority,
81 // if a core has used up its local shared memory, try to allocate the 
82 // shared memory that belong to its neighbours first, if failed, check 
83 // current memory allocation rate, if it has already reached the threshold,
84 // start gc, otherwise, allocate the shared memory globally.  If all the 
85 // shared memory has been used up, start gc.
86 void * mixedmalloc_I(int coren,
87                      int isize,
88                      int * allocsize) {
89   void * mem=fixedmalloc_I(coren,isize,allocsize);
90   if (mem!=NULL)
91     return mem;
92
93   //try global allocator instead
94   return globalmalloc_I(coren, isize, allocsite);
95
96
97
98 // Allocate all the memory chunks globally, do not consider the host cores
99 // When all the shared memory are used up, start gc.
100 void * globalmalloc_I(int coren, unsigned INTPTR memcheck, int * allocsize) {
101   block_t firstfree=NOFREEBLOCK;
102   block_t lowestblock=allocationinfo.lowestfreeblock;
103
104   for(block_t searchblock=lowestblock;searchblock<GCNUMBLOCK;searchblock++) {
105     struct blockrecord * block=&allocationinfo.blocktable[searchblock];
106     if (block->status==BS_FREE) {
107       if(firstfree==NOFREEBLOCK)
108         firstfree=searchblock;
109       unsigned INTPTR freespace=block->freespace&~BAMBOO_CACHE_LINE_MASK;
110       if (freespace>=memcheck) {
111         //we have a block
112         //mark block as used
113         block->status=BS_USED;
114         void *blockptr=OFFSET2BASEVA(searchblock)+gcbaseva;
115         unsigned INTPTR usedspace=((block->usedspace-1)&~BAMBOO_CACHE_LINE_MASK)+BAMBOO_CACHE_LINE_SIZE;
116         allocationinfo.lowestfreeblock=firstfree;
117         void *startaddr=blockptr+usedspace;
118         *allocsize=freespace;
119         return startaddr;
120       }
121     }
122   }
123   return NULL;
124
125
126 void * smemalloc(int coren, int isize, int * allocsize) {
127   BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
128   void *retval=smemalloc_I(coren, isize, allocsize);
129   BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
130   return retval;
131 }
132
133 // malloc from the shared memory
134 void * smemalloc_I(int coren, int isize, int * allocsize) {
135 #ifdef SMEML
136   void *mem = localmalloc_I(coren, isize, allocsize);
137 #elif defined(SMEMF)
138   void *mem = fixedmalloc_I(coren, isize, allocsize);
139 #elif defined(SMEMM)
140   void *mem = mixedmalloc_I(coren, isize, allocsize);
141 #elif defined(SMEMG)
142   void *mem = globalmalloc_I(coren, isize, allocsize);
143 #endif
144
145   if(mem == NULL) {
146     // not enough shared global memory
147     // trigger gc
148     if(!gcflag) {
149       gcflag = true;
150       if(!gc_status_info.gcprocessing) {
151         // inform other cores to stop and wait for gc
152         gcprecheck = true;
153         for(int i = 0; i < NUMCORESACTIVE; i++) {
154           // reuse the gcnumsendobjs & gcnumreceiveobjs
155           gcnumsendobjs[0][i] = 0;
156           gcnumreceiveobjs[0][i] = 0;
157         }
158         GC_SEND_MSG_1_TO_CLIENT(GCSTARTPRE);
159       }
160     }
161     return NULL;
162   }
163   return mem;
164 }
165 #else
166 // malloc from the shared memory
167 void * smemalloc_I(int coren,
168                    int size,
169                    int * allocsize) {
170   void * mem = NULL;
171   int toallocate = (size>(BAMBOO_SMEM_SIZE)) ? (size) : (BAMBOO_SMEM_SIZE);
172   if(toallocate > bamboo_free_smem_size) {
173     // no enough mem
174     mem = NULL;
175   } else {
176     mem = (void *)bamboo_free_smemp;
177     bamboo_free_smemp = ((void*)bamboo_free_smemp) + toallocate;
178     bamboo_free_smem_size -= toallocate;
179   }
180   *allocsize = toallocate;
181   if(mem == NULL) {
182     // no enough shared global memory
183     *allocsize = 0;
184     BAMBOO_EXIT();
185   }
186   return mem;
187
188 #endif // MULTICORE_GC
189
190 #endif // MULTICORE