more changes
[IRC.git] / Robust / src / Runtime / bamboo / multicoregccompact.c
1 #ifdef MULTICORE_GC
2 #include "multicoregccompact.h"
3 #include "runtime_arch.h"
4 #include "multicoreruntime.h"
5 #include "multicoregarbage.h"
6 #include "markbit.h"
7
8 bool gc_checkCoreStatus() {
9   for(int i = 0; i < NUMCORES4GC; ++i) {
10     if(gccorestatus[i] != 0) {
11       return false;
12     }
13   }  
14   return true;
15 }
16
17 void gc_resetCoreStatus() {
18   for(int i = 0; i < NUMCORES4GC; ++i) {
19     gccorestatus[i] = 1;
20   }
21 }
22
23 void initOrig_Dst(struct moveHelper * orig,struct moveHelper * to) {
24   // init the dst ptr
25   to->localblocknum = 0;
26   BASEPTR(to->base, BAMBOO_NUM_OF_CORE, to->localblocknum);
27   to->ptr = to->base;
28   to->bound=to->base+BLOCKSIZE(to->localblocknum);
29   
30   // init the orig ptr
31   orig->localblocknum = 0;
32   orig->ptr=orig->base = to->base;
33   orig->bound = orig->base + BLOCKSIZE(orig->localblocknum);
34 }
35
36 void getSpaceLocally(struct moveHelper *to) {
37   //we have space on our core...just keep going
38   to->localblocknum++;
39   BASEPTR(to->base,BAMBOO_NUM_OF_CORE, to->localblocknum);
40   to->ptr=to->base;
41   to->bound = to->base + BLOCKSIZE(to->localblocknum);
42 }
43
44 void getSpaceRemotely(struct moveHelper *to, unsigned int minimumbytes) {
45   //need to get another block from elsewhere
46   //set flag to wait for memory
47   gctomove=false;
48   //send request for memory
49   send_msg_3(STARTUPCORE,GCFINISHCOMPACT,BAMBOO_NUM_OF_CORE, minimumbytes);
50   //wait for flag to be set that we received message
51   while(!gctomove) ;
52
53   //store pointer
54   to->ptr = gcmovestartaddr;
55
56   //set localblock number to high number to indicate this block isn't local
57   to->localblocknum = MAXBLOCK;
58   unsigned int globalblocknum;
59   BLOCKINDEX(globalblocknum, to->ptr);
60   to->base = gcbaseva + OFFSET2BASEVA(globalblocknum);
61   to->bound = gcbaseva + BOUNDPTR(globalblocknum);
62 }
63
64 void getSpace(struct moveHelper *to, unsigned int minimumbytes) {
65   //need more space to compact into
66   if (to->localblocknum < gcblock2fill) {
67     getSpaceLocally(to);
68   } else {
69     getSpaceRemotely(to, minimumbytes);
70   }
71 }
72
73 void compacthelper(struct moveHelper * orig,struct moveHelper * to) {
74   bool senttopmessage=false;
75   while(true) {
76     if ((gcheaptop < ((unsigned INTPTR)(to->bound-to->ptr)))&&!senttopmessage) {
77       //This block is the last for this core...let the startup know
78       send_msg_3(STARTUPCORE, GCRETURNMEM, BAMBOO_NUM_OF_CORE, to->ptr+gcheaptop);
79       //Only send the message once
80       senttopmessage=true;
81     }
82
83     unsigned int minimumbytes=compactblocks(orig, to);
84     if (orig->ptr==orig->bound) {
85       //need more data to compact
86       //increment the core
87       orig->localblocknum++;
88       BASEPTR(orig->base,BAMBOO_NUM_OF_CORE, orig->localblocknum);
89       orig->ptr=orig->base;
90       orig->bound = orig->base + BLOCKSIZE(orig->localblocknum);
91       if (orig->base >= gcbaseva+BAMBOO_SHARED_MEM_SIZE)
92         break;
93     }
94     if (minimumbytes!=0) {
95       getSpace(to, minimumbytes);
96     }
97   }
98   
99   send_msg_3(STARTUPCORE,GCFINISHCOMPACT,BAMBOO_NUM_OF_CORE, 0);
100 }
101
102 /* Should be invoked with interrupt turned off. */
103
104 void * assignSpareMem_I(unsigned int sourcecore, unsigned int requiredmem) {
105   return NULL;
106 }
107
108 void * assignSpareMem(unsigned int sourcecore,unsigned int requiredmem) {
109   BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
110   void * retval=assignSpareMem_I(sourcecore, requiredmem);
111   BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
112   return retval;
113 }
114
115 /* should be invoked with interrupt turned off */
116
117 void * gcfindSpareMem_I(unsigned int requiredmem,unsigned int requiredcore) {
118   void * startaddr;
119   for(int k = 0; k < NUMCORES4GC; k++) {
120     
121   }
122   // If we cannot find spare mem right now, hold the request
123   gcrequiredmems[requiredcore] = requiredmem;
124   gcmovepending++;
125   return NULL;
126
127
128 bool gcfindSpareMem(unsigned int requiredmem,unsigned int requiredcore) {
129   BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
130   bool retval=gcfindSpareMem_I(requiredmem, requiredcore);
131   BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
132   return retval;
133 }
134
135 /* This function is performance critical...  spend more time optimizing it */
136
137 unsigned int compactblocks(struct moveHelper * orig, struct moveHelper * to) {
138   void *toptrinit=to->ptr;
139   void *toptr=toptr;
140   void *tobound=to->bound;
141   void *origptr=orig->ptr;
142   void *origbound=orig->bound;
143   unsigned INTPTR origendoffset=ALIGNTOTABLEINDEX((unsigned INTPTR)(origbound-gcbaseva));
144   unsigned int objlength;
145
146   while(origptr<origbound) {
147     //Try to skip over stuff fast first
148     unsigned INTPTR offset=(unsigned INTPTR) (origptr-gcbaseva);
149     unsigned INTPTR arrayoffset=ALIGNTOTABLEINDEX(offset);
150     if (!gcmarktbl[arrayoffset]) {
151       do {
152         arrayoffset++;
153         if (arrayoffset<origendoffset) {
154           //finished with block...
155           origptr=origbound;
156           to->ptr=toptr;
157           orig->ptr=origptr;
158           gcheaptop-=(unsigned INTPTR)(toptr-toptrinit)
159           return 0;
160         }
161       } while(!gcmarktbl[arrayoffset]);
162       origptr=CONVERTTABLEINDEXTOPTR(arrayoffset);
163     }
164
165     //Scan more carefully next
166     objlength=getMarkedLength(origptr);
167
168     if (objlength!=NOTMARKED) {
169       unsigned int length=ALIGNSIZETOBYTES(objlength);
170       void *endtoptr=toptr+length;
171       if (endtoptr>tobound) {
172         gcheaptop-=(unsigned INTPTR)(toptr-toptrinit)   
173         to->ptr=tobound;
174         orig->ptr=origptr;
175         return length;
176       }
177       //good to move objects and update pointers
178       gcmappingtbl[OBJMAPPINGINDEX(origptr)]=toptr;
179       origptr+=length;
180       toptr=endtoptr;
181     } else
182       origptr+=ALIGNMENTSIZE;
183   }
184 }
185
186 void compact() {
187   BAMBOO_ASSERT(COMPACTPHASE == gc_status_info.gcphase);
188   BAMBOO_CACHE_MF();
189   
190   // initialize structs for compacting
191   struct moveHelper orig={0,NULL,NULL,0,NULL,0,0,0,0};
192   struct moveHelper to={0,NULL,NULL,0,NULL,0,0,0,0};
193   initOrig_Dst(&orig, &to);
194
195   CACHEADAPT_SAMPLING_DATA_REVISE_INIT(&orig, &to);
196
197   compacthelper(&orig, &to);
198
199
200 void master_compact() {
201   // predict number of blocks to fill for each core
202   void * tmpheaptop = 0;
203   numblockspercore = loadbalance(&tmpheaptop);
204   
205   GC_PRINTF("mark phase finished \n");
206   
207   gc_resetCoreStatus();
208   //initialize local data structures first....we don't want remote requests messing data up
209   unsigned int initblocks=numblockspercore*NUMCORES4GC;
210   allocationinfo.lowestfreeblock=NOFREEBLOCKS;
211
212   //assigned blocks
213   for(int i=0;i<initblocks;i++) {
214     allocationinfo.blocktable[i].status=BS_INIT;
215   }
216
217   //free blocks
218   for(int i=initblocks;i<GCNUMBLOCK;i++) {
219     allocationinfo.blocktable[i].status=BS_FREE;
220     allocationinfo.blocktable[i].usedspace=0;
221   }
222
223   //start all of the cores
224   for(int i = 0; i < NUMCORES4GC; i++) {
225     // init some data strutures for compact phase
226     gcrequiredmems[i] = 0;
227     gccorestatus[i] = 1;
228     //send start compact messages to all cores
229     if(i != STARTUPCORE) {
230       send_msg_2(i, GCSTARTCOMPACT, numblockspercore);
231     } else {
232       gcblock2fill = numblockspercore;
233     }
234   }
235   BAMBOO_CACHE_MF();
236   GCPROFILE_ITEM();
237   // compact phase
238   compact();
239   /* wait for all cores to finish compacting */
240
241   while(gc_checkCoreStatus())
242     ;
243
244   GCPROFILE_ITEM();
245
246   GC_PRINTF("compact phase finished \n");
247 }
248
249 #endif // MULTICORE_GC