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