initial multicore gargbage collection, not finish yet
[IRC.git] / Robust / src / Runtime / multicoregarbage.c
1 #ifdef MULTICORE_GC
2 #include "multicoregarbage.h"
3 #include "multicoreruntime.h"
4 #include "runtime_arch.h"
5 #include "SimpleHash.h"
6 #include "GenericHashtable.h"
7
8 extern struct genhashtable * activetasks;
9 extern struct parameterwrapper ** objectqueues[][NUMCLASSES];
10 extern struct taskparamdescriptor *currtpd;
11 //extern struct RuntimeHash *fdtoobject;
12
13 struct largeObjList lObjList;
14 struct markedObjList mObjList;
15 INTPTR curr_heaptop = 0;
16
17 struct markedObjList {
18         struct markedObjItem * head;
19         struct markedObjItem * tail;
20 };
21
22 struct largeObjList {
23         struct largeObjItem * head;
24         struct largeObjItem * tail;
25 };
26
27 bool isLarge(void * ptr, int * ttype, int * tsize) {
28         // check if a pointer is referring to a large object
29         int type = ((int *)ptr)[0];
30         int size = 0;
31         if(type < NUMCLASSES) {
32                 // a normal object
33                 size = classsize[type];
34         } else {        
35                 // an array 
36                 struct ArrayObject *ao=(struct ArrayObject *)ptr;
37                 int elementsize=classsize[type];
38                 int length=ao->___length___; 
39                 size=sizeof(struct ArrayObject)+length*elementsize;
40         }
41         *ttype = type;
42         *tsize = size;
43         return(!isLocal(ptr + size));
44 }
45
46 int hostcore(void * ptr) {
47         // check the host core of ptr
48         int host = 0;
49         int x = 0;
50         int y = 0;
51         RESIDECORE(ptr, &x, &y);
52         host = (x == 0)?(x * bamboo_height + y) : (x * bamboo_height + y - 2);
53         return host;
54 }
55
56 bool isLocal(void * ptr) {
57         // check if a pointer is in shared heap on this core
58         return hostcore(ptr) == BAMBOO_NUM_OF_CORE;
59 }
60
61 void insertMarkedObj(struct markedObjList * list, struct markedObjItem * toinsert) {
62         // insert a markedObjItem
63         struct markedObjItem * tmp = list->head;
64         if(tmp == NULL) {
65                 list->head = toinsert;
66                 list->tail = toinsert;
67         } else if(tmp->orig > toinsert->orig) {
68                 // insert into the head of the list
69                 toinsert->next = tmp;
70                 list->head = toinsert;
71         } else {
72                 struct markedObjItem * next = tmp->next;
73                 while(next != NULL) {
74                         if(next->orig < toinsert->orig) {
75                                 tmp = next;
76                                 next = tmp->next;
77                         } else if((next->orig == toinsert->orig) || (tmp->orig == toinsert->orig)) {
78                                 // has been inserted
79                                 RUNFREE(toinsert);
80                                 toinsert = NULL;
81                                 break;
82                         } else {
83                                 // insert after tmp
84                                 toinsert->next = next;
85                                 tmp->next = tmp;
86                                 break;
87                         }
88                 } // while(next != NULL)
89                 if(next == NULL) {
90                         if(tmp->orig == toinsert->orig) {
91                                 RUNFREE(toinsert);
92                                 toinsert = NULL;
93                         } else {
94                                 // insert to the tail of the list
95                                 tmp->next = toinsert;
96                                 list->tail = toinsert;
97                         }
98                 } // if(next == NULL)
99         }
100 }
101
102 struct markedObjItem * getStartItem(struct markedObjItem * moi, INTPTR start) {
103         // find the markedobj whose start address is start
104         struct markedObjItem * tostart = moi;
105         while(tostart->orig < start) {
106                 tostart = tostart->next;
107         }
108         return tostart;
109 }
110
111 void transferMarkResults() {
112         // TODO, need distiguish between send and cache
113         // invoked inside interruptiong handler
114 }
115
116 void gc() {
117         // core coordinator routine
118         if(0 == BAMBOO_NUM_OF_CORE) {
119                 // change to UDN1
120                 bme_install_interrupt_handler(INT_UDN_AVAIL, gc_msghandler);
121 #ifdef DEBUG
122                 tprintf("Process %x(%d): change udn interrupt handler\n", BAMBOO_NUM_OF_CORE, 
123                                 BAMBOO_NUM_OF_CORE);
124 #endif
125                 __insn_mtspr(SPR_UDN_TAG_1, UDN1_DEMUX_TAG);
126                 // enable udn interrupts
127                 //__insn_mtspr(SPR_INTERRUPT_MASK_RESET_2_1, INT_MASK_HI(INT_UDN_AVAIL));
128                 __insn_mtspr(SPR_UDN_AVAIL_EN, (1<<1));
129                 BAMBOO_CLOSE_CRITICAL_SECTION_MSG();
130
131                 int i = 0;
132                 gcwaitconfirm = false;
133                 gcwaitconfirm = 0;
134                 gcphase = 0;
135                 for(i = 1; i < NUMCORES - 1; i++) {
136                         // send GC start messages to all cores
137                         send_msg_1(true, i, 0x11);
138                 }
139                 bool isfirst = true;
140                 lObjList.head = NULL;
141                 lObjList.tail = NULL;
142                 mObjList.head = NULL;
143                 mObjList.tail = NULL;
144
145                 // mark phase
146                 while(gcphase == 0) {
147                         mark(isfirst);
148                         if(isfirst) {
149                                 isfirst = false;
150                         }
151
152                         bool allStall = false;
153                         // check gcstatus
154                         if((!gcwaitconfirm) || 
155                                         (gcwaitconfirm && (gcnumconfirm == 0))) {
156                                 BAMBOO_START_CRITICAL_SECTION_STATUS();  
157                                 gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
158                                 gcnumsendobjs[BAMBOO_NUM_OF_CORE] = gcself_numsendobjs;
159                                 gcnumreceiveobjs[BAMBOO_NUM_OF_CORE] = gcself_numreceiveobjs;
160                                 // check the status of all cores
161                                 allStall = true;
162                                 for(i = 0; i < NUMCORES; ++i) {
163                                         if(gccorestatus[i] != 0) {
164                                                 allStall = false;
165                                                 break;
166                                         }
167                                 }
168                                 if(allStall) {
169                                         // check if the sum of send objs and receive obj are the same
170                                         // yes->check if the info is the latest; no->go on executing
171                                         int sumsendobj = 0;
172                                         for(i = 0; i < NUMCORES; ++i) {
173                                                 sumsendobj += gcnumsendobjs[i];
174                                         }               
175                                         for(i = 0; i < NUMCORES; ++i) {
176                                                 sumsendobj -= gcnumreceiveobjs[i];
177                                         }
178                                         if(0 == sumsendobj) {
179                                                 if(!gcwaitconfirm) {
180                                                         // the first time found all cores stall
181                                                         // send out status confirm msg to all other cores
182                                                         // reset the corestatus array too
183                                                         gccorestatus[BAMBOO_NUM_OF_CORE] = 1;
184                                                         gcwaitconfirm = true;
185                                                         gcnumconfirm = NUMCORES - 1;
186                                                         for(i = 1; i < NUMCORES; ++i) { 
187                                                                 gccorestatus[i] = 1;
188                                                                 // send mark phase finish confirm request msg to core i
189                                                                 send_msg_1(true, i, 0x18);
190                                                         }
191                                                 } else {
192                                                         // all the core status info are the latest
193                                                         // stop mark phase
194                                                         gcphase = 1;
195                                                         for(i = 0; i < NUMCORES; ++i) {
196                                                                 gccorestatus[i] = 1;
197                                                         }
198                                                 } // if(!gcwautconfirm) else()
199                                         } // if(0 == sumsendobj)
200                                 } // if(allStall)
201                                 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();  
202                         } // if((!gcwaitconfirm)...
203                 }  // while(gcphase == 0)
204                 // send msgs to all cores requiring large objs info
205                 gcnumconfirm = NUMCORES - 1;
206                 for(i = 1; i < NUMCORES; ++i) {
207                         send_msg_1(true, i, 0x1e);
208                 }       
209                 while(gcnumconfirm != 0) {} // wait for responses
210                 // TODO compute load balance
211
212                 // TODO cache all large objects
213                 for(i = 1; i < NUMCORES; ++i) {
214                         //TODO send start compact messages to all cores
215
216                 }
217
218                 // compact phase
219                 compact();
220                 gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
221                 while(gcphase == 1) {
222                         // check the status of all cores
223                         allStall = true;
224                         for(i = 0; i < NUMCORES; ++i) {
225                                 if(gccorestatus[i] != 0) {
226                                         allStall = false;
227                                         break;
228                                 }
229                         }       
230                         if(allStall) {
231                                 for(i = 0; i < NUMCORES; ++i) {
232                                         gccorestatus[i] = 1;
233                                 }
234                                 break;
235                         }
236                 } // while(gcphase == 1)
237                 // TODO merge all mapping information
238                 gcphase = 2;
239                 for(i = 1; i < NUMCORES; ++i) {
240                         // send start flush messages to all cores
241                         send_msg_1(true, i, 0x13);
242                 }
243
244                 // flush phase
245                 flush();
246                 gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
247                 while(gcphase == 2) {
248                         // check the status of all cores
249                         allStall = true;
250                         for(i = 0; i < NUMCORES; ++i) {
251                                 if(gccorestatus[i] != 0) {
252                                         allStall = false;
253                                         break;
254                                 }
255                         }       
256                         if(allStall) {
257                                 break;
258                         }
259                 } // while(gcphase == 2)
260                 // TODO merge all mapping information
261                 gcphase = 3;
262                 for(i = 1; i < NUMCORES; ++i) {
263                         // send gc finish messages to all cores
264                         send_msg_1(true, i, 0x17);
265                 }
266
267                 // change to UDN0
268                 bme_install_interrupt_handler(INT_UDN_AVAIL, udn_inter_handle);
269 #ifdef DEBUG
270                 tprintf("Process %x(%d): change back udn interrupt handler\n", BAMBOO_NUM_OF_CORE, 
271                                 BAMBOO_NUM_OF_CORE);
272 #endif
273                 __insn_mtspr(SPR_UDN_TAG_0, UDN0_DEMUX_TAG);
274                 // enable udn interrupts
275                 //__insn_mtspr(SPR_INTERRUPT_MASK_RESET_2_1, INT_MASK_HI(INT_UDN_AVAIL));
276                 __insn_mtspr(SPR_UDN_AVAIL_EN, (1<<0));
277                 BAMBOO_START_CRITICAL_SECTION_MSG();
278                 
279                 return;
280         } else {
281                 BAMBOO_EXIT(0xb001);
282         }
283 }
284
285 void mark(bool isfirst) {
286         if(isfirst) {
287                 if(gcphase != 0) {
288                         BAMBOO_EXIT(0xb002);
289                 }
290                 gcbusystatus = 1;
291                 // initialize gctomark queue
292                 while(!isEmpty(gctomark)) {
293                         getItem(gctomark);
294                 }
295                 // enqueue current stack  TODO
296                 
297                 // enqueue objectsets
298                 int i;
299             for(i=0; i<NUMCLASSES; i++) {
300                         struct parameterwrapper ** queues=objectqueues[BAMBOO_NUM_OF_CORE][i];
301                         int length = numqueues[BAMBOO_NUM_OF_CORE][i];
302                         for(j = 0; j < length; ++j) {
303                                 struct parameterwrapper * parameter = queues[j];
304                                 struct ObjectHash * set=parameter->objectset;
305                                 struct ObjectNode * ptr=set->listhead;
306                                 while(ptr!=NULL) {
307                                         void *orig=(void *)ptr->key;
308                                         addNewItem(gctomark, orig); 
309                                         ptr=ptr->lnext;
310                                 }
311                         }
312                 }
313                 // euqueue current task descriptor
314                 for(i=0; i<currtpd->numParameters; i++) {
315           void *orig=currtpd->parameterArray[i];
316               addNewItem(gctomark, orig);  
317         }
318                 // euqueue active tasks
319                 struct genpointerlist * ptr=activetasks->list;
320             while(ptr!=NULL) {
321           struct taskparamdescriptor *tpd=ptr->src;
322               int i;
323           for(i=0; i<tpd->numParameters; i++) {
324                           void * orig=tpd->parameterArray[i];
325                           addNewItem(gctomark, orig); 
326           }
327               ptr=ptr->inext;
328             }
329         }
330
331         // mark phase
332         while(gcphase == 0) {
333                 while(!isEmpty(gctomark)) {
334                         voit * ptr = getItem(gctomark);
335                         int size = 0;
336                         int type = 0;
337                         if(isLarge(ptr, &type, &size)) {
338                                 // ptr is a large object
339                                 struct largeObjItem * loi = 
340                                         (struct largeObjItem *)RUNMALLOC(sizeof(struct largeObjItem));  
341                                 loi->orig = (INTPTR)ptr;
342                                 loi->dst = (INTPTR)0;
343                                 loi->length = size;
344                                 if(lObjList.head == NULL) {
345                                         lObjList.head = lObjList.tail = loi;
346                                 } else {
347                                         lObjList.tail->next = loi;
348                                         lObjList.tail = loi;
349                                 }
350                         } else if (isLocal(ptr)) {
351                                 // ptr is an active object on this core
352                                 if(type == -1) {
353                                         // nothing to do 
354                                 }
355                                 curr_heaptop += size;
356                                 struct markedObjItem * moi = 
357                                         (struct markedObjItem *)RUNMALLOC(sizeof(struct markedObjItem)); 
358                                 moi->orig = (INTPTR)ptr;
359                                 moi->dst = (INTPTR)0;
360                                 insertMarkedObj(&mObjList, moi);
361                         }
362                         // scan all pointers in ptr
363                         unsigned INTPTR * pointer;
364                         pointer=pointerarray[type];
365                         if (pointer==0) {
366                                 /* Array of primitives */
367                                 /* Do nothing */
368                         } else if (((INTPTR)pointer)==1) {
369                                 /* Array of pointers */
370                                 struct ArrayObject *ao=(struct ArrayObject *) ptr;
371                                 int length=ao->___length___;
372                                 int j;
373                                 for(j=0; j<length; j++) {
374                                         void *objptr=((void **)(((char *)&ao->___length___)+sizeof(int)))[j];
375                                         int host = hostcore(objptr);
376                                         if(BAMBOO_NUM_OF_CORE == host) {
377                                                 // on this core
378                                                 addNewItem(gctomark, objptr);  
379                                         } else {
380                                                 // send a msg to host informing that objptr is active
381                                                 send_msg_2(true, host, 0x1a, objptr);
382                                                 gcself_numsendobjs++;
383                                         }
384                                 }
385                         } else {
386                                 INTPTR size=pointer[0];
387                                 int i;
388                                 for(i=1; i<=size; i++) {
389                                         unsigned int offset=pointer[i];
390                                         void * objptr=*((void **)(((char *)ptr)+offset));
391                                         int host = hostcore(objptr);
392                                         if(BAMBOO_NUM_OF_CORE == host) {
393                                                 // on this core
394                                                 addNewItem(gctomark, objptr);  
395                                         } else {
396                                                 // send a msg to host informing that objptr is active
397                                                 send_msg_2(true, host, 0x1a, objptr);
398                                                 gcself_numsendobjs++;
399                                         }
400                                 }
401                         }
402                 } // while(!isEmpty(gctomark))
403                 gcbusystatus = false;
404                 // send mark finish msg to core coordinator
405                 send_msg_4(true, STARTUPCORE, 0x14, BAMBOO_NUM_OF_CORE, gcself_numsendobjs, gcself_numreceiveobjs); 
406
407                 if(BAMBOO_NUM_OF_CORE == 0) {
408                         return;
409                 }
410         } // while(gcphase == 0)
411 } // mark()
412
413 void compact() {
414         if(gcphase != 1) {
415                 BAMBOO_EXIT(0xb003);
416         }
417         curr_heaptop = 0;
418         struct markedObjItem * moi = mObjList.head;
419         bool iscopy = true;
420         while(moi != NULL) {
421                 if((cinstruction == NULL) || (cinstruction->tomoveobjs == NULL) 
422                                 || (curr_heaptop < cinstruction->tomoveobjs->starts[0])) {
423                         // objs to compact
424                         int type = ((int *)(moi->orig))[0];
425                         int size = 0;
426                         if(type == -1) {
427                                 // do nothing 
428                         }
429                         if(type < NUMCLASSES) {
430                                 // a normal object
431                                 size = classsize[type];
432                                 moi->dst = curr_heaptop;
433                                 curr_heaptop += size;
434                                 if(iscopy) {
435                                         memcpy(moi->dst, moi->orig, size);
436                                         genputtable(pointertbl, moi->orig, moi->dst);
437                                 }
438                         } else {
439                                 // an array 
440                                 struct ArrayObject *ao=(struct ArrayObject *)ptr;
441                                 int elementsize=classsize[type];
442                                 int length=ao->___length___;
443                                 size=sizeof(struct ArrayObject)+length*elementsize;
444                                 moi->dst = curr_heaptop;
445                                 curr_heaptop += size;
446                                 if(iscopy) {
447                                         memcpy(moi->dst, moi->orig, size);
448                                         genputtable(pointertbl, moi->orig, moi->dst);
449                                 }
450                         }
451                 } else {
452                         iscopy = false;;
453                 }
454                 moi = moi->next;
455         } // while(moi != NULL)
456         if(moi == NULL) {
457                 if(cinstruction->incomingobjs != NULL) {
458                         for(int j = 0; j < cinstruction->incomingobjs->length; j++) {
459                                 // send messages to corresponding cores to start moving
460                                 send_msg_2(true, cinstruction->incomingobjs->dsts[j], 0x1b, BAMBOO_NUM_OF_CORE);
461                         }
462                 }
463         } else {
464                 int num_dsts = cinstruction->tomoveobjs->length;
465                 while(num_dsts > 0) {
466                         while(!gctomove) {}
467                         // start moving objects to other cores
468                         gctomove = 0;
469                         while(!isEmpty(gcdsts)) {
470                                 int dst = (int)(getItem(gcdsts));
471                                 num_dsts--;
472                                 int j = 0;
473                                 for(j = 0; j < cinstruction->tomoveobjs->length; j++) {
474                                         if(dst == cinstruction->tomoveobjs->dsts[j]) {
475                                                 break;
476                                         }
477                                 }
478                                 INTPTR top = cinstruction->tomoveobjs->dststarts[j];
479                                 INTPTR start = cinstruction->tomoveobjs->starts[j];
480                                 INTPTR end = cinstruction->tomoveobjs->ends[j];
481                                 struct markedObjItem * tomove = getStartItem(moi, start);
482                                 do {
483                                         int type = ((int *)(tomove->orig))[0];
484                                         int size = 0;
485                                         if(type == -1) {
486                                                 // do nothing
487                                         }
488                                         if(type < NUMCLASSES) {
489                                                 // a normal object
490                                                 size = classsize[type];
491                                                 moi->dst = top;
492                                                 top += size;
493                                                 memcpy(moi->dst, moi->orig, size);
494                                                 genputtable(pointertbl, moi->orig, moi->dst);
495                                         } else {                                                
496                                                 // an array 
497                                                 struct ArrayObject *ao=(struct ArrayObject *)ptr;
498                                                 int elementsize=classsize[type];
499                                                 int length=ao->___length___;
500                                                 size=sizeof(struct ArrayObject)+length*elementsize;
501                                                 moi->dst = top;
502                                                 top += size;
503                                                 memcpy(moi->dst, moi->orig, size);
504                                                 genputtable(pointertbl, moi->orig, moi->dst);
505                                         }
506                                         tomove = tomove->next;
507                                 } while(tomove->orig < end);
508                         } // while(!isEmpty(gcdsts))
509                 } // while(num_dsts > 0)
510         } // if(moi == NULL) else()
511         if((cinstruction != NULL) && (cinstruction->largeobjs != NULL)) {
512                 // move all large objects
513                 do {
514                         // dequeue the first large obj
515                         struct largeObjItem * loi = cinstruction->largeobjs;
516                         cinstruction->largeobjs = loi->next;
517                         // move this large obj
518                         memcpy(loi->dst, loi->orig, loi->length);
519                         genputtable(pointertbl, loi->orig, loi->dst);
520                         RUNFREE(loi);
521                 }while(cinstruction->largeobjs != NULL);
522         }
523         // send compact finish message to core coordinator
524         send_msg_2(true, STARTUPCORE, 0x15, BAMBOO_NUM_OF_CORE);
525         
526 } // compact()
527
528 void flush() {
529         struct markedObjItem * moi = mObjList.head;
530         while(moi != NULL) {
531                 void * ptr = moi->dst;
532                 int type = ((int *)(ptr))[0];
533                 // scan all pointers in ptr
534                 unsigned INTPTR * pointer;
535                 pointer=pointerarray[type];
536                 if (pointer==0) {
537                         /* Array of primitives */
538                         /* Do nothing */
539                 } else if (((INTPTR)pointer)==1) {
540                         /* Array of pointers */
541                         struct ArrayObject *ao=(struct ArrayObject *) ptr;
542                         int length=ao->___length___;
543                         int j;
544                         for(j=0; j<length; j++) {
545                                 void *objptr=((void **)(((char *)&ao->___length___)+sizeof(int)))[j];
546                                 // change to new address
547                                 void *dstptr = gengettable(pointertbl, objptr);
548                                 if(NULL == dstptr) {
549                                         // send msg to host core for the mapping info
550                                         obj2map = (int)objptr;
551                                         ismapped = false;
552                                         mappedobj = NULL;
553                                         send_msg_3(true, hostcore(objptr), 0x1c, (int)objptr, BAMBOO_NUM_OF_CORE);
554                                         while(!ismapped) {}
555                                         dstptr = mappedobj;
556                                 }
557                                 ((void **)(((char *)&ao->___length___)+sizeof(int)))[j] = dstptr;
558                         }
559                 } else {
560                         INTPTR size=pointer[0];
561                         int i;
562                         for(i=1; i<=size; i++) {
563                                 unsigned int offset=pointer[i];
564                                 void * objptr=*((void **)(((char *)ptr)+offset));
565                                 // change to new address
566                                 void *dstptr = gengettable(pointertbl, objptr);
567                                 if(NULL == dstptr) {
568                                         // send msg to host core for the mapping info
569                                         obj2map = (int)objptr;
570                                         ismapped = false;
571                                         mappedobj = NULL;
572                                         send_msg_3(true, hostcore(objptr), 0x1c, (int)objptr, BAMBOO_NUM_OF_CORE);
573                                         while(!ismapped) {}
574                                         dstptr = mappedobj;
575                                 }
576                                 *((void **)(((char *)ptr)+offset)) = dstptr;
577                         }
578                 }
579                 moi = moi->next;
580         } // while(moi != NULL)
581         // send flush finish message to core coordinator
582         send_msg_2(true, STARTUPCORE, 0x16, BAMBOO_NUM_OF_CORE);
583         
584 } // flush()
585
586 void collect() {
587         // core collector routine
588         // change to UDN1
589         bme_install_interrupt_handler(INT_UDN_AVAIL, gc_msghandler);
590 #ifdef DEBUG
591         tprintf("Process %x(%d): change udn interrupt handler\n", BAMBOO_NUM_OF_CORE, 
592                         BAMBOO_NUM_OF_CORE);
593 #endif
594         __insn_mtspr(SPR_UDN_TAG_1, UDN1_DEMUX_TAG);
595         // enable udn interrupts
596         //__insn_mtspr(SPR_INTERRUPT_MASK_RESET_2_1, INT_MASK_HI(INT_UDN_AVAIL));
597         __insn_mtspr(SPR_UDN_AVAIL_EN, (1<<1));
598         BAMBOO_CLOSE_CRITICAL_SECTION_MSG();
599
600         lObjList.head = NULL;
601         lObjList.tail = NULL;
602         mObjList.head = NULL;
603         mObjList.tail = NULL;
604         mark(true);
605         compact();
606         while(gcphase != 2) {}
607         flush();
608         
609         while(true) {
610                 if(gcphase == 3) {
611                         // change to UDN0
612                         bme_install_interrupt_handler(INT_UDN_AVAIL, udn_inter_handle);
613 #ifdef DEBUG
614                         tprintf("Process %x(%d): change back udn interrupt handler\n", BAMBOO_NUM_OF_CORE, 
615                                         BAMBOO_NUM_OF_CORE);
616 #endif
617                         __insn_mtspr(SPR_UDN_TAG_0, UDN0_DEMUX_TAG);
618                         // enable udn interrupts
619                         //__insn_mtspr(SPR_INTERRUPT_MASK_RESET_2_1, INT_MASK_HI(INT_UDN_AVAIL));
620                         __insn_mtspr(SPR_UDN_AVAIL_EN, (1<<0));
621                         BAMBOO_START_CRITICAL_SECTION_MSG();
622
623                         return;
624                 }
625         }
626 }
627
628 /* Message format:
629  *      type + Msgbody
630  * type:11 -- GC start
631  *      12 -- compact phase start
632  *      13 -- flush phase start
633  *      14 -- mark phase finish
634  *      15 -- compact phase finish
635  *      16 -- flush phase finish
636  *      17 -- GC finish
637  *      18 -- marked phase finish confirm request
638  *      19 -- marked phase finish confirm response
639  *      1a -- markedObj msg
640  *      1b -- start moving objs msg
641  *      1c -- ask for mapping info of a markedObj
642  *      1d -- mapping info of a markedObj
643  *      1e -- large objs info request
644  *      1f -- large objs info response
645  *
646  * GCMsg: 11 (size is always 1 * sizeof(int))
647  *        12 + size of msg + (num of objs to move + (start address + end address + dst core + start dst)+)? + (num of incoming objs + (start dst + orig core)+)? + (num of large obj lists + (start address + lenght + start dst)+)?
648  *        13 (size is always 1 * sizeof(int))
649  *        14 + corenum + gcsendobjs + gcreceiveobjs (size if always 4 * sizeof(int))
650  *        15/16 + corenum (size is always 2 * sizeof(int))
651  *        17 (size is always 1 * sizeof(int))
652  *        18 (size if always 1 * sizeof(int))
653  *        19 + size of msg + corenum + gcsendobjs + gcreceiveobjs (size is always 5 * sizeof(int))
654  *        1a + obj's address (size is always 2 * sizeof(int))
655  *        1b + corenum ( size is always 2 * sizeof(int))
656  *        1c + obj's address + corenum (size is always 3 * sizeof(int))
657  *        1d + obj's address + dst address (size if always 3 * sizeof(int))
658  *        1e (size is always 1 * sizeof(int))
659  *        1f + size of msg + corenum + (num of large obj lists + (start address + length)+)?
660  *
661  * NOTE: for Tilera, all GCMsgs except the GC start msg should be processed with a different net/port with other msgs
662  */
663
664
665 int gc_msghandler() {
666   int deny = 0;
667   int i = 0;
668   
669 gcmsg:
670   if(receiveGCMsg() == -1) {
671           return -1;
672   }
673
674   if(gcmsgdataindex == gcmsglength) {
675     // received a whole msg
676     int type, data1;             // will receive at least 2 words including type
677     type = gcmsgdata[0];
678     data1 = gcmsgdata[1];
679     switch(gctype) {
680     case 0x12: {
681                 // a compact phase start msg
682                 if(cinstruction == NULL) {
683                         cinstruction = (struct compactInstr *)RUNMALLOC(sizeof(struct compactInstr));
684                 } else {
685                         // clean up out of data info
686                         if(cinstruction->tomoveobjs != NULL) {
687                                 RUNFREE(cinstruction->tomoveobjs->starts);
688                                 RUNFREE(cinstruction->tomoveobjs->ends);
689                                 RUNFREE(cinstruction->tomoveobjs->dststarts);
690                                 RUNFREE(cinstruction->tomoveobjs->dsts);
691                                 RUNFREE(cinstruction->tomoveobjs);
692                                 cinstruction->tomoveobjs = NULL;
693                         }
694                         if(cinstruction->incomingobjs != NULL) {
695                                 RUNFREE();
696                                 RUNFREE(cinstruction->incomingobjs->starts);
697                                 RUNFREE(cinstruction->incomingobjs->dsts);
698                                 RUNFREE(cinstruction->incomingobjs);
699                                 cinstruction->incomingobjs = NULL;
700                         }
701                         // largeobj items should have been freed when processed
702                         if(cinstruction->largeobjs != NULL) {
703                                 BAMBOO_EXIT(0xb005);
704                         }
705                 }
706                 if(data1 > 2) {
707                         // have objs to move etc.
708                         int startindex = 2;
709                         // process objs to move
710                         int num = gcmsgdata[startindex++];
711                         if(num > 0) {
712                                 cinstruction->tomoveobjs = (struct moveObj *)RUNMALLOC(sizeof(struct moveObj));
713                                 cinstruction->tomoveobjs->length = num;
714                                 cinstruction->tomoveobjs->starts = (INTPTR *)RUNMALLOC(num * sizeof(INTPTR));
715                                 cinstruction->tomoveobjs->ends = (INTPTR *)RUNMALLOC(num * sizeof(INTPTR));
716                                 cinstruction->tomoveobjs->dststarts = (INTPTR *)RUNMALLOC(num * sizeof(INTPTR));
717                                 cinstruction->tomoveobjs->dsts = (INTPTR *)RUNMALLOC(num * sizeof(INTPTR));
718                                 for(i = 0; i < num; i++) {
719                                         cinstruction->tomoveobjs->starts[i] = gcmsgdata[startindex++];
720                                         cinstruction->tomoveobjs->ends[i] = gcmsgdata[startindex++];
721                                         cinstruction->tomoveobjs->dsts[i] = gcmsgdata[startindex++];
722                                         cinstruction->tomoveobjs->dststarts[i] = gcmsgdata[startindex++];
723                                 }
724                         }
725                         // process incoming objs
726                         num = gcmsgdata[startindex++];
727                         if(num > 0) {
728                                 cinstruction->incomingobjs = (struct moveObj *)RUNMALLOC(sizeof(struct moveObj));
729                                 cinstruction->incomingobjs->length = num;
730                                 cinstruction->incomingobjs->starts = (INTPTR *)RUNMALLOC(num * sizeof(INTPTR));
731                                 cinstruction->incomingobjs->dsts = (INTPTR *)RUNMALLOC(num * sizeof(INTPTR));
732                                 for(i = 0; i < num; i++) {
733                                         cinstruction->incomingobjs->starts[i] = gcmsgdata[startindex++];
734                                         cinstruction->incomingobjs->dsts[i] = gcmsgdata[startindex++];
735                                 }
736                         }
737                         // process large objs
738                         num = gcmsgdata[startindex++];
739                         for(i = 0; i < num; i++) {
740                                 struct largeObjItem * loi = (struct largeObjItem *)RUNMALLOC(sizeof(struct largeObjItem ));
741                                 loi->orig = gcmsgdata[startindex++];
742                                 loi->length = gcmsgdata[startindex++];
743                                 loi->dst = gcmsgdata[startindex++];
744                                 loi->next = NULL;
745                                 if(i > 0) {
746                                         cinstruction->largeobjs->next = loi;
747                                 }
748                                 cinstruction->largeobjs = loi;
749                         }
750                 }
751                 gcphase = 1;
752                 break;
753         }
754
755         case 0x13: {
756                 // received a flush phase start msg
757                 gcphase = 2;
758                 break;
759         }
760
761         case 0x14: {
762                 // received a mark phase finish msg
763                 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
764                   // non startup core can not receive this msg
765                   // return -1
766 #ifndef TILERA
767                   BAMBOO_DEBUGPRINT_REG(data1);
768 #endif
769                   BAMBOO_EXIT(0xb006);
770       } 
771       if(data1 < NUMCORES) {
772                   gccorestatus[data1] = 0;
773                   gcnumsendobjs[data1] = gcmsgdata[2];
774                   gcnumreceiveobjs[data1] = gcmsgdata[3];
775       }
776           break;
777         }
778         
779         case 0x15: {
780                 // received a compact phase finish msg
781                 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
782                   // non startup core can not receive this msg
783                   // return -1
784 #ifndef TILERA
785                   BAMBOO_DEBUGPRINT_REG(data1);
786 #endif
787                   BAMBOO_EXIT(0xb006);
788       } 
789       if(data1 < NUMCORES) {
790                   gccorestatus[data1] = 0;
791       }
792           break;
793         }
794
795         case 0x16: {
796                 // received a flush phase finish msg
797                 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
798                   // non startup core can not receive this msg
799                   // return -1
800 #ifndef TILERA
801                   BAMBOO_DEBUGPRINT_REG(data1);
802 #endif
803                   BAMBOO_EXIT(0xb006);
804       } 
805       if(data1 < NUMCORES) {
806                   gccorestatus[data1] = 0;
807       }
808           break;
809         }
810
811         case 0x17: {
812                 // received a GC finish msg
813                 gcphase = 3;
814                 break;
815         }
816
817         case 0x18: {
818                 // received a marked phase finish confirm request msg
819                 if((BAMBOO_NUM_OF_CORE == STARTUPCORE) || (BAMBOO_NUM_OF_CORE > NUMCORES - 1)) {
820                   // wrong core to receive such msg
821                   BAMBOO_EXIT(0xa013);
822       } else {
823                   // send response msg
824                   if(gcisMsgSending) {
825                           cache_msg_5(true, STARTUPCORE, 0x19, BAMBOO_NUM_OF_CORE, gcbusystatus, gcself_numsendobjs, gcself_numreceiveobjs);
826                   } else {
827                           send_msg_5(true, STARTUPCORE, 0x19, BAMBOO_NUM_OF_CORE, gcbusystatus, gcself_numsendobjs, gcself_numreceiveobjs);
828                   }
829       }
830           break;
831         }
832
833         case 0x19: {
834                 // received a marked phase finish confirm response msg
835                 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
836                   // wrong core to receive such msg
837 #ifndef TILERA
838                   BAMBOO_DEBUGPRINT_REG(gcmsgdata[2]);
839 #endif
840                   BAMBOO_EXIT(0xb014);
841       } else {
842                   if(gcwaitconfirm) {
843                           gcnumconfirm--;
844                   }
845                   gccorestatus[data1] = gcmsgdata[2];
846                   gcnumsendobjs[data1] = gcmsgdata[3];
847                   gcnumreceiveobjs[data1] = gcmsgdata[4];
848       }
849           break;
850         }
851
852         case 0x1a: {
853                 // received a markedObj msg
854                 addNewItem(gctomark, data1);
855                 gcself_numreceiveobjs++;
856                 gcbusystatus = true;
857                 break;
858         }
859
860         case 0x1b: {
861                 // received a start moving objs msg
862                 addNewItem_I(gcdsts, data1);
863                 tomove = true;
864                 break;
865         }
866         
867         case 0x1c: {
868                 // received a mapping info request msg
869                 void * dstptr = gengettable(pointertbl, data1);
870                 if(NULL == dstptr) {
871                         // no such pointer in this core, something is wrong
872                         BAMBOO_EXIT(0xb008);
873                 } else {
874                         // send back the mapping info
875                         if(gcisMsgSending) {
876                                 cache_msg_3(true, gcmsgdata[2], 0x1d, data1, dstptr);
877                         } else {
878                                 send_msg_3(true, gcmsgdata[2], 0x1d, data1, dstptr);
879                         }
880                 }
881                 break;
882         }
883
884         case 0x1d: {
885                 // received a mapping info response msg
886                 if(data1 != obj2map) {
887                         // obj not matched, something is wrong
888                         BAMBOO_EXIT(0xb009);
889                 } else {
890                         mappedobj = gcmsgdata[2];
891                         genputtable(pointertbl, obj2map, mappedobj);
892                 }
893                 ismapped = true;
894                 break;
895         }
896
897         case 0x1e: {
898                 // received a large objs info request msg
899                 transferMarkResults();
900                 break;
901         }
902
903         case 0x1f: {
904                 // received a large objs info response msg
905                 // TODO
906                 gcwaitconfirm--;
907                 break;
908         }
909                         
910         default:
911       break;
912     }
913     for(gcmsgdataindex--; gcmsgdataindex > 0; --gcmsgdataindex) {
914       gcmsgdata[gcmsgdataindex] = -1;
915     }
916     gcmsgtype = -1;
917     gcmsglength = 30;
918
919     if(BAMBOO_GCMSG_AVAIL() != 0) {
920       goto gcmsg;
921     }
922 #ifdef PROFILE
923         /*if(isInterrupt) {
924             profileTaskEnd();
925     }*/
926 #endif
927     return type;
928   } else {
929     // not a whole msg
930 #ifdef DEBUG
931 #ifndef TILERA
932     BAMBOO_DEBUGPRINT(0xe88d);
933 #endif
934 #endif
935     return -2;
936   }
937 }
938 #endif