d4b5813df0596554a5664335cd0967d437b11bb3
[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 INLINE 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 INLINE 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(!checkMark(objptr)) {
65       // this is the first time that this object is discovered,
66       // set the flag as DISCOVERED
67
68       setMark(objptr);
69       gc_enqueue(objptr);
70     }
71   } else {
72     // check if this obj has been forwarded already
73     if(MGCHashadd(gcforwardobjtbl, (unsigned int)objptr)) {
74       // if not, send msg to host informing that objptr is active
75       send_msg_2(host,GCMARKEDOBJ,objptr);
76       GCPROFILE_RECORD_FORWARD_OBJ();
77       gcself_numsendobjs++;
78     }
79   }
80 }
81
82 void markgarbagelist(struct garbagelist * listptr) {
83   for(;listptr!=NULL;listptr=listptr->next) {
84     int size=listptr->size;
85     for(int i=0; i<size; i++) {
86       MARKOBJ(listptr->array[i]);
87     }
88   }
89 }
90
91 // enqueue root objs
92 void tomark(struct garbagelist * stackptr) {
93   BAMBOO_ASSERT(MARKPHASE == gc_status_info.gcphase);
94   
95   gc_status_info.gcbusystatus = true;
96   
97   // enqueue current stack
98   markgarbagelist(stackptr);
99   
100   // enqueue static pointers global_defs_p
101   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
102     markgarbagelist((struct garbagelist *)global_defs_p);
103   }
104   
105 #ifdef TASK
106   // enqueue objectsets
107   if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
108     for(int i=0; i<NUMCLASSES; i++) {
109       struct parameterwrapper ** queues = objectqueues[BAMBOO_NUM_OF_CORE][i];
110       int length = numqueues[BAMBOO_NUM_OF_CORE][i];
111       for(int j = 0; j < length; ++j) {
112         struct parameterwrapper * parameter = queues[j];
113         struct ObjectHash * set=parameter->objectset;
114         struct ObjectNode * ptr=set->listhead;
115         for(;ptr!=NULL;ptr=ptr->lnext) {
116           MARKOBJNONNULL((void *)ptr->key);
117         }
118       }
119     }
120   }
121   
122   // enqueue current task descriptor
123   if(currtpd != NULL) {
124     for(int i=0; i<currtpd->numParameters; i++) {
125       // currtpd->parameterArray[i] can not be NULL
126       MARKOBJNONNULL(currtpd->parameterArray[i]);
127     }
128   }
129
130   // enqueue active tasks
131   if(activetasks != NULL) {
132     struct genpointerlist * ptr=activetasks->list;
133     for(;ptr!=NULL;ptr=ptr->inext) {
134       struct taskparamdescriptor *tpd=ptr->src;
135       for(int i=0; i<tpd->numParameters; i++) {
136         // the tpd->parameterArray[i] can not be NULL
137         MARKOBJNONNULL(tpd->parameterArray[i]);
138       }
139     }
140   }
141
142   // enqueue cached transferred obj
143   struct QueueItem * tmpobjptr =  getHead(&objqueue);
144   for(;tmpobjptr != NULL;tmpobjptr=getNextQueueItem(tmpobjptr)) {
145     struct transObjInfo * objInfo=(struct transObjInfo *)(tmpobjptr->objectptr);
146     // the objptr can not be NULL
147     MARKOBJNONNULL(objInfo->objptr);
148   }
149
150   // enqueue cached objs to be transferred
151   struct QueueItem * item = getHead(totransobjqueue);
152   for(;item != NULL;item=getNextQueueItem(item)) {
153     struct transObjInfo * totransobj=(struct transObjInfo *)(item->objectptr);
154     // the objptr can not be NULL
155     MARKOBJNONNULL(totransobj->objptr);
156   }
157
158   // enqueue lock related info
159   for(int i = 0; i < runtime_locklen; i++) {
160     MARKOBJ((void *)(runtime_locks[i].redirectlock));
161     MARKOBJ((void *)(runtime_locks[i].value));
162   }
163 #endif 
164
165 #ifdef MGC
166   // enqueue global thread queue
167   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
168     lockthreadqueue();
169     unsigned int thread_counter = *((unsigned int*)(bamboo_thread_queue+1));
170     if(thread_counter > 0) {
171       unsigned int start = *((unsigned int*)(bamboo_thread_queue+2));
172       for(int i = thread_counter; i > 0; i--) {
173         // the thread obj can not be NULL
174         MARKOBJNONNULL((void *)bamboo_thread_queue[4+start]);
175         start = (start+1)&bamboo_max_thread_num_mask;
176       }
177     }
178   }
179
180   // enqueue the bamboo_threadlocks
181   for(int i = 0; i < bamboo_threadlocks.index; i++) {
182     // the locks can not be NULL
183     MARKOBJNONNULL((void *)(bamboo_threadlocks.locks[i].object));
184   }
185
186   // enqueue the bamboo_current_thread
187   MARKOBJ(bamboo_current_thread);
188 #endif
189 }
190
191 INLINE void scanPtrsInObj(void * ptr, int type) {
192   // scan all pointers in ptr
193   unsigned int * pointer = pointerarray[type];
194   if (pointer==0) {
195     /* Array of primitives */
196 #ifdef OBJECTHASPOINTERS
197     pointer=pointerarray[OBJECTTYPE];
198     //handle object class
199     int size=pointer[0];
200     for(int i=1; i<=size; i++) {
201       unsigned int offset=pointer[i];
202       void * objptr=*((void **)(((char *)ptr)+offset));
203       MARKOBJ(objptr);
204     }
205 #endif
206   } else if (((unsigned int)pointer)==1) {
207     /* Array of pointers */
208     struct ArrayObject *ao=(struct ArrayObject *) ptr;
209     int length=ao->___length___;
210     for(int i=0; i<length; i++) {
211       void *objptr=((void **)(((char *)&ao->___length___)+sizeof(int)))[i];
212       MARKOBJ(objptr);
213     }
214 #ifdef OBJECTHASPOINTERS
215     pointer=pointerarray[OBJECTTYPE];
216     //handle object class
217     int size=pointer[0];
218     for(int i=1; i<=size; i++) {
219       unsigned int offset=pointer[i];
220       void * objptr=*((void **)(((char *)ptr)+offset));
221       MARKOBJ(objptr);
222     }
223 #endif
224   } else {
225     /* Normal Object */
226     int size=pointer[0];
227     for(int i=1; i<=size; i++) {
228       unsigned int offset=pointer[i];
229       void * objptr=*((void **)(((char *)ptr)+offset));
230       MARKOBJ(objptr);
231     }
232   }
233 }
234
235 void mark(struct garbagelist * stackptr) {
236   // enqueue root objs
237   tomark(stackptr);
238
239   unsigned int isize = 0;
240   bool sendStall = false;
241   // mark phase
242   while(MARKPHASE == gc_status_info.gcphase) {
243     int counter = 0;
244     while(gc_moreItems()) {
245       sendStall = false;
246       gc_status_info.gcbusystatus = true;
247       void * ptr = gc_dequeue();
248       unsigned int size = 0;
249       unsigned int type = 0;
250       bool islarge=isLarge(ptr, &type, &size);
251       unsigned int iunits = ALIGNUNITS(size);
252
253       //debugging for the next five lines
254
255       setLengthMarked(ptr,iunits);
256
257       if(islarge) {
258         // ptr is a large object and not marked or enqueued
259         printf("NEED TO SUPPORT LARGE OBJECTS!\n");
260       } else {
261         // ptr is an unmarked active object on this core
262         unsigned int isize=iunits<<ALIGNMENTSHIFT;
263         gccurr_heaptop += isize;
264       }
265       // scan the pointers in object
266       scanPtrsInObj(ptr, type);
267     }
268
269     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
270     //make sure the queue is still empty...now we have interrupts off, things can't change on us...
271
272     if (!gc_moreItems_I()) {
273       gc_status_info.gcbusystatus = false;
274       // send mark finish msg to core coordinator
275       if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
276         int entry_index = waitconfirm ? (gcnumsrobjs_index==0) : gcnumsrobjs_index;
277         gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
278         gcnumsendobjs[entry_index][BAMBOO_NUM_OF_CORE]=gcself_numsendobjs;
279         gcnumreceiveobjs[entry_index][BAMBOO_NUM_OF_CORE]=gcself_numreceiveobjs;
280         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
281         checkMarkStatus();
282       } else {
283         if(!sendStall) {
284           send_msg_4(STARTUPCORE,GCFINISHMARK,BAMBOO_NUM_OF_CORE,gcself_numsendobjs,gcself_numreceiveobjs);
285           sendStall = true;
286         }
287         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
288       }
289     }
290   }
291
292
293 #endif // MULTICORE_GC