fix some bugs in Bamboo
[IRC.git] / Robust / src / Runtime / multicoretask.c
1 #ifdef TASK
2 #include "runtime.h"
3 #include "multicoreruntime.h"
4 #include "runtime_arch.h"
5 #include "GenericHashtable.h"
6
7 #ifndef INLINE
8 #define INLINE    inline __attribute__((always_inline))
9 #endif // #ifndef INLINE
10
11 //  data structures for task invocation
12 struct genhashtable * activetasks;
13 struct taskparamdescriptor * currtpd;
14 struct LockValue runtime_locks[MAXTASKPARAMS];
15 int runtime_locklen;
16
17 // specific functions used inside critical sections
18 void enqueueObject_I(void * ptr,
19                      struct parameterwrapper ** queues,
20                      int length);
21 int enqueuetasks_I(struct parameterwrapper *parameter,
22                    struct parameterwrapper *prevptr,
23                    struct ___Object___ *ptr,
24                    int * enterflags,
25                    int numenterflags);
26
27 #ifdef MULTICORE_GC
28 inline __attribute__((always_inline))
29 void setupsmemmode(void) {
30 #ifdef SMEML
31   bamboo_smem_mode = SMEMLOCAL;
32 #elif defined SMEMF
33   bamboo_smem_mode = SMEMFIXED;
34 #elif defined SMEMM
35   bamboo_smem_mode = SMEMMIXED;
36 #elif defined SMEMG
37   bamboo_smem_mode = SMEMGLOBAL;
38 #else
39   // defaultly using local mode
40   //bamboo_smem_mode = SMEMLOCAL;
41   bamboo_smem_mode = SMEMGLOBAL;
42 #endif
43 } // void setupsmemmode(void)
44 #endif
45
46 inline __attribute__((always_inline))
47 void initruntimedata() {
48   int i;
49   // initialize the arrays
50   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
51     // startup core to initialize corestatus[]
52     for(i = 0; i < NUMCORESACTIVE; ++i) {
53       corestatus[i] = 1;
54       numsendobjs[i] = 0;
55       numreceiveobjs[i] = 0;
56 #ifdef PROFILE
57       // initialize the profile data arrays
58       profilestatus[i] = 1;
59 #endif
60 #ifdef MULTICORE_GC
61       gccorestatus[i] = 1;
62       gcnumsendobjs[i] = 0;
63       gcnumreceiveobjs[i] = 0;
64 #endif
65     } // for(i = 0; i < NUMCORESACTIVE; ++i)
66 #ifdef MULTICORE_GC
67     for(i = 0; i < NUMCORES4GC; ++i) {
68       gcloads[i] = 0;
69       gcrequiredmems[i] = 0;
70       gcstopblock[i] = 0;
71       gcfilledblocks[i] = 0;
72     } // for(i = 0; i < NUMCORES4GC; ++i)
73 #ifdef GC_PROFILE
74     gc_infoIndex = 0;
75     gc_infoOverflow = false;
76 #endif
77 #endif
78     numconfirm = 0;
79     waitconfirm = false;
80
81     // TODO for test
82     total_num_t6 = 0;
83   }
84
85   busystatus = true;
86   self_numsendobjs = 0;
87   self_numreceiveobjs = 0;
88
89   for(i = 0; i < BAMBOO_MSG_BUF_LENGTH; ++i) {
90     msgdata[i] = -1;
91   }
92   msgdataindex = 0;
93   msgdatalast = 0;
94   msglength = BAMBOO_MSG_BUF_LENGTH;
95   msgdatafull = false;
96   for(i = 0; i < BAMBOO_OUT_BUF_LENGTH; ++i) {
97     outmsgdata[i] = -1;
98   }
99   outmsgindex = 0;
100   outmsglast = 0;
101   outmsgleft = 0;
102   isMsgHanging = false;
103   isMsgSending = false;
104
105   smemflag = true;
106   bamboo_cur_msp = NULL;
107   bamboo_smem_size = 0;
108   totransobjqueue = createQueue_I();
109
110 #ifdef MULTICORE_GC
111   gcflag = false;
112   gcprocessing = false;
113   gcphase = FINISHPHASE;
114   gccurr_heaptop = 0;
115   gcself_numsendobjs = 0;
116   gcself_numreceiveobjs = 0;
117   gcmarkedptrbound = 0;
118   //mgchashCreate(2000, 0.75);
119   gcpointertbl = allocateRuntimeHash_I(20);
120   //gcpointertbl = allocateMGCHash(20);
121   gcforwardobjtbl = allocateMGCHash_I(20, 3);
122   gcobj2map = 0;
123   gcmappedobj = 0;
124   gcismapped = false;
125   gcnumlobjs = 0;
126   gcheaptop = 0;
127   gctopcore = 0;
128   gctopblock = 0;
129   gcmovestartaddr = 0;
130   gctomove = false;
131   gcmovepending = 0;
132   gcblock2fill = 0;
133   gcsbstarttbl = BAMBOO_BASE_VA;
134   bamboo_smemtbl = (void *)gcsbstarttbl
135                    + (BAMBOO_SHARED_MEM_SIZE/BAMBOO_SMEM_SIZE)*sizeof(INTPTR);
136 #else
137   // create the lock table, lockresult table and obj queue
138   locktable.size = 20;
139   locktable.bucket =
140     (struct RuntimeNode **) RUNMALLOC_I(sizeof(struct RuntimeNode *)*20);
141   /* Set allocation blocks*/
142   locktable.listhead=NULL;
143   locktable.listtail=NULL;
144   /*Set data counts*/
145   locktable.numelements = 0;
146   lockobj = 0;
147   lock2require = 0;
148   lockresult = 0;
149   lockflag = false;
150   lockRedirectTbl = allocateRuntimeHash_I(20);
151   objRedirectLockTbl = allocateRuntimeHash_I(20);
152 #endif
153 #ifndef INTERRUPT
154   reside = false;
155 #endif
156   objqueue.head = NULL;
157   objqueue.tail = NULL;
158
159   currtpd = NULL;
160
161 #ifdef PROFILE
162   stall = false;
163   //isInterrupt = true;
164   totalexetime = -1;
165   //interrupttime = 0;
166   taskInfoIndex = 0;
167   taskInfoOverflow = false;
168   // TODO
169   interruptInfoIndex = 0;
170   interruptInfoOverflow = false;
171 #endif
172
173   for(i = 0; i < MAXTASKPARAMS; i++) {
174     runtime_locks[i].redirectlock = 0;
175     runtime_locks[i].value = 0;
176   }
177   runtime_locklen = 0;
178 }
179
180 inline __attribute__((always_inline))
181 void disruntimedata() {
182 #ifdef MULTICORE_GC
183   //mgchashDelete();
184   freeRuntimeHash(gcpointertbl);
185   //freeMGCHash(gcpointertbl);
186   freeMGCHash(gcforwardobjtbl);
187 #else
188   freeRuntimeHash(lockRedirectTbl);
189   freeRuntimeHash(objRedirectLockTbl);
190   RUNFREE(locktable.bucket);
191 #endif
192   if(activetasks != NULL) {
193     genfreehashtable(activetasks);
194   }
195   if(currtpd != NULL) {
196     RUNFREE(currtpd->parameterArray);
197     RUNFREE(currtpd);
198     currtpd = NULL;
199   }
200   BAMBOO_LOCAL_MEM_CLOSE();
201   BAMBOO_SHARE_MEM_CLOSE();
202 }
203
204 inline __attribute__((always_inline))
205 bool checkObjQueue() {
206   bool rflag = false;
207   struct transObjInfo * objInfo = NULL;
208   int grount = 0;
209
210 #ifdef PROFILE
211 #ifdef ACCURATEPROFILE
212   bool isChecking = false;
213   if(!isEmpty(&objqueue)) {
214     profileTaskStart("objqueue checking");
215     isChecking = true;
216   }       // if(!isEmpty(&objqueue))
217 #endif
218 #endif
219
220   while(!isEmpty(&objqueue)) {
221     void * obj = NULL;
222     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
223 #ifdef DEBUG
224     BAMBOO_DEBUGPRINT(0xf001);
225 #endif
226 #ifdef PROFILE
227     //isInterrupt = false;
228 #endif
229 #ifdef DEBUG
230     BAMBOO_DEBUGPRINT(0xeee1);
231 #endif
232     rflag = true;
233     objInfo = (struct transObjInfo *)getItem(&objqueue);
234     obj = objInfo->objptr;
235 #ifdef DEBUG
236     BAMBOO_DEBUGPRINT_REG((int)obj);
237 #endif
238     // grab lock and flush the obj
239     grount = 0;
240     getwritelock_I(obj);
241     while(!lockflag) {
242       BAMBOO_WAITING_FOR_LOCK(0);
243           // check for outgoing sends
244           if (isMsgHanging) {
245                 extern inline void send_hanging_msg(bool);
246                 send_hanging_msg(true);
247           } 
248     }             // while(!lockflag)
249     grount = lockresult;
250 #ifdef DEBUG
251     BAMBOO_DEBUGPRINT_REG(grount);
252 #endif
253
254     lockresult = 0;
255     lockobj = 0;
256     lock2require = 0;
257     lockflag = false;
258 #ifndef INTERRUPT
259     reside = false;
260 #endif
261
262     if(grount == 1) {
263       int k = 0;
264       // flush the object
265 #ifdef CACHEFLUSH
266       BAMBOO_CACHE_FLUSH_RANGE((int)obj,sizeof(int));
267       BAMBOO_CACHE_FLUSH_RANGE((int)obj,
268                                classsize[((struct ___Object___ *)obj)->type]);
269 #endif
270       // enqueue the object
271       for(k = 0; k < objInfo->length; ++k) {
272         int taskindex = objInfo->queues[2 * k];
273         int paramindex = objInfo->queues[2 * k + 1];
274         struct parameterwrapper ** queues =
275           &(paramqueues[BAMBOO_NUM_OF_CORE][taskindex][paramindex]);
276 #ifdef DEBUG
277         BAMBOO_DEBUGPRINT_REG(taskindex);
278         BAMBOO_DEBUGPRINT_REG(paramindex);
279         struct ___Object___ * tmpptr = (struct ___Object___ *)obj;
280         tprintf("Process %x(%d): receive obj %x(%lld), ptrflag %x\n",
281                 BAMBOO_NUM_OF_CORE, BAMBOO_NUM_OF_CORE, (int)obj,
282                 (long)obj, tmpptr->flag);
283 #endif
284         enqueueObject_I(obj, queues, 1);
285 #ifdef DEBUG
286         BAMBOO_DEBUGPRINT_REG(hashsize(activetasks));
287 #endif
288       }                   // for(k = 0; k < objInfo->length; ++k)
289       releasewritelock_I(obj);
290       RUNFREE(objInfo->queues);
291       RUNFREE(objInfo);
292     } else {
293       // can not get lock
294       // put it at the end of the queue if no update version in the queue
295       struct QueueItem * qitem = getHead(&objqueue);
296       struct QueueItem * prev = NULL;
297       while(qitem != NULL) {
298                   struct transObjInfo * tmpinfo =
299                           (struct transObjInfo *)(qitem->objectptr);
300                   if(tmpinfo->objptr == obj) {
301                           // the same object in the queue, which should be enqueued
302                           // recently. Current one is outdate, do not re-enqueue it
303                           RUNFREE(objInfo->queues);
304                           RUNFREE(objInfo);
305                           goto objqueuebreak;
306                   } else {
307                           prev = qitem;
308                   }                         // if(tmpinfo->objptr == obj)
309                   qitem = getNextQueueItem(prev);
310           }                   // while(qitem != NULL)
311                           // try to execute active tasks already enqueued first
312       addNewItem_I(&objqueue, objInfo);
313 #ifdef PROFILE
314       //isInterrupt = true;
315 #endif
316 objqueuebreak:
317       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
318 #ifdef DEBUG
319       BAMBOO_DEBUGPRINT(0xf000);
320 #endif
321       break;
322     }             // if(grount == 1)
323     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
324 #ifdef DEBUG
325     BAMBOO_DEBUGPRINT(0xf000);
326 #endif
327   }       // while(!isEmpty(&objqueue))
328
329 #ifdef PROFILE
330 #ifdef ACCURATEPROFILE
331   if(isChecking) {
332     profileTaskEnd();
333   }       // if(isChecking)
334 #endif
335 #endif
336
337 #ifdef DEBUG
338   BAMBOO_DEBUGPRINT(0xee02);
339 #endif
340   return rflag;
341 }
342
343 inline __attribute__((always_inline))
344 void checkCoreStatus() {
345   bool allStall = false;
346   int i = 0;
347   int sumsendobj = 0;
348   if((!waitconfirm) ||
349      (waitconfirm && (numconfirm == 0))) {
350 #ifdef DEBUG
351     BAMBOO_DEBUGPRINT(0xee04);
352     BAMBOO_DEBUGPRINT_REG(waitconfirm);
353 #endif
354     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
355 #ifdef DEBUG
356     BAMBOO_DEBUGPRINT(0xf001);
357 #endif
358     corestatus[BAMBOO_NUM_OF_CORE] = 0;
359     numsendobjs[BAMBOO_NUM_OF_CORE] = self_numsendobjs;
360     numreceiveobjs[BAMBOO_NUM_OF_CORE] = self_numreceiveobjs;
361     // check the status of all cores
362     allStall = true;
363 #ifdef DEBUG
364     BAMBOO_DEBUGPRINT_REG(NUMCORESACTIVE);
365 #endif
366     for(i = 0; i < NUMCORESACTIVE; ++i) {
367 #ifdef DEBUG
368       BAMBOO_DEBUGPRINT(0xe000 + corestatus[i]);
369 #endif
370       if(corestatus[i] != 0) {
371                   allStall = false;
372                   break;
373       }
374     }             // for(i = 0; i < NUMCORESACTIVE; ++i)
375     if(allStall) {
376       // check if the sum of send objs and receive obj are the same
377       // yes->check if the info is the latest; no->go on executing
378       sumsendobj = 0;
379       for(i = 0; i < NUMCORESACTIVE; ++i) {
380                   sumsendobj += numsendobjs[i];
381 #ifdef DEBUG
382                   BAMBOO_DEBUGPRINT(0xf000 + numsendobjs[i]);
383 #endif
384       }                   // for(i = 0; i < NUMCORESACTIVE; ++i)
385       for(i = 0; i < NUMCORESACTIVE; ++i) {
386                   sumsendobj -= numreceiveobjs[i];
387 #ifdef DEBUG
388                   BAMBOO_DEBUGPRINT(0xf000 + numreceiveobjs[i]);
389 #endif
390       }                   // for(i = 0; i < NUMCORESACTIVE; ++i)
391       if(0 == sumsendobj) {
392         if(!waitconfirm) {
393           // the first time found all cores stall
394           // send out status confirm msg to all other cores
395           // reset the corestatus array too
396 #ifdef DEBUG
397           BAMBOO_DEBUGPRINT(0xee05);
398 #endif
399           corestatus[BAMBOO_NUM_OF_CORE] = 1;
400           waitconfirm = true;
401           numconfirm = NUMCORESACTIVE - 1;
402           BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
403           for(i = 1; i < NUMCORESACTIVE; ++i) {
404             corestatus[i] = 1;
405             // send status confirm msg to core i
406             send_msg_1(i, STATUSCONFIRM);
407           }                               // for(i = 1; i < NUMCORESACTIVE; ++i)
408           return;
409         } else {
410           // all the core status info are the latest
411           // terminate; for profiling mode, send request to all
412           // other cores to pour out profiling data
413 #ifdef DEBUG
414           BAMBOO_DEBUGPRINT(0xee06);
415 #endif
416
417 #ifdef USEIO
418           totalexetime = BAMBOO_GET_EXE_TIME() - bamboo_start_time;
419 #else
420 #ifdef PROFILE
421           //BAMBOO_DEBUGPRINT_REG(interrupttime);
422 #endif
423
424           BAMBOO_DEBUGPRINT(BAMBOO_GET_EXE_TIME() - bamboo_start_time);
425           //BAMBOO_DEBUGPRINT_REG(total_num_t6); // TODO for test
426           BAMBOO_DEBUGPRINT(0xbbbbbbbb);
427 #endif
428           // profile mode, send msgs to other cores to request pouring
429           // out progiling data
430 #ifdef PROFILE
431           BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
432 #ifdef DEBUG
433           BAMBOO_DEBUGPRINT(0xf000);
434 #endif
435           for(i = 1; i < NUMCORESACTIVE; ++i) {
436             // send profile request msg to core i
437             send_msg_2(i, PROFILEOUTPUT, totalexetime);
438           } // for(i = 1; i < NUMCORESACTIVE; ++i)
439           // pour profiling data on startup core
440           outputProfileData();
441           while(true) {
442             BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
443 #ifdef DEBUG
444             BAMBOO_DEBUGPRINT(0xf001);
445 #endif
446             profilestatus[BAMBOO_NUM_OF_CORE] = 0;
447             // check the status of all cores
448             allStall = true;
449 #ifdef DEBUG
450             BAMBOO_DEBUGPRINT_REG(NUMCORESACTIVE);
451 #endif
452             for(i = 0; i < NUMCORESACTIVE; ++i) {
453 #ifdef DEBUG
454               BAMBOO_DEBUGPRINT(0xe000 + profilestatus[i]);
455 #endif
456               if(profilestatus[i] != 0) {
457                 allStall = false;
458                 break;
459               }
460             }  // for(i = 0; i < NUMCORESACTIVE; ++i)
461             if(!allStall) {
462               int halt = 100;
463               BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
464 #ifdef DEBUG
465               BAMBOO_DEBUGPRINT(0xf000);
466 #endif
467               while(halt--) {
468               }
469             } else {
470               BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
471               break;
472             }                                     // if(!allStall)
473           }                               // while(true)
474 #endif
475
476           // gc_profile mode, ourput gc prfiling data
477 #ifdef MULTICORE_GC
478 #ifdef GC_PROFILE
479           gc_outputProfileData();
480 #endif // #ifdef GC_PROFILE
481 #endif // #ifdef MULTICORE_GC
482           disruntimedata();
483           BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
484           terminate();                               // All done.
485         }                         // if(!waitconfirm)
486       } else {
487         // still some objects on the fly on the network
488         // reset the waitconfirm and numconfirm
489 #ifdef DEBUG
490         BAMBOO_DEBUGPRINT(0xee07);
491 #endif
492         waitconfirm = false;
493         numconfirm = 0;
494       }                   //  if(0 == sumsendobj)
495     } else {
496       // not all cores are stall, keep on waiting
497 #ifdef DEBUG
498       BAMBOO_DEBUGPRINT(0xee08);
499 #endif
500       waitconfirm = false;
501       numconfirm = 0;
502     }             //  if(allStall)
503     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
504 #ifdef DEBUG
505     BAMBOO_DEBUGPRINT(0xf000);
506 #endif
507   }       // if((!waitconfirm) ||
508 }
509
510 // main function for each core
511 inline void run(void * arg) {
512   int i = 0;
513   int argc = 1;
514   char ** argv = NULL;
515   bool sendStall = false;
516   bool isfirst = true;
517   bool tocontinue = false;
518
519   corenum = BAMBOO_GET_NUM_OF_CORE();
520 #ifdef DEBUG
521   BAMBOO_DEBUGPRINT(0xeeee);
522   BAMBOO_DEBUGPRINT_REG(corenum);
523   BAMBOO_DEBUGPRINT(STARTUPCORE);
524 #endif
525
526   // initialize runtime data structures
527   initruntimedata();
528
529   // other architecture related initialization
530   initialization();
531   initCommunication();
532
533   initializeexithandler();
534
535   // main process of the execution module
536   if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
537     // non-executing cores, only processing communications
538     activetasks = NULL;
539 /*#ifdef PROFILE
540         BAMBOO_DEBUGPRINT(0xee01);
541         BAMBOO_DEBUGPRINT_REG(taskInfoIndex);
542         BAMBOO_DEBUGPRINT_REG(taskInfoOverflow);
543                 profileTaskStart("msg handling");
544         }
545  #endif*/
546 #ifdef PROFILE
547     //isInterrupt = false;
548 #endif
549     fakeExecution();
550   } else {
551     /* Create queue of active tasks */
552     activetasks=
553       genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd,
554                            (int (*)(void *,void *)) &comparetpd);
555
556     /* Process task information */
557     processtasks();
558
559     if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
560       /* Create startup object */
561       createstartupobject(argc, argv);
562     }
563
564 #ifdef DEBUG
565     BAMBOO_DEBUGPRINT(0xee00);
566 #endif
567
568     while(true) {
569 #ifdef MULTICORE_GC
570       // check if need to do GC
571       gc(NULL);
572 #endif
573
574       // check if there are new active tasks can be executed
575       executetasks();
576       if(busystatus) {
577         sendStall = false;
578       }
579
580 #ifndef INTERRUPT
581       while(receiveObject() != -1) {
582       }
583 #endif
584
585 #ifdef DEBUG
586       BAMBOO_DEBUGPRINT(0xee01);
587 #endif
588
589       // check if there are some pending objects,
590       // if yes, enqueue them and executetasks again
591       tocontinue = checkObjQueue();
592
593       if(!tocontinue) {
594         // check if stop
595         if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
596           if(isfirst) {
597 #ifdef DEBUG
598             BAMBOO_DEBUGPRINT(0xee03);
599 #endif
600             isfirst = false;
601           }
602           checkCoreStatus();
603         } else {
604           if(!sendStall) {
605 #ifdef DEBUG
606             BAMBOO_DEBUGPRINT(0xee09);
607 #endif
608 #ifdef PROFILE
609             if(!stall) {
610 #endif
611             if(isfirst) {
612               // wait for some time
613               int halt = 10000;
614 #ifdef DEBUG
615               BAMBOO_DEBUGPRINT(0xee0a);
616 #endif
617               while(halt--) {
618               }
619               isfirst = false;
620             } else {
621               // send StallMsg to startup core
622 #ifdef DEBUG
623               BAMBOO_DEBUGPRINT(0xee0b);
624 #endif
625               // send stall msg
626               send_msg_4(STARTUPCORE, TRANSTALL, BAMBOO_NUM_OF_CORE,
627                          self_numsendobjs, self_numreceiveobjs);
628               sendStall = true;
629               isfirst = true;
630               busystatus = false;
631             }
632 #ifdef PROFILE
633           }
634 #endif
635           } else {
636             isfirst = true;
637             busystatus = false;
638 #ifdef DEBUG
639             BAMBOO_DEBUGPRINT(0xee0c);
640 #endif
641           }                         // if(!sendStall)
642         }                   // if(STARTUPCORE == BAMBOO_NUM_OF_CORE)
643       }             // if(!tocontinue)
644     }       // while(true)
645   } // if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1)
646
647 } // run()
648
649 struct ___createstartupobject____I_locals {
650   INTPTR size;
651   void * next;
652   struct  ___StartupObject___ * ___startupobject___;
653   struct ArrayObject * ___stringarray___;
654 }; // struct ___createstartupobject____I_locals
655
656 void createstartupobject(int argc,
657                          char ** argv) {
658   int i;
659
660   /* Allocate startup object     */
661 #ifdef MULTICORE_GC
662   struct ___createstartupobject____I_locals ___locals___={2, NULL, NULL, NULL};
663   struct ___StartupObject___ *startupobject=
664     (struct ___StartupObject___*) allocate_new(&___locals___, STARTUPTYPE);
665   ___locals___.___startupobject___ = startupobject;
666   struct ArrayObject * stringarray=
667     allocate_newarray(&___locals___, STRINGARRAYTYPE, argc-1);
668   ___locals___.___stringarray___ = stringarray;
669 #else
670   struct ___StartupObject___ *startupobject=
671     (struct ___StartupObject___*) allocate_new(STARTUPTYPE);
672   struct ArrayObject * stringarray=
673     allocate_newarray(STRINGARRAYTYPE, argc-1);
674 #endif
675   /* Build array of strings */
676   startupobject->___parameters___=stringarray;
677   for(i=1; i<argc; i++) {
678     int length=strlen(argv[i]);
679 #ifdef MULTICORE_GC
680     struct ___String___ *newstring=NewString(&___locals___, argv[i],length);
681 #else
682     struct ___String___ *newstring=NewString(argv[i],length);
683 #endif
684     ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=
685       newstring;
686   }
687
688   startupobject->version = 0;
689   startupobject->lock = NULL;
690
691   /* Set initialized flag for startup object */
692   flagorandinit(startupobject,1,0xFFFFFFFF);
693   enqueueObject(startupobject, NULL, 0);
694 #ifdef CACHEFLUSH
695   BAMBOO_CACHE_FLUSH_ALL();
696 #endif
697 }
698
699 int hashCodetpd(struct taskparamdescriptor *ftd) {
700   int hash=(int)ftd->task;
701   int i;
702   for(i=0; i<ftd->numParameters; i++) {
703     hash^=(int)ftd->parameterArray[i];
704   }
705   return hash;
706 }
707
708 int comparetpd(struct taskparamdescriptor *ftd1,
709                struct taskparamdescriptor *ftd2) {
710   int i;
711   if (ftd1->task!=ftd2->task)
712     return 0;
713   for(i=0; i<ftd1->numParameters; i++)
714     if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
715       return 0;
716   return 1;
717 }
718
719 /* This function sets a tag. */
720 #ifdef MULTICORE_GC
721 void tagset(void *ptr,
722             struct ___Object___ * obj,
723             struct ___TagDescriptor___ * tagd) {
724 #else
725 void tagset(struct ___Object___ * obj,
726             struct ___TagDescriptor___ * tagd) {
727 #endif
728   struct ArrayObject * ao=NULL;
729   struct ___Object___ * tagptr=obj->___tags___;
730   if (tagptr==NULL) {
731     obj->___tags___=(struct ___Object___ *)tagd;
732   } else {
733     /* Have to check if it is already set */
734     if (tagptr->type==TAGTYPE) {
735       struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
736       if (td==tagd) {
737         return;
738       }
739 #ifdef MULTICORE_GC
740       int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
741       struct ArrayObject * ao=
742         allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
743       obj=(struct ___Object___ *)ptrarray[2];
744       tagd=(struct ___TagDescriptor___ *)ptrarray[3];
745       td=(struct ___TagDescriptor___ *) obj->___tags___;
746 #else
747       ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
748 #endif
749
750       ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
751       ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
752       obj->___tags___=(struct ___Object___ *) ao;
753       ao->___cachedCode___=2;
754     } else {
755       /* Array Case */
756       int i;
757       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
758       for(i=0; i<ao->___cachedCode___; i++) {
759         struct ___TagDescriptor___ * td=
760           ARRAYGET(ao, struct ___TagDescriptor___*, i);
761         if (td==tagd) {
762           return;
763         }
764       }
765       if (ao->___cachedCode___<ao->___length___) {
766         ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
767         ao->___cachedCode___++;
768       } else {
769 #ifdef MULTICORE_GC
770         int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
771         struct ArrayObject * aonew=
772           allocate_newarray(&ptrarray,TAGARRAYTYPE,
773                             TAGARRAYINTERVAL+ao->___length___);
774         obj=(struct ___Object___ *)ptrarray[2];
775         tagd=(struct ___TagDescriptor___ *) ptrarray[3];
776         ao=(struct ArrayObject *)obj->___tags___;
777 #else
778         struct ArrayObject * aonew=
779           allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
780 #endif
781
782         aonew->___cachedCode___=ao->___length___+1;
783         for(i=0; i<ao->___length___; i++) {
784           ARRAYSET(aonew, struct ___TagDescriptor___*, i,
785                    ARRAYGET(ao, struct ___TagDescriptor___*, i));
786         }
787         ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
788       }
789     }
790   }
791
792   {
793     struct ___Object___ * tagset=tagd->flagptr;
794     if(tagset==NULL) {
795       tagd->flagptr=obj;
796     } else if (tagset->type!=OBJECTARRAYTYPE) {
797 #ifdef MULTICORE_GC
798       int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
799       struct ArrayObject * ao=
800         allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
801       obj=(struct ___Object___ *)ptrarray[2];
802       tagd=(struct ___TagDescriptor___ *)ptrarray[3];
803 #else
804       struct ArrayObject * ao=
805         allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
806 #endif
807       ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
808       ARRAYSET(ao, struct ___Object___ *, 1, obj);
809       ao->___cachedCode___=2;
810       tagd->flagptr=(struct ___Object___ *)ao;
811     } else {
812       struct ArrayObject *ao=(struct ArrayObject *) tagset;
813       if (ao->___cachedCode___<ao->___length___) {
814         ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
815       } else {
816         int i;
817 #ifdef MULTICORE_GC
818         int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
819         struct ArrayObject * aonew=
820           allocate_newarray(&ptrarray,OBJECTARRAYTYPE,
821                             OBJECTARRAYINTERVAL+ao->___length___);
822         obj=(struct ___Object___ *)ptrarray[2];
823         tagd=(struct ___TagDescriptor___ *)ptrarray[3];
824         ao=(struct ArrayObject *)tagd->flagptr;
825 #else
826         struct ArrayObject * aonew=
827           allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL+ao->___length___);
828 #endif
829         aonew->___cachedCode___=ao->___cachedCode___+1;
830         for(i=0; i<ao->___length___; i++) {
831           ARRAYSET(aonew, struct ___Object___*, i,
832                    ARRAYGET(ao, struct ___Object___*, i));
833         }
834         ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
835         tagd->flagptr=(struct ___Object___ *) aonew;
836       }
837     }
838   }
839 }
840
841 /* This function clears a tag. */
842 #ifdef MULTICORE_GC
843 void tagclear(void *ptr,
844               struct ___Object___ * obj,
845               struct ___TagDescriptor___ * tagd) {
846 #else
847 void tagclear(struct ___Object___ * obj,
848               struct ___TagDescriptor___ * tagd) {
849 #endif
850   /* We'll assume that tag is alway there.
851      Need to statically check for this of course. */
852   struct ___Object___ * tagptr=obj->___tags___;
853
854   if (tagptr->type==TAGTYPE) {
855     if ((struct ___TagDescriptor___ *)tagptr==tagd)
856       obj->___tags___=NULL;
857   } else {
858     struct ArrayObject *ao=(struct ArrayObject *) tagptr;
859     int i;
860     for(i=0; i<ao->___cachedCode___; i++) {
861       struct ___TagDescriptor___ * td=
862         ARRAYGET(ao, struct ___TagDescriptor___ *, i);
863       if (td==tagd) {
864         ao->___cachedCode___--;
865         if (i<ao->___cachedCode___)
866           ARRAYSET(ao, struct ___TagDescriptor___ *, i,
867                    ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
868         ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
869         if (ao->___cachedCode___==0)
870           obj->___tags___=NULL;
871         goto PROCESSCLEAR;
872       }
873     }
874   }
875 PROCESSCLEAR:
876   {
877     struct ___Object___ *tagset=tagd->flagptr;
878     if (tagset->type!=OBJECTARRAYTYPE) {
879       if (tagset==obj)
880         tagd->flagptr=NULL;
881     } else {
882       struct ArrayObject *ao=(struct ArrayObject *) tagset;
883       int i;
884       for(i=0; i<ao->___cachedCode___; i++) {
885         struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
886         if (tobj==obj) {
887           ao->___cachedCode___--;
888           if (i<ao->___cachedCode___)
889             ARRAYSET(ao, struct ___Object___ *, i,
890                      ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
891           ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
892           if (ao->___cachedCode___==0)
893             tagd->flagptr=NULL;
894           goto ENDCLEAR;
895         }
896       }
897     }
898   }
899 ENDCLEAR:
900   return;
901 }
902
903 /* This function allocates a new tag. */
904 #ifdef MULTICORE_GC
905 struct ___TagDescriptor___ * allocate_tag(void *ptr,
906                                           int index) {
907   struct ___TagDescriptor___ * v=
908     (struct ___TagDescriptor___ *) FREEMALLOC((struct garbagelist *) ptr,
909                                               classsize[TAGTYPE]);
910 #else
911 struct ___TagDescriptor___ * allocate_tag(int index) {
912   struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
913 #endif
914   v->type=TAGTYPE;
915   v->flag=index;
916   return v;
917 }
918
919
920
921 /* This function updates the flag for object ptr.  It or's the flag
922    with the or mask and and's it with the andmask. */
923
924 void flagbody(struct ___Object___ *ptr,
925               int flag,
926               struct parameterwrapper ** queues,
927               int length,
928               bool isnew);
929
930 int flagcomp(const int *val1, const int *val2) {
931   return (*val1)-(*val2);
932 }
933
934 void flagorand(void * ptr,
935                int ormask,
936                int andmask,
937                struct parameterwrapper ** queues,
938                int length) {
939   {
940     int oldflag=((int *)ptr)[1];
941     int flag=ormask|oldflag;
942     flag&=andmask;
943     flagbody(ptr, flag, queues, length, false);
944   }
945 }
946
947 bool intflagorand(void * ptr,
948                   int ormask,
949                   int andmask) {
950   {
951     int oldflag=((int *)ptr)[1];
952     int flag=ormask|oldflag;
953     flag&=andmask;
954     if (flag==oldflag)   /* Don't do anything */
955       return false;
956     else {
957       flagbody(ptr, flag, NULL, 0, false);
958       return true;
959     }
960   }
961 }
962
963 void flagorandinit(void * ptr,
964                    int ormask,
965                    int andmask) {
966   int oldflag=((int *)ptr)[1];
967   int flag=ormask|oldflag;
968   flag&=andmask;
969   flagbody(ptr,flag,NULL,0,true);
970 }
971
972 void flagbody(struct ___Object___ *ptr,
973               int flag,
974               struct parameterwrapper ** vqueues,
975               int vlength,
976               bool isnew) {
977   struct parameterwrapper * flagptr = NULL;
978   int i = 0;
979   struct parameterwrapper ** queues = vqueues;
980   int length = vlength;
981   int next;
982   int UNUSED, UNUSED2;
983   int * enterflags = NULL;
984   if((!isnew) && (queues == NULL)) {
985     if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
986       queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
987       length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
988     } else {
989       return;
990     }
991   }
992   ptr->flag=flag;
993
994   /*Remove object from all queues */
995   for(i = 0; i < length; ++i) {
996     flagptr = queues[i];
997     ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next,
998                   (int *) &enterflags, &UNUSED, &UNUSED2);
999     ObjectHashremove(flagptr->objectset, (int)ptr);
1000     if (enterflags!=NULL)
1001       RUNFREE(enterflags);
1002   }
1003 }
1004
1005 void enqueueObject(void * vptr,
1006                    struct parameterwrapper ** vqueues,
1007                    int vlength) {
1008   struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1009
1010   {
1011     //struct QueueItem *tmpptr;
1012     struct parameterwrapper * parameter=NULL;
1013     int j;
1014     int i;
1015     struct parameterwrapper * prevptr=NULL;
1016     struct ___Object___ *tagptr=NULL;
1017     struct parameterwrapper ** queues = vqueues;
1018     int length = vlength;
1019     if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
1020       return;
1021     }
1022     if(queues == NULL) {
1023       queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
1024       length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
1025     }
1026     tagptr=ptr->___tags___;
1027
1028     /* Outer loop iterates through all parameter queues an object of
1029        this type could be in.  */
1030     for(j = 0; j < length; ++j) {
1031       parameter = queues[j];
1032       /* Check tags */
1033       if (parameter->numbertags>0) {
1034         if (tagptr==NULL)
1035           goto nextloop;                               //that means the object has no tag
1036         //but that param needs tag
1037         else if(tagptr->type==TAGTYPE) {                         //one tag
1038           //struct ___TagDescriptor___ * tag=
1039           //(struct ___TagDescriptor___*) tagptr;
1040           for(i=0; i<parameter->numbertags; i++) {
1041             //slotid is parameter->tagarray[2*i];
1042             int tagid=parameter->tagarray[2*i+1];
1043             if (tagid!=tagptr->flag)
1044               goto nextloop;                                           /*We don't have this tag */
1045           }
1046         } else {                         //multiple tags
1047           struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1048           for(i=0; i<parameter->numbertags; i++) {
1049             //slotid is parameter->tagarray[2*i];
1050             int tagid=parameter->tagarray[2*i+1];
1051             int j;
1052             for(j=0; j<ao->___cachedCode___; j++) {
1053               if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
1054                 goto foundtag;
1055             }
1056             goto nextloop;
1057 foundtag:
1058             ;
1059           }
1060         }
1061       }
1062
1063       /* Check flags */
1064       for(i=0; i<parameter->numberofterms; i++) {
1065         int andmask=parameter->intarray[i*2];
1066         int checkmask=parameter->intarray[i*2+1];
1067         if ((ptr->flag&andmask)==checkmask) {
1068           enqueuetasks(parameter, prevptr, ptr, NULL, 0);
1069           prevptr=parameter;
1070           break;
1071         }
1072       }
1073 nextloop:
1074       ;
1075     }
1076   }
1077 }
1078
1079 void enqueueObject_I(void * vptr,
1080                      struct parameterwrapper ** vqueues,
1081                      int vlength) {
1082   struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1083
1084   {
1085     //struct QueueItem *tmpptr;
1086     struct parameterwrapper * parameter=NULL;
1087     int j;
1088     int i;
1089     struct parameterwrapper * prevptr=NULL;
1090     struct ___Object___ *tagptr=NULL;
1091     struct parameterwrapper ** queues = vqueues;
1092     int length = vlength;
1093     if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
1094       return;
1095     }
1096     if(queues == NULL) {
1097       queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
1098       length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
1099     }
1100     tagptr=ptr->___tags___;
1101
1102     /* Outer loop iterates through all parameter queues an object of
1103        this type could be in.  */
1104     for(j = 0; j < length; ++j) {
1105       parameter = queues[j];
1106       /* Check tags */
1107       if (parameter->numbertags>0) {
1108         if (tagptr==NULL)
1109           goto nextloop;                               //that means the object has no tag
1110         //but that param needs tag
1111         else if(tagptr->type==TAGTYPE) {                         //one tag
1112           //struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1113           for(i=0; i<parameter->numbertags; i++) {
1114             //slotid is parameter->tagarray[2*i];
1115             int tagid=parameter->tagarray[2*i+1];
1116             if (tagid!=tagptr->flag)
1117               goto nextloop;                                           /*We don't have this tag */
1118           }
1119         } else {                         //multiple tags
1120           struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1121           for(i=0; i<parameter->numbertags; i++) {
1122             //slotid is parameter->tagarray[2*i];
1123             int tagid=parameter->tagarray[2*i+1];
1124             int j;
1125             for(j=0; j<ao->___cachedCode___; j++) {
1126               if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
1127                 goto foundtag;
1128             }
1129             goto nextloop;
1130 foundtag:
1131             ;
1132           }
1133         }
1134       }
1135
1136       /* Check flags */
1137       for(i=0; i<parameter->numberofterms; i++) {
1138         int andmask=parameter->intarray[i*2];
1139         int checkmask=parameter->intarray[i*2+1];
1140         if ((ptr->flag&andmask)==checkmask) {
1141           enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
1142           prevptr=parameter;
1143           break;
1144         }
1145       }
1146 nextloop:
1147       ;
1148     }
1149   }
1150 }
1151
1152
1153 int * getAliasLock(void ** ptrs,
1154                    int length,
1155                    struct RuntimeHash * tbl) {
1156   if(length == 0) {
1157     return (int*)(RUNMALLOC(sizeof(int)));
1158   } else {
1159     int i = 0;
1160     int locks[length];
1161     int locklen = 0;
1162     bool redirect = false;
1163     int redirectlock = 0;
1164     for(; i < length; i++) {
1165       struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
1166       int lock = 0;
1167       int j = 0;
1168       if(ptr->lock == NULL) {
1169         lock = (int)(ptr);
1170       } else {
1171         lock = (int)(ptr->lock);
1172       }
1173       if(redirect) {
1174         if(lock != redirectlock) {
1175           RuntimeHashadd(tbl, lock, redirectlock);
1176         }
1177       } else {
1178         if(RuntimeHashcontainskey(tbl, lock)) {
1179           // already redirected
1180           redirect = true;
1181           RuntimeHashget(tbl, lock, &redirectlock);
1182           for(; j < locklen; j++) {
1183             if(locks[j] != redirectlock) {
1184               RuntimeHashadd(tbl, locks[j], redirectlock);
1185             }
1186           }
1187         } else {
1188           bool insert = true;
1189           for(j = 0; j < locklen; j++) {
1190             if(locks[j] == lock) {
1191               insert = false;
1192               break;
1193             } else if(locks[j] > lock) {
1194               break;
1195             }
1196           }
1197           if(insert) {
1198             int h = locklen;
1199             for(; h > j; h--) {
1200               locks[h] = locks[h-1];
1201             }
1202             locks[j] = lock;
1203             locklen++;
1204           }
1205         }
1206       }
1207     }
1208     if(redirect) {
1209       return (int *)redirectlock;
1210     } else {
1211       return (int *)(locks[0]);
1212     }
1213   }
1214 }
1215
1216 void addAliasLock(void * ptr,
1217                   int lock) {
1218   struct ___Object___ * obj = (struct ___Object___ *)ptr;
1219   if(((int)ptr != lock) && (obj->lock != (int*)lock)) {
1220     // originally no alias lock associated or have a different alias lock
1221     // flush it as the new one
1222     obj->lock = (int *)lock;
1223   }
1224 }
1225
1226 #ifdef PROFILE
1227 inline void setTaskExitIndex(int index) {
1228   taskInfoArray[taskInfoIndex]->exitIndex = index;
1229 }
1230
1231 inline void addNewObjInfo(void * nobj) {
1232   if(taskInfoArray[taskInfoIndex]->newObjs == NULL) {
1233     taskInfoArray[taskInfoIndex]->newObjs = createQueue();
1234   }
1235   addNewItem(taskInfoArray[taskInfoIndex]->newObjs, nobj);
1236 }
1237 #endif
1238
1239 #ifdef MULTICORE_GC
1240 void * localmalloc_I(int coren,
1241                      int isize,
1242                      int * allocsize) {
1243   void * mem = NULL;
1244   int i = 0;
1245   int j = 0;
1246   int tofindb = gc_core2block[2*coren+i]+(NUMCORES4GC*2)*j;
1247   int totest = tofindb;
1248   int bound = BAMBOO_SMEM_SIZE_L;
1249   int foundsmem = 0;
1250   int size = 0;
1251   do {
1252     bound = (totest < NUMCORES4GC) ? BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
1253     int nsize = bamboo_smemtbl[totest];
1254     bool islocal = true;
1255     if(nsize < bound) {
1256       bool tocheck = true;
1257       // have some space in the block
1258       if(totest == tofindb) {
1259         // the first partition
1260         size = bound - nsize;
1261       } else if(nsize == 0) {
1262         // an empty partition, can be appended
1263         size += bound;
1264       } else {
1265         // not an empty partition, can not be appended
1266         // the last continuous block is not big enough, go to check the next
1267         // local block
1268         islocal = true;
1269         tocheck = false;
1270       }                   // if(totest == tofindb) else if(nsize == 0) else ...
1271       if(tocheck) {
1272         if(size >= isize) {
1273           // have enough space in the block, malloc
1274           foundsmem = 1;
1275           break;
1276         } else {
1277           // no enough space yet, try to append next continuous block
1278           islocal = false;
1279         }                         // if(size > isize) else ...
1280       }                   // if(tocheck)
1281     }             // if(nsize < bound)
1282     if(islocal) {
1283       // no space in the block, go to check the next block
1284       i++;
1285       if(2==i) {
1286         i = 0;
1287         j++;
1288       }
1289       tofindb = totest = gc_core2block[2*coren+i]+(NUMCORES4GC*2)*j;
1290     } else {
1291       totest += 1;
1292     }             // if(islocal) else ...
1293     if(totest > gcnumblock-1-bamboo_reserved_smem) {
1294       // no more local mem, do not find suitable block
1295       foundsmem = 2;
1296       break;
1297     }             // if(totest > gcnumblock-1-bamboo_reserved_smem) ...
1298   } while(true);
1299
1300   if(foundsmem == 1) {
1301     // find suitable block
1302     mem = gcbaseva+bamboo_smemtbl[tofindb]+((tofindb<NUMCORES4GC) ?
1303                                             (BAMBOO_SMEM_SIZE_L*tofindb) : (BAMBOO_LARGE_SMEM_BOUND+
1304                                                                             (tofindb-NUMCORES4GC)*BAMBOO_SMEM_SIZE));
1305     *allocsize = size;
1306     // set bamboo_smemtbl
1307     for(i = tofindb; i <= totest; i++) {
1308       bamboo_smemtbl[i]=(i<NUMCORES4GC) ? BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
1309     }
1310   } else if(foundsmem == 2) {
1311     // no suitable block
1312     *allocsize = 0;
1313   }
1314
1315   return mem;
1316 } // void * localmalloc_I(int, int, int *)
1317
1318 void * globalmalloc_I(int coren,
1319                       int isize,
1320                       int * allocsize) {
1321   void * mem = NULL;
1322   int tofindb = bamboo_free_block;       //0;
1323   int totest = tofindb;
1324   int bound = BAMBOO_SMEM_SIZE_L;
1325   int foundsmem = 0;
1326   int size = 0;
1327   if(tofindb > gcnumblock-1-bamboo_reserved_smem) {
1328     *allocsize = 0;
1329     return NULL;
1330   }
1331   do {
1332     bound = (totest < NUMCORES4GC) ? BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
1333     int nsize = bamboo_smemtbl[totest];
1334     bool isnext = false;
1335     if(nsize < bound) {
1336       bool tocheck = true;
1337       // have some space in the block
1338       if(totest == tofindb) {
1339         // the first partition
1340         size = bound - nsize;
1341       } else if(nsize == 0) {
1342         // an empty partition, can be appended
1343         size += bound;
1344       } else {
1345         // not an empty partition, can not be appended
1346         // the last continuous block is not big enough, start another block
1347         isnext = true;
1348         tocheck = false;
1349       }                   // if(totest == tofindb) else if(nsize == 0) else ...
1350       if(tocheck) {
1351         if(size >= isize) {
1352           // have enough space in the block, malloc
1353           foundsmem = 1;
1354           break;
1355         }                         // if(size > isize)
1356       }                   // if(tocheck)
1357     } else {
1358       isnext = true;
1359     }            // if(nsize < bound) else ...
1360     totest += 1;
1361     if(totest > gcnumblock-1-bamboo_reserved_smem) {
1362       // no more local mem, do not find suitable block
1363       foundsmem = 2;
1364       break;
1365     }             // if(totest > gcnumblock-1-bamboo_reserved_smem) ...
1366     if(isnext) {
1367       // start another block
1368       tofindb = totest;
1369     }             // if(islocal)
1370   } while(true);
1371
1372   if(foundsmem == 1) {
1373     // find suitable block
1374     mem = gcbaseva+bamboo_smemtbl[tofindb]+((tofindb<NUMCORES4GC) ?
1375                                             (BAMBOO_SMEM_SIZE_L*tofindb) : (BAMBOO_LARGE_SMEM_BOUND+
1376                                                                             (tofindb-NUMCORES4GC)*BAMBOO_SMEM_SIZE));
1377     *allocsize = size;
1378     // set bamboo_smemtbl
1379     for(int i = tofindb; i <= totest; i++) {
1380       bamboo_smemtbl[i]=(i<NUMCORES4GC) ? BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
1381     }
1382     if(tofindb == bamboo_free_block) {
1383       bamboo_free_block = totest+1;
1384     }
1385   } else if(foundsmem == 2) {
1386     // no suitable block
1387     *allocsize = 0;
1388     mem = NULL;
1389   }
1390
1391   return mem;
1392 } // void * globalmalloc_I(int, int, int *)
1393 #endif // #ifdef MULTICORE_GC
1394
1395 // malloc from the shared memory
1396 void * smemalloc_I(int coren,
1397                    int size,
1398                    int * allocsize) {
1399   void * mem = NULL;
1400 #ifdef MULTICORE_GC
1401   int isize = size+(BAMBOO_CACHE_LINE_SIZE);
1402
1403   // go through the bamboo_smemtbl for suitable partitions
1404   switch(bamboo_smem_mode) {
1405   case SMEMLOCAL: {
1406     mem = localmalloc_I(coren, isize, allocsize);
1407     break;
1408   }
1409
1410   case SMEMFIXED: {
1411     // TODO not supported yet
1412     BAMBOO_EXIT(0xe001);
1413     break;
1414   }
1415
1416   case SMEMMIXED: {
1417     // TODO not supported yet
1418     BAMBOO_EXIT(0xe002);
1419     break;
1420   }
1421
1422   case SMEMGLOBAL: {
1423     mem = globalmalloc_I(coren, isize, allocsize);
1424     break;
1425   }
1426
1427   default:
1428     break;
1429   }
1430
1431   if(mem == NULL) {
1432 #else
1433   // TODO
1434 #ifdef PROFILE
1435   /*if(!interruptInfoOverflow) {
1436     InterruptInfo* intInfo = RUNMALLOC_I(sizeof(struct interrupt_info));
1437     interruptInfoArray[interruptInfoIndex] = intInfo;
1438     intInfo->startTime = BAMBOO_GET_EXE_TIME();
1439     intInfo->endTime = -1;
1440   }*/
1441 #endif  
1442   int toallocate = (size>(BAMBOO_SMEM_SIZE)) ? (size) : (BAMBOO_SMEM_SIZE);
1443   //mem = mspace_calloc(bamboo_free_msp, 1, toallocate);
1444   if(toallocate > bamboo_free_smem_size) {
1445         // no enough mem
1446         mem = NULL;
1447   } else {
1448         mem = (void *)bamboo_free_smemp;
1449         bamboo_free_smemp = ((void*)bamboo_free_smemp) + toallocate;
1450         bamboo_free_smem_size -= toallocate;
1451         //BAMBOO_MEMSET_WH(mem, '\0', toallocate);
1452   }
1453   *allocsize = toallocate;
1454 #ifdef PROFILE
1455   /*if(!interruptInfoOverflow) {
1456     interruptInfoArray[interruptInfoIndex]->endTime=BAMBOO_GET_EXE_TIME();
1457     interruptInfoIndex++;
1458     if(interruptInfoIndex == INTERRUPTINFOLENGTH) {
1459       interruptInfoOverflow = true;
1460     }
1461   }*/
1462 #endif
1463   if(mem == NULL) {
1464 #endif // MULTICORE_GC
1465     // no enough shared global memory
1466     *allocsize = 0;
1467 #ifdef MULTICORE_GC
1468     gcflag = true;
1469     return NULL;
1470 #else
1471     BAMBOO_DEBUGPRINT(0xa001);
1472     BAMBOO_EXIT(0xa001);
1473 #endif
1474   }
1475   return mem;
1476 }  // void * smemalloc_I(int, int, int)
1477
1478 INLINE int checkMsgLength_I(int size) {
1479 #ifdef DEBUG
1480 #ifndef TILERA
1481   BAMBOO_DEBUGPRINT(0xcccc);
1482 #endif
1483 #endif
1484   int type = msgdata[msgdataindex];
1485   switch(type) {
1486   case STATUSCONFIRM:
1487   case TERMINATE:
1488 #ifdef MULTICORE_GC
1489   case GCSTARTINIT:
1490   case GCSTART:
1491   case GCSTARTFLUSH:
1492   case GCFINISH:
1493   case GCMARKCONFIRM:
1494   case GCLOBJREQUEST:
1495 #endif
1496     {
1497       msglength = 1;
1498       break;
1499     }
1500
1501   case PROFILEOUTPUT:
1502   case PROFILEFINISH:
1503 #ifdef MULTICORE_GC
1504   case GCSTARTCOMPACT:
1505   case GCFINISHINIT:
1506   case GCFINISHFLUSH:
1507   case GCMARKEDOBJ:
1508 #endif
1509     {
1510       msglength = 2;
1511       break;
1512     }
1513
1514   case MEMREQUEST:
1515   case MEMRESPONSE:
1516 #ifdef MULTICORE_GC
1517   case GCMAPREQUEST:
1518   case GCMAPINFO:
1519   case GCLOBJMAPPING:
1520 #endif
1521     {
1522       msglength = 3;
1523       break;
1524     }
1525
1526   case TRANSTALL:
1527   case LOCKGROUNT:
1528   case LOCKDENY:
1529   case LOCKRELEASE:
1530   case REDIRECTGROUNT:
1531   case REDIRECTDENY:
1532   case REDIRECTRELEASE:
1533 #ifdef MULTICORE_GC
1534   case GCFINISHMARK:
1535   case GCMOVESTART:
1536 #endif
1537     {
1538       msglength = 4;
1539       break;
1540     }
1541
1542   case LOCKREQUEST:
1543   case STATUSREPORT:
1544 #ifdef MULTICORE_GC
1545   case GCFINISHCOMPACT:
1546   case GCMARKREPORT:
1547 #endif
1548     {
1549       msglength = 5;
1550       break;
1551     }
1552
1553   case REDIRECTLOCK:
1554   {
1555     msglength = 6;
1556     break;
1557   }
1558
1559   case TRANSOBJ:                // nonfixed size
1560 #ifdef MULTICORE_GC
1561   case GCLOBJINFO:
1562 #endif
1563     {             // nonfixed size
1564       if(size > 1) {
1565         msglength = msgdata[msgdataindex+1];
1566       } else {
1567         return -1;
1568       }
1569       break;
1570     }
1571
1572   default:
1573   {
1574     BAMBOO_DEBUGPRINT_REG(type);
1575     BAMBOO_DEBUGPRINT_REG(msgdataindex);
1576     int i = 6;
1577     while(i-- > 0) {
1578       BAMBOO_DEBUGPRINT(msgdata[msgdataindex+i]);
1579     }
1580     BAMBOO_EXIT(0xd005);
1581     break;
1582   }
1583   }
1584 #ifdef DEBUG
1585 #ifndef TILERA
1586   BAMBOO_DEBUGPRINT_REG(msgdata[msgdataindex]);
1587 #endif
1588 #endif
1589 #ifdef DEBUG
1590 #ifndef TILERA
1591   BAMBOO_DEBUGPRINT(0xffff);
1592 #endif
1593 #endif
1594   return msglength;
1595 }
1596
1597 INLINE void processmsg_transobj_I() {
1598   MSG_INDEXINC_I();
1599   struct transObjInfo * transObj = RUNMALLOC_I(sizeof(struct transObjInfo));
1600   int k = 0;
1601 #ifdef DEBUG
1602 #ifndef CLOSE_PRINT
1603   BAMBOO_DEBUGPRINT(0xe880);
1604 #endif
1605 #endif
1606   if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
1607 #ifndef CLOSE_PRINT
1608     BAMBOO_DEBUGPRINT_REG(msgdata[msgdataindex] /*[2]*/);
1609 #endif
1610     BAMBOO_EXIT(0xa002);
1611   }
1612   // store the object and its corresponding queue info, enqueue it later
1613   transObj->objptr = (void *)msgdata[msgdataindex];       //[2]
1614   MSG_INDEXINC_I();
1615   transObj->length = (msglength - 3) / 2;
1616   transObj->queues = RUNMALLOC_I(sizeof(int)*(msglength - 3));
1617   for(k = 0; k < transObj->length; ++k) {
1618     transObj->queues[2*k] = msgdata[msgdataindex];             //[3+2*k];
1619     MSG_INDEXINC_I();
1620 #ifdef DEBUG
1621 #ifndef CLOSE_PRINT
1622     //BAMBOO_DEBUGPRINT_REG(transObj->queues[2*k]);
1623 #endif
1624 #endif
1625     transObj->queues[2*k+1] = msgdata[msgdataindex];             //[3+2*k+1];
1626     MSG_INDEXINC_I();
1627 #ifdef DEBUG
1628 #ifndef CLOSE_PRINT
1629     //BAMBOO_DEBUGPRINT_REG(transObj->queues[2*k+1]);
1630 #endif
1631 #endif
1632   }
1633   // check if there is an existing duplicate item
1634   {
1635     struct QueueItem * qitem = getHead(&objqueue);
1636     struct QueueItem * prev = NULL;
1637     while(qitem != NULL) {
1638       struct transObjInfo * tmpinfo =
1639         (struct transObjInfo *)(qitem->objectptr);
1640       if(tmpinfo->objptr == transObj->objptr) {
1641         // the same object, remove outdate one
1642         RUNFREE(tmpinfo->queues);
1643         RUNFREE(tmpinfo);
1644         removeItem(&objqueue, qitem);
1645         //break;
1646       } else {
1647         prev = qitem;
1648       }
1649       if(prev == NULL) {
1650         qitem = getHead(&objqueue);
1651       } else {
1652         qitem = getNextQueueItem(prev);
1653       }
1654     }
1655     addNewItem_I(&objqueue, (void *)transObj);
1656   }
1657   ++(self_numreceiveobjs);
1658 }
1659
1660 INLINE void processmsg_transtall_I() {
1661   if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1662     // non startup core can not receive stall msg
1663 #ifndef CLOSE_PRINT
1664     BAMBOO_DEBUGPRINT_REG(msgdata[msgdataindex] /*[1]*/);
1665 #endif
1666     BAMBOO_EXIT(0xa003);
1667   }
1668   int num_core = msgdata[msgdataindex];       //[1]
1669   MSG_INDEXINC_I();
1670   if(num_core < NUMCORESACTIVE) {
1671 #ifdef DEBUG
1672 #ifndef CLOSE_PRINT
1673     BAMBOO_DEBUGPRINT(0xe881);
1674 #endif
1675 #endif
1676     corestatus[num_core] = 0;
1677     numsendobjs[num_core] = msgdata[msgdataindex];             //[2];
1678     MSG_INDEXINC_I();
1679     numreceiveobjs[num_core] = msgdata[msgdataindex];             //[3];
1680     MSG_INDEXINC_I();
1681   }
1682 }
1683
1684 #ifndef MULTICORE_GC
1685 INLINE void processmsg_lockrequest_I() {
1686   // check to see if there is a lock exist for the required obj
1687   // msgdata[1] -> lock type
1688   int locktype = msgdata[msgdataindex];       //[1];
1689   MSG_INDEXINC_I();
1690   int data2 = msgdata[msgdataindex];       // obj pointer
1691   MSG_INDEXINC_I();
1692   int data3 = msgdata[msgdataindex];       // lock
1693   MSG_INDEXINC_I();
1694   int data4 = msgdata[msgdataindex];       // request core
1695   MSG_INDEXINC_I();
1696   // -1: redirected, 0: approved, 1: denied
1697   int deny = processlockrequest(locktype, data3, data2, data4, data4, true);
1698   if(deny == -1) {
1699     // this lock request is redirected
1700     return;
1701   } else {
1702     // send response msg
1703     // for 32 bit machine, the size is always 4 words, cache the msg first
1704     int tmp = deny==1 ? LOCKDENY : LOCKGROUNT;
1705     //if(isMsgSending) {
1706     cache_msg_4(data4, tmp, locktype, data2, data3);
1707     /*} else {
1708             send_msg_4(data4, tmp, locktype, data2, data3);
1709        }*/
1710   }
1711 }
1712
1713 INLINE void processmsg_lockgrount_I() {
1714   MSG_INDEXINC_I();
1715   if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
1716 #ifndef CLOSE_PRINT
1717     BAMBOO_DEBUGPRINT_REG(msgdata[msgdataindex] /*[2]*/);
1718 #endif
1719     BAMBOO_EXIT(0xa004);
1720   }
1721   int data2 = msgdata[msgdataindex];
1722   MSG_INDEXINC_I();
1723   int data3 = msgdata[msgdataindex];
1724   MSG_INDEXINC_I();
1725   if((lockobj == data2) && (lock2require == data3)) {
1726 #ifdef DEBUG
1727 #ifndef CLOSE_PRINT
1728     BAMBOO_DEBUGPRINT(0xe882);
1729 #endif
1730 #endif
1731     lockresult = 1;
1732     lockflag = true;
1733 #ifndef INTERRUPT
1734     reside = false;
1735 #endif
1736   } else {
1737     // conflicts on lockresults
1738 #ifndef CLOSE_PRINT
1739     BAMBOO_DEBUGPRINT_REG(data2);
1740 #endif
1741     BAMBOO_EXIT(0xa005);
1742   }
1743 }
1744
1745 INLINE void processmsg_lockdeny_I() {
1746   MSG_INDEXINC_I();
1747   int data2 = msgdata[msgdataindex];
1748   MSG_INDEXINC_I();
1749   int data3 = msgdata[msgdataindex];
1750   MSG_INDEXINC_I();
1751   if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
1752 #ifndef CLOSE_PRINT
1753     BAMBOO_DEBUGPRINT_REG(data2);
1754 #endif
1755     BAMBOO_EXIT(0xa006);
1756   }
1757   if((lockobj == data2) && (lock2require == data3)) {
1758 #ifdef DEBUG
1759 #ifndef CLOSE_PRINT
1760     BAMBOO_DEBUGPRINT(0xe883);
1761 #endif
1762 #endif
1763     lockresult = 0;
1764     lockflag = true;
1765 #ifndef INTERRUPT
1766     reside = false;
1767 #endif
1768   } else {
1769     // conflicts on lockresults
1770 #ifndef CLOSE_PRINT
1771     BAMBOO_DEBUGPRINT_REG(data2);
1772 #endif
1773     BAMBOO_EXIT(0xa007);
1774   }
1775 }
1776
1777 INLINE void processmsg_lockrelease_I() {
1778   int data1 = msgdata[msgdataindex];
1779   MSG_INDEXINC_I();
1780   int data2 = msgdata[msgdataindex];
1781   MSG_INDEXINC_I();
1782   // receive lock release msg
1783   processlockrelease(data1, data2, 0, false);
1784 }
1785
1786 INLINE void processmsg_redirectlock_I() {
1787   // check to see if there is a lock exist for the required obj
1788   int data1 = msgdata[msgdataindex];
1789   MSG_INDEXINC_I();       //msgdata[1]; // lock type
1790   int data2 = msgdata[msgdataindex];
1791   MSG_INDEXINC_I();      //msgdata[2]; // obj pointer
1792   int data3 = msgdata[msgdataindex];
1793   MSG_INDEXINC_I();       //msgdata[3]; // redirect lock
1794   int data4 = msgdata[msgdataindex];
1795   MSG_INDEXINC_I();       //msgdata[4]; // root request core
1796   int data5 = msgdata[msgdataindex];
1797   MSG_INDEXINC_I();       //msgdata[5]; // request core
1798   int deny = processlockrequest(data1, data3, data2, data5, data4, true);
1799   if(deny == -1) {
1800     // this lock request is redirected
1801     return;
1802   } else {
1803     // send response msg
1804     // for 32 bit machine, the size is always 4 words, cache the msg first
1805     //if(isMsgSending) {
1806     cache_msg_4(data4, deny==1 ? REDIRECTDENY : REDIRECTGROUNT,
1807                 data1, data2, data3);
1808     /*} else {
1809             send_msg_4(data4, deny==1?REDIRECTDENY:REDIRECTGROUNT,
1810                                                      data1, data2, data3);
1811        }*/
1812   }
1813 }
1814
1815 INLINE void processmsg_redirectgrount_I() {
1816   MSG_INDEXINC_I();
1817   int data2 = msgdata[msgdataindex];
1818   MSG_INDEXINC_I();
1819   if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
1820 #ifndef CLOSE_PRINT
1821     BAMBOO_DEBUGPRINT_REG(data2);
1822 #endif
1823     BAMBOO_EXIT(0xa00a);
1824   }
1825   if(lockobj == data2) {
1826 #ifdef DEBUG
1827 #ifndef CLOSE_PRINT
1828     BAMBOO_DEBUGPRINT(0xe891);
1829 #endif
1830 #endif
1831     int data3 = msgdata[msgdataindex];
1832     MSG_INDEXINC_I();
1833     lockresult = 1;
1834     lockflag = true;
1835     RuntimeHashadd_I(objRedirectLockTbl, lockobj, data3);
1836 #ifndef INTERRUPT
1837     reside = false;
1838 #endif
1839   } else {
1840     // conflicts on lockresults
1841 #ifndef CLOSE_PRINT
1842     BAMBOO_DEBUGPRINT_REG(data2);
1843 #endif
1844     BAMBOO_EXIT(0xa00b);
1845   }
1846 }
1847
1848 INLINE void processmsg_redirectdeny_I() {
1849   MSG_INDEXINC_I();
1850   int data2 = msgdata[msgdataindex];
1851   MSG_INDEXINC_I();
1852   if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
1853 #ifndef CLOSE_PRINT
1854     BAMBOO_DEBUGPRINT_REG(data2);
1855 #endif
1856     BAMBOO_EXIT(0xa00c);
1857   }
1858   if(lockobj == data2) {
1859 #ifdef DEBUG
1860 #ifndef CLOSE_PRINT
1861     BAMBOO_DEBUGPRINT(0xe892);
1862 #endif
1863 #endif
1864     lockresult = 0;
1865     lockflag = true;
1866 #ifndef INTERRUPT
1867     reside = false;
1868 #endif
1869   } else {
1870     // conflicts on lockresults
1871 #ifndef CLOSE_PRINT
1872     BAMBOO_DEBUGPRINT_REG(data2);
1873 #endif
1874     BAMBOO_EXIT(0xa00d);
1875   }
1876 }
1877
1878 INLINE void processmsg_redirectrelease_I() {
1879   int data1 = msgdata[msgdataindex];
1880   MSG_INDEXINC_I();
1881   int data2 = msgdata[msgdataindex];
1882   MSG_INDEXINC_I();
1883   int data3 = msgdata[msgdataindex];
1884   MSG_INDEXINC_I();
1885   processlockrelease(data1, data2, data3, true);
1886 }
1887 #endif // #ifndef MULTICORE_GC
1888
1889 #ifdef PROFILE
1890 INLINE void processmsg_profileoutput_I() {
1891   if(BAMBOO_NUM_OF_CORE == STARTUPCORE) {
1892     // startup core can not receive profile output finish msg
1893     BAMBOO_EXIT(0xa008);
1894   }
1895 #ifdef DEBUG
1896 #ifndef CLOSE_PRINT
1897   BAMBOO_DEBUGPRINT(0xe885);
1898 #endif
1899 #endif
1900   stall = true;
1901   totalexetime = msgdata[msgdataindex];       //[1]
1902   MSG_INDEXINC_I();
1903   outputProfileData();
1904   // cache the msg first
1905   //if(isMsgSending) {
1906   cache_msg_2(STARTUPCORE, PROFILEFINISH, BAMBOO_NUM_OF_CORE);
1907   /*} else {
1908           send_msg_2(STARTUPCORE, PROFILEFINISH, BAMBOO_NUM_OF_CORE);
1909      }*/
1910 }
1911
1912 INLINE void processmsg_profilefinish_I() {
1913   if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1914     // non startup core can not receive profile output finish msg
1915 #ifndef CLOSE_PRINT
1916     BAMBOO_DEBUGPRINT_REG(msgdata[msgdataindex /*1*/]);
1917 #endif
1918     BAMBOO_EXIT(0xa009);
1919   }
1920 #ifdef DEBUG
1921 #ifndef CLOSE_PRINT
1922   BAMBOO_DEBUGPRINT(0xe886);
1923 #endif
1924 #endif
1925   int data1 = msgdata[msgdataindex];
1926   MSG_INDEXINC_I();
1927   profilestatus[data1] = 0;
1928 }
1929 #endif // #ifdef PROFILE
1930
1931 INLINE void processmsg_statusconfirm_I() {
1932   if((BAMBOO_NUM_OF_CORE == STARTUPCORE)
1933      || (BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1)) {
1934     // wrong core to receive such msg
1935     BAMBOO_EXIT(0xa00e);
1936   } else {
1937     // send response msg
1938 #ifdef DEBUG
1939 #ifndef CLOSE_PRINT
1940     BAMBOO_DEBUGPRINT(0xe887);
1941 #endif
1942 #endif
1943     // cache the msg first
1944     //if(isMsgSending) {
1945     cache_msg_5(STARTUPCORE, STATUSREPORT,
1946                 busystatus ? 1 : 0, BAMBOO_NUM_OF_CORE,
1947                 self_numsendobjs, self_numreceiveobjs);
1948     /*} else {
1949             send_msg_5(STARTUPCORE, STATUSREPORT, busystatus?1:0,
1950                                                      BAMBOO_NUM_OF_CORE, self_numsendobjs,
1951                                                      self_numreceiveobjs);
1952        }*/
1953   }
1954 }
1955
1956 INLINE void processmsg_statusreport_I() {
1957   int data1 = msgdata[msgdataindex];
1958   MSG_INDEXINC_I();
1959   int data2 = msgdata[msgdataindex];
1960   MSG_INDEXINC_I();
1961   int data3 = msgdata[msgdataindex];
1962   MSG_INDEXINC_I();
1963   int data4 = msgdata[msgdataindex];
1964   MSG_INDEXINC_I();
1965   // receive a status confirm info
1966   if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1967     // wrong core to receive such msg
1968 #ifndef CLOSE_PRINT
1969     BAMBOO_DEBUGPRINT_REG(data2);
1970 #endif
1971     BAMBOO_EXIT(0xa00f);
1972   } else {
1973 #ifdef DEBUG
1974 #ifndef CLOSE_PRINT
1975     BAMBOO_DEBUGPRINT(0xe888);
1976 #endif
1977 #endif
1978     if(waitconfirm) {
1979       numconfirm--;
1980     }
1981     corestatus[data2] = data1;
1982     numsendobjs[data2] = data3;
1983     numreceiveobjs[data2] = data4;
1984   }
1985 }
1986
1987 INLINE void processmsg_terminate_I() {
1988 #ifdef DEBUG
1989 #ifndef CLOSE_PRINT
1990   BAMBOO_DEBUGPRINT(0xe889);
1991 #endif
1992 #endif
1993   disruntimedata();
1994   BAMBOO_EXIT_APP(0);
1995 }
1996
1997 INLINE void processmsg_memrequest_I() {
1998 #ifdef PROFILE
1999   if(!interruptInfoOverflow) {
2000     InterruptInfo* intInfo = RUNMALLOC_I(sizeof(struct interrupt_info));
2001     interruptInfoArray[interruptInfoIndex] = intInfo;
2002     intInfo->startTime = BAMBOO_GET_EXE_TIME();
2003     intInfo->endTime = -1;
2004   }
2005 #endif
2006   int data1 = msgdata[msgdataindex];
2007   MSG_INDEXINC_I();
2008   int data2 = msgdata[msgdataindex];
2009   MSG_INDEXINC_I();
2010   // receive a shared memory request msg
2011   if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
2012     // wrong core to receive such msg
2013 #ifndef CLOSE_PRINT
2014     BAMBOO_DEBUGPRINT_REG(data2);
2015 #endif
2016     BAMBOO_EXIT(0xa010);
2017   } else {
2018 #ifdef DEBUG
2019 #ifndef CLOSE_PRINT
2020     BAMBOO_DEBUGPRINT(0xe88a);
2021 #endif
2022 #endif
2023     int allocsize = 0;
2024     void * mem = NULL;
2025 #ifdef MULTICORE_GC
2026     if(gcprocessing) {
2027       // is currently doing gc, dump this msg
2028       if(INITPHASE == gcphase) {
2029         // if still in the initphase of gc, send a startinit msg again,
2030         // cache the msg first
2031         //if(isMsgSending) {
2032         cache_msg_1(data2, GCSTARTINIT);
2033         /*} else {
2034                 send_msg_1(data2, GCSTARTINIT);
2035            }*/
2036       }
2037     } else {
2038 #endif
2039     mem = smemalloc_I(data2, data1, &allocsize);
2040     if(mem != NULL) {
2041       // send the start_va to request core, cache the msg first
2042       //if(isMsgSending) {
2043       cache_msg_3(data2, MEMRESPONSE, mem, allocsize);
2044       /*} else {
2045               send_msg_3(data2, MEMRESPONSE, mem, allocsize);
2046          }*/
2047     } // if mem == NULL, the gcflag of the startup core has been set
2048     // and the gc should be started later, then a GCSTARTINIT msg
2049     // will be sent to the requesting core to notice it to start gc
2050     // and try malloc again
2051 #ifdef MULTICORE_GC
2052   }
2053 #endif
2054   }
2055 #ifdef PROFILE
2056   if(!interruptInfoOverflow) {
2057     interruptInfoArray[interruptInfoIndex]->endTime=BAMBOO_GET_EXE_TIME();
2058     interruptInfoIndex++;
2059     if(interruptInfoIndex == INTERRUPTINFOLENGTH) {
2060       interruptInfoOverflow = true;
2061     }
2062   }
2063 #endif
2064 }
2065
2066 INLINE void processmsg_memresponse_I() {
2067   int data1 = msgdata[msgdataindex];
2068   MSG_INDEXINC_I();
2069   int data2 = msgdata[msgdataindex];
2070   MSG_INDEXINC_I();
2071   // receive a shared memory response msg
2072 #ifdef DEBUG
2073 #ifndef CLOSE_PRINT
2074   BAMBOO_DEBUGPRINT(0xe88b);
2075 #endif
2076 #endif
2077 #ifdef MULTICORE_GC
2078   // if is currently doing gc, dump this msg
2079   if(!gcprocessing) {
2080 #endif
2081   if(data2 == 0) {
2082     bamboo_smem_size = 0;
2083     bamboo_cur_msp = 0;
2084   } else {
2085 #ifdef MULTICORE_GC
2086     // fill header to store the size of this mem block
2087     memset(data1, 0, BAMBOO_CACHE_LINE_SIZE);
2088     (*((int*)data1)) = data2;
2089     bamboo_smem_size = data2 - BAMBOO_CACHE_LINE_SIZE;
2090     bamboo_cur_msp = data1 + BAMBOO_CACHE_LINE_SIZE;
2091 #else
2092     bamboo_smem_size = data2;
2093     bamboo_cur_msp =(void*)(data1);
2094 #endif
2095   }
2096   smemflag = true;
2097 #ifdef MULTICORE_GC
2098 }
2099 #endif
2100 }
2101
2102 #ifdef MULTICORE_GC
2103 INLINE void processmsg_gcstartinit_I() {
2104   gcflag = true;
2105   gcphase = INITPHASE;
2106   if(!smemflag) {
2107     // is waiting for response of mem request
2108     // let it return NULL and start gc
2109     bamboo_smem_size = 0;
2110     bamboo_cur_msp = NULL;
2111     smemflag = true;
2112   }
2113 }
2114
2115 INLINE void processmsg_gcstart_I() {
2116 #ifdef DEBUG
2117 #ifndef CLOSE_PRINT
2118   BAMBOO_DEBUGPRINT(0xe88c);
2119 #endif
2120 #endif
2121   // set the GC flag
2122   gcphase = MARKPHASE;
2123 }
2124
2125 INLINE void processmsg_gcstartcompact_I() {
2126   gcblock2fill = msgdata[msgdataindex];
2127   MSG_INDEXINC_I();       //msgdata[1];
2128   gcphase = COMPACTPHASE;
2129 }
2130
2131 INLINE void processmsg_gcstartflush_I() {
2132   gcphase = FLUSHPHASE;
2133 }
2134
2135 INLINE void processmsg_gcfinishinit_I() {
2136   int data1 = msgdata[msgdataindex];
2137   MSG_INDEXINC_I();
2138   // received a init phase finish msg
2139   if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
2140     // non startup core can not receive this msg
2141 #ifndef CLOSE_PRINT
2142     BAMBOO_DEBUGPRINT_REG(data1);
2143 #endif
2144     BAMBOO_EXIT(0xb001);
2145   }
2146 #ifdef DEBUG
2147   BAMBOO_DEBUGPRINT(0xe88c);
2148   BAMBOO_DEBUGPRINT_REG(data1);
2149 #endif
2150   // All cores should do init GC
2151   if(data1 < NUMCORESACTIVE) {
2152     gccorestatus[data1] = 0;
2153   }
2154 }
2155
2156 INLINE void processmsg_gcfinishmark_I() {
2157   int data1 = msgdata[msgdataindex];
2158   MSG_INDEXINC_I();
2159   int data2 = msgdata[msgdataindex];
2160   MSG_INDEXINC_I();
2161   int data3 = msgdata[msgdataindex];
2162   MSG_INDEXINC_I();
2163   // received a mark phase finish msg
2164   if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
2165     // non startup core can not receive this msg
2166 #ifndef CLOSE_PRINT
2167     BAMBOO_DEBUGPRINT_REG(data1);
2168 #endif
2169     BAMBOO_EXIT(0xb002);
2170   }
2171   // all cores should do mark
2172   if(data1 < NUMCORESACTIVE) {
2173     gccorestatus[data1] = 0;
2174     gcnumsendobjs[data1] = data2;
2175     gcnumreceiveobjs[data1] = data3;
2176   }
2177 }
2178
2179 INLINE void processmsg_gcfinishcompact_I() {
2180   if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
2181     // non startup core can not receive this msg
2182     // return -1
2183 #ifndef CLOSE_PRINT
2184     BAMBOO_DEBUGPRINT_REG(msgdata[msgdataindex] /*[1]*/);
2185 #endif
2186     BAMBOO_EXIT(0xb003);
2187   }
2188   int cnum = msgdata[msgdataindex];
2189   MSG_INDEXINC_I();       //msgdata[1];
2190   int filledblocks = msgdata[msgdataindex];
2191   MSG_INDEXINC_I();       //msgdata[2];
2192   int heaptop = msgdata[msgdataindex];
2193   MSG_INDEXINC_I();       //msgdata[3];
2194   int data4 = msgdata[msgdataindex];
2195   MSG_INDEXINC_I();       //msgdata[4];
2196   // only gc cores need to do compact
2197   if(cnum < NUMCORES4GC) {
2198     if(COMPACTPHASE == gcphase) {
2199       gcfilledblocks[cnum] = filledblocks;
2200       gcloads[cnum] = heaptop;
2201     }
2202     if(data4 > 0) {
2203       // ask for more mem
2204       int startaddr = 0;
2205       int tomove = 0;
2206       int dstcore = 0;
2207       if(gcfindSpareMem_I(&startaddr, &tomove, &dstcore, data4, cnum)) {
2208         // cache the msg first
2209         //if(isMsgSending) {
2210         cache_msg_4(cnum, GCMOVESTART, dstcore, startaddr, tomove);
2211         /*} else {
2212                       send_msg_4(cnum, GCMOVESTART, dstcore, startaddr, tomove);
2213               }*/
2214       }
2215     } else {
2216       gccorestatus[cnum] = 0;
2217     }             // if(data4>0)
2218   }       // if(cnum < NUMCORES4GC)
2219 }
2220
2221 INLINE void processmsg_gcfinishflush_I() {
2222   int data1 = msgdata[msgdataindex];
2223   MSG_INDEXINC_I();
2224   // received a flush phase finish msg
2225   if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
2226     // non startup core can not receive this msg
2227     // return -1
2228 #ifndef CLOSE_PRINT
2229     BAMBOO_DEBUGPRINT_REG(data1);
2230 #endif
2231     BAMBOO_EXIT(0xb004);
2232   }
2233   // all cores should do flush
2234   if(data1 < NUMCORESACTIVE) {
2235     gccorestatus[data1] = 0;
2236   }
2237 }
2238
2239 INLINE void processmsg_gcmarkconfirm_I() {
2240   if((BAMBOO_NUM_OF_CORE == STARTUPCORE)
2241      || (BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1)) {
2242     // wrong core to receive such msg
2243     BAMBOO_EXIT(0xb005);
2244   } else {
2245     // send response msg, cahce the msg first
2246     //if(isMsgSending) {
2247     cache_msg_5(STARTUPCORE, GCMARKREPORT, BAMBOO_NUM_OF_CORE,
2248                 gcbusystatus, gcself_numsendobjs,
2249                 gcself_numreceiveobjs);
2250     /*} else {
2251             send_msg_5(STARTUPCORE, GCMARKREPORT, BAMBOO_NUM_OF_CORE,
2252                                                      gcbusystatus, gcself_numsendobjs,
2253                                                      gcself_numreceiveobjs);
2254        }*/
2255   }
2256 }
2257
2258 INLINE void processmsg_gcmarkreport_I() {
2259   int data1 = msgdata[msgdataindex];
2260   MSG_INDEXINC_I();
2261   int data2 = msgdata[msgdataindex];
2262   MSG_INDEXINC_I();
2263   int data3 = msgdata[msgdataindex];
2264   MSG_INDEXINC_I();
2265   int data4 = msgdata[msgdataindex];
2266   MSG_INDEXINC_I();
2267   // received a marked phase finish confirm response msg
2268   if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
2269     // wrong core to receive such msg
2270 #ifndef CLOSE_PRINT
2271     BAMBOO_DEBUGPRINT_REG(data2);
2272 #endif
2273     BAMBOO_EXIT(0xb006);
2274   } else {
2275     if(waitconfirm) {
2276       numconfirm--;
2277     }
2278     gccorestatus[data1] = data2;
2279     gcnumsendobjs[data1] = data3;
2280     gcnumreceiveobjs[data1] = data4;
2281   }
2282 }
2283
2284 INLINE void processmsg_gcmarkedobj_I() {
2285   int data1 = msgdata[msgdataindex];
2286   MSG_INDEXINC_I();
2287   // received a markedObj msg
2288   if(((int *)data1)[6] == INIT) {
2289     // this is the first time that this object is discovered,
2290     // set the flag as DISCOVERED
2291     ((int *)data1)[6] = DISCOVERED;
2292     gc_enqueue_I(data1);
2293   }
2294   gcself_numreceiveobjs++;
2295   gcbusystatus = true;
2296 }
2297
2298 INLINE void processmsg_gcmovestart_I() {
2299   gctomove = true;
2300   gcdstcore = msgdata[msgdataindex];
2301   MSG_INDEXINC_I();       //msgdata[1];
2302   gcmovestartaddr = msgdata[msgdataindex];
2303   MSG_INDEXINC_I();       //msgdata[2];
2304   gcblock2fill = msgdata[msgdataindex];
2305   MSG_INDEXINC_I();       //msgdata[3];
2306 }
2307
2308 INLINE void processmsg_gcmaprequest_I() {
2309 #ifdef GC_PROFILE
2310   //unsigned long long ttime = BAMBOO_GET_EXE_TIME();
2311 #endif
2312   void * dstptr = NULL;
2313   int data1 = msgdata[msgdataindex];
2314   MSG_INDEXINC_I();
2315   //dstptr = mgchashSearch(msgdata[1]);
2316 #ifdef GC_PROFILE
2317   unsigned long long ttime = BAMBOO_GET_EXE_TIME();
2318 #endif
2319   RuntimeHashget(gcpointertbl, data1, &dstptr);
2320 #ifdef GC_PROFILE
2321   flushstalltime += BAMBOO_GET_EXE_TIME() - ttime;
2322 #endif
2323   int data2 = msgdata[msgdataindex];
2324   MSG_INDEXINC_I();
2325   //MGCHashget(gcpointertbl, msgdata[1], &dstptr);
2326 #ifdef GC_PROFILE
2327   unsigned long long ttimei = BAMBOO_GET_EXE_TIME();
2328 #endif
2329   if(NULL == dstptr) {
2330     // no such pointer in this core, something is wrong
2331 #ifdef DEBUG
2332     BAMBOO_DEBUGPRINT_REG(data1);
2333     BAMBOO_DEBUGPRINT_REG(data2);
2334 #endif
2335     BAMBOO_EXIT(0xb007);
2336     //assume that the object was not moved, use the original address
2337     /*if(isMsgSending) {
2338             cache_msg_3(msgdata[2], GCMAPINFO, msgdata[1], msgdata[1]);
2339        } else {
2340             send_msg_3(msgdata[2], GCMAPINFO, msgdata[1], msgdata[1]);
2341        }*/
2342   } else {
2343     // send back the mapping info, cache the msg first
2344     //if(isMsgSending) {
2345     cache_msg_3(data2, GCMAPINFO, data1, (int)dstptr);
2346     /*} else {
2347             send_msg_3(data2, GCMAPINFO, data1, (int)dstptr);
2348        }*/
2349   }
2350 #ifdef GC_PROFILE
2351   flushstalltime_i += BAMBOO_GET_EXE_TIME()-ttimei;
2352   //num_mapinforequest_i++;
2353 #endif
2354 }
2355
2356 INLINE void processmsg_gcmapinfo_I() {
2357 #ifdef GC_PROFILE
2358   //unsigned long long ttime = BAMBOO_GET_EXE_TIME();
2359 #endif
2360   int data1 = msgdata[msgdataindex];
2361   MSG_INDEXINC_I();
2362   if(data1 != gcobj2map) {
2363     // obj not matched, something is wrong
2364 #ifdef DEBUG
2365     BAMBOO_DEBUGPRINT_REG(gcobj2map);
2366     BAMBOO_DEBUGPRINT_REG(msgdata[1]);
2367 #endif
2368     BAMBOO_EXIT(0xb008);
2369   } else {
2370     gcmappedobj = msgdata[msgdataindex];                     // [2]
2371     MSG_INDEXINC_I();
2372     //mgchashReplace_I(msgdata[1], msgdata[2]);
2373     //mgchashInsert_I(gcobj2map, gcmappedobj);
2374     RuntimeHashadd_I(gcpointertbl, gcobj2map, gcmappedobj);
2375     //MGCHashadd_I(gcpointertbl, gcobj2map, gcmappedobj);
2376   }
2377   gcismapped = true;
2378 #ifdef GC_PROFILE
2379   //flushstalltime += BAMBOO_GET_EXE_TIME() - ttime;
2380 #endif
2381 }
2382
2383 INLINE void processmsg_gclobjinfo_I() {
2384   numconfirm--;
2385
2386   int data1 = msgdata[msgdataindex];
2387   MSG_INDEXINC_I();
2388   int data2 = msgdata[msgdataindex];
2389   MSG_INDEXINC_I();
2390   if(BAMBOO_NUM_OF_CORE > NUMCORES4GC - 1) {
2391 #ifndef CLOSE_PRINT
2392     BAMBOO_DEBUGPRINT_REG(data2);
2393 #endif
2394     BAMBOO_EXIT(0xb009);
2395   }
2396   // store the mark result info
2397   int cnum = data2;
2398   gcloads[cnum] = msgdata[msgdataindex];
2399   MSG_INDEXINC_I();       // msgdata[3];
2400   int data4 = msgdata[msgdataindex];
2401   MSG_INDEXINC_I();
2402   if(gcheaptop < data4) {
2403     gcheaptop = data4;
2404   }
2405   // large obj info here
2406   for(int k = 5; k < data1; ) {
2407     int lobj = msgdata[msgdataindex];
2408     MSG_INDEXINC_I();             //msgdata[k++];
2409     int length = msgdata[msgdataindex];
2410     MSG_INDEXINC_I();             //msgdata[k++];
2411     gc_lobjenqueue_I(lobj, length, cnum);
2412     gcnumlobjs++;
2413   }       // for(int k = 5; k < msgdata[1];)
2414 }
2415
2416 INLINE void processmsg_gclobjmapping_I() {
2417   int data1 = msgdata[msgdataindex];
2418   MSG_INDEXINC_I();
2419   int data2 = msgdata[msgdataindex];
2420   MSG_INDEXINC_I();
2421   //mgchashInsert_I(msgdata[1], msgdata[2]);
2422   RuntimeHashadd_I(gcpointertbl, data1, data2);
2423   //MGCHashadd_I(gcpointertbl, msgdata[1], msgdata[2]);
2424 }
2425 #endif // #ifdef MULTICORE_GC
2426
2427 // receive object transferred from other cores
2428 // or the terminate message from other cores
2429 // Should be invoked in critical sections!!
2430 // NOTICE: following format is for threadsimulate version only
2431 //         RAW version please see previous description
2432 // format: type + object
2433 // type: -1--stall msg
2434 //      !-1--object
2435 // return value: 0--received an object
2436 //               1--received nothing
2437 //               2--received a Stall Msg
2438 //               3--received a lock Msg
2439 //               RAW version: -1 -- received nothing
2440 //                            otherwise -- received msg type
2441 int receiveObject(int send_port_pending) {
2442 msg:
2443   // get the incoming msgs
2444   if(receiveMsg(send_port_pending) == -1) {
2445     return -1;
2446   }
2447 processmsg:
2448   // processing received msgs
2449   int size = 0;
2450   MSG_REMAINSIZE_I(&size);
2451   if((size == 0) || (checkMsgLength_I(size) == -1)) {
2452     // not a whole msg
2453     // have new coming msg
2454     if(BAMBOO_MSG_AVAIL() != 0) {
2455       goto msg;
2456     } else {
2457       return -1;
2458     }
2459   }
2460
2461   if(msglength <= size) {
2462     // have some whole msg
2463     //if(msgdataindex == msglength) {
2464     // received a whole msg
2465     MSGTYPE type;
2466     type = msgdata[msgdataindex]; //[0]
2467     MSG_INDEXINC_I();
2468     msgdatafull = false;
2469     // TODO
2470     //tprintf("msg type: %x\n", type);
2471     switch(type) {
2472     case TRANSOBJ: {
2473       // receive a object transfer msg
2474       processmsg_transobj_I();
2475       break;
2476     }                     // case TRANSOBJ
2477
2478     case TRANSTALL: {
2479       // receive a stall msg
2480       processmsg_transtall_I();
2481       break;
2482     }                     // case TRANSTALL
2483
2484 // GC version have no lock msgs
2485 #ifndef MULTICORE_GC
2486     case LOCKREQUEST: {
2487       // receive lock request msg, handle it right now
2488       processmsg_lockrequest_I();
2489       break;
2490     }                     // case LOCKREQUEST
2491
2492     case LOCKGROUNT: {
2493       // receive lock grount msg
2494       processmsg_lockgrount_I();
2495       break;
2496     }                     // case LOCKGROUNT
2497
2498     case LOCKDENY: {
2499       // receive lock deny msg
2500       processmsg_lockdeny_I();
2501       break;
2502     }                     // case LOCKDENY
2503
2504     case LOCKRELEASE: {
2505       processmsg_lockrelease_I();
2506       break;
2507     }                     // case LOCKRELEASE
2508 #endif // #ifndef MULTICORE_GC
2509
2510 #ifdef PROFILE
2511     case PROFILEOUTPUT: {
2512       // receive an output profile data request msg
2513       processmsg_profileoutput_I();
2514       break;
2515     }                     // case PROFILEOUTPUT
2516
2517     case PROFILEFINISH: {
2518       // receive a profile output finish msg
2519       processmsg_profilefinish_I();
2520       break;
2521     }                     // case PROFILEFINISH
2522 #endif // #ifdef PROFILE
2523
2524 // GC version has no lock msgs
2525 #ifndef MULTICORE_GC
2526     case REDIRECTLOCK: {
2527       // receive a redirect lock request msg, handle it right now
2528       processmsg_redirectlock_I();
2529       break;
2530     }                     // case REDIRECTLOCK
2531
2532     case REDIRECTGROUNT: {
2533       // receive a lock grant msg with redirect info
2534       processmsg_redirectgrount_I();
2535       break;
2536     }                     // case REDIRECTGROUNT
2537
2538     case REDIRECTDENY: {
2539       // receive a lock deny msg with redirect info
2540       processmsg_redirectdeny_I();
2541       break;
2542     }                     // case REDIRECTDENY
2543
2544     case REDIRECTRELEASE: {
2545       // receive a lock release msg with redirect info
2546       processmsg_redirectrelease_I();
2547       break;
2548     }                     // case REDIRECTRELEASE
2549 #endif // #ifndef MULTICORE_GC
2550
2551     case STATUSCONFIRM: {
2552       // receive a status confirm info
2553       processmsg_statusconfirm_I();
2554       break;
2555     }                     // case STATUSCONFIRM
2556
2557     case STATUSREPORT: {
2558       processmsg_statusreport_I();
2559       break;
2560     }                     // case STATUSREPORT
2561
2562     case TERMINATE: {
2563       // receive a terminate msg
2564       processmsg_terminate_I();
2565       break;
2566     }                     // case TERMINATE
2567
2568     case MEMREQUEST: {
2569       processmsg_memrequest_I();
2570       break;
2571     }                     // case MEMREQUEST
2572
2573     case MEMRESPONSE: {
2574       processmsg_memresponse_I();
2575       break;
2576     }                     // case MEMRESPONSE
2577
2578 #ifdef MULTICORE_GC
2579     // GC msgs
2580     case GCSTARTINIT: {
2581       processmsg_gcstartinit_I();
2582       break;
2583     }                     // case GCSTARTINIT
2584
2585     case GCSTART: {
2586       // receive a start GC msg
2587       processmsg_gcstart_I();
2588       break;
2589     }                     // case GCSTART
2590
2591     case GCSTARTCOMPACT: {
2592       // a compact phase start msg
2593       processmsg_gcstartcompact_I();
2594       break;
2595     }                     // case GCSTARTCOMPACT
2596
2597     case GCSTARTFLUSH: {
2598       // received a flush phase start msg
2599       processmsg_gcstartflush_I();
2600       break;
2601     }                     // case GCSTARTFLUSH
2602
2603     case GCFINISHINIT: {
2604       processmsg_gcfinishinit_I();
2605       break;
2606     }                     // case GCFINISHINIT
2607
2608     case GCFINISHMARK: {
2609       processmsg_gcfinishmark_I();
2610       break;
2611     }                     // case GCFINISHMARK
2612
2613     case GCFINISHCOMPACT: {
2614       // received a compact phase finish msg
2615       processmsg_gcfinishcompact_I();
2616       break;
2617     }                     // case GCFINISHCOMPACT
2618
2619     case GCFINISHFLUSH: {
2620       processmsg_gcfinishflush_I();
2621       break;
2622     }                     // case GCFINISHFLUSH
2623
2624     case GCFINISH: {
2625       // received a GC finish msg
2626       gcphase = FINISHPHASE;
2627       break;
2628     }                     // case GCFINISH
2629
2630     case GCMARKCONFIRM: {
2631       // received a marked phase finish confirm request msg
2632       // all cores should do mark
2633       processmsg_gcmarkconfirm_I();
2634       break;
2635     }                     // case GCMARKCONFIRM
2636
2637     case GCMARKREPORT: {
2638       processmsg_gcmarkreport_I();
2639       break;
2640     }                     // case GCMARKREPORT
2641
2642     case GCMARKEDOBJ: {
2643       processmsg_gcmarkedobj_I();
2644       break;
2645     }                     // case GCMARKEDOBJ
2646
2647     case GCMOVESTART: {
2648       // received a start moving objs msg
2649       processmsg_gcmovestart_I();
2650       break;
2651     }                     // case GCMOVESTART
2652
2653     case GCMAPREQUEST: {
2654       // received a mapping info request msg
2655       processmsg_gcmaprequest_I();
2656       break;
2657     }                     // case GCMAPREQUEST
2658
2659     case GCMAPINFO: {
2660       // received a mapping info response msg
2661       processmsg_gcmapinfo_I();
2662       break;
2663     }                     // case GCMAPINFO
2664
2665     case GCLOBJREQUEST: {
2666       // received a large objs info request msg
2667       transferMarkResults_I();
2668       break;
2669     }                     // case GCLOBJREQUEST
2670
2671     case GCLOBJINFO: {
2672       // received a large objs info response msg
2673       processmsg_gclobjinfo_I();
2674       break;
2675     }                     // case GCLOBJINFO
2676
2677     case GCLOBJMAPPING: {
2678       // received a large obj mapping info msg
2679       processmsg_gclobjmapping_I();
2680       break;
2681     }                     // case GCLOBJMAPPING
2682
2683 #endif // #ifdef MULTICORE_GC
2684
2685     default:
2686       break;
2687     }             // switch(type)
2688                   //memset(msgdata, '\0', sizeof(int) * msgdataindex);
2689                   //msgdataindex = 0;
2690     msglength = BAMBOO_MSG_BUF_LENGTH;
2691     // TODO
2692     //printf("++ msg: %x \n", type);
2693     if(msgdataindex != msgdatalast) {
2694       // still have available msg
2695       goto processmsg;
2696     }
2697 #ifdef DEBUG
2698 #ifndef CLOSE_PRINT
2699     BAMBOO_DEBUGPRINT(0xe88d);
2700 #endif
2701 #endif
2702
2703     // have new coming msg
2704     if(BAMBOO_MSG_AVAIL() != 0) {
2705       goto msg;
2706     }
2707
2708 #ifdef PROFILE
2709 /*if(isInterrupt) {
2710                 profileTaskEnd();
2711         }*/
2712 #endif
2713     return (int)type;
2714   } else {
2715     // not a whole msg
2716 #ifdef DEBUG
2717 #ifndef CLOSE_PRINT
2718     BAMBOO_DEBUGPRINT(0xe88e);
2719 #endif
2720 #endif
2721 #ifdef PROFILE
2722     /*  if(isInterrupt) {
2723                             profileTaskEnd();
2724                     }*/
2725 #endif
2726     return -2;
2727   }
2728 }
2729
2730 int enqueuetasks(struct parameterwrapper *parameter,
2731                  struct parameterwrapper *prevptr,
2732                  struct ___Object___ *ptr,
2733                  int * enterflags,
2734                  int numenterflags) {
2735   void * taskpointerarray[MAXTASKPARAMS];
2736   int j;
2737   //int numparams=parameter->task->numParameters;
2738   int numiterators=parameter->task->numTotal-1;
2739   int retval=1;
2740
2741   struct taskdescriptor * task=parameter->task;
2742
2743   //this add the object to parameterwrapper
2744   ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags,
2745                 numenterflags, enterflags==NULL);
2746
2747   /* Add enqueued object to parameter vector */
2748   taskpointerarray[parameter->slot]=ptr;
2749
2750   /* Reset iterators */
2751   for(j=0; j<numiterators; j++) {
2752     toiReset(&parameter->iterators[j]);
2753   }
2754
2755   /* Find initial state */
2756   for(j=0; j<numiterators; j++) {
2757 backtrackinit:
2758     if(toiHasNext(&parameter->iterators[j],taskpointerarray OPTARG(failed)))
2759       toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
2760     else if (j>0) {
2761       /* Need to backtrack */
2762       toiReset(&parameter->iterators[j]);
2763       j--;
2764       goto backtrackinit;
2765     } else {
2766       /* Nothing to enqueue */
2767       return retval;
2768     }
2769   }
2770
2771   while(1) {
2772     /* Enqueue current state */
2773     //int launch = 0;
2774     struct taskparamdescriptor *tpd=
2775       RUNMALLOC(sizeof(struct taskparamdescriptor));
2776     tpd->task=task;
2777     tpd->numParameters=numiterators+1;
2778     tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
2779
2780     for(j=0; j<=numiterators; j++) {
2781       //store the actual parameters
2782       tpd->parameterArray[j]=taskpointerarray[j];
2783     }
2784     /* Enqueue task */
2785     if (( /*!gencontains(failedtasks, tpd)&&*/
2786           !gencontains(activetasks,tpd))) {
2787       genputtable(activetasks, tpd, tpd);
2788     } else {
2789       RUNFREE(tpd->parameterArray);
2790       RUNFREE(tpd);
2791     }
2792
2793     /* This loop iterates to the next parameter combination */
2794     if (numiterators==0)
2795       return retval;
2796
2797     for(j=numiterators-1; j<numiterators; j++) {
2798 backtrackinc:
2799       if(toiHasNext(&parameter->iterators[j],taskpointerarray OPTARG(failed)))
2800         toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
2801       else if (j>0) {
2802         /* Need to backtrack */
2803         toiReset(&parameter->iterators[j]);
2804         j--;
2805         goto backtrackinc;
2806       } else {
2807         /* Nothing more to enqueue */
2808         return retval;
2809       }
2810     }
2811   }
2812   return retval;
2813 }
2814
2815 int enqueuetasks_I(struct parameterwrapper *parameter,
2816                    struct parameterwrapper *prevptr,
2817                    struct ___Object___ *ptr,
2818                    int * enterflags,
2819                    int numenterflags) {
2820   void * taskpointerarray[MAXTASKPARAMS];
2821   int j;
2822   //int numparams=parameter->task->numParameters;
2823   int numiterators=parameter->task->numTotal-1;
2824   int retval=1;
2825   //int addnormal=1;
2826   //int adderror=1;
2827
2828   struct taskdescriptor * task=parameter->task;
2829
2830   //this add the object to parameterwrapper
2831   ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags,
2832                   numenterflags, enterflags==NULL);
2833
2834   /* Add enqueued object to parameter vector */
2835   taskpointerarray[parameter->slot]=ptr;
2836
2837   /* Reset iterators */
2838   for(j=0; j<numiterators; j++) {
2839     toiReset(&parameter->iterators[j]);
2840   }
2841
2842   /* Find initial state */
2843   for(j=0; j<numiterators; j++) {
2844 backtrackinit:
2845     if(toiHasNext(&parameter->iterators[j],taskpointerarray OPTARG(failed)))
2846       toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
2847     else if (j>0) {
2848       /* Need to backtrack */
2849       toiReset(&parameter->iterators[j]);
2850       j--;
2851       goto backtrackinit;
2852     } else {
2853       /* Nothing to enqueue */
2854       return retval;
2855     }
2856   }
2857
2858   while(1) {
2859     /* Enqueue current state */
2860     //int launch = 0;
2861     struct taskparamdescriptor *tpd=
2862       RUNMALLOC_I(sizeof(struct taskparamdescriptor));
2863     tpd->task=task;
2864     tpd->numParameters=numiterators+1;
2865     tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
2866
2867     for(j=0; j<=numiterators; j++) {
2868       //store the actual parameters
2869       tpd->parameterArray[j]=taskpointerarray[j];
2870     }
2871     /* Enqueue task */
2872     if (( /*!gencontains(failedtasks, tpd)&&*/
2873           !gencontains(activetasks,tpd))) {
2874       genputtable_I(activetasks, tpd, tpd);
2875     } else {
2876       RUNFREE(tpd->parameterArray);
2877       RUNFREE(tpd);
2878     }
2879
2880     /* This loop iterates to the next parameter combination */
2881     if (numiterators==0)
2882       return retval;
2883
2884     for(j=numiterators-1; j<numiterators; j++) {
2885 backtrackinc:
2886       if(toiHasNext(&parameter->iterators[j], taskpointerarray OPTARG(failed)))
2887         toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
2888       else if (j>0) {
2889         /* Need to backtrack */
2890         toiReset(&parameter->iterators[j]);
2891         j--;
2892         goto backtrackinc;
2893       } else {
2894         /* Nothing more to enqueue */
2895         return retval;
2896       }
2897     }
2898   }
2899   return retval;
2900 }
2901
2902 #ifdef MULTICORE_GC
2903 #define OFFSET 2
2904 #else
2905 #define OFFSET 0
2906 #endif
2907
2908 int containstag(struct ___Object___ *ptr,
2909                 struct ___TagDescriptor___ *tag);
2910
2911 #ifndef MULTICORE_GC
2912 void releasewritelock_r(void * lock, void * redirectlock) {
2913   int targetcore = 0;
2914   int reallock = (int)lock;
2915   targetcore = (reallock >> 5) % NUMCORES;
2916
2917 #ifdef DEBUG
2918   BAMBOO_DEBUGPRINT(0xe671);
2919   BAMBOO_DEBUGPRINT_REG((int)lock);
2920   BAMBOO_DEBUGPRINT_REG(reallock);
2921   BAMBOO_DEBUGPRINT_REG(targetcore);
2922 #endif
2923
2924   if(targetcore == BAMBOO_NUM_OF_CORE) {
2925     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
2926 #ifdef DEBUG
2927     BAMBOO_DEBUGPRINT(0xf001);
2928 #endif
2929     // reside on this core
2930     if(!RuntimeHashcontainskey(locktbl, reallock)) {
2931       // no locks for this object, something is wrong
2932       BAMBOO_EXIT(0xa011);
2933     } else {
2934       int rwlock_obj = 0;
2935       struct LockValue * lockvalue = NULL;
2936 #ifdef DEBUG
2937       BAMBOO_DEBUGPRINT(0xe672);
2938 #endif
2939       RuntimeHashget(locktbl, reallock, &rwlock_obj);
2940       lockvalue = (struct LockValue *)rwlock_obj;
2941 #ifdef DEBUG
2942       BAMBOO_DEBUGPRINT_REG(lockvalue->value);
2943 #endif
2944       lockvalue->value++;
2945       lockvalue->redirectlock = (int)redirectlock;
2946 #ifdef DEBUG
2947       BAMBOO_DEBUGPRINT_REG(lockvalue->value);
2948 #endif
2949     }
2950     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
2951 #ifdef DEBUG
2952     BAMBOO_DEBUGPRINT(0xf000);
2953 #endif
2954     return;
2955   } else {
2956     // send lock release with redirect info msg
2957     // for 32 bit machine, the size is always 4 words
2958     send_msg_4(targetcore, REDIRECTRELEASE, 1, (int)lock,
2959                (int)redirectlock);
2960   }
2961 }
2962 #endif
2963
2964 void executetasks() {
2965   void * taskpointerarray[MAXTASKPARAMS+OFFSET];
2966   int numparams=0;
2967   int numtotal=0;
2968   struct ___Object___ * tmpparam = NULL;
2969   struct parameterdescriptor * pd=NULL;
2970   struct parameterwrapper *pw=NULL;
2971   int j = 0;
2972   int x = 0;
2973   bool islock = true;
2974
2975   int grount = 0;
2976   int andmask=0;
2977   int checkmask=0;
2978
2979 newtask:
2980   while(hashsize(activetasks)>0) {
2981 #ifdef MULTICORE_GC
2982     gc(NULL);
2983 #endif
2984 #ifdef DEBUG
2985     BAMBOO_DEBUGPRINT(0xe990);
2986 #endif
2987
2988     /* See if there are any active tasks */
2989     //if (hashsize(activetasks)>0) {
2990     int i;
2991 #ifdef PROFILE
2992 #ifdef ACCURATEPROFILE
2993     profileTaskStart("tpd checking");
2994 #endif
2995 #endif
2996     //long clock1;
2997     //clock1 = BAMBOO_GET_EXE_TIME();
2998
2999     busystatus = true;
3000     currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
3001     genfreekey(activetasks, currtpd);
3002
3003     numparams=currtpd->task->numParameters;
3004     numtotal=currtpd->task->numTotal;
3005
3006     // clear the lockRedirectTbl
3007     // (TODO, this table should be empty after all locks are released)
3008     // reset all locks
3009     /*for(j = 0; j < MAXTASKPARAMS; j++) {
3010             runtime_locks[j].redirectlock = 0;
3011             runtime_locks[j].value = 0;
3012        }*/
3013     // get all required locks
3014     runtime_locklen = 0;
3015     // check which locks are needed
3016     for(i = 0; i < numparams; i++) {
3017       void * param = currtpd->parameterArray[i];
3018       int tmplock = 0;
3019       int j = 0;
3020       bool insert = true;
3021       if(((struct ___Object___ *)param)->type == STARTUPTYPE) {
3022         islock = false;
3023         taskpointerarray[i+OFFSET]=param;
3024         goto execute;
3025       }
3026       if(((struct ___Object___ *)param)->lock == NULL) {
3027         tmplock = (int)param;
3028       } else {
3029         tmplock = (int)(((struct ___Object___ *)param)->lock);
3030       }
3031       // insert into the locks array
3032       for(j = 0; j < runtime_locklen; j++) {
3033         if(runtime_locks[j].value == tmplock) {
3034           insert = false;
3035           break;
3036         } else if(runtime_locks[j].value > tmplock) {
3037           break;
3038         }
3039       }
3040       if(insert) {
3041         int h = runtime_locklen;
3042         for(; h > j; h--) {
3043           runtime_locks[h].redirectlock = runtime_locks[h-1].redirectlock;
3044           runtime_locks[h].value = runtime_locks[h-1].value;
3045         }
3046         runtime_locks[j].value = tmplock;
3047         runtime_locks[j].redirectlock = (int)param;
3048         runtime_locklen++;
3049       }
3050     }       // line 2713: for(i = 0; i < numparams; i++)
3051             // grab these required locks
3052 #ifdef DEBUG
3053     BAMBOO_DEBUGPRINT(0xe991);
3054 #endif
3055     //long clock2;
3056     //clock2 = BAMBOO_GET_EXE_TIME();
3057
3058     for(i = 0; i < runtime_locklen; i++) {
3059       int * lock = (int *)(runtime_locks[i].redirectlock);
3060       islock = true;
3061       // require locks for this parameter if it is not a startup object
3062 #ifdef DEBUG
3063       BAMBOO_DEBUGPRINT_REG((int)lock);
3064       BAMBOO_DEBUGPRINT_REG((int)(runtime_locks[i].value));
3065 #endif
3066       getwritelock(lock);
3067       BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
3068 #ifdef DEBUG
3069       BAMBOO_DEBUGPRINT(0xf001);
3070 #endif
3071 #ifdef PROFILE
3072       //isInterrupt = false;
3073 #endif
3074       while(!lockflag) {
3075         BAMBOO_WAITING_FOR_LOCK(0);
3076         // check for outgoing sends
3077     if (isMsgHanging) {
3078       extern inline void send_hanging_msg(bool);
3079       send_hanging_msg(true);
3080     } 
3081           }
3082 #ifndef INTERRUPT
3083       if(reside) {
3084         while(BAMBOO_WAITING_FOR_LOCK(0) != -1) {
3085           // check for outgoing sends
3086           if (isMsgHanging) {
3087                 extern inline void send_hanging_msg(bool);
3088                 send_hanging_msg(true);
3089           } 
3090         }
3091       }
3092 #endif
3093       grount = lockresult;
3094
3095       lockresult = 0;
3096       lockobj = 0;
3097       lock2require = 0;
3098       lockflag = false;
3099 #ifndef INTERRUPT
3100       reside = false;
3101 #endif
3102 #ifdef PROFILE
3103       //isInterrupt = true;
3104 #endif
3105       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
3106 #ifdef DEBUG
3107       BAMBOO_DEBUGPRINT(0xf000);
3108 #endif
3109
3110       if(grount == 0) {
3111 #ifdef DEBUG
3112         BAMBOO_DEBUGPRINT(0xe992);
3113         BAMBOO_DEBUGPRINT_REG(lock);
3114 #endif
3115         // check if has the lock already
3116         // can not get the lock, try later
3117         // release all grabbed locks for previous parameters
3118         for(j = 0; j < i; ++j) {
3119           lock = (int*)(runtime_locks[j].redirectlock);
3120           releasewritelock(lock);
3121         }
3122         genputtable(activetasks, currtpd, currtpd);
3123         if(hashsize(activetasks) == 1) {
3124           // only one task right now, wait a little while before next try
3125           int halt = 10000;
3126           while(halt--) {
3127           }
3128         }
3129 #ifdef PROFILE
3130 #ifdef ACCURATEPROFILE
3131         // fail, set the end of the checkTaskInfo
3132         profileTaskEnd();
3133 #endif
3134 #endif
3135         goto newtask;
3136         //}
3137       }
3138     }       // line 2752:  for(i = 0; i < runtime_locklen; i++)
3139
3140     /*long clock3;
3141        clock3 = BAMBOO_GET_EXE_TIME();
3142        //tprintf("sort: %d, grab: %d \n", clock2-clock1, clock3-clock2);*/
3143
3144 #ifdef DEBUG
3145     BAMBOO_DEBUGPRINT(0xe993);
3146 #endif
3147     /* Make sure that the parameters are still in the queues */
3148     for(i=0; i<numparams; i++) {
3149       void * parameter=currtpd->parameterArray[i];
3150
3151       // flush the object
3152 #ifdef CACHEFLUSH
3153       BAMBOO_CACHE_FLUSH_RANGE((int)parameter,
3154                                classsize[((struct ___Object___ *)parameter)->type]);
3155 #endif
3156       tmpparam = (struct ___Object___ *)parameter;
3157       pd=currtpd->task->descriptorarray[i];
3158       pw=(struct parameterwrapper *) pd->queue;
3159       /* Check that object is still in queue */
3160       {
3161         if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
3162 #ifdef DEBUG
3163           BAMBOO_DEBUGPRINT(0xe994);
3164           BAMBOO_DEBUGPRINT_REG(parameter);
3165 #endif
3166           // release grabbed locks
3167           for(j = 0; j < runtime_locklen; ++j) {
3168             int * lock = (int *)(runtime_locks[j].redirectlock);
3169             releasewritelock(lock);
3170           }
3171           RUNFREE(currtpd->parameterArray);
3172           RUNFREE(currtpd);
3173           currtpd = NULL;
3174           goto newtask;
3175         }
3176       }   // line2865
3177           /* Check if the object's flags still meets requirements */
3178       {
3179         int tmpi = 0;
3180         bool ismet = false;
3181         for(tmpi = 0; tmpi < pw->numberofterms; ++tmpi) {
3182           andmask=pw->intarray[tmpi*2];
3183           checkmask=pw->intarray[tmpi*2+1];
3184           if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
3185             ismet = true;
3186             break;
3187           }
3188         }
3189         if (!ismet) {
3190           // flags are never suitable
3191           // remove this obj from the queue
3192           int next;
3193           int UNUSED, UNUSED2;
3194           int * enterflags;
3195 #ifdef DEBUG
3196           BAMBOO_DEBUGPRINT(0xe995);
3197           BAMBOO_DEBUGPRINT_REG(parameter);
3198 #endif
3199           ObjectHashget(pw->objectset, (int) parameter, (int *) &next,
3200                         (int *) &enterflags, &UNUSED, &UNUSED2);
3201           ObjectHashremove(pw->objectset, (int)parameter);
3202           if (enterflags!=NULL)
3203             RUNFREE(enterflags);
3204           // release grabbed locks
3205           for(j = 0; j < runtime_locklen; ++j) {
3206             int * lock = (int *)(runtime_locks[j].redirectlock);
3207             releasewritelock(lock);
3208           }
3209           RUNFREE(currtpd->parameterArray);
3210           RUNFREE(currtpd);
3211           currtpd = NULL;
3212 #ifdef PROFILE
3213 #ifdef ACCURATEPROFILE
3214           // fail, set the end of the checkTaskInfo
3215           profileTaskEnd();
3216 #endif
3217 #endif
3218           goto newtask;
3219         }   // line 2878: if (!ismet)
3220       }   // line 2867
3221 parameterpresent:
3222       ;
3223       /* Check that object still has necessary tags */
3224       for(j=0; j<pd->numbertags; j++) {
3225         int slotid=pd->tagarray[2*j]+numparams;
3226         struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
3227         if (!containstag(parameter, tagd)) {
3228 #ifdef DEBUG
3229           BAMBOO_DEBUGPRINT(0xe996);
3230 #endif
3231           {
3232             // release grabbed locks
3233             int tmpj = 0;
3234             for(tmpj = 0; tmpj < runtime_locklen; ++tmpj) {
3235               int * lock = (int *)(runtime_locks[tmpj].redirectlock);
3236               releasewritelock(lock);
3237             }
3238           }
3239           RUNFREE(currtpd->parameterArray);
3240           RUNFREE(currtpd);
3241           currtpd = NULL;
3242           goto newtask;
3243         }   // line2911: if (!containstag(parameter, tagd))
3244       }   // line 2808: for(j=0; j<pd->numbertags; j++)
3245
3246       taskpointerarray[i+OFFSET]=parameter;
3247     }   // line 2824: for(i=0; i<numparams; i++)
3248         /* Copy the tags */
3249     for(; i<numtotal; i++) {
3250       taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
3251     }
3252
3253     {
3254 execute:
3255       /* Actually call task */
3256 #ifdef MULTICORE_GC
3257       ((int *)taskpointerarray)[0]=currtpd->numParameters;
3258       taskpointerarray[1]=NULL;
3259 #endif
3260 #ifdef PROFILE
3261 #ifdef ACCURATEPROFILE
3262       // check finish, set the end of the checkTaskInfo
3263       profileTaskEnd();
3264 #endif
3265       profileTaskStart(currtpd->task->name);
3266 #endif
3267       // TODO
3268       //long clock4;
3269       //clock4 = BAMBOO_GET_EXE_TIME();
3270       //tprintf("sort: %d, grab: %d, check: %d \n", (int)(clock2-clock1), (int)(clock3-clock2), (int)(clock4-clock3));
3271
3272 #ifdef DEBUG
3273       BAMBOO_DEBUGPRINT(0xe997);
3274 #endif
3275       ((void (*)(void **))currtpd->task->taskptr)(taskpointerarray);
3276       // TODO
3277       //long clock5;
3278       //clock5 = BAMBOO_GET_EXE_TIME();
3279       // tprintf("sort: %d, grab: %d, check: %d \n", (int)(clock2-clock1), (int)(clock3-clock2), (int)(clock4-clock3));
3280
3281 #ifdef PROFILE
3282 #ifdef ACCURATEPROFILE
3283       // task finish, set the end of the checkTaskInfo
3284       profileTaskEnd();
3285       // new a PostTaskInfo for the post-task execution
3286       profileTaskStart("post task execution");
3287 #endif
3288 #endif
3289 #ifdef DEBUG
3290       BAMBOO_DEBUGPRINT(0xe998);
3291       BAMBOO_DEBUGPRINT_REG(islock);
3292 #endif
3293
3294       if(islock) {
3295 #ifdef DEBUG
3296         BAMBOO_DEBUGPRINT(0xe999);
3297 #endif
3298         for(i = 0; i < runtime_locklen; ++i) {
3299           void * ptr = (void *)(runtime_locks[i].redirectlock);
3300           int * lock = (int *)(runtime_locks[i].value);
3301 #ifdef DEBUG
3302           BAMBOO_DEBUGPRINT_REG((int)ptr);
3303           BAMBOO_DEBUGPRINT_REG((int)lock);
3304           BAMBOO_DEBUGPRINT_REG(*((int*)lock+5));
3305 #endif
3306 #ifndef MULTICORE_GC
3307           if(RuntimeHashcontainskey(lockRedirectTbl, (int)lock)) {
3308             int redirectlock;
3309             RuntimeHashget(lockRedirectTbl, (int)lock, &redirectlock);
3310             RuntimeHashremovekey(lockRedirectTbl, (int)lock);
3311             releasewritelock_r(lock, (int *)redirectlock);
3312           } else {
3313 #else
3314           {
3315 #endif
3316             releasewritelock(ptr);
3317           }
3318         }
3319       }     // line 3015: if(islock)
3320
3321       //long clock6;
3322       //clock6 = BAMBOO_GET_EXE_TIME();
3323       //tprintf("sort: %d, grab: %d, check: %d \n", (int)(clock2-clock1), (int)(clock3-clock2), (int)(clock4-clock3));
3324
3325 #ifdef PROFILE
3326       // post task execution finish, set the end of the postTaskInfo
3327       profileTaskEnd();
3328 #endif
3329
3330       // Free up task parameter descriptor
3331       RUNFREE(currtpd->parameterArray);
3332       RUNFREE(currtpd);
3333       currtpd = NULL;
3334 #ifdef DEBUG
3335       BAMBOO_DEBUGPRINT(0xe99a);
3336 #endif
3337       //long clock7;
3338       //clock7 = BAMBOO_GET_EXE_TIME();
3339       //tprintf("sort: %d, grab: %d, check: %d, release: %d, other %d \n", (int)(clock2-clock1), (int)(clock3-clock2), (int)(clock4-clock3), (int)(clock6-clock5), (int)(clock7-clock6));
3340
3341     }   //
3342     //} //  if (hashsize(activetasks)>0)
3343   } //  while(hashsize(activetasks)>0)
3344 #ifdef DEBUG
3345   BAMBOO_DEBUGPRINT(0xe99b);
3346 #endif
3347 }
3348
3349 /* This function processes an objects tags */
3350 void processtags(struct parameterdescriptor *pd,
3351                  int index,
3352                  struct parameterwrapper *parameter,
3353                  int * iteratorcount,
3354                  int *statusarray,
3355                  int numparams) {
3356   int i;
3357
3358   for(i=0; i<pd->numbertags; i++) {
3359     int slotid=pd->tagarray[2*i];
3360     int tagid=pd->tagarray[2*i+1];
3361
3362     if (statusarray[slotid+numparams]==0) {
3363       parameter->iterators[*iteratorcount].istag=1;
3364       parameter->iterators[*iteratorcount].tagid=tagid;
3365       parameter->iterators[*iteratorcount].slot=slotid+numparams;
3366       parameter->iterators[*iteratorcount].tagobjectslot=index;
3367       statusarray[slotid+numparams]=1;
3368       (*iteratorcount)++;
3369     }
3370   }
3371 }
3372
3373
3374 void processobject(struct parameterwrapper *parameter,
3375                    int index,
3376                    struct parameterdescriptor *pd,
3377                    int *iteratorcount,
3378                    int * statusarray,
3379                    int numparams) {
3380   int i;
3381   int tagcount=0;
3382   struct ObjectHash * objectset=
3383     ((struct parameterwrapper *)pd->queue)->objectset;
3384
3385   parameter->iterators[*iteratorcount].istag=0;
3386   parameter->iterators[*iteratorcount].slot=index;
3387   parameter->iterators[*iteratorcount].objectset=objectset;
3388   statusarray[index]=1;
3389
3390   for(i=0; i<pd->numbertags; i++) {
3391     int slotid=pd->tagarray[2*i];
3392     //int tagid=pd->tagarray[2*i+1];
3393     if (statusarray[slotid+numparams]!=0) {
3394       /* This tag has already been enqueued, use it to narrow search */
3395       parameter->iterators[*iteratorcount].tagbindings[tagcount]=
3396         slotid+numparams;
3397       tagcount++;
3398     }
3399   }
3400   parameter->iterators[*iteratorcount].numtags=tagcount;
3401
3402   (*iteratorcount)++;
3403 }
3404
3405 /* This function builds the iterators for a task & parameter */
3406
3407 void builditerators(struct taskdescriptor * task,
3408                     int index,
3409                     struct parameterwrapper * parameter) {
3410   int statusarray[MAXTASKPARAMS];
3411   int i;
3412   int numparams=task->numParameters;
3413   int iteratorcount=0;
3414   for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
3415
3416   statusarray[index]=1; /* Initial parameter */
3417   /* Process tags for initial iterator */
3418
3419   processtags(task->descriptorarray[index], index, parameter,
3420               &iteratorcount, statusarray, numparams);
3421
3422   while(1) {
3423 loopstart:
3424     /* Check for objects with existing tags */
3425     for(i=0; i<numparams; i++) {
3426       if (statusarray[i]==0) {
3427         struct parameterdescriptor *pd=task->descriptorarray[i];
3428         int j;
3429         for(j=0; j<pd->numbertags; j++) {
3430           int slotid=pd->tagarray[2*j];
3431           if(statusarray[slotid+numparams]!=0) {
3432             processobject(parameter, i, pd, &iteratorcount, statusarray,
3433                           numparams);
3434             processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
3435             goto loopstart;
3436           }
3437         }
3438       }
3439     }
3440
3441     /* Next do objects w/ unbound tags*/
3442
3443     for(i=0; i<numparams; i++) {
3444       if (statusarray[i]==0) {
3445         struct parameterdescriptor *pd=task->descriptorarray[i];
3446         if (pd->numbertags>0) {
3447           processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
3448           processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
3449           goto loopstart;
3450         }
3451       }
3452     }
3453
3454     /* Nothing with a tag enqueued */
3455
3456     for(i=0; i<numparams; i++) {
3457       if (statusarray[i]==0) {
3458         struct parameterdescriptor *pd=task->descriptorarray[i];
3459         processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
3460         processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
3461         goto loopstart;
3462       }
3463     }
3464
3465     /* Nothing left */
3466     return;
3467   }
3468 }
3469
3470 void printdebug() {
3471   int i;
3472   int j;
3473   if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
3474     return;
3475   }
3476   for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
3477     struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
3478 #ifndef RAW
3479     printf("%s\n", task->name);
3480 #endif
3481     for(j=0; j<task->numParameters; j++) {
3482       struct parameterdescriptor *param=task->descriptorarray[j];
3483       struct parameterwrapper *parameter=param->queue;
3484       struct ObjectHash * set=parameter->objectset;
3485       struct ObjectIterator objit;
3486 #ifndef RAW
3487       printf("  Parameter %d\n", j);
3488 #endif
3489       ObjectHashiterator(set, &objit);
3490       while(ObjhasNext(&objit)) {
3491         struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
3492         struct ___Object___ * tagptr=obj->___tags___;
3493         int nonfailed=Objdata4(&objit);
3494         int numflags=Objdata3(&objit);
3495         int flags=Objdata2(&objit);
3496         Objnext(&objit);
3497 #ifndef RAW
3498         printf("    Contains %lx\n", obj);
3499         printf("      flag=%d\n", obj->flag);
3500 #endif
3501         if (tagptr==NULL) {
3502         } else if (tagptr->type==TAGTYPE) {
3503 #ifndef RAW
3504           printf("      tag=%lx\n",tagptr);
3505 #else
3506           ;
3507 #endif
3508         } else {
3509           int tagindex=0;
3510           struct ArrayObject *ao=(struct ArrayObject *)tagptr;
3511           for(; tagindex<ao->___cachedCode___; tagindex++) {
3512 #ifndef RAW
3513             printf("      tag=%lx\n",ARRAYGET(ao, struct ___TagDescriptor___*,
3514                                               tagindex));
3515 #else
3516             ;
3517 #endif
3518           }
3519         }
3520       }
3521     }
3522   }
3523 }
3524
3525
3526 /* This function processes the task information to create queues for
3527    each parameter type. */
3528
3529 void processtasks() {
3530   int i;
3531   if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
3532     return;
3533   }
3534   for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
3535     struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
3536     int j;
3537
3538     /* Build objectsets */
3539     for(j=0; j<task->numParameters; j++) {
3540       struct parameterdescriptor *param=task->descriptorarray[j];
3541       struct parameterwrapper *parameter=param->queue;
3542       parameter->objectset=allocateObjectHash(10);
3543       parameter->task=task;
3544     }
3545
3546     /* Build iterators for parameters */
3547     for(j=0; j<task->numParameters; j++) {
3548       struct parameterdescriptor *param=task->descriptorarray[j];
3549       struct parameterwrapper *parameter=param->queue;
3550       builditerators(task, j, parameter);
3551     }
3552   }
3553 }
3554
3555 void toiReset(struct tagobjectiterator * it) {
3556   if (it->istag) {
3557     it->tagobjindex=0;
3558   } else if (it->numtags>0) {
3559     it->tagobjindex=0;
3560   } else {
3561     ObjectHashiterator(it->objectset, &it->it);
3562   }
3563 }
3564
3565 int toiHasNext(struct tagobjectiterator *it,
3566                void ** objectarray OPTARG(int * failed)) {
3567   if (it->istag) {
3568     /* Iterate tag */
3569     /* Get object with tags */
3570     struct ___Object___ *obj=objectarray[it->tagobjectslot];
3571     struct ___Object___ *tagptr=obj->___tags___;
3572     if (tagptr->type==TAGTYPE) {
3573       if ((it->tagobjindex==0)&& /* First object */
3574           (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
3575         return 1;
3576       else
3577         return 0;
3578     } else {
3579       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
3580       int tagindex=it->tagobjindex;
3581       for(; tagindex<ao->___cachedCode___; tagindex++) {
3582         struct ___TagDescriptor___ *td=
3583           ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
3584         if (td->flag==it->tagid) {
3585           it->tagobjindex=tagindex; /* Found right type of tag */
3586           return 1;
3587         }
3588       }
3589       return 0;
3590     }
3591   } else if (it->numtags>0) {
3592     /* Use tags to locate appropriate objects */
3593     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
3594     struct ___Object___ *objptr=tag->flagptr;
3595     int i;
3596     if (objptr->type!=OBJECTARRAYTYPE) {
3597       if (it->tagobjindex>0)
3598         return 0;
3599       if (!ObjectHashcontainskey(it->objectset, (int) objptr))
3600         return 0;
3601       for(i=1; i<it->numtags; i++) {
3602         struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
3603         if (!containstag(objptr,tag2))
3604           return 0;
3605       }
3606       return 1;
3607     } else {
3608       struct ArrayObject *ao=(struct ArrayObject *) objptr;
3609       int tagindex;
3610       int i;
3611       for(tagindex=it->tagobjindex; tagindex<ao->___cachedCode___; tagindex++) {
3612         struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
3613         if (!ObjectHashcontainskey(it->objectset, (int) objptr))
3614           continue;
3615         for(i=1; i<it->numtags; i++) {
3616           struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
3617           if (!containstag(objptr,tag2))
3618             goto nexttag;
3619         }
3620         it->tagobjindex=tagindex;
3621         return 1;
3622 nexttag:
3623         ;
3624       }
3625       it->tagobjindex=tagindex;
3626       return 0;
3627     }
3628   } else {
3629     return ObjhasNext(&it->it);
3630   }
3631 }
3632
3633 int containstag(struct ___Object___ *ptr,
3634                 struct ___TagDescriptor___ *tag) {
3635   int j;
3636   struct ___Object___ * objptr=tag->flagptr;
3637   if (objptr->type==OBJECTARRAYTYPE) {
3638     struct ArrayObject *ao=(struct ArrayObject *)objptr;
3639     for(j=0; j<ao->___cachedCode___; j++) {
3640       if (ptr==ARRAYGET(ao, struct ___Object___*, j)) {
3641         return 1;
3642       }
3643     }
3644     return 0;
3645   } else {
3646     return objptr==ptr;
3647   }
3648 }
3649
3650 void toiNext(struct tagobjectiterator *it,
3651              void ** objectarray OPTARG(int * failed)) {
3652   /* hasNext has all of the intelligence */
3653   if(it->istag) {
3654     /* Iterate tag */
3655     /* Get object with tags */
3656     struct ___Object___ *obj=objectarray[it->tagobjectslot];
3657     struct ___Object___ *tagptr=obj->___tags___;
3658     if (tagptr->type==TAGTYPE) {
3659       it->tagobjindex++;
3660       objectarray[it->slot]=tagptr;
3661     } else {
3662       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
3663       objectarray[it->slot]=
3664         ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
3665     }
3666   } else if (it->numtags>0) {
3667     /* Use tags to locate appropriate objects */
3668     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
3669     struct ___Object___ *objptr=tag->flagptr;
3670     if (objptr->type!=OBJECTARRAYTYPE) {
3671       it->tagobjindex++;
3672       objectarray[it->slot]=objptr;
3673     } else {
3674       struct ArrayObject *ao=(struct ArrayObject *) objptr;
3675       objectarray[it->slot]=
3676         ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
3677     }
3678   } else {
3679     /* Iterate object */
3680     objectarray[it->slot]=(void *)Objkey(&it->it);
3681     Objnext(&it->it);
3682   }
3683 }
3684
3685 #ifdef PROFILE
3686 inline void profileTaskStart(char * taskname) {
3687   if(!taskInfoOverflow) {
3688     TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
3689     taskInfoArray[taskInfoIndex] = taskInfo;
3690     taskInfo->taskName = taskname;
3691     taskInfo->startTime = BAMBOO_GET_EXE_TIME();
3692     taskInfo->endTime = -1;
3693     taskInfo->exitIndex = -1;
3694     taskInfo->newObjs = NULL;
3695   }
3696 }
3697
3698 inline void profileTaskEnd() {
3699   if(!taskInfoOverflow) {
3700     taskInfoArray[taskInfoIndex]->endTime = BAMBOO_GET_EXE_TIME();
3701     taskInfoIndex++;
3702     if(taskInfoIndex == TASKINFOLENGTH) {
3703       taskInfoOverflow = true;
3704       //taskInfoIndex = 0;
3705     }
3706   }
3707 }
3708
3709 // output the profiling data
3710 void outputProfileData() {
3711 #ifdef USEIO
3712   int i;
3713   unsigned long long totaltasktime = 0;
3714   unsigned long long preprocessingtime = 0;
3715   unsigned long long objqueuecheckingtime = 0;
3716   unsigned long long postprocessingtime = 0;
3717   //int interruptiontime = 0;
3718   unsigned long long other = 0;
3719   unsigned long long averagetasktime = 0;
3720   int tasknum = 0;
3721
3722   printf("Task Name, Start Time, End Time, Duration, Exit Index(, NewObj Name, Num)+\n");
3723   // output task related info
3724   for(i = 0; i < taskInfoIndex; i++) {
3725     TaskInfo* tmpTInfo = taskInfoArray[i];
3726     unsigned long long duration = tmpTInfo->endTime - tmpTInfo->startTime;
3727     printf("%s, %lld, %lld, %lld, %lld",
3728            tmpTInfo->taskName, tmpTInfo->startTime, tmpTInfo->endTime,
3729            duration, tmpTInfo->exitIndex);
3730     // summarize new obj info
3731     if(tmpTInfo->newObjs != NULL) {
3732       struct RuntimeHash * nobjtbl = allocateRuntimeHash(5);
3733       struct RuntimeIterator * iter = NULL;
3734       while(0 == isEmpty(tmpTInfo->newObjs)) {
3735         char * objtype = (char *)(getItem(tmpTInfo->newObjs));
3736         if(RuntimeHashcontainskey(nobjtbl, (int)(objtype))) {
3737           int num = 0;
3738           RuntimeHashget(nobjtbl, (int)objtype, &num);
3739           RuntimeHashremovekey(nobjtbl, (int)objtype);
3740           num++;
3741           RuntimeHashadd(nobjtbl, (int)objtype, num);
3742         } else {
3743           RuntimeHashadd(nobjtbl, (int)objtype, 1);
3744         }
3745         //printf(stderr, "new obj!\n");
3746       }
3747
3748       // output all new obj info
3749       iter = RuntimeHashcreateiterator(nobjtbl);
3750       while(RunhasNext(iter)) {
3751         char * objtype = (char *)Runkey(iter);
3752         int num = Runnext(iter);
3753         printf(", %s, %d", objtype, num);
3754       }
3755     }
3756     printf("\n");
3757     if(strcmp(tmpTInfo->taskName, "tpd checking") == 0) {
3758       preprocessingtime += duration;
3759     } else if(strcmp(tmpTInfo->taskName, "post task execution") == 0) {
3760       postprocessingtime += duration;
3761     } else if(strcmp(tmpTInfo->taskName, "objqueue checking") == 0) {
3762       objqueuecheckingtime += duration;
3763     } else {
3764       totaltasktime += duration;
3765       averagetasktime += duration;
3766       tasknum++;
3767     }
3768   }
3769
3770   if(taskInfoOverflow) {
3771     printf("Caution: task info overflow!\n");
3772   }
3773
3774   other = totalexetime-totaltasktime-preprocessingtime-postprocessingtime;
3775   averagetasktime /= tasknum;
3776
3777   printf("\nTotal time: %lld\n", totalexetime);
3778   printf("Total task execution time: %lld (%d%%)\n", totaltasktime,
3779          (int)(((double)totaltasktime/(double)totalexetime)*100));
3780   printf("Total objqueue checking time: %lld (%d%%)\n",
3781          objqueuecheckingtime,
3782          (int)(((double)objqueuecheckingtime/(double)totalexetime)*100));
3783   printf("Total pre-processing time: %lld (%d%%)\n", preprocessingtime,
3784          (int)(((double)preprocessingtime/(double)totalexetime)*100));
3785   printf("Total post-processing time: %lld (%d%%)\n", postprocessingtime,
3786          (int)(((double)postprocessingtime/(double)totalexetime)*100));
3787   printf("Other time: %lld (%d%%)\n", other,
3788          (int)(((double)other/(double)totalexetime)*100));
3789
3790
3791   printf("\nAverage task execution time: %lld\n", averagetasktime);
3792
3793   //printf("\nTotal time spent for interruptions: %lld\n", interrupttime);
3794 #else
3795   int i = 0;
3796   int j = 0;
3797
3798   BAMBOO_DEBUGPRINT(0xdddd);
3799   // output task related info
3800   for(i= 0; i < taskInfoIndex; i++) {
3801     TaskInfo* tmpTInfo = taskInfoArray[i];
3802     char* tmpName = tmpTInfo->taskName;
3803     int nameLen = strlen(tmpName);
3804     BAMBOO_DEBUGPRINT(0xddda);
3805     for(j = 0; j < nameLen; j++) {
3806       BAMBOO_DEBUGPRINT_REG(tmpName[j]);
3807     }
3808     BAMBOO_DEBUGPRINT(0xdddb);
3809     BAMBOO_DEBUGPRINT_REG(tmpTInfo->startTime);
3810     BAMBOO_DEBUGPRINT_REG(tmpTInfo->endTime);
3811     BAMBOO_DEBUGPRINT_REG(tmpTInfo->exitIndex);
3812     if(tmpTInfo->newObjs != NULL) {
3813       struct RuntimeHash * nobjtbl = allocateRuntimeHash(5);
3814       struct RuntimeIterator * iter = NULL;
3815       while(0 == isEmpty(tmpTInfo->newObjs)) {
3816         char * objtype = (char *)(getItem(tmpTInfo->newObjs));
3817         if(RuntimeHashcontainskey(nobjtbl, (int)(objtype))) {
3818           int num = 0;
3819           RuntimeHashget(nobjtbl, (int)objtype, &num);
3820           RuntimeHashremovekey(nobjtbl, (int)objtype);
3821           num++;
3822           RuntimeHashadd(nobjtbl, (int)objtype, num);
3823         } else {
3824           RuntimeHashadd(nobjtbl, (int)objtype, 1);
3825         }
3826       }
3827
3828       // ouput all new obj info
3829       iter = RuntimeHashcreateiterator(nobjtbl);
3830       while(RunhasNext(iter)) {
3831         char * objtype = (char *)Runkey(iter);
3832         int num = Runnext(iter);
3833         int nameLen = strlen(objtype);
3834         BAMBOO_DEBUGPRINT(0xddda);
3835         for(j = 0; j < nameLen; j++) {
3836           BAMBOO_DEBUGPRINT_REG(objtype[j]);
3837         }
3838         BAMBOO_DEBUGPRINT(0xdddb);
3839         BAMBOO_DEBUGPRINT_REG(num);
3840       }
3841     }
3842     BAMBOO_DEBUGPRINT(0xdddc);
3843   }
3844
3845   if(taskInfoOverflow) {
3846     BAMBOO_DEBUGPRINT(0xefee);
3847   }
3848
3849   // output interrupt related info
3850   for(i = 0; i < interruptInfoIndex; i++) {
3851     InterruptInfo* tmpIInfo = interruptInfoArray[i];
3852     BAMBOO_DEBUGPRINT(0xddde);
3853     BAMBOO_DEBUGPRINT_REG(tmpIInfo->startTime);
3854     BAMBOO_DEBUGPRINT_REG(tmpIInfo->endTime);
3855     BAMBOO_DEBUGPRINT(0xdddf);
3856   }
3857
3858   if(interruptInfoOverflow) {
3859     BAMBOO_DEBUGPRINT(0xefef);
3860   }
3861
3862   BAMBOO_DEBUGPRINT(0xeeee);
3863 #endif
3864 }
3865 #endif  // #ifdef PROFILE
3866
3867 #endif