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