Some code clean and make the cache adapt version compile
[IRC.git] / Robust / src / Runtime / bamboo / multicoregcmark.c
1 #ifdef MULTICORE_GC
2 #include "multicoregcmark.h"
3 #include "runtime.h"
4 #include "multicoreruntime.h"
5 #include "GenericHashtable.h"
6 #include "gcqueue.h"
7
8 #ifdef TASK
9 extern struct parameterwrapper ** objectqueues[][NUMCLASSES];
10 extern int numqueues[][NUMCLASSES];
11 extern struct genhashtable * activetasks;
12 extern struct parameterwrapper ** objectqueues[][NUMCLASSES];
13 extern struct taskparamdescriptor *currtpd;
14 extern struct LockValue runtime_locks[MAXTASKPARAMS];
15 extern int runtime_locklen;
16 #endif
17
18 extern struct global_defs_t * global_defs_p;
19
20 #ifdef SMEMM
21 extern unsigned int gcmem_mixed_threshold;
22 extern unsigned int gcmem_mixed_usedmem;
23 #endif
24
25 #ifdef MGC
26 extern struct lockvector bamboo_threadlocks;
27 #endif
28
29 INLINE void gettype_size(void * ptr, int * ttype, unsigned int * tsize) {
30   int type = ((int *)ptr)[0];
31   unsigned int size;
32   if(type < NUMCLASSES) {
33     // a normal object
34     *tsize = classsize[type];
35     *ttype = type;
36   } else {
37     // an array
38     struct ArrayObject *ao=(struct ArrayObject *)ptr;
39     unsigned int elementsize=classsize[type];
40     unsigned int length=ao->___length___;
41     *tsize = sizeof(struct ArrayObject)+length*elementsize;
42     *ttype = type;
43   } 
44 }
45
46 INLINE bool isLarge(void * ptr, int * ttype, unsigned int * tsize) {
47   // check if a pointer is referring to a large object
48   gettype_size(ptr, ttype, tsize);
49   unsigned int bound = (BAMBOO_SMEM_SIZE);
50   if(((unsigned int)ptr-gcbaseva) < (BAMBOO_LARGE_SMEM_BOUND)) {
51     bound = (BAMBOO_SMEM_SIZE_L);
52   }
53   // ptr is a start of a block  OR it acrosses the boundary of current block
54   return (((((unsigned int)ptr-gcbaseva)%(bound))==0)||
55           ((bound-(((unsigned int)ptr-gcbaseva)%bound)) < (*tsize)));
56
57
58 INLINE unsigned int hostcore(void * ptr) {
59   // check the host core of ptr
60   unsigned int host = 0;
61   RESIDECORE(ptr, &host);
62   return host;
63
64
65 //push the null check into the mark macro
66 //#define MARKOBJ(objptr, ii) {void * marktmpptr=objptr; if (marktmpptr!=NULL) markObj(marktmpptr, __LINE__, ii);}
67
68 //#define MARKOBJNONNULL(objptr, ii) {markObj(objptr, __LINE__, ii);}
69
70 #define MARKOBJ(objptr, ii) {void * marktmpptr=objptr; if (marktmpptr!=NULL) markObj(marktmpptr);}
71
72 #define MARKOBJNONNULL(objptr, ii) {markObj(objptr);}
73
74 // NOTE: the objptr should not be NULL and should be a shared obj
75 INLINE void markObj(void * objptr) {
76   unsigned int host = hostcore(objptr);
77   if(BAMBOO_NUM_OF_CORE == host) {
78     // on this core
79     if(((struct ___Object___ *)objptr)->marked == INIT) {
80       // this is the first time that this object is discovered,
81       // set the flag as DISCOVERED
82       ((struct ___Object___ *)objptr)->marked = DISCOVERED;
83       BAMBOO_CACHE_FLUSH_LINE(objptr);
84       gc_enqueue(objptr);
85     }
86   } else {
87     // check if this obj has been forwarded
88     if(!MGCHashcontains(gcforwardobjtbl, (int)objptr)) {
89       // send a msg to host informing that objptr is active
90       send_msg_2(host,GCMARKEDOBJ,objptr);
91       GCPROFILE_RECORD_FORWARD_OBJ();
92       gcself_numsendobjs++;
93       MGCHashadd(gcforwardobjtbl, (int)objptr);
94     }
95   }
96
97
98 INLINE void markgarbagelist(struct garbagelist * listptr) {
99   for(;listptr!=NULL;listptr=listptr->next) {
100     int size=listptr->size;
101     for(int i=0; i<size; i++) {
102       MARKOBJ(listptr->array[i], i);
103     }
104   }
105 }
106
107 // enqueue root objs
108 INLINE void tomark(struct garbagelist * stackptr) {
109   BAMBOO_ASSERT(MARKPHASE == gc_status_info.gcphase);
110
111   gc_status_info.gcbusystatus = true;
112   gcnumlobjs = 0;
113
114   // enqueue current stack
115   markgarbagelist(stackptr);
116
117   // enqueue static pointers global_defs_p
118   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
119     markgarbagelist((struct garbagelist *)global_defs_p);
120   }
121
122 #ifdef TASK
123   // enqueue objectsets
124   if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
125     for(int i=0; i<NUMCLASSES; i++) {
126       struct parameterwrapper ** queues = objectqueues[BAMBOO_NUM_OF_CORE][i];
127       int length = numqueues[BAMBOO_NUM_OF_CORE][i];
128       for(int j = 0; j < length; ++j) {
129         struct parameterwrapper * parameter = queues[j];
130         struct ObjectHash * set=parameter->objectset;
131         struct ObjectNode * ptr=set->listhead;
132         for(;ptr!=NULL;ptr=ptr->lnext) {
133           MARKOBJNONNULL((void *)ptr->key, 0);
134         }
135       }
136     }
137   }
138
139   // euqueue current task descriptor
140   if(currtpd != NULL) {
141     for(int i=0; i<currtpd->numParameters; i++) {
142       // currtpd->parameterArray[i] can not be NULL
143       MARKOBJNONNULL(currtpd->parameterArray[i], i);
144     }
145   }
146
147   // euqueue active tasks
148   if(activetasks != NULL) {
149     struct genpointerlist * ptr=activetasks->list;
150     for(;ptr!=NULL;ptr=ptr->inext) {
151       struct taskparamdescriptor *tpd=ptr->src;
152       for(int i=0; i<tpd->numParameters; i++) {
153         // the tpd->parameterArray[i] can not be NULL
154         MARKOBJNONNULL(tpd->parameterArray[i], i);
155       }
156     }
157   }
158
159   // enqueue cached transferred obj
160   struct QueueItem * tmpobjptr =  getHead(&objqueue);
161   for(;tmpobjptr != NULL;tmpobjptr=getNextQueueItem(tmpobjptr)) {
162     struct transObjInfo * objInfo=(struct transObjInfo *)(tmpobjptr->objectptr);
163     // the objptr can not be NULL
164     MARKOBJNONNULL(objInfo->objptr, 0);
165   }
166
167   // enqueue cached objs to be transferred
168   struct QueueItem * item = getHead(totransobjqueue);
169   for(;item != NULL;item=getNextQueueItem(item)) {
170     struct transObjInfo * totransobj=(struct transObjInfo *)(item->objectptr);
171     // the objptr can not be NULL
172     MARKOBJNONNULL(totransobj->objptr, 0);
173   }
174
175   // enqueue lock related info
176   for(int i = 0; i < runtime_locklen; i++) {
177     MARKOBJ((void *)(runtime_locks[i].redirectlock), 0);
178     MARKOBJ((void *)(runtime_locks[i].value), i);
179   }
180 #endif 
181
182 #ifdef MGC
183   // enqueue global thread queue
184   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
185     lockthreadqueue();
186     unsigned int thread_counter = *((unsigned int*)(bamboo_thread_queue+1));
187     if(thread_counter > 0) {
188       unsigned int start = *((unsigned int*)(bamboo_thread_queue+2));
189       for(int i = thread_counter; i > 0; i--) {
190         // the thread obj can not be NULL
191         MARKOBJNONNULL((void *)bamboo_thread_queue[4+start], 0);
192         start = (start+1)&bamboo_max_thread_num_mask;
193       }
194     }
195   }
196
197   // enqueue the bamboo_threadlocks
198   for(int i = 0; i < bamboo_threadlocks.index; i++) {
199     // the locks can not be NULL
200     MARKOBJNONNULL((void *)(bamboo_threadlocks.locks[i].object), i);
201   }
202
203   // enqueue the bamboo_current_thread
204   MARKOBJ((void *)bamboo_current_thread, 0);
205 #endif
206 }
207
208 INLINE void scanPtrsInObj(void * ptr, int type) {
209   // scan all pointers in ptr
210   unsigned int * pointer = pointerarray[type];
211   if (pointer==0) {
212     /* Array of primitives */
213 #ifdef OBJECTHASPOINTERS
214     pointer=pointerarray[OBJECTTYPE];
215     //handle object class
216     int size=pointer[0];
217     for(int i=1; i<=size; i++) {
218       unsigned int offset=pointer[i];
219       void * objptr=*((void **)(((char *)ptr)+offset));
220       MARKOBJ(objptr, i);
221     }
222 #endif
223   } else if (((unsigned int)pointer)==1) {
224     /* Array of pointers */
225     struct ArrayObject *ao=(struct ArrayObject *) ptr;
226     int length=ao->___length___;
227     for(int i=0; i<length; i++) {
228       void *objptr=((void **)(((char *)&ao->___length___)+sizeof(int)))[i];
229       MARKOBJ(objptr, i);
230     }
231 #ifdef OBJECTHASPOINTERS
232     pointer=pointerarray[OBJECTTYPE];
233     //handle object class
234     int size=pointer[0];
235     for(int i=1; i<=size; i++) {
236       unsigned int offset=pointer[i];
237       void * objptr=*((void **)(((char *)ptr)+offset));
238       MARKOBJ(objptr, i);
239     }
240 #endif
241   } else {
242     /* Normal Object */
243     int size=pointer[0];
244     for(int i=1; i<=size; i++) {
245       unsigned int offset=pointer[i];
246       void * objptr=*((void **)(((char *)ptr)+offset));
247       MARKOBJ(objptr, i);
248     }
249   }
250 }
251
252 INLINE void mark(bool isfirst, struct garbagelist * stackptr) {
253   if(isfirst) {
254     // enqueue root objs
255     tomark(stackptr);
256     gccurr_heaptop = 0; // record the size of all active objs in this core
257                         // aligned but does not consider block boundaries
258     gcmarkedptrbound = 0;
259   }
260   unsigned int isize = 0;
261   bool sendStall = false;
262   // mark phase
263   while(MARKPHASE == gc_status_info.gcphase) {
264     int counter = 0;
265     while(gc_moreItems2()) {
266       sendStall = false;
267       gc_status_info.gcbusystatus = true;
268       unsigned int ptr = gc_dequeue2();
269
270       unsigned int size = 0;
271       unsigned int isize = 0;
272       unsigned int type = 0;
273       // check if it is a local obj on this core
274       if(((struct ___Object___ *)ptr)->marked!=DISCOVERED) {
275         // ptr has been marked
276         continue;
277       } else if(isLarge(ptr, &type, &size)) {
278         // ptr is a large object and not marked or enqueued
279         gc_lobjenqueue(ptr, size, BAMBOO_NUM_OF_CORE);
280         gcnumlobjs++;
281       } else {
282         // ptr is an unmarked active object on this core
283         ALIGNSIZE(size, &isize);
284         gccurr_heaptop += isize;
285         
286         if((unsigned int)(ptr + size) > (unsigned int)gcmarkedptrbound) {
287           gcmarkedptrbound = (unsigned int)(ptr + size);
288         }
289       }
290       // mark this obj
291       ((struct ___Object___ *)ptr)->marked = MARKED;
292       BAMBOO_CACHE_FLUSH_LINE(ptr);
293       // scan the pointers in object
294       scanPtrsInObj(ptr, type);      
295     }   
296     gc_status_info.gcbusystatus = false;
297     // send mark finish msg to core coordinator
298     if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
299       int entry_index = waitconfirm ? (gcnumsrobjs_index==0) : gcnumsrobjs_index;
300       gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
301       gcnumsendobjs[entry_index][BAMBOO_NUM_OF_CORE]=gcself_numsendobjs;
302       gcnumreceiveobjs[entry_index][BAMBOO_NUM_OF_CORE]=gcself_numreceiveobjs;
303       gcloads[BAMBOO_NUM_OF_CORE] = gccurr_heaptop;
304     } else {
305       if(!sendStall) {
306         send_msg_4(STARTUPCORE,GCFINISHMARK,BAMBOO_NUM_OF_CORE,gcself_numsendobjs,gcself_numreceiveobjs);
307         sendStall = true;
308       }
309     }
310     
311     if(BAMBOO_NUM_OF_CORE == STARTUPCORE)
312       return;
313   }
314
315   BAMBOO_CACHE_MF();
316
317
318 #endif // MULTICORE_GC