355f03d4772524e3830e10a0e721b3dca7d4586f
[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 //  data structures for task invocation
8 struct genhashtable * activetasks;
9 struct taskparamdescriptor * currtpd;
10
11 // specific functions used inside critical sections
12 void enqueueObject_I(void * ptr, 
13                                  struct parameterwrapper ** queues, 
14                                                                                  int length);
15 int enqueuetasks_I(struct parameterwrapper *parameter, 
16                                struct parameterwrapper *prevptr, 
17                                                                          struct ___Object___ *ptr, 
18                                                                          int * enterflags, 
19                                                                          int numenterflags);
20
21 inline __attribute__((always_inline)) 
22 void initruntimedata() {
23         int i;
24         // initialize the arrays
25   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
26     // startup core to initialize corestatus[]
27     for(i = 0; i < NUMCORES; ++i) {
28       corestatus[i] = 1;
29       numsendobjs[i] = 0; 
30       numreceiveobjs[i] = 0;
31 #ifdef PROFILE
32                         // initialize the profile data arrays
33                         profilestatus[i] = 1;
34 #endif
35 #ifdef MULTICORE_GC
36                         gccorestatus[i] = 1;
37                         gcnumsendobjs[i] = 0; 
38       gcnumreceiveobjs[i] = 0;
39                         gcloads[i] = 0;
40                         gcrequiredmems[i] = 0;
41                         gcstopblock[i] = 0;
42                         gcfilledblocks[i] = 0;
43 #endif
44     } // for(i = 0; i < NUMCORES; ++i)
45                 numconfirm = 0;
46                 waitconfirm = false; 
47                 
48                 // TODO for test
49                 total_num_t6 = 0;
50   }
51
52   busystatus = true;
53   self_numsendobjs = 0;
54   self_numreceiveobjs = 0;
55
56   for(i = 0; i < BAMBOO_MSG_BUF_LENGTH; ++i) {
57     msgdata[i] = -1;
58   }
59   msgtype = -1;
60   msgdataindex = 0;
61   msglength = BAMBOO_MSG_BUF_LENGTH;
62   for(i = 0; i < BAMBOO_OUT_BUF_LENGTH; ++i) {
63     outmsgdata[i] = -1;
64   }
65   outmsgindex = 0;
66   outmsglast = 0;
67   outmsgleft = 0;
68   isMsgHanging = false;
69   isMsgSending = false;
70
71   smemflag = true;
72   bamboo_cur_msp = NULL;
73   bamboo_smem_size = 0;
74         totransobjqueue = createQueue();
75
76 #ifdef MULTICORE_GC
77         gcflag = false;
78         gcprocessing = false;
79         gcphase = FINISHPHASE;
80         gccurr_heaptop = 0;
81         gcself_numsendobjs = 0;
82         gcself_numreceiveobjs = 0;
83         gcmarkedptrbound = 0;
84         gcpointertbl = allocateRuntimeHash(20);
85         gcobj2map = 0;
86         gcmappedobj = 0;
87         gcismapped = false;
88         gcnumlobjs = 0;
89         gcheaptop = 0;
90         gctopcore = 0;
91         gcheapdirection = 1;
92         gcmovestartaddr = 0;
93         gctomove = false;
94         gcmovepending = 0;
95         gcblock2fill = 0;
96         gcsbstarttbl = BAMBOO_BASE_VA;
97 #else
98         // create the lock table, lockresult table and obj queue
99   locktable.size = 20;
100   locktable.bucket = 
101                 (struct RuntimeNode **) RUNMALLOC_I(sizeof(struct RuntimeNode *)*20);
102   /* Set allocation blocks*/
103   locktable.listhead=NULL;
104   locktable.listtail=NULL;
105   /*Set data counts*/
106   locktable.numelements = 0;
107   lockobj = 0;
108   lock2require = 0;
109   lockresult = 0;
110   lockflag = false;
111         lockRedirectTbl = allocateRuntimeHash(20);
112   objRedirectLockTbl = allocateRuntimeHash(20);
113 #endif
114 #ifndef INTERRUPT
115   reside = false;
116 #endif  
117   objqueue.head = NULL;
118   objqueue.tail = NULL;
119
120         currtpd = NULL;
121
122 #ifdef PROFILE
123   stall = false;
124   //isInterrupt = true;
125   totalexetime = -1;
126   taskInfoIndex = 0;
127   taskInfoOverflow = false;
128   /*interruptInfoIndex = 0;
129   interruptInfoOverflow = false;*/
130 #endif
131 }
132
133 inline __attribute__((always_inline))
134 void disruntimedata() {
135 #ifdef MULTICORE_GC
136         freeRuntimeHash(gcpointertbl);
137 #else
138         freeRuntimeHash(lockRedirectTbl);
139         freeRuntimeHash(objRedirectLockTbl);
140         RUNFREE(locktable.bucket);
141 #endif
142         genfreehashtable(activetasks);
143         if(currtpd != NULL) {
144                 RUNFREE(currtpd->parameterArray);
145                 RUNFREE(currtpd);
146                 currtpd = NULL;
147         }
148 }
149
150 inline __attribute__((always_inline))
151 bool checkObjQueue() {
152         bool rflag = false;
153         struct transObjInfo * objInfo = NULL;
154         int grount = 0;
155
156 #ifdef PROFILE
157 #ifdef ACCURATEPROFILE
158         bool isChecking = false;
159         if(!isEmpty(&objqueue)) {
160                 profileTaskStart("objqueue checking");
161                 isChecking = true;
162         } // if(!isEmpty(&objqueue))
163 #endif
164 #endif
165
166         while(!isEmpty(&objqueue)) {
167                 void * obj = NULL;
168                 BAMBOO_START_CRITICAL_SECTION_OBJ_QUEUE();
169 #ifdef DEBUG
170                 BAMBOO_DEBUGPRINT(0xf001);
171 #endif
172 #ifdef PROFILE
173                 //isInterrupt = false;
174 #endif 
175 #ifdef DEBUG
176                 BAMBOO_DEBUGPRINT(0xeee1);
177 #endif
178                 rflag = true;
179                 objInfo = (struct transObjInfo *)getItem(&objqueue); 
180                 obj = objInfo->objptr;
181 #ifdef DEBUG
182                 BAMBOO_DEBUGPRINT_REG((int)obj);
183 #endif
184                 // grab lock and flush the obj
185                 grount = 0;
186                 getwritelock_I(obj);
187                 while(!lockflag) {
188                         BAMBOO_WAITING_FOR_LOCK();
189                 } // while(!lockflag)
190                 grount = lockresult;
191 #ifdef DEBUG
192                 BAMBOO_DEBUGPRINT_REG(grount);
193 #endif
194
195                 lockresult = 0;
196                 lockobj = 0;
197                 lock2require = 0;
198                 lockflag = false;
199 #ifndef INTERRUPT
200                 reside = false;
201 #endif
202
203                 if(grount == 1) {
204                         int k = 0;
205                         // flush the object
206 #ifdef CACHEFLUSH
207                         BAMBOO_CACHE_FLUSH_RANGE((int)obj,sizeof(int));
208                         BAMBOO_CACHE_FLUSH_RANGE((int)obj, 
209                                         classsize[((struct ___Object___ *)obj)->type]);
210 #endif
211                         // enqueue the object
212                         for(k = 0; k < objInfo->length; ++k) {
213                                 int taskindex = objInfo->queues[2 * k];
214                                 int paramindex = objInfo->queues[2 * k + 1];
215                                 struct parameterwrapper ** queues = 
216                                         &(paramqueues[BAMBOO_NUM_OF_CORE][taskindex][paramindex]);
217 #ifdef DEBUG
218                                 BAMBOO_DEBUGPRINT_REG(taskindex);
219                                 BAMBOO_DEBUGPRINT_REG(paramindex);
220                                 struct ___Object___ * tmpptr = (struct ___Object___ *)obj;
221                                 tprintf("Process %x(%d): receive obj %x(%lld), ptrflag %x\n", 
222                                                                 BAMBOO_NUM_OF_CORE, BAMBOO_NUM_OF_CORE, (int)obj, 
223                                                                 (long)obj, tmpptr->flag);
224 #endif
225                                 enqueueObject_I(obj, queues, 1);
226 #ifdef DEBUG                             
227                                 BAMBOO_DEBUGPRINT_REG(hashsize(activetasks));
228 #endif
229                         } // for(k = 0; k < objInfo->length; ++k)
230                         releasewritelock_I(obj);
231                         RUNFREE(objInfo->queues);
232                         RUNFREE(objInfo);
233                 } else {
234                         // can not get lock
235                         // put it at the end of the queue if no update version in the queue
236                         struct QueueItem * qitem = getHead(&objqueue);
237                         struct QueueItem * prev = NULL;
238                         while(qitem != NULL) {
239                                 struct transObjInfo * tmpinfo = 
240                                         (struct transObjInfo *)(qitem->objectptr);
241                                 if(tmpinfo->objptr == obj) {
242                                         // the same object in the queue, which should be enqueued
243                                         // recently. Current one is outdate, do not re-enqueue it
244                                         RUNFREE(objInfo->queues);
245                                         RUNFREE(objInfo);
246                                         goto objqueuebreak;
247                                 } else {
248                                         prev = qitem;
249                                 } // if(tmpinfo->objptr == obj)
250                                 qitem = getNextQueueItem(prev);
251                         } // while(qitem != NULL)
252                         // try to execute active tasks already enqueued first
253                         addNewItem_I(&objqueue, objInfo);
254 #ifdef PROFILE
255                         //isInterrupt = true;
256 #endif
257 objqueuebreak:
258                         BAMBOO_CLOSE_CRITICAL_SECTION_OBJ_QUEUE();
259 #ifdef DEBUG
260                         BAMBOO_DEBUGPRINT(0xf000);
261 #endif
262                         break;
263                 } // if(grount == 1)
264                 BAMBOO_CLOSE_CRITICAL_SECTION_OBJ_QUEUE();
265 #ifdef DEBUG
266                 BAMBOO_DEBUGPRINT(0xf000);
267 #endif
268         } // while(!isEmpty(&objqueue))
269
270 #ifdef PROFILE
271 #ifdef ACCURATEPROFILE
272         if(isChecking) {
273                 profileTaskEnd();
274         } // if(isChecking)
275 #endif
276 #endif
277
278 #ifdef DEBUG
279         BAMBOO_DEBUGPRINT(0xee02);
280 #endif
281         return rflag;
282 }
283
284 inline __attribute__((always_inline))
285 void checkCoreStatus() {
286         bool allStall = false;
287         int i = 0;
288         int sumsendobj = 0;
289         if((!waitconfirm) || 
290                         (waitconfirm && (numconfirm == 0))) {
291 #ifdef DEBUG
292                 BAMBOO_DEBUGPRINT(0xee04);
293                 BAMBOO_DEBUGPRINT_REG(waitconfirm);
294 #endif
295                 BAMBOO_START_CRITICAL_SECTION_STATUS();
296 #ifdef DEBUG
297                 BAMBOO_DEBUGPRINT(0xf001);
298 #endif
299                 corestatus[BAMBOO_NUM_OF_CORE] = 0;
300                 numsendobjs[BAMBOO_NUM_OF_CORE] = self_numsendobjs;
301                 numreceiveobjs[BAMBOO_NUM_OF_CORE] = self_numreceiveobjs;
302                 // check the status of all cores
303                 allStall = true;
304 #ifdef DEBUG
305                 BAMBOO_DEBUGPRINT_REG(NUMCORES);
306 #endif
307                 for(i = 0; i < NUMCORES; ++i) {
308 #ifdef DEBUG
309                         BAMBOO_DEBUGPRINT(0xe000 + corestatus[i]);
310 #endif
311                         if(corestatus[i] != 0) {
312                                 allStall = false;
313                                 break;
314                         }
315                 } // for(i = 0; i < NUMCORES; ++i)
316                 if(allStall) {
317                         // check if the sum of send objs and receive obj are the same
318                         // yes->check if the info is the latest; no->go on executing
319                         sumsendobj = 0;
320                         for(i = 0; i < NUMCORES; ++i) {
321                                 sumsendobj += numsendobjs[i];
322 #ifdef DEBUG
323                                 BAMBOO_DEBUGPRINT(0xf000 + numsendobjs[i]);
324 #endif
325                         } // for(i = 0; i < NUMCORES; ++i)      
326                         for(i = 0; i < NUMCORES; ++i) {
327                                 sumsendobj -= numreceiveobjs[i];
328 #ifdef DEBUG
329                                 BAMBOO_DEBUGPRINT(0xf000 + numreceiveobjs[i]);
330 #endif
331                         } // for(i = 0; i < NUMCORES; ++i)
332                         if(0 == sumsendobj) {
333                                 if(!waitconfirm) {
334                                         // the first time found all cores stall
335                                         // send out status confirm msg to all other cores
336                                         // reset the corestatus array too
337 #ifdef DEBUG
338                                         BAMBOO_DEBUGPRINT(0xee05);
339 #endif
340                                         corestatus[BAMBOO_NUM_OF_CORE] = 1;
341                                         for(i = 1; i < NUMCORES; ++i) { 
342                                                 corestatus[i] = 1;
343                                                 // send status confirm msg to core i
344                                                 send_msg_1(i, STATUSCONFIRM);
345                                         } // for(i = 1; i < NUMCORES; ++i)
346                                         waitconfirm = true;
347                                         numconfirm = NUMCORES - 1;
348                                 } else {
349                                         // all the core status info are the latest
350                                         // terminate; for profiling mode, send request to all
351                                         // other cores to pour out profiling data
352 #ifdef DEBUG
353                                         BAMBOO_DEBUGPRINT(0xee06);
354 #endif                                            
355                          
356 #ifdef USEIO
357                                         totalexetime = BAMBOO_GET_EXE_TIME();
358 #else
359                                         BAMBOO_DEBUGPRINT(BAMBOO_GET_EXE_TIME());
360                                         BAMBOO_DEBUGPRINT_REG(total_num_t6); // TODO for test
361                                         BAMBOO_DEBUGPRINT(0xbbbbbbbb);
362 #endif
363                                         // profile mode, send msgs to other cores to request pouring
364                                         // out progiling data
365 #ifdef PROFILE
366                                         BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
367 #ifdef DEBUG
368                                         BAMBOO_DEBUGPRINT(0xf000);
369 #endif
370                                         for(i = 1; i < NUMCORES; ++i) {
371                                                 // send profile request msg to core i
372                                                 send_msg_2(i, PROFILEOUTPUT, totalexetime);
373                                         } // for(i = 1; i < NUMCORES; ++i)
374                                         // pour profiling data on startup core
375                                         outputProfileData();
376                                         while(true) {
377                                                 BAMBOO_START_CRITICAL_SECTION_STATUS();
378 #ifdef DEBUG
379                                                 BAMBOO_DEBUGPRINT(0xf001);
380 #endif
381                                                 profilestatus[BAMBOO_NUM_OF_CORE] = 0;
382                                                 // check the status of all cores
383                                                 allStall = true;
384 #ifdef DEBUG
385                                                 BAMBOO_DEBUGPRINT_REG(NUMCORES);
386 #endif  
387                                                 for(i = 0; i < NUMCORES; ++i) {
388 #ifdef DEBUG
389                                                         BAMBOO_DEBUGPRINT(0xe000 + profilestatus[i]);
390 #endif
391                                                         if(profilestatus[i] != 0) {
392                                                                 allStall = false;
393                                                                 break;
394                                                         }
395                                                 }  // for(i = 0; i < NUMCORES; ++i)
396                                                 if(!allStall) {
397                                                         int halt = 100;
398                                                         BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
399 #ifdef DEBUG
400                                                         BAMBOO_DEBUGPRINT(0xf000);
401 #endif
402                                                         while(halt--) {
403                                                         }
404                                                 } else {
405                                                         break;
406                                                 } // if(!allStall)
407                                         } // while(true)
408 #endif
409                                         disruntimedata();
410                                         terminate(); // All done.
411                                 } // if(!waitconfirm)
412                         } else {
413                                 // still some objects on the fly on the network
414                                 // reset the waitconfirm and numconfirm
415 #ifdef DEBUG
416                                         BAMBOO_DEBUGPRINT(0xee07);
417 #endif
418                                 waitconfirm = false;
419                                 numconfirm = 0;
420                         } //  if(0 == sumsendobj)
421                 } else {
422                         // not all cores are stall, keep on waiting
423 #ifdef DEBUG
424                         BAMBOO_DEBUGPRINT(0xee08);
425 #endif
426                         waitconfirm = false;
427                         numconfirm = 0;
428                 } //  if(allStall)
429                 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
430 #ifdef DEBUG
431                 BAMBOO_DEBUGPRINT(0xf000);
432 #endif
433         } // if((!waitconfirm) ||
434 }
435
436 // main function for each core
437 inline void run(void * arg) {
438   int i = 0;
439   int argc = 1;
440   char ** argv = NULL;
441   bool sendStall = false;
442   bool isfirst = true;
443   bool tocontinue = false;
444
445   corenum = BAMBOO_GET_NUM_OF_CORE();
446 #ifdef DEBUG
447   BAMBOO_DEBUGPRINT(0xeeee);
448   BAMBOO_DEBUGPRINT_REG(corenum);
449   BAMBOO_DEBUGPRINT(STARTUPCORE);
450 #endif
451
452         // initialize runtime data structures
453         initruntimedata();
454
455   // other architecture related initialization
456   initialization();
457   initCommunication();
458
459   initializeexithandler();
460
461   // main process of the execution module
462   if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
463         // non-executing cores, only processing communications
464     activetasks = NULL;
465 /*#ifdef PROFILE
466         BAMBOO_DEBUGPRINT(0xee01);
467         BAMBOO_DEBUGPRINT_REG(taskInfoIndex);
468         BAMBOO_DEBUGPRINT_REG(taskInfoOverflow);
469                 profileTaskStart("msg handling");
470         }
471  #endif*/
472 #ifdef PROFILE
473     //isInterrupt = false;
474 #endif
475                 fakeExecution();
476   } else {
477           /* Create queue of active tasks */
478           activetasks=
479                         genallocatehashtable((unsigned int(*) (void *)) &hashCodetpd,
480                            (int(*) (void *,void *)) &comparetpd);
481           
482           /* Process task information */
483           processtasks();
484           
485           if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
486                   /* Create startup object */
487                   createstartupobject(argc, argv);
488           }
489
490 #ifdef DEBUG
491           BAMBOO_DEBUGPRINT(0xee00);
492 #endif
493
494           while(true) {
495 #ifdef MULTICORE_GC
496                         // check if need to do GC
497                         gc(NULL);
498 #endif
499
500                   // check if there are new active tasks can be executed
501                   executetasks();
502                         if(busystatus) {
503                                 sendStall = false;
504                         }
505
506 #ifndef INTERRUPT
507                   while(receiveObject() != -1) {
508                   }
509 #endif  
510
511 #ifdef DEBUG
512                   BAMBOO_DEBUGPRINT(0xee01);
513 #endif  
514                   
515                   // check if there are some pending objects, 
516                         // if yes, enqueue them and executetasks again
517                   tocontinue = checkObjQueue();
518
519                   if(!tocontinue) {
520                           // check if stop
521                           if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
522                                   if(isfirst) {
523 #ifdef DEBUG
524                                           BAMBOO_DEBUGPRINT(0xee03);
525 #endif
526                                           isfirst = false;
527                                   }
528                                         checkCoreStatus();
529                           } else {
530                                   if(!sendStall) {
531 #ifdef DEBUG
532                                           BAMBOO_DEBUGPRINT(0xee09);
533 #endif
534 #ifdef PROFILE
535                                           if(!stall) {
536 #endif
537                                                   if(isfirst) {
538                                                           // wait for some time
539                                                           int halt = 10000;
540 #ifdef DEBUG
541                                                           BAMBOO_DEBUGPRINT(0xee0a);
542 #endif
543                                                           while(halt--) {
544                                                           }
545                                                           isfirst = false;
546                                                   } else {
547                                                           // send StallMsg to startup core
548 #ifdef DEBUG
549                                                           BAMBOO_DEBUGPRINT(0xee0b);
550 #endif
551                                                           // send stall msg
552                                                           send_msg_4(STARTUPCORE, TRANSTALL, BAMBOO_NUM_OF_CORE, 
553                                                                                        self_numsendobjs, self_numreceiveobjs);
554                                                           sendStall = true;
555                                                           isfirst = true;
556                                                           busystatus = false;
557                                                   }
558 #ifdef PROFILE
559                                           }
560 #endif
561                                   } else {
562                                           isfirst = true;
563                                           busystatus = false;
564 #ifdef DEBUG
565                                           BAMBOO_DEBUGPRINT(0xee0c);
566 #endif
567                                   } // if(!sendStall)
568                           } // if(STARTUPCORE == BAMBOO_NUM_OF_CORE) 
569                   } // if(!tocontinue)
570           } // while(true) 
571   } // if(BAMBOO_NUM_OF_CORE > NUMCORES - 1)
572
573 } // run()
574
575 struct ___createstartupobject____I_locals {
576   INTPTR size;
577   void * next;
578   struct  ___StartupObject___ * ___startupobject___;
579   struct ArrayObject * ___stringarray___;
580 }; // struct ___createstartupobject____I_locals
581
582 void createstartupobject(int argc, 
583                                      char ** argv) {
584   int i;
585
586   /* Allocate startup object     */
587 #ifdef MULTICORE_GC
588         struct ___createstartupobject____I_locals ___locals___={2, NULL, NULL, NULL};
589   struct ___StartupObject___ *startupobject=
590                 (struct ___StartupObject___*) allocate_new(&___locals___, STARTUPTYPE);
591         ___locals___.___startupobject___ = startupobject;
592   struct ArrayObject * stringarray=
593                 allocate_newarray(&___locals___, STRINGARRAYTYPE, argc-1);
594         ___locals___.___stringarray___ = stringarray;
595 #else
596   struct ___StartupObject___ *startupobject=
597                 (struct ___StartupObject___*) allocate_new(STARTUPTYPE);
598   struct ArrayObject * stringarray=
599                 allocate_newarray(STRINGARRAYTYPE, argc-1);
600 #endif
601   /* Build array of strings */
602   startupobject->___parameters___=stringarray;
603   for(i=1; i<argc; i++) {
604     int length=strlen(argv[i]);
605 #ifdef MULTICORE_GC
606     struct ___String___ *newstring=NewString(&___locals___, argv[i],length);
607 #else
608     struct ___String___ *newstring=NewString(argv[i],length);
609 #endif
610     ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=
611                         newstring;
612   }
613
614   startupobject->version = 0;
615   startupobject->lock = NULL;
616
617   /* Set initialized flag for startup object */
618   flagorandinit(startupobject,1,0xFFFFFFFF);
619   enqueueObject(startupobject, NULL, 0);
620 #ifdef CACHEFLUSH
621   BAMBOO_CACHE_FLUSH_ALL();
622 #endif
623 }
624
625 int hashCodetpd(struct taskparamdescriptor *ftd) {
626   int hash=(int)ftd->task;
627   int i;
628   for(i=0; i<ftd->numParameters; i++) {
629     hash^=(int)ftd->parameterArray[i];
630   }
631   return hash;
632 }
633
634 int comparetpd(struct taskparamdescriptor *ftd1, 
635                            struct taskparamdescriptor *ftd2) {
636   int i;
637   if (ftd1->task!=ftd2->task)
638     return 0;
639   for(i=0; i<ftd1->numParameters; i++)
640     if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
641       return 0;
642   return 1;
643 }
644
645 /* This function sets a tag. */
646 #ifdef MULTICORE_GC
647 void tagset(void *ptr, 
648                         struct ___Object___ * obj, 
649                                                 struct ___TagDescriptor___ * tagd) {
650 #else
651 void tagset(struct ___Object___ * obj, 
652                         struct ___TagDescriptor___ * tagd) {
653 #endif
654   struct ArrayObject * ao=NULL;
655   struct ___Object___ * tagptr=obj->___tags___;
656   if (tagptr==NULL) {
657     obj->___tags___=(struct ___Object___ *)tagd;
658   } else {
659     /* Have to check if it is already set */
660     if (tagptr->type==TAGTYPE) {
661       struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
662       if (td==tagd) {
663         return;
664       }
665 #ifdef MULTICORE_GC
666       int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
667       struct ArrayObject * ao=
668                                 allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
669       obj=(struct ___Object___ *)ptrarray[2];
670       tagd=(struct ___TagDescriptor___ *)ptrarray[3];
671       td=(struct ___TagDescriptor___ *) obj->___tags___;
672 #else
673       ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
674 #endif
675
676       ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
677       ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
678       obj->___tags___=(struct ___Object___ *) ao;
679       ao->___cachedCode___=2;
680     } else {
681       /* Array Case */
682       int i;
683       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
684       for(i=0; i<ao->___cachedCode___; i++) {
685         struct ___TagDescriptor___ * td=
686                 ARRAYGET(ao, struct ___TagDescriptor___*, i);
687         if (td==tagd) {
688           return;
689         }
690       }
691       if (ao->___cachedCode___<ao->___length___) {
692         ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
693         ao->___cachedCode___++;
694       } else {
695 #ifdef MULTICORE_GC
696         int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
697         struct ArrayObject * aonew=
698                 allocate_newarray(&ptrarray,TAGARRAYTYPE,
699                                               TAGARRAYINTERVAL+ao->___length___);
700         obj=(struct ___Object___ *)ptrarray[2];
701         tagd=(struct ___TagDescriptor___ *) ptrarray[3];
702         ao=(struct ArrayObject *)obj->___tags___;
703 #else
704         struct ArrayObject * aonew=
705                 allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
706 #endif
707
708         aonew->___cachedCode___=ao->___length___+1;
709         for(i=0; i<ao->___length___; i++) {
710           ARRAYSET(aonew, struct ___TagDescriptor___*, i, 
711                                      ARRAYGET(ao, struct ___TagDescriptor___*, i));
712         }
713         ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
714       }
715     }
716   }
717
718   {
719     struct ___Object___ * tagset=tagd->flagptr;
720     if(tagset==NULL) {
721       tagd->flagptr=obj;
722     } else if (tagset->type!=OBJECTARRAYTYPE) {
723 #ifdef MULTICORE_GC
724       int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
725       struct ArrayObject * ao=
726                                 allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
727       obj=(struct ___Object___ *)ptrarray[2];
728       tagd=(struct ___TagDescriptor___ *)ptrarray[3];
729 #else
730       struct ArrayObject * ao=
731                                 allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
732 #endif
733       ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
734       ARRAYSET(ao, struct ___Object___ *, 1, obj);
735       ao->___cachedCode___=2;
736       tagd->flagptr=(struct ___Object___ *)ao;
737     } else {
738       struct ArrayObject *ao=(struct ArrayObject *) tagset;
739       if (ao->___cachedCode___<ao->___length___) {
740         ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
741       } else {
742         int i;
743 #ifdef MULTICORE_GC
744         int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
745         struct ArrayObject * aonew=
746                 allocate_newarray(&ptrarray,OBJECTARRAYTYPE,
747                                               OBJECTARRAYINTERVAL+ao->___length___);
748         obj=(struct ___Object___ *)ptrarray[2];
749         tagd=(struct ___TagDescriptor___ *)ptrarray[3];
750         ao=(struct ArrayObject *)tagd->flagptr;
751 #else
752         struct ArrayObject * aonew=
753                 allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
754 #endif
755         aonew->___cachedCode___=ao->___cachedCode___+1;
756         for(i=0; i<ao->___length___; i++) {
757           ARRAYSET(aonew, struct ___Object___*, i, 
758                                      ARRAYGET(ao, struct ___Object___*, i));
759         }
760         ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
761         tagd->flagptr=(struct ___Object___ *) aonew;
762       }
763     }
764   }
765 }
766
767 /* This function clears a tag. */
768 #ifdef MULTICORE_GC
769 void tagclear(void *ptr, 
770                           struct ___Object___ * obj, 
771                                                         struct ___TagDescriptor___ * tagd) {
772 #else
773 void tagclear(struct ___Object___ * obj, 
774                           struct ___TagDescriptor___ * tagd) {
775 #endif
776   /* We'll assume that tag is alway there.
777      Need to statically check for this of course. */
778   struct ___Object___ * tagptr=obj->___tags___;
779
780   if (tagptr->type==TAGTYPE) {
781     if ((struct ___TagDescriptor___ *)tagptr==tagd)
782       obj->___tags___=NULL;
783   } else {
784     struct ArrayObject *ao=(struct ArrayObject *) tagptr;
785     int i;
786     for(i=0; i<ao->___cachedCode___; i++) {
787       struct ___TagDescriptor___ * td=
788                                 ARRAYGET(ao, struct ___TagDescriptor___ *, i);
789       if (td==tagd) {
790         ao->___cachedCode___--;
791         if (i<ao->___cachedCode___)
792           ARRAYSET(ao, struct ___TagDescriptor___ *, i, 
793                                 ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
794         ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
795         if (ao->___cachedCode___==0)
796           obj->___tags___=NULL;
797         goto PROCESSCLEAR;
798       }
799     }
800   }
801 PROCESSCLEAR:
802   {
803     struct ___Object___ *tagset=tagd->flagptr;
804     if (tagset->type!=OBJECTARRAYTYPE) {
805       if (tagset==obj)
806         tagd->flagptr=NULL;
807     } else {
808       struct ArrayObject *ao=(struct ArrayObject *) tagset;
809       int i;
810       for(i=0; i<ao->___cachedCode___; i++) {
811         struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
812         if (tobj==obj) {
813           ao->___cachedCode___--;
814           if (i<ao->___cachedCode___)
815             ARRAYSET(ao, struct ___Object___ *, i, 
816                                         ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
817           ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
818           if (ao->___cachedCode___==0)
819             tagd->flagptr=NULL;
820           goto ENDCLEAR;
821         }
822       }
823     }
824   }
825 ENDCLEAR:
826   return;
827 }
828
829 /* This function allocates a new tag. */
830 #ifdef MULTICORE_GC
831 struct ___TagDescriptor___ * allocate_tag(void *ptr, 
832                                                       int index) {
833   struct ___TagDescriptor___ * v=
834                 (struct ___TagDescriptor___ *) FREEMALLOC((struct garbagelist *) ptr, 
835                                                                       classsize[TAGTYPE]);
836 #else
837 struct ___TagDescriptor___ * allocate_tag(int index) {
838   struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
839 #endif
840   v->type=TAGTYPE;
841   v->flag=index;
842   return v;
843 }
844
845
846
847 /* This function updates the flag for object ptr.  It or's the flag
848    with the or mask and and's it with the andmask. */
849
850 void flagbody(struct ___Object___ *ptr, 
851                           int flag, 
852                                                         struct parameterwrapper ** queues, 
853                                                         int length, 
854                                                         bool isnew);
855
856 int flagcomp(const int *val1, const int *val2) {
857   return (*val1)-(*val2);
858 }
859
860 void flagorand(void * ptr, 
861                            int ormask, 
862                                                          int andmask, 
863                                                          struct parameterwrapper ** queues, 
864                                                          int length) {
865   {
866     int oldflag=((int *)ptr)[1];
867     int flag=ormask|oldflag;
868     flag&=andmask;
869     flagbody(ptr, flag, queues, length, false);
870   }
871 }
872
873 bool intflagorand(void * ptr, 
874                               int ormask, 
875                                                                         int andmask) {
876   {
877     int oldflag=((int *)ptr)[1];
878     int flag=ormask|oldflag;
879     flag&=andmask;
880     if (flag==oldflag)   /* Don't do anything */
881       return false;
882     else {
883       flagbody(ptr, flag, NULL, 0, false);
884       return true;
885     }
886   }
887 }
888
889 void flagorandinit(void * ptr, 
890                                int ormask, 
891                                                                          int andmask) {
892   int oldflag=((int *)ptr)[1];
893   int flag=ormask|oldflag;
894   flag&=andmask;
895   flagbody(ptr,flag,NULL,0,true);
896 }
897
898 void flagbody(struct ___Object___ *ptr, 
899                           int flag, 
900                                                         struct parameterwrapper ** vqueues, 
901                                                         int vlength, 
902                                                         bool isnew) {
903   struct parameterwrapper * flagptr = NULL;
904   int i = 0;
905   struct parameterwrapper ** queues = vqueues;
906   int length = vlength;
907   int next;
908   int UNUSED, UNUSED2;
909   int * enterflags = NULL;
910   if((!isnew) && (queues == NULL)) {
911     if(BAMBOO_NUM_OF_CORE < NUMCORES) {
912                 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
913                 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
914         } else {
915                 return;
916         }
917   }
918   ptr->flag=flag;
919
920   /*Remove object from all queues */
921   for(i = 0; i < length; ++i) {
922     flagptr = queues[i];
923     ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next, 
924                                           (int *) &enterflags, &UNUSED, &UNUSED2);
925     ObjectHashremove(flagptr->objectset, (int)ptr);
926     if (enterflags!=NULL)
927       RUNFREE(enterflags);
928   }
929 }
930
931 void enqueueObject(void * vptr, 
932                                struct parameterwrapper ** vqueues, 
933                                                                          int vlength) {
934         struct ___Object___ *ptr = (struct ___Object___ *)vptr;
935         
936         {
937                 //struct QueueItem *tmpptr;
938                 struct parameterwrapper * parameter=NULL;
939                 int j;
940                 int i;
941                 struct parameterwrapper * prevptr=NULL;
942                 struct ___Object___ *tagptr=NULL;
943                 struct parameterwrapper ** queues = vqueues;
944                 int length = vlength;
945                 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
946                         return;
947                 }
948                 if(queues == NULL) {
949                         queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
950                         length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
951                 }
952                 tagptr=ptr->___tags___;
953
954                 /* Outer loop iterates through all parameter queues an object of
955                    this type could be in.  */
956                 for(j = 0; j < length; ++j) {
957                         parameter = queues[j];     
958                         /* Check tags */
959                         if (parameter->numbertags>0) {
960                                 if (tagptr==NULL)
961                                         goto nextloop; //that means the object has no tag 
962                                                  //but that param needs tag
963                                 else if(tagptr->type==TAGTYPE) { //one tag
964                                         //struct ___TagDescriptor___ * tag=
965                                         //(struct ___TagDescriptor___*) tagptr;  
966                                         for(i=0; i<parameter->numbertags; i++) {
967                                                 //slotid is parameter->tagarray[2*i];
968                                                 int tagid=parameter->tagarray[2*i+1];
969                                                 if (tagid!=tagptr->flag)
970                                                         goto nextloop; /*We don't have this tag */
971                                         }
972                                 } else { //multiple tags
973                                         struct ArrayObject * ao=(struct ArrayObject *) tagptr;
974                                         for(i=0; i<parameter->numbertags; i++) {
975                                                 //slotid is parameter->tagarray[2*i];
976                                                 int tagid=parameter->tagarray[2*i+1];
977                                                 int j;
978                                                 for(j=0; j<ao->___cachedCode___; j++) {
979                                                         if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
980                                                                 goto foundtag;
981                                                 }
982                                                 goto nextloop;
983 foundtag:
984                                                 ;
985                                         }
986                                 }
987                         }
988         
989                         /* Check flags */
990                         for(i=0; i<parameter->numberofterms; i++) {
991                                 int andmask=parameter->intarray[i*2];
992                                 int checkmask=parameter->intarray[i*2+1];
993                                 if ((ptr->flag&andmask)==checkmask) {
994                                         enqueuetasks(parameter, prevptr, ptr, NULL, 0);
995                                         prevptr=parameter;
996                                         break;
997                                 }
998                         }
999 nextloop:
1000                         ;
1001                 }
1002         }
1003 }
1004
1005 void enqueueObject_I(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 > NUMCORES - 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=(struct ___TagDescriptor___*) tagptr;         
1039                                         for(i=0; i<parameter->numbertags; i++) {
1040                                                 //slotid is parameter->tagarray[2*i];
1041                                                 int tagid=parameter->tagarray[2*i+1];
1042                                                 if (tagid!=tagptr->flag)
1043                                                         goto nextloop; /*We don't have this tag */
1044                                         }
1045                                 } else { //multiple tags
1046                                         struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1047                                         for(i=0; i<parameter->numbertags; i++) {
1048                                                 //slotid is parameter->tagarray[2*i];
1049                                                 int tagid=parameter->tagarray[2*i+1];
1050                                                 int j;
1051                                                 for(j=0; j<ao->___cachedCode___; j++) {
1052                                                         if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
1053                                                                 goto foundtag;
1054                                                 }
1055                                                 goto nextloop;
1056 foundtag:
1057                                                 ;
1058                                         }
1059                                 }
1060                         }
1061
1062                         /* Check flags */
1063                         for(i=0; i<parameter->numberofterms; i++) {
1064                                 int andmask=parameter->intarray[i*2];
1065                                 int checkmask=parameter->intarray[i*2+1];
1066                                 if ((ptr->flag&andmask)==checkmask) {
1067                                         enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
1068                                         prevptr=parameter;
1069                                         break;
1070                                 }
1071                         }
1072 nextloop:
1073                         ;
1074                 }
1075         }
1076 }
1077
1078
1079 int * getAliasLock(void ** ptrs, 
1080                                int length, 
1081                                                                          struct RuntimeHash * tbl) {
1082         if(length == 0) {
1083                 return (int*)(RUNMALLOC(sizeof(int)));
1084         } else {
1085                 int i = 0;
1086                 int locks[length];
1087                 int locklen = 0;
1088                 bool redirect = false;
1089                 int redirectlock = 0;
1090                 for(; i < length; i++) {
1091                         struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
1092                         int lock = 0;
1093                         int j = 0;
1094                         if(ptr->lock == NULL) {
1095                                 lock = (int)(ptr);
1096                         } else {
1097                                 lock = (int)(ptr->lock);
1098                         }
1099                         if(redirect) {
1100                                 if(lock != redirectlock) {
1101                                         RuntimeHashadd(tbl, lock, redirectlock);
1102                                 }
1103                         } else {
1104                                 if(RuntimeHashcontainskey(tbl, lock)) {
1105                                         // already redirected
1106                                         redirect = true;
1107                                         RuntimeHashget(tbl, lock, &redirectlock);
1108                                         for(; j < locklen; j++) {
1109                                                 if(locks[j] != redirectlock) {
1110                                                         RuntimeHashadd(tbl, locks[j], redirectlock);
1111                                                 }
1112                                         }
1113                                 } else {
1114                                         bool insert = true;
1115                                         for(j = 0; j < locklen; j++) {
1116                                                 if(locks[j] == lock) {
1117                                                         insert = false;
1118                                                         break;
1119                                                 } else if(locks[j] > lock) {
1120                                                         break;
1121                                                 }
1122                                         }
1123                                         if(insert) {
1124                                                 int h = locklen;
1125                                                 for(; h > j; h--) {
1126                                                         locks[h] = locks[h-1];
1127                                                 }       
1128                                                 locks[j] = lock;
1129                                                 locklen++;
1130                                         }
1131                                 }
1132                         }
1133                 }
1134                 if(redirect) {
1135                         return (int *)redirectlock;
1136                 } else {
1137                         return (int *)(locks[0]);
1138                 }
1139         }
1140 }
1141
1142 void addAliasLock(void * ptr, 
1143                               int lock) {
1144   struct ___Object___ * obj = (struct ___Object___ *)ptr;
1145   if(((int)ptr != lock) && (obj->lock != (int*)lock)) {
1146     // originally no alias lock associated or have a different alias lock
1147     // flush it as the new one
1148     obj->lock = (int *)lock;
1149   }
1150 }
1151
1152 #ifdef PROFILE
1153 inline void setTaskExitIndex(int index) {
1154         taskInfoArray[taskInfoIndex]->exitIndex = index;
1155 }
1156
1157 inline void addNewObjInfo(void * nobj) {
1158         if(taskInfoArray[taskInfoIndex]->newObjs == NULL) {
1159                 taskInfoArray[taskInfoIndex]->newObjs = createQueue();
1160         }
1161         addNewItem(taskInfoArray[taskInfoIndex]->newObjs, nobj);
1162 }
1163 #endif
1164
1165 void * smemalloc(int size, 
1166                              int * allocsize) {
1167         void * mem = NULL;
1168         int isize = size;
1169 #ifdef MULTICORE_GC
1170         // go through free mem list for suitable blocks
1171         struct freeMemItem * freemem = bamboo_free_mem_list->head;
1172         struct freeMemItem * prev = NULL;
1173         do {
1174                 if(freemem->size >= isize) {
1175                         // found one
1176                         break;
1177                 }
1178                 prev = freemem;
1179                 freemem = freemem->next;
1180         } while(freemem != NULL);
1181         if(freemem != NULL) {
1182                 mem = (void *)(freemem->ptr);
1183                 // check the remaining space in this block
1184                 int remain = (int)(mem-(BAMBOO_BASE_VA));
1185                 int bound = (BAMBOO_SMEM_SIZE);
1186                 if(remain < BAMBOO_LARGE_SMEM_BOUND) {
1187                         bound = (BAMBOO_SMEM_SIZE_L);
1188                 }
1189                 remain = bound - remain%bound;
1190                 if(remain < isize) {
1191                         // this object acrosses blocks
1192                         // try to align the block if required a block
1193                         if((isize == BAMBOO_SMEM_SIZE) && (freemem->size >= isize + remain)) {
1194                                 isize += remain;
1195                         }
1196                 }
1197                 *allocsize = isize;
1198                 freemem->ptr = ((void*)freemem->ptr) + isize;
1199                 freemem->size -= isize;
1200         } else {
1201 #else
1202         mem = mspace_calloc(bamboo_free_msp, 1, isize);
1203         *allocsize = isize;
1204         if(mem == NULL) {
1205 #endif
1206                 // no enough shared global memory
1207                 *allocsize = 0;
1208 #ifdef MULTICORE_GC
1209                 gcflag = true;
1210                 return NULL;
1211 #else
1212                 BAMBOO_DEBUGPRINT(0xa001);
1213                 BAMBOO_EXIT(0xa001);
1214 #endif
1215         }
1216         return mem;
1217 }
1218
1219 // receive object transferred from other cores
1220 // or the terminate message from other cores
1221 // Should be invoked in critical sections!!
1222 // NOTICE: following format is for threadsimulate version only
1223 //         RAW version please see previous description
1224 // format: type + object
1225 // type: -1--stall msg
1226 //      !-1--object
1227 // return value: 0--received an object
1228 //               1--received nothing
1229 //               2--received a Stall Msg
1230 //               3--received a lock Msg
1231 //               RAW version: -1 -- received nothing
1232 //                            otherwise -- received msg type
1233 int receiveObject() {
1234   int deny = 0;
1235   
1236 msg:
1237   if(receiveMsg() == -1) {
1238           return -1;
1239   }
1240
1241   if(msgdataindex == msglength) {
1242     // received a whole msg
1243     MSGTYPE type; 
1244     type = msgdata[0];
1245     switch(type) {
1246     case TRANSOBJ: {
1247       // receive a object transfer msg
1248       struct transObjInfo * transObj = 
1249                                 RUNMALLOC_I(sizeof(struct transObjInfo));
1250       int k = 0;
1251 #ifdef DEBUG
1252 #ifndef TILERA
1253                         BAMBOO_DEBUGPRINT(0xe880);
1254 #endif
1255 #endif
1256       if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1257 #ifndef TILERA
1258                                 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1259 #endif
1260                                 BAMBOO_EXIT(0xa002);
1261                         } 
1262       // store the object and its corresponding queue info, enqueue it later
1263       transObj->objptr = (void *)msgdata[2]; 
1264       transObj->length = (msglength - 3) / 2;
1265       transObj->queues = RUNMALLOC_I(sizeof(int)*(msglength - 3));
1266       for(k = 0; k < transObj->length; ++k) {
1267                                 transObj->queues[2*k] = msgdata[3+2*k];
1268 #ifdef DEBUG
1269 #ifndef TILERA
1270                                 BAMBOO_DEBUGPRINT_REG(transObj->queues[2*k]);
1271 #endif
1272 #endif
1273                                 transObj->queues[2*k+1] = msgdata[3+2*k+1];
1274 #ifdef DEBUG
1275 #ifndef TILERA
1276                                 BAMBOO_DEBUGPRINT_REG(transObj->queues[2*k+1]);
1277 #endif
1278 #endif
1279                         }
1280       // check if there is an existing duplicate item
1281       {
1282                                 struct QueueItem * qitem = getHead(&objqueue);
1283                                 struct QueueItem * prev = NULL;
1284                                 while(qitem != NULL) {
1285                                         struct transObjInfo * tmpinfo = 
1286                                                 (struct transObjInfo *)(qitem->objectptr);
1287                                         if(tmpinfo->objptr == transObj->objptr) {
1288                                                 // the same object, remove outdate one
1289                                                 removeItem(&objqueue, qitem);
1290                                                 //break;
1291                                         } else {
1292                                                 prev = qitem;
1293                                         }
1294                                         if(prev == NULL) {
1295                                                 qitem = getHead(&objqueue);
1296                                         } else {
1297                                                 qitem = getNextQueueItem(prev);
1298                                         }
1299                                 }
1300                                 addNewItem_I(&objqueue, (void *)transObj);
1301                         }
1302       ++(self_numreceiveobjs);
1303       break;
1304     }
1305
1306     case TRANSTALL: {
1307       // receive a stall msg
1308       if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1309                   // non startup core can not receive stall msg
1310 #ifndef TILERA
1311                                 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1312 #endif
1313                                 BAMBOO_EXIT(0xa003);
1314       } 
1315       if(msgdata[1] < NUMCORES) {
1316 #ifdef DEBUG
1317 #ifndef TILERA
1318                                 BAMBOO_DEBUGPRINT(0xe881);
1319 #endif
1320 #endif
1321                                 corestatus[msgdata[1]] = 0;
1322                                 numsendobjs[msgdata[1]] = msgdata[2];
1323                                 numreceiveobjs[msgdata[1]] = msgdata[3];
1324       }
1325       break;
1326     }
1327
1328 // GC version have no lock msgs
1329 #ifndef MULTICORE_GC
1330     case LOCKREQUEST: {
1331       // receive lock request msg, handle it right now
1332       // check to see if there is a lock exist for the required obj
1333                         // msgdata[1] -> lock type
1334                         int data2 = msgdata[2]; // obj pointer
1335       int data3 = msgdata[3]; // lock
1336                         int data4 = msgdata[4]; // request core
1337                         // -1: redirected, 0: approved, 1: denied
1338       deny = processlockrequest(msgdata[1], data3, data2, 
1339                                                               data4, data4, true);  
1340                         if(deny == -1) {
1341                                 // this lock request is redirected
1342                                 break;
1343                         } else {
1344                                 // send response msg
1345                                 // for 32 bit machine, the size is always 4 words
1346                                 int tmp = deny==1?LOCKDENY:LOCKGROUNT;
1347                                 if(isMsgSending) {
1348                                         cache_msg_4(data4, tmp, msgdata[1], data2, data3);
1349                                 } else {
1350                                         send_msg_4(data4, tmp, msgdata[1], data2, data3);
1351                                 }
1352                         }
1353       break;
1354     }
1355
1356     case LOCKGROUNT: {
1357       // receive lock grount msg
1358       if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1359 #ifndef TILERA
1360                                 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1361 #endif
1362                                 BAMBOO_EXIT(0xa004);
1363       } 
1364       if((lockobj == msgdata[2]) && (lock2require == msgdata[3])) {
1365 #ifdef DEBUG
1366 #ifndef TILERA
1367                                 BAMBOO_DEBUGPRINT(0xe882);
1368 #endif
1369 #endif
1370                                 lockresult = 1;
1371                                 lockflag = true;
1372 #ifndef INTERRUPT
1373                                 reside = false;
1374 #endif
1375                         } else {
1376                                 // conflicts on lockresults
1377 #ifndef TILERA
1378                                 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1379 #endif
1380                                 BAMBOO_EXIT(0xa005);
1381       }
1382       break;
1383     }
1384
1385     case LOCKDENY: {
1386       // receive lock deny msg
1387       if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1388 #ifndef TILERA
1389                                 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1390 #endif
1391                                 BAMBOO_EXIT(0xa006);
1392       } 
1393       if((lockobj == msgdata[2]) && (lock2require == msgdata[3])) {
1394 #ifdef DEBUG
1395 #ifndef TILERA
1396                                 BAMBOO_DEBUGPRINT(0xe883);
1397 #endif
1398 #endif
1399                                 lockresult = 0;
1400                                 lockflag = true;
1401 #ifndef INTERRUPT
1402                                 reside = false;
1403 #endif
1404                                 } else {
1405                                 // conflicts on lockresults
1406 #ifndef TILERA
1407                                 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1408 #endif
1409                                 BAMBOO_EXIT(0xa007);
1410       }
1411       break;
1412     }
1413
1414     case LOCKRELEASE: {
1415       // receive lock release msg
1416                         processlockrelease(msgdata[1], msgdata[2], 0, false);
1417       break;
1418     }
1419 #endif
1420
1421 #ifdef PROFILE
1422     case PROFILEOUTPUT: {
1423       // receive an output profile data request msg
1424       if(BAMBOO_NUM_OF_CORE == STARTUPCORE) {
1425                                 // startup core can not receive profile output finish msg
1426                                 BAMBOO_EXIT(0xa008);
1427       }
1428 #ifdef DEBUG
1429 #ifndef TILEAR
1430                         BAMBOO_DEBUGPRINT(0xe885);
1431 #endif
1432 #endif
1433                         stall = true;
1434                         totalexetime = msgdata[1];
1435                         outputProfileData();
1436                         if(isMsgSending) {
1437                                 cache_msg_2(STARTUPCORE, PROFILEFINISH, BAMBOO_NUM_OF_CORE);
1438                         } else {
1439                                 send_msg_2(STARTUPCORE, PROFILEFINISH, BAMBOO_NUM_OF_CORE);
1440                         }
1441       break;
1442     }
1443
1444     case PROFILEFINISH: {
1445       // receive a profile output finish msg
1446       if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1447                                 // non startup core can not receive profile output finish msg
1448 #ifndef TILERA
1449                                 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1450 #endif
1451                                 BAMBOO_EXIT(0xa009);
1452       }
1453 #ifdef DEBUG
1454 #ifndef TILERA
1455                         BAMBOO_DEBUGPRINT(0xe886);
1456 #endif
1457 #endif
1458                         profilestatus[msgdata[1]] = 0;
1459       break;
1460     }
1461 #endif
1462
1463 // GC version has no lock msgs
1464 #ifndef MULTICORE_GC
1465         case REDIRECTLOCK: {
1466           // receive a redirect lock request msg, handle it right now
1467                 // check to see if there is a lock exist for the required obj
1468           int data1 = msgdata[1]; // lock type
1469           int data2 = msgdata[2]; // obj pointer
1470                 int data3 = msgdata[3]; // redirect lock
1471           int data4 = msgdata[4]; // root request core
1472           int data5 = msgdata[5]; // request core
1473           deny = processlockrequest(msgdata[1], data3, data2, data5, data4, true);
1474           if(deny == -1) {
1475                   // this lock request is redirected
1476                   break;
1477           } else {
1478                   // send response msg
1479                   // for 32 bit machine, the size is always 4 words
1480                   if(isMsgSending) {
1481                           cache_msg_4(data4, deny==1?REDIRECTDENY:REDIRECTGROUNT, 
1482                                                         data1, data2, data3);
1483                   } else {
1484                           send_msg_4(data4, deny==1?REDIRECTDENY:REDIRECTGROUNT, 
1485                                                        data1, data2, data3);
1486                   }
1487           }
1488           break;
1489         }
1490
1491         case REDIRECTGROUNT: {
1492                 // receive a lock grant msg with redirect info
1493                 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1494 #ifndef TILERA
1495                         BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1496 #endif
1497                         BAMBOO_EXIT(0xa00a);
1498                 }
1499                 if(lockobj == msgdata[2]) {
1500 #ifdef DEBUG
1501 #ifndef TILERA
1502                   BAMBOO_DEBUGPRINT(0xe891);
1503 #endif
1504 #endif
1505                   lockresult = 1;
1506                   lockflag = true;
1507                   RuntimeHashadd_I(objRedirectLockTbl, lockobj, msgdata[3]);
1508 #ifndef INTERRUPT
1509                   reside = false;
1510 #endif
1511                 } else {
1512                   // conflicts on lockresults
1513 #ifndef TILERA
1514                   BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1515 #endif
1516                   BAMBOO_EXIT(0xa00b);
1517                 }
1518                 break;
1519         }
1520         
1521         case REDIRECTDENY: {
1522           // receive a lock deny msg with redirect info
1523           if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1524 #ifndef TILERA
1525                   BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1526 #endif
1527                   BAMBOO_EXIT(0xa00c);
1528           }
1529                 if(lockobj == msgdata[2]) {
1530 #ifdef DEBUG
1531 #ifndef TILERA
1532                   BAMBOO_DEBUGPRINT(0xe892);
1533 #endif
1534 #endif
1535                   lockresult = 0;
1536                   lockflag = true;
1537 #ifndef INTERRUPT
1538                   reside = false;
1539 #endif
1540                 } else {
1541                   // conflicts on lockresults
1542 #ifndef TILERA
1543                   BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1544 #endif
1545                   BAMBOO_EXIT(0xa00d);
1546                 }
1547                 break;
1548         }
1549
1550         case REDIRECTRELEASE: {
1551           // receive a lock release msg with redirect info
1552                 processlockrelease(msgdata[1], msgdata[2], msgdata[3], true);
1553                 break;
1554         }
1555 #endif
1556         
1557         case STATUSCONFIRM: {
1558       // receive a status confirm info
1559           if((BAMBOO_NUM_OF_CORE == STARTUPCORE) 
1560                                 || (BAMBOO_NUM_OF_CORE > NUMCORES - 1)) {
1561                   // wrong core to receive such msg
1562                   BAMBOO_EXIT(0xa00e);
1563                 } else {
1564                   // send response msg
1565 #ifdef DEBUG
1566 #ifndef TILERA
1567                   BAMBOO_DEBUGPRINT(0xe887);
1568 #endif
1569 #endif
1570                   if(isMsgSending) {
1571                           cache_msg_5(STARTUPCORE, STATUSREPORT, 
1572                                                         busystatus?1:0, BAMBOO_NUM_OF_CORE,
1573                                                                                 self_numsendobjs, self_numreceiveobjs);
1574                   } else {
1575                           send_msg_5(STARTUPCORE, STATUSREPORT, 
1576                                                        busystatus?1:0, BAMBOO_NUM_OF_CORE,
1577                                                                          self_numsendobjs, self_numreceiveobjs);
1578                   }
1579                 }
1580           break;
1581         }
1582
1583         case STATUSREPORT: {
1584           // receive a status confirm info
1585           if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1586                   // wrong core to receive such msg
1587 #ifndef TILERA
1588                   BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1589 #endif
1590                   BAMBOO_EXIT(0xa00f);
1591                 } else {
1592 #ifdef DEBUG
1593 #ifndef TILERA
1594                   BAMBOO_DEBUGPRINT(0xe888);
1595 #endif
1596 #endif
1597                   if(waitconfirm) {
1598                           numconfirm--;
1599                   }
1600                   corestatus[msgdata[2]] = msgdata[1];
1601                         numsendobjs[msgdata[2]] = msgdata[3];
1602                         numreceiveobjs[msgdata[2]] = msgdata[4];
1603                 }
1604           break;
1605         }
1606
1607         case TERMINATE: {
1608           // receive a terminate msg
1609 #ifdef DEBUG
1610 #ifndef TILERA
1611                 BAMBOO_DEBUGPRINT(0xe889);
1612 #endif
1613 #endif
1614                 disruntimedata();
1615                 BAMBOO_EXIT(0);
1616           break;
1617         }
1618
1619         case MEMREQUEST: {
1620           // receive a shared memory request msg
1621           if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1622                   // wrong core to receive such msg
1623 #ifndef TILERA
1624                   BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1625 #endif
1626                   BAMBOO_EXIT(0xa010);
1627                 } else {
1628 #ifdef DEBUG
1629 #ifndef TILERA
1630                   BAMBOO_DEBUGPRINT(0xe88a);
1631 #endif
1632 #endif
1633 #ifdef MULTICORE_GC
1634                         if(gcprocessing) {
1635                                 // is currently doing gc, dump this msg
1636                                 break;
1637                         }
1638 #endif
1639                         int allocsize = 0;
1640                   void * mem = smemalloc(msgdata[1], &allocsize);
1641                         if(mem == NULL) {
1642                                 break;
1643                         }
1644                         // send the start_va to request core
1645                         if(isMsgSending) {
1646                                 cache_msg_3(msgdata[2], MEMRESPONSE, mem, allocsize);
1647                         } else {
1648                                 send_msg_3( msgdata[2], MEMRESPONSE, mem, allocsize);
1649                         } 
1650                 }
1651           break;
1652         }
1653
1654         case MEMRESPONSE: {
1655                 // receive a shared memory response msg
1656 #ifdef DEBUG
1657 #ifndef TILERA
1658           BAMBOO_DEBUGPRINT(0xe88b);
1659 #endif
1660 #endif
1661 #ifdef MULTICORE_GC
1662                 if(gcprocessing) {
1663                         // is currently doing gc, dump this msg
1664                         break;
1665                 }
1666 #endif
1667           if(msgdata[2] == 0) {
1668                   bamboo_smem_size = 0;
1669                   bamboo_cur_msp = 0;
1670           } else {
1671                         // fill header to store the size of this mem block
1672                         (*((int*)msgdata[1])) = msgdata[2];
1673                   bamboo_smem_size = msgdata[2] - BAMBOO_CACHE_LINE_SIZE;
1674 #ifdef MULTICORE_GC
1675                         bamboo_cur_msp = msgdata[1] + BAMBOO_CACHE_LINE_SIZE;
1676 #else
1677                   bamboo_cur_msp = 
1678                                 create_mspace_with_base((void*)(msgdata[1]+BAMBOO_CACHE_LINE_SIZE),
1679                                                          msgdata[2]-BAMBOO_CACHE_LINE_SIZE, 
1680                                                                                                                                  0);
1681 #endif
1682           }
1683           smemflag = true;
1684           break;
1685         }
1686
1687 #ifdef MULTICORE_GC
1688         // GC msgs
1689         case GCSTARTINIT: {
1690                 gcflag = true;
1691                 gcphase = INITPHASE;
1692                 if(!smemflag) {
1693                         // is waiting for response of mem request
1694                         // let it return NULL and start gc
1695                         bamboo_smem_size = 0;
1696                         bamboo_cur_msp = NULL;
1697                         smemflag = true;
1698                 }
1699           break;
1700         }
1701
1702         case GCSTART: {
1703                 // receive a start GC msg
1704 #ifdef DEBUG
1705 #ifndef TILERA
1706           BAMBOO_DEBUGPRINT(0xe88c);
1707 #endif
1708 #endif
1709           // set the GC flag
1710                 gcphase = MARKPHASE;
1711           break;
1712         }
1713
1714         case GCSTARTCOMPACT: {
1715                 // a compact phase start msg
1716                 gcblock2fill = msgdata[1];
1717                 gcphase = COMPACTPHASE;
1718                 break;
1719         }
1720
1721         case GCSTARTFLUSH: {
1722                 // received a flush phase start msg
1723                 gcphase = FLUSHPHASE;
1724                 break;
1725         }
1726         
1727         case GCFINISHINIT: {
1728                 // received a init phase finish msg
1729                 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1730                   // non startup core can not receive this msg
1731 #ifndef TILERA
1732                   BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1733 #endif
1734                   BAMBOO_EXIT(0xb001);
1735                 }
1736 #ifdef DEBUG
1737                 BAMBOO_DEBUGPRINT(0xe88c);
1738                 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1739 #endif
1740                 if(msgdata[1] < NUMCORES) {
1741                         gccorestatus[msgdata[1]] = 0;
1742                 }
1743         }
1744
1745         case GCFINISHMARK: {
1746                 // received a mark phase finish msg
1747                 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1748                   // non startup core can not receive this msg
1749 #ifndef TILERA
1750                   BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1751 #endif
1752                   BAMBOO_EXIT(0xb002);
1753                 } 
1754                 if(msgdata[1] < NUMCORES) {
1755                         gccorestatus[msgdata[1]] = 0;
1756                         gcnumsendobjs[msgdata[1]] = msgdata[2];
1757                         gcnumreceiveobjs[msgdata[1]] = msgdata[3];
1758                 }
1759           break;
1760         }
1761         
1762         case GCFINISHCOMPACT: {
1763                 // received a compact phase finish msg
1764                 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1765                   // non startup core can not receive this msg
1766                   // return -1
1767 #ifndef TILERA
1768                   BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1769 #endif
1770                   BAMBOO_EXIT(0xb003);
1771                 }
1772                 int cnum = msgdata[1];
1773                 int filledblocks = msgdata[2];
1774                 int heaptop = msgdata[3];
1775                 int data4 = msgdata[4];
1776                 if(cnum < NUMCORES) {
1777                         if(COMPACTPHASE == gcphase) {
1778                                 gcfilledblocks[cnum] = filledblocks;
1779                                 gcloads[cnum] = heaptop;
1780                         }
1781                         if(data4 > 0) {
1782                                 // ask for more mem
1783                                 int startaddr = 0;
1784                                 int tomove = 0;
1785                                 int dstcore = 0;
1786                                 if(gcfindSpareMem_I(&startaddr, &tomove, &dstcore, data4, cnum)) {
1787                                         if(isMsgSending) {
1788                                                 cache_msg_4(cnum, GCMOVESTART, dstcore, startaddr, tomove);
1789                                         } else {
1790                                                 send_msg_4(cnum, GCMOVESTART, dstcore, startaddr, tomove);
1791                                         }
1792                                 }
1793                         } else {
1794                                 gccorestatus[cnum] = 0;
1795                                 // check if there is pending move request
1796                                 /*if(gcmovepending > 0) {
1797                                         int j;
1798                                         for(j = 0; j < NUMCORES; j++) {
1799                                                 if(gcrequiredmems[j]>0) {
1800                                                         break;
1801                                                 }
1802                                         }
1803                                         if(j < NUMCORES) {
1804                                                 // find match
1805                                                 int tomove = 0;
1806                                                 int startaddr = 0;
1807                                                 gcrequiredmems[j] = assignSpareMem_I(cnum, 
1808                                                                                                                                                                                            gcrequiredmems[j], 
1809                                                                                                                                                                                            &tomove, 
1810                                                                                                                                                                                            &startaddr);
1811                                                 if(STARTUPCORE == j) {
1812                                                         gcdstcore = cnum;
1813                                                         gctomove = true;
1814                                                         gcmovestartaddr = startaddr;
1815                                                         gcblock2fill = tomove;
1816                                                 } else {
1817                                                         if(isMsgSending) {
1818                                                                 cache_msg_4(j, GCMOVESTART, cnum, startaddr, tomove);
1819                                                         } else {
1820                                                                 send_msg_4(j, GCMOVESTART, cnum, startaddr, tomove);
1821                                                         }
1822                                                 } // if(STARTUPCORE == j)
1823                                                 if(gcrequiredmems[j] == 0) {
1824                                                         gcmovepending--;
1825                                                 }
1826                                         } // if(j < NUMCORES)
1827                                 } // if(gcmovepending > 0) */
1828                         } // if(data4>0)
1829                 } // if(cnum < NUMCORES)
1830           break;
1831         }
1832
1833         case GCFINISHFLUSH: {
1834                 // received a flush phase finish msg
1835                 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1836                   // non startup core can not receive this msg
1837                   // return -1
1838 #ifndef TILERA
1839                   BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1840 #endif
1841                   BAMBOO_EXIT(0xb004);
1842                 } 
1843                 if(msgdata[1] < NUMCORES) {
1844                   gccorestatus[msgdata[1]] = 0;
1845                 }
1846           break;
1847         }
1848
1849         case GCFINISH: {
1850                 // received a GC finish msg
1851                 gcphase = FINISHPHASE;
1852                 break;
1853         }
1854
1855         case GCMARKCONFIRM: {
1856                 // received a marked phase finish confirm request msg
1857                 if((BAMBOO_NUM_OF_CORE == STARTUPCORE) 
1858                                 || (BAMBOO_NUM_OF_CORE > NUMCORES - 1)) {
1859                   // wrong core to receive such msg
1860                   BAMBOO_EXIT(0xb005);
1861                 } else {
1862                   // send response msg
1863                   if(isMsgSending) {
1864                           cache_msg_5(STARTUPCORE, GCMARKREPORT, BAMBOO_NUM_OF_CORE, 
1865                                                         gcbusystatus, gcself_numsendobjs, 
1866                                                                                 gcself_numreceiveobjs);
1867                   } else {
1868                           send_msg_5(STARTUPCORE, GCMARKREPORT, BAMBOO_NUM_OF_CORE, 
1869                                                        gcbusystatus, gcself_numsendobjs, gcself_numreceiveobjs);
1870                   }
1871                 }
1872           break;
1873         }
1874
1875         case GCMARKREPORT: {
1876                 // received a marked phase finish confirm response msg
1877                 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1878                   // wrong core to receive such msg
1879 #ifndef TILERA
1880                   BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1881 #endif
1882                   BAMBOO_EXIT(0xb006);
1883                 } else {
1884                   if(waitconfirm) {
1885                           numconfirm--;
1886                   }
1887                   gccorestatus[msgdata[1]] = msgdata[2];
1888                   gcnumsendobjs[msgdata[1]] = msgdata[3];
1889                   gcnumreceiveobjs[msgdata[1]] = msgdata[4];
1890                 }
1891           break;
1892         }
1893
1894         case GCMARKEDOBJ: {
1895                 // received a markedObj msg
1896                 gc_enqueue_I(msgdata[1]);
1897                 gcself_numreceiveobjs++;
1898                 gcbusystatus = true;
1899                 break;
1900         }
1901
1902         case GCMOVESTART: {
1903                 // received a start moving objs msg
1904                 gctomove = true;
1905                 gcdstcore = msgdata[1];
1906                 gcmovestartaddr = msgdata[2];
1907                 gcblock2fill = msgdata[3];
1908                 break;
1909         }
1910         
1911         case GCMAPREQUEST: {
1912                 // received a mapping info request msg
1913                 void * dstptr = NULL;
1914                 RuntimeHashget(gcpointertbl, msgdata[1], &dstptr);
1915                 if(NULL == dstptr) {
1916                         // no such pointer in this core, something is wrong
1917 #ifdef DEBUG
1918                         BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1919                         BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1920 #endif
1921                         BAMBOO_EXIT(0xb007);
1922                 } else {
1923                         // send back the mapping info
1924                         if(isMsgSending) {
1925                                 cache_msg_3(msgdata[2], GCMAPINFO, msgdata[1], (int)dstptr);
1926                         } else {
1927                                 send_msg_3(msgdata[2], GCMAPINFO, msgdata[1], (int)dstptr);
1928                         }
1929                 }
1930                 break;
1931         }
1932
1933         case GCMAPINFO: {
1934                 // received a mapping info response msg
1935                 if(msgdata[1] != gcobj2map) {
1936                         // obj not matched, something is wrong
1937 #ifdef DEBUG
1938                         BAMBOO_DEBUGPRINT_REG(gcobj2map);
1939                         BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1940 #endif
1941                         BAMBOO_EXIT(0xb008);
1942                 } else {
1943                         gcmappedobj = msgdata[2];
1944                         RuntimeHashadd_I(gcpointertbl, gcobj2map, gcmappedobj);
1945                 }
1946                 gcismapped = true;
1947                 break;
1948         }
1949
1950         case GCLOBJREQUEST: {
1951                 // received a large objs info request msg
1952                 transferMarkResults_I();
1953                 break;
1954         }
1955
1956         case GCLOBJINFO: {
1957                 // received a large objs info response msg
1958                 numconfirm--;
1959
1960                 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1961 #ifndef TILERA
1962                         BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1963 #endif
1964                         BAMBOO_EXIT(0xb009);
1965                 } 
1966                 // store the mark result info 
1967                 int cnum = msgdata[2];
1968                 gcloads[cnum] = msgdata[3];
1969                 if(gcheaptop < msgdata[4]) {
1970                         gcheaptop = msgdata[4];
1971                 }
1972                 // large obj info here
1973           for(int k = 5; k < msgdata[1];) {
1974                         gc_lobjenqueue_I(msgdata[k++], msgdata[k++], cnum);
1975                         gcnumlobjs++;
1976                 } // for(int k = 5; k < msgdata[1];)
1977                 break;
1978         }
1979         
1980         case GCLOBJMAPPING: {
1981                 // received a large obj mapping info msg
1982                 RuntimeHashadd_I(gcpointertbl, msgdata[1], msgdata[2]);
1983                 break;
1984         }
1985
1986 #endif
1987
1988         default:
1989                 break;
1990         }
1991         for(msgdataindex--; msgdataindex > 0; --msgdataindex) {
1992                 msgdata[msgdataindex] = -1;
1993         }
1994         msgtype = -1;
1995         msglength = 30;
1996 #ifdef DEBUG
1997 #ifndef TILERA
1998         BAMBOO_DEBUGPRINT(0xe88d);
1999 #endif
2000 #endif
2001
2002         if(BAMBOO_MSG_AVAIL() != 0) {
2003                 goto msg;
2004         }
2005 #ifdef PROFILE
2006 /*if(isInterrupt) {
2007                 profileTaskEnd();
2008         }*/
2009 #endif
2010         return (int)type;
2011 } else {
2012         // not a whole msg
2013 #ifdef DEBUG
2014 #ifndef TILERA
2015         BAMBOO_DEBUGPRINT(0xe88e);
2016 #endif
2017 #endif
2018 #ifdef PROFILE
2019 /*  if(isInterrupt) {
2020                   profileTaskEnd();
2021                 }*/
2022 #endif
2023     return -2;
2024   }
2025 }
2026
2027 int enqueuetasks(struct parameterwrapper *parameter, 
2028                              struct parameterwrapper *prevptr, 
2029                                                                  struct ___Object___ *ptr, 
2030                                                                  int * enterflags, 
2031                                                                  int numenterflags) {
2032   void * taskpointerarray[MAXTASKPARAMS];
2033   int j;
2034   //int numparams=parameter->task->numParameters;
2035   int numiterators=parameter->task->numTotal-1;
2036   int retval=1;
2037
2038   struct taskdescriptor * task=parameter->task;
2039
2040    //this add the object to parameterwrapper
2041    ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags, 
2042                                    numenterflags, enterflags==NULL);
2043
2044   /* Add enqueued object to parameter vector */
2045   taskpointerarray[parameter->slot]=ptr;
2046
2047   /* Reset iterators */
2048   for(j=0; j<numiterators; j++) {
2049     toiReset(&parameter->iterators[j]);
2050   }
2051
2052   /* Find initial state */
2053   for(j=0; j<numiterators; j++) {
2054 backtrackinit:
2055     if(toiHasNext(&parameter->iterators[j],taskpointerarray OPTARG(failed)))
2056       toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
2057     else if (j>0) {
2058       /* Need to backtrack */
2059       toiReset(&parameter->iterators[j]);
2060       j--;
2061       goto backtrackinit;
2062     } else {
2063       /* Nothing to enqueue */
2064       return retval;
2065     }
2066   }
2067
2068   while(1) {
2069     /* Enqueue current state */
2070     //int launch = 0;
2071     struct taskparamdescriptor *tpd=
2072                         RUNMALLOC(sizeof(struct taskparamdescriptor));
2073     tpd->task=task;
2074     tpd->numParameters=numiterators+1;
2075     tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
2076
2077     for(j=0; j<=numiterators; j++) {
2078                         //store the actual parameters
2079       tpd->parameterArray[j]=taskpointerarray[j]; 
2080     }
2081     /* Enqueue task */
2082     if ((/*!gencontains(failedtasks, tpd)&&*/ 
2083                                         !gencontains(activetasks,tpd))) {
2084                 genputtable(activetasks, tpd, tpd);
2085     } else {
2086       RUNFREE(tpd->parameterArray);
2087       RUNFREE(tpd);
2088     }
2089
2090     /* This loop iterates to the next parameter combination */
2091     if (numiterators==0)
2092       return retval;
2093
2094     for(j=numiterators-1; j<numiterators; j++) {
2095 backtrackinc:
2096       if(toiHasNext(&parameter->iterators[j],taskpointerarray OPTARG(failed)))
2097         toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
2098       else if (j>0) {
2099         /* Need to backtrack */
2100         toiReset(&parameter->iterators[j]);
2101         j--;
2102         goto backtrackinc;
2103       } else {
2104         /* Nothing more to enqueue */
2105         return retval;
2106       }
2107     }
2108   }
2109   return retval;
2110 }
2111
2112 int enqueuetasks_I(struct parameterwrapper *parameter, 
2113                                struct parameterwrapper *prevptr, 
2114                                                                          struct ___Object___ *ptr, 
2115                                                                          int * enterflags, 
2116                                                                          int numenterflags) {
2117   void * taskpointerarray[MAXTASKPARAMS];
2118   int j;
2119   //int numparams=parameter->task->numParameters;
2120   int numiterators=parameter->task->numTotal-1;
2121   int retval=1;
2122   //int addnormal=1;
2123   //int adderror=1;
2124
2125   struct taskdescriptor * task=parameter->task;
2126
2127    //this add the object to parameterwrapper
2128    ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags, 
2129                                      numenterflags, enterflags==NULL);  
2130
2131   /* Add enqueued object to parameter vector */
2132   taskpointerarray[parameter->slot]=ptr;
2133
2134   /* Reset iterators */
2135   for(j=0; j<numiterators; j++) {
2136     toiReset(&parameter->iterators[j]);
2137   }
2138
2139   /* Find initial state */
2140   for(j=0; j<numiterators; j++) {
2141 backtrackinit:
2142     if(toiHasNext(&parameter->iterators[j],taskpointerarray OPTARG(failed)))
2143       toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
2144     else if (j>0) {
2145       /* Need to backtrack */
2146       toiReset(&parameter->iterators[j]);
2147       j--;
2148       goto backtrackinit;
2149     } else {
2150       /* Nothing to enqueue */
2151       return retval;
2152     }
2153   }
2154
2155   while(1) {
2156     /* Enqueue current state */
2157     //int launch = 0;
2158     struct taskparamdescriptor *tpd=
2159                         RUNMALLOC_I(sizeof(struct taskparamdescriptor));
2160     tpd->task=task;
2161     tpd->numParameters=numiterators+1;
2162     tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
2163
2164     for(j=0; j<=numiterators; j++) {
2165                         //store the actual parameters
2166       tpd->parameterArray[j]=taskpointerarray[j]; 
2167     }
2168     /* Enqueue task */
2169     if ((/*!gencontains(failedtasks, tpd)&&*/ 
2170                                         !gencontains(activetasks,tpd))) {
2171                 genputtable_I(activetasks, tpd, tpd);
2172     } else {
2173       RUNFREE(tpd->parameterArray);
2174       RUNFREE(tpd);
2175     }
2176
2177     /* This loop iterates to the next parameter combination */
2178     if (numiterators==0)
2179       return retval;
2180
2181     for(j=numiterators-1; j<numiterators; j++) {
2182 backtrackinc:
2183       if(toiHasNext(&parameter->iterators[j], taskpointerarray OPTARG(failed)))
2184         toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
2185       else if (j>0) {
2186         /* Need to backtrack */
2187         toiReset(&parameter->iterators[j]);
2188         j--;
2189         goto backtrackinc;
2190       } else {
2191         /* Nothing more to enqueue */
2192         return retval;
2193       }
2194     }
2195   }
2196   return retval;
2197 }
2198
2199 #ifdef MULTICORE_GC
2200 #define OFFSET 2
2201 #else
2202 #define OFFSET 0
2203 #endif
2204
2205 int containstag(struct ___Object___ *ptr, 
2206                             struct ___TagDescriptor___ *tag);
2207
2208 #ifndef MULTICORE_GC
2209 void releasewritelock_r(void * lock, void * redirectlock) {
2210   int targetcore = 0;
2211   int reallock = (int)lock;
2212   targetcore = (reallock >> 5) % BAMBOO_TOTALCORE;
2213
2214 #ifdef DEBUG
2215   BAMBOO_DEBUGPRINT(0xe671);
2216   BAMBOO_DEBUGPRINT_REG((int)lock);
2217   BAMBOO_DEBUGPRINT_REG(reallock);
2218   BAMBOO_DEBUGPRINT_REG(targetcore);
2219 #endif
2220
2221   if(targetcore == BAMBOO_NUM_OF_CORE) {
2222         BAMBOO_START_CRITICAL_SECTION_LOCK();
2223 #ifdef DEBUG
2224         BAMBOO_DEBUGPRINT(0xf001);
2225 #endif
2226     // reside on this core
2227     if(!RuntimeHashcontainskey(locktbl, reallock)) {
2228       // no locks for this object, something is wrong
2229       BAMBOO_EXIT(0xa011);
2230     } else {
2231       int rwlock_obj = 0;
2232           struct LockValue * lockvalue = NULL;
2233 #ifdef DEBUG
2234       BAMBOO_DEBUGPRINT(0xe672);
2235 #endif
2236       RuntimeHashget(locktbl, reallock, &rwlock_obj);
2237           lockvalue = (struct LockValue *)rwlock_obj;
2238 #ifdef DEBUG
2239       BAMBOO_DEBUGPRINT_REG(lockvalue->value);
2240 #endif
2241       lockvalue->value++;
2242           lockvalue->redirectlock = (int)redirectlock;
2243 #ifdef DEBUG
2244       BAMBOO_DEBUGPRINT_REG(lockvalue->value);
2245 #endif
2246     }
2247         BAMBOO_CLOSE_CRITICAL_SECTION_LOCK();
2248 #ifdef DEBUG
2249         BAMBOO_DEBUGPRINT(0xf000);
2250 #endif
2251     return;
2252   } else {
2253           // send lock release with redirect info msg
2254           // for 32 bit machine, the size is always 4 words
2255           send_msg_4(targetcore, REDIRECTRELEASE, 1, (int)lock, (int)redirectlock);
2256   }
2257 }
2258 #endif
2259
2260 void executetasks() {
2261   void * taskpointerarray[MAXTASKPARAMS+OFFSET];
2262   int numparams=0;
2263   int numtotal=0;
2264   struct ___Object___ * tmpparam = NULL;
2265   struct parameterdescriptor * pd=NULL;
2266   struct parameterwrapper *pw=NULL;
2267   int j = 0;
2268   int x = 0;
2269   bool islock = true;
2270
2271   struct LockValue locks[MAXTASKPARAMS];
2272   int locklen = 0;
2273   int grount = 0;
2274   int andmask=0;
2275   int checkmask=0;
2276
2277
2278 newtask:
2279   while(hashsize(activetasks)>0) {
2280 #ifdef MULTICORE_GC
2281                 gc(NULL);
2282 #endif
2283 #ifdef DEBUG
2284     BAMBOO_DEBUGPRINT(0xe990);
2285 #endif
2286
2287     /* See if there are any active tasks */
2288     if (hashsize(activetasks)>0) {
2289       int i;
2290 #ifdef PROFILE
2291 #ifdef ACCURATEPROFILE
2292           profileTaskStart("tpd checking");
2293 #endif
2294 #endif
2295           busystatus = true;
2296       currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
2297       genfreekey(activetasks, currtpd);
2298
2299       numparams=currtpd->task->numParameters;
2300       numtotal=currtpd->task->numTotal;
2301
2302           // clear the lockRedirectTbl 
2303                 // (TODO, this table should be empty after all locks are released)
2304           // reset all locks
2305           for(j = 0; j < MAXTASKPARAMS; j++) {
2306                   locks[j].redirectlock = 0;
2307                   locks[j].value = 0;
2308           }
2309           // get all required locks
2310           locklen = 0;
2311           // check which locks are needed
2312           for(i = 0; i < numparams; i++) {
2313                   void * param = currtpd->parameterArray[i];
2314                   int tmplock = 0;
2315                   int j = 0;
2316                   bool insert = true;
2317                   if(((struct ___Object___ *)param)->type == STARTUPTYPE) {
2318                           islock = false;
2319                           taskpointerarray[i+OFFSET]=param;
2320                           goto execute;
2321                   }
2322                   if(((struct ___Object___ *)param)->lock == NULL) {
2323                           tmplock = (int)param;
2324                   } else {
2325                           tmplock = (int)(((struct ___Object___ *)param)->lock);
2326                   }
2327                   // insert into the locks array
2328                   for(j = 0; j < locklen; j++) {
2329                           if(locks[j].value == tmplock) {
2330                                   insert = false;
2331                                   break;
2332                           } else if(locks[j].value > tmplock) {
2333                                   break;
2334                           }
2335                   }
2336                   if(insert) {
2337                           int h = locklen;
2338                           for(; h > j; h--) {
2339                                   locks[h].redirectlock = locks[h-1].redirectlock;
2340                                   locks[h].value = locks[h-1].value;
2341                           }
2342                           locks[j].value = tmplock;
2343                           locks[j].redirectlock = (int)param;
2344                           locklen++;
2345                   }               
2346           } // line 2713: for(i = 0; i < numparams; i++) 
2347           // grab these required locks
2348 #ifdef DEBUG
2349           BAMBOO_DEBUGPRINT(0xe991);
2350 #endif
2351           for(i = 0; i < locklen; i++) {
2352                   int * lock = (int *)(locks[i].redirectlock);
2353                   islock = true;
2354                   // require locks for this parameter if it is not a startup object
2355 #ifdef DEBUG
2356                   BAMBOO_DEBUGPRINT_REG((int)lock);
2357                   BAMBOO_DEBUGPRINT_REG((int)(locks[i].value));
2358 #endif
2359                   getwritelock(lock);
2360                   BAMBOO_START_CRITICAL_SECTION();
2361 #ifdef DEBUG
2362                   BAMBOO_DEBUGPRINT(0xf001);
2363 #endif
2364 #ifdef PROFILE
2365                   //isInterrupt = false;
2366 #endif 
2367                   while(!lockflag) { 
2368                           BAMBOO_WAITING_FOR_LOCK();
2369                   }
2370 #ifndef INTERRUPT
2371                   if(reside) {
2372                           while(BAMBOO_WAITING_FOR_LOCK() != -1) {
2373                           }
2374                   }
2375 #endif
2376                   grount = lockresult;
2377
2378                   lockresult = 0;
2379                   lockobj = 0;
2380                   lock2require = 0;
2381                   lockflag = false;
2382 #ifndef INTERRUPT
2383                   reside = false;
2384 #endif
2385 #ifdef PROFILE
2386                   //isInterrupt = true;
2387 #endif
2388                   BAMBOO_CLOSE_CRITICAL_SECTION();
2389 #ifdef DEBUG
2390                   BAMBOO_DEBUGPRINT(0xf000);
2391 #endif
2392
2393                   if(grount == 0) {
2394                           int j = 0;
2395 #ifdef DEBUG
2396                           BAMBOO_DEBUGPRINT(0xe992);
2397 #endif
2398                           // can not get the lock, try later
2399                           // releas all grabbed locks for previous parameters
2400                           for(j = 0; j < i; ++j) {
2401                                   lock = (int*)(locks[j].redirectlock);
2402                                   releasewritelock(lock);
2403                           }
2404                           genputtable(activetasks, currtpd, currtpd);
2405                           if(hashsize(activetasks) == 1) {
2406                                   // only one task right now, wait a little while before next try
2407                                   int halt = 10000;
2408                                   while(halt--) {
2409                                   }
2410                           }
2411 #ifdef PROFILE
2412 #ifdef ACCURATEPROFILE
2413                           // fail, set the end of the checkTaskInfo
2414                           profileTaskEnd();
2415 #endif
2416 #endif
2417                           goto newtask;
2418                   } // line 2794: if(grount == 0)
2419           } // line 2752:  for(i = 0; i < locklen; i++)
2420
2421 #ifdef DEBUG
2422         BAMBOO_DEBUGPRINT(0xe993);
2423 #endif
2424       /* Make sure that the parameters are still in the queues */
2425       for(i=0; i<numparams; i++) {
2426         void * parameter=currtpd->parameterArray[i];
2427
2428         // flush the object
2429 #ifdef CACHEFLUSH
2430         BAMBOO_CACHE_FLUSH_RANGE((int)parameter, 
2431                         classsize[((struct ___Object___ *)parameter)->type]);
2432 #endif
2433         tmpparam = (struct ___Object___ *)parameter;
2434         pd=currtpd->task->descriptorarray[i];
2435         pw=(struct parameterwrapper *) pd->queue;
2436         /* Check that object is still in queue */
2437         {
2438           if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
2439 #ifdef DEBUG
2440             BAMBOO_DEBUGPRINT(0xe994);
2441 #endif
2442             // release grabbed locks
2443             for(j = 0; j < locklen; ++j) {
2444                 int * lock = (int *)(locks[j].redirectlock);
2445                 releasewritelock(lock);
2446             }
2447             RUNFREE(currtpd->parameterArray);
2448             RUNFREE(currtpd);
2449                         currtpd = NULL;
2450             goto newtask;
2451           }
2452         } // line2865
2453         /* Check if the object's flags still meets requirements */
2454         {
2455           int tmpi = 0;
2456           bool ismet = false;
2457           for(tmpi = 0; tmpi < pw->numberofterms; ++tmpi) {
2458             andmask=pw->intarray[tmpi*2];
2459             checkmask=pw->intarray[tmpi*2+1];
2460             if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
2461               ismet = true;
2462               break;
2463             }
2464           }
2465           if (!ismet) {
2466             // flags are never suitable
2467             // remove this obj from the queue
2468             int next;
2469             int UNUSED, UNUSED2;
2470             int * enterflags;
2471 #ifdef DEBUG
2472             BAMBOO_DEBUGPRINT(0xe995);
2473 #endif
2474             ObjectHashget(pw->objectset, (int) parameter, (int *) &next, 
2475                                                   (int *) &enterflags, &UNUSED, &UNUSED2);
2476             ObjectHashremove(pw->objectset, (int)parameter);
2477             if (enterflags!=NULL)
2478               RUNFREE(enterflags);
2479             // release grabbed locks
2480             for(j = 0; j < locklen; ++j) {
2481                  int * lock = (int *)(locks[j].redirectlock);
2482                 releasewritelock(lock);
2483             }
2484             RUNFREE(currtpd->parameterArray);
2485             RUNFREE(currtpd);
2486                         currtpd = NULL;
2487 #ifdef PROFILE
2488 #ifdef ACCURATEPROFILE
2489             // fail, set the end of the checkTaskInfo
2490                 profileTaskEnd();
2491 #endif
2492 #endif
2493             goto newtask;
2494           } // line 2878: if (!ismet)
2495         } // line 2867
2496 parameterpresent:
2497         ;
2498         /* Check that object still has necessary tags */
2499         for(j=0; j<pd->numbertags; j++) {
2500           int slotid=pd->tagarray[2*j]+numparams;
2501           struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
2502           if (!containstag(parameter, tagd)) {
2503 #ifdef DEBUG
2504             BAMBOO_DEBUGPRINT(0xe996);
2505 #endif
2506                 {
2507                 // release grabbed locks
2508                 int tmpj = 0;
2509             for(tmpj = 0; tmpj < locklen; ++tmpj) {
2510                  int * lock = (int *)(locks[tmpj].redirectlock);
2511                 releasewritelock(lock);
2512             }
2513                 }
2514             RUNFREE(currtpd->parameterArray);
2515             RUNFREE(currtpd);
2516                         currtpd = NULL;
2517             goto newtask;
2518           } // line2911: if (!containstag(parameter, tagd))
2519         } // line 2808: for(j=0; j<pd->numbertags; j++)
2520
2521         taskpointerarray[i+OFFSET]=parameter;
2522       } // line 2824: for(i=0; i<numparams; i++)
2523       /* Copy the tags */
2524       for(; i<numtotal; i++) {
2525         taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
2526       }
2527
2528       {
2529 execute:
2530           /* Actually call task */
2531 #ifdef MULTICORE_GC
2532           ((int *)taskpointerarray)[0]=currtpd->numParameters;
2533           taskpointerarray[1]=NULL;
2534 #endif
2535 #ifdef PROFILE
2536 #ifdef ACCURATEPROFILE
2537           // check finish, set the end of the checkTaskInfo
2538           profileTaskEnd();
2539 #endif
2540           profileTaskStart(currtpd->task->name);
2541 #endif
2542
2543 #ifdef DEBUG
2544                 BAMBOO_DEBUGPRINT(0xe997);
2545 #endif
2546                 ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
2547 #ifdef PROFILE
2548 #ifdef ACCURATEPROFILE
2549           // task finish, set the end of the checkTaskInfo
2550           profileTaskEnd();
2551           // new a PostTaskInfo for the post-task execution
2552           profileTaskStart("post task execution");
2553 #endif
2554 #endif
2555 #ifdef DEBUG
2556           BAMBOO_DEBUGPRINT(0xe998);
2557           BAMBOO_DEBUGPRINT_REG(islock);
2558 #endif
2559
2560           if(islock) {
2561 #ifdef DEBUG
2562                   BAMBOO_DEBUGPRINT(0xe999);
2563 #endif
2564             for(i = 0; i < locklen; ++i) {
2565                                 void * ptr = (void *)(locks[i].redirectlock);
2566               int * lock = (int *)(locks[i].value);
2567 #ifdef DEBUG
2568                   BAMBOO_DEBUGPRINT_REG((int)ptr);
2569                   BAMBOO_DEBUGPRINT_REG((int)lock);
2570 #endif
2571 #ifndef MULTICORE_GC
2572                   if(RuntimeHashcontainskey(lockRedirectTbl, (int)lock)) {
2573                           int redirectlock;
2574                           RuntimeHashget(lockRedirectTbl, (int)lock, &redirectlock);
2575                           RuntimeHashremovekey(lockRedirectTbl, (int)lock);
2576                           releasewritelock_r(lock, (int *)redirectlock);
2577                   } else {
2578 #else
2579                                 {
2580 #endif
2581                 releasewritelock(ptr);
2582                   }
2583             }
2584           } // line 3015: if(islock)
2585
2586 #ifdef PROFILE
2587           // post task execution finish, set the end of the postTaskInfo
2588           profileTaskEnd();
2589 #endif
2590
2591           // Free up task parameter descriptor
2592           RUNFREE(currtpd->parameterArray);
2593           RUNFREE(currtpd);
2594                 currtpd = NULL;
2595 #ifdef DEBUG
2596           BAMBOO_DEBUGPRINT(0xe99a);
2597 #endif
2598       } //  
2599     } //  if (hashsize(activetasks)>0)  
2600   } //  while(hashsize(activetasks)>0)
2601 #ifdef DEBUG
2602   BAMBOO_DEBUGPRINT(0xe99b);
2603 #endif
2604 }
2605
2606 /* This function processes an objects tags */
2607 void processtags(struct parameterdescriptor *pd, 
2608                              int index, 
2609                                                                  struct parameterwrapper *parameter, 
2610                                                                  int * iteratorcount, 
2611                                                                  int *statusarray, 
2612                                                                  int numparams) {
2613   int i;
2614
2615   for(i=0; i<pd->numbertags; i++) {
2616     int slotid=pd->tagarray[2*i];
2617     int tagid=pd->tagarray[2*i+1];
2618
2619     if (statusarray[slotid+numparams]==0) {
2620       parameter->iterators[*iteratorcount].istag=1;
2621       parameter->iterators[*iteratorcount].tagid=tagid;
2622       parameter->iterators[*iteratorcount].slot=slotid+numparams;
2623       parameter->iterators[*iteratorcount].tagobjectslot=index;
2624       statusarray[slotid+numparams]=1;
2625       (*iteratorcount)++;
2626     }
2627   }
2628 }
2629
2630
2631 void processobject(struct parameterwrapper *parameter, 
2632                                int index, 
2633                                                                          struct parameterdescriptor *pd, 
2634                                                                          int *iteratorcount, 
2635                                                                          int * statusarray, 
2636                                                                          int numparams) {
2637   int i;
2638   int tagcount=0;
2639   struct ObjectHash * objectset=
2640                 ((struct parameterwrapper *)pd->queue)->objectset;
2641
2642   parameter->iterators[*iteratorcount].istag=0;
2643   parameter->iterators[*iteratorcount].slot=index;
2644   parameter->iterators[*iteratorcount].objectset=objectset;
2645   statusarray[index]=1;
2646
2647   for(i=0; i<pd->numbertags; i++) {
2648     int slotid=pd->tagarray[2*i];
2649     //int tagid=pd->tagarray[2*i+1];
2650     if (statusarray[slotid+numparams]!=0) {
2651       /* This tag has already been enqueued, use it to narrow search */
2652       parameter->iterators[*iteratorcount].tagbindings[tagcount]=
2653                                 slotid+numparams;
2654       tagcount++;
2655     }
2656   }
2657   parameter->iterators[*iteratorcount].numtags=tagcount;
2658
2659   (*iteratorcount)++;
2660 }
2661
2662 /* This function builds the iterators for a task & parameter */
2663
2664 void builditerators(struct taskdescriptor * task, 
2665                                 int index, 
2666                                                                                 struct parameterwrapper * parameter) {
2667   int statusarray[MAXTASKPARAMS];
2668   int i;
2669   int numparams=task->numParameters;
2670   int iteratorcount=0;
2671   for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
2672
2673   statusarray[index]=1; /* Initial parameter */
2674   /* Process tags for initial iterator */
2675
2676   processtags(task->descriptorarray[index], index, parameter, 
2677                                 &iteratorcount, statusarray, numparams);
2678
2679   while(1) {
2680 loopstart:
2681     /* Check for objects with existing tags */
2682     for(i=0; i<numparams; i++) {
2683       if (statusarray[i]==0) {
2684         struct parameterdescriptor *pd=task->descriptorarray[i];
2685         int j;
2686         for(j=0; j<pd->numbertags; j++) {
2687           int slotid=pd->tagarray[2*j];
2688           if(statusarray[slotid+numparams]!=0) {
2689             processobject(parameter, i, pd, &iteratorcount, statusarray, 
2690                                                   numparams);
2691             processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2692             goto loopstart;
2693           }
2694         }
2695       }
2696     }
2697
2698     /* Next do objects w/ unbound tags*/
2699
2700     for(i=0; i<numparams; i++) {
2701       if (statusarray[i]==0) {
2702         struct parameterdescriptor *pd=task->descriptorarray[i];
2703         if (pd->numbertags>0) {
2704           processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2705           processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2706           goto loopstart;
2707         }
2708       }
2709     }
2710
2711     /* Nothing with a tag enqueued */
2712
2713     for(i=0; i<numparams; i++) {
2714       if (statusarray[i]==0) {
2715         struct parameterdescriptor *pd=task->descriptorarray[i];
2716         processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2717         processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2718         goto loopstart;
2719       }
2720     }
2721
2722     /* Nothing left */
2723     return;
2724   }
2725 }
2726
2727 void printdebug() {
2728   int i;
2729   int j;
2730   if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
2731     return;
2732   }
2733   for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
2734     struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
2735 #ifndef RAW 
2736         printf("%s\n", task->name);
2737 #endif
2738     for(j=0; j<task->numParameters; j++) {
2739       struct parameterdescriptor *param=task->descriptorarray[j];
2740       struct parameterwrapper *parameter=param->queue;
2741       struct ObjectHash * set=parameter->objectset;
2742       struct ObjectIterator objit;
2743 #ifndef RAW
2744           printf("  Parameter %d\n", j);
2745 #endif
2746       ObjectHashiterator(set, &objit);
2747       while(ObjhasNext(&objit)) {
2748         struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
2749         struct ___Object___ * tagptr=obj->___tags___;
2750         int nonfailed=Objdata4(&objit);
2751         int numflags=Objdata3(&objit);
2752         int flags=Objdata2(&objit);
2753         Objnext(&objit);
2754 #ifndef RAW
2755         printf("    Contains %lx\n", obj);
2756         printf("      flag=%d\n", obj->flag);
2757 #endif
2758         if (tagptr==NULL) {
2759         } else if (tagptr->type==TAGTYPE) {
2760 #ifndef RAW
2761           printf("      tag=%lx\n",tagptr);
2762 #else
2763           ;
2764 #endif
2765         } else {
2766           int tagindex=0;
2767           struct ArrayObject *ao=(struct ArrayObject *)tagptr;
2768           for(; tagindex<ao->___cachedCode___; tagindex++) {
2769 #ifndef RAW
2770                   printf("      tag=%lx\n",ARRAYGET(ao, struct ___TagDescriptor___*, 
2771                                                  tagindex));
2772 #else
2773                   ;
2774 #endif
2775           }
2776         }
2777       }
2778     }
2779   }
2780 }
2781
2782
2783 /* This function processes the task information to create queues for
2784    each parameter type. */
2785
2786 void processtasks() {
2787   int i;
2788   if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
2789     return;
2790   }
2791   for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
2792     struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
2793     int j;
2794
2795     /* Build objectsets */
2796     for(j=0; j<task->numParameters; j++) {
2797       struct parameterdescriptor *param=task->descriptorarray[j];
2798       struct parameterwrapper *parameter=param->queue;
2799       parameter->objectset=allocateObjectHash(10);
2800       parameter->task=task;
2801     }
2802
2803     /* Build iterators for parameters */
2804     for(j=0; j<task->numParameters; j++) {
2805       struct parameterdescriptor *param=task->descriptorarray[j];
2806       struct parameterwrapper *parameter=param->queue;
2807       builditerators(task, j, parameter);
2808     }
2809   }
2810 }
2811
2812 void toiReset(struct tagobjectiterator * it) {
2813   if (it->istag) {
2814     it->tagobjindex=0;
2815   } else if (it->numtags>0) {
2816     it->tagobjindex=0;
2817   } else {
2818     ObjectHashiterator(it->objectset, &it->it);
2819   }
2820 }
2821
2822 int toiHasNext(struct tagobjectiterator *it, 
2823                            void ** objectarray OPTARG(int * failed)) {
2824   if (it->istag) {
2825     /* Iterate tag */
2826     /* Get object with tags */
2827     struct ___Object___ *obj=objectarray[it->tagobjectslot];
2828     struct ___Object___ *tagptr=obj->___tags___;
2829     if (tagptr->type==TAGTYPE) {
2830       if ((it->tagobjindex==0)&& /* First object */
2831           (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
2832         return 1;
2833       else
2834         return 0;
2835     } else {
2836       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
2837       int tagindex=it->tagobjindex;
2838       for(; tagindex<ao->___cachedCode___; tagindex++) {
2839         struct ___TagDescriptor___ *td=
2840                 ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
2841         if (td->flag==it->tagid) {
2842           it->tagobjindex=tagindex; /* Found right type of tag */
2843           return 1;
2844         }
2845       }
2846       return 0;
2847     }
2848   } else if (it->numtags>0) {
2849     /* Use tags to locate appropriate objects */
2850     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
2851     struct ___Object___ *objptr=tag->flagptr;
2852     int i;
2853     if (objptr->type!=OBJECTARRAYTYPE) {
2854       if (it->tagobjindex>0)
2855         return 0;
2856       if (!ObjectHashcontainskey(it->objectset, (int) objptr))
2857         return 0;
2858       for(i=1; i<it->numtags; i++) {
2859         struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
2860         if (!containstag(objptr,tag2))
2861           return 0;
2862       }
2863       return 1;
2864     } else {
2865       struct ArrayObject *ao=(struct ArrayObject *) objptr;
2866       int tagindex;
2867       int i;
2868       for(tagindex=it->tagobjindex;tagindex<ao->___cachedCode___;tagindex++) {
2869         struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
2870         if (!ObjectHashcontainskey(it->objectset, (int) objptr))
2871           continue;
2872         for(i=1; i<it->numtags; i++) {
2873           struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
2874           if (!containstag(objptr,tag2))
2875             goto nexttag;
2876         }
2877         it->tagobjindex=tagindex;
2878         return 1;
2879 nexttag:
2880         ;
2881       }
2882       it->tagobjindex=tagindex;
2883       return 0;
2884     }
2885   } else {
2886     return ObjhasNext(&it->it);
2887   }
2888 }
2889
2890 int containstag(struct ___Object___ *ptr, 
2891                             struct ___TagDescriptor___ *tag) {
2892   int j;
2893   struct ___Object___ * objptr=tag->flagptr;
2894   if (objptr->type==OBJECTARRAYTYPE) {
2895     struct ArrayObject *ao=(struct ArrayObject *)objptr;
2896     for(j=0; j<ao->___cachedCode___; j++) {
2897       if (ptr==ARRAYGET(ao, struct ___Object___*, j))
2898         return 1;
2899     }
2900     return 0;
2901   } else
2902     return objptr==ptr;
2903 }
2904
2905 void toiNext(struct tagobjectiterator *it, 
2906                          void ** objectarray OPTARG(int * failed)) {
2907   /* hasNext has all of the intelligence */
2908   if(it->istag) {
2909     /* Iterate tag */
2910     /* Get object with tags */
2911     struct ___Object___ *obj=objectarray[it->tagobjectslot];
2912     struct ___Object___ *tagptr=obj->___tags___;
2913     if (tagptr->type==TAGTYPE) {
2914       it->tagobjindex++;
2915       objectarray[it->slot]=tagptr;
2916     } else {
2917       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
2918       objectarray[it->slot]=
2919                                 ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
2920     }
2921   } else if (it->numtags>0) {
2922     /* Use tags to locate appropriate objects */
2923     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
2924     struct ___Object___ *objptr=tag->flagptr;
2925     if (objptr->type!=OBJECTARRAYTYPE) {
2926       it->tagobjindex++;
2927       objectarray[it->slot]=objptr;
2928     } else {
2929       struct ArrayObject *ao=(struct ArrayObject *) objptr;
2930       objectarray[it->slot]=
2931                                 ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
2932     }
2933   } else {
2934     /* Iterate object */
2935     objectarray[it->slot]=(void *)Objkey(&it->it);
2936     Objnext(&it->it);
2937   }
2938 }
2939 #endif