bug fix in multicore gc
[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
75 #ifdef MULTICORE_GC
76         gcflag = false;
77         gcprocessing = false;
78         gcphase = FINISHPHASE;
79         gccurr_heaptop = 0;
80         gcself_numsendobjs = 0;
81         gcself_numreceiveobjs = 0;
82         gcmarkedptrbound = 0;
83         gcpointertbl = allocateRuntimeHash(20);
84         gcobj2map = 0;
85         gcmappedobj = 0;
86         gcismapped = false;
87         gcnumlobjs = 0;
88         gcheaptop = 0;
89         gctopcore = 0;
90         gcheapdirection = 1;
91         gcmovestartaddr = 0;
92         gctomove = false;
93         //gchead = gctail = gctail2 = NULL;
94         //gclobjhead = gclobjtail = gclobjtail2 = NULL;
95         //gcheadindex=gctailindex=gctailindex2 = 0;
96         //gclobjheadindex=gclobjtailindex=gclobjtailindex2 = 0;
97         gcmovepending = 0;
98         gcblock2fill = 0;
99 #else
100         // create the lock table, lockresult table and obj queue
101   locktable.size = 20;
102   locktable.bucket = 
103                 (struct RuntimeNode **) RUNMALLOC_I(sizeof(struct RuntimeNode *)*20);
104   /* Set allocation blocks*/
105   locktable.listhead=NULL;
106   locktable.listtail=NULL;
107   /*Set data counts*/
108   locktable.numelements = 0;
109   lockobj = 0;
110   lock2require = 0;
111   lockresult = 0;
112   lockflag = false;
113         lockRedirectTbl = allocateRuntimeHash(20);
114   objRedirectLockTbl = allocateRuntimeHash(20);
115 #endif
116 #ifndef INTERRUPT
117   reside = false;
118 #endif  
119   objqueue.head = NULL;
120   objqueue.tail = 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         RUNFREE(currtpd);
144 }
145
146 inline __attribute__((always_inline))
147 bool checkObjQueue() {
148         bool rflag = false;
149         struct transObjInfo * objInfo = NULL;
150         int grount = 0;
151
152 #ifdef PROFILE
153 #ifdef ACCURATEPROFILE
154         bool isChecking = false;
155         if(!isEmpty(&objqueue)) {
156                 profileTaskStart("objqueue checking");
157                 isChecking = true;
158         } // if(!isEmpty(&objqueue))
159 #endif
160 #endif
161
162         while(!isEmpty(&objqueue)) {
163                 void * obj = NULL;
164                 BAMBOO_START_CRITICAL_SECTION_OBJ_QUEUE();
165 #ifdef DEBUG
166                 BAMBOO_DEBUGPRINT(0xf001);
167 #endif
168 #ifdef PROFILE
169                 //isInterrupt = false;
170 #endif 
171 #ifdef DEBUG
172                 BAMBOO_DEBUGPRINT(0xeee1);
173 #endif
174                 rflag = true;
175                 objInfo = (struct transObjInfo *)getItem(&objqueue); 
176                 obj = objInfo->objptr;
177 #ifdef DEBUG
178                 BAMBOO_DEBUGPRINT_REG((int)obj);
179 #endif
180                 // grab lock and flush the obj
181                 grount = 0;
182                 getwritelock_I(obj);
183                 while(!lockflag) {
184                         BAMBOO_WAITING_FOR_LOCK();
185                 } // while(!lockflag)
186                 grount = lockresult;
187 #ifdef DEBUG
188                 BAMBOO_DEBUGPRINT_REG(grount);
189 #endif
190
191                 lockresult = 0;
192                 lockobj = 0;
193                 lock2require = 0;
194                 lockflag = false;
195 #ifndef INTERRUPT
196                 reside = false;
197 #endif
198
199                 if(grount == 1) {
200                         int k = 0;
201                         // flush the object
202 #ifdef CACHEFLUSH
203                         BAMBOO_CACHE_FLUSH_RANGE((int)obj,sizeof(int));
204                         BAMBOO_CACHE_FLUSH_RANGE((int)obj, 
205                                         classsize[((struct ___Object___ *)obj)->type]);
206 #endif
207                         // enqueue the object
208                         for(k = 0; k < objInfo->length; ++k) {
209                                 int taskindex = objInfo->queues[2 * k];
210                                 int paramindex = objInfo->queues[2 * k + 1];
211                                 struct parameterwrapper ** queues = 
212                                         &(paramqueues[BAMBOO_NUM_OF_CORE][taskindex][paramindex]);
213 #ifdef DEBUG
214                                 BAMBOO_DEBUGPRINT_REG(taskindex);
215                                 BAMBOO_DEBUGPRINT_REG(paramindex);
216                                 struct ___Object___ * tmpptr = (struct ___Object___ *)obj;
217                                 tprintf("Process %x(%d): receive obj %x(%lld), ptrflag %x\n", 
218                                                                 BAMBOO_NUM_OF_CORE, BAMBOO_NUM_OF_CORE, (int)obj, 
219                                                                 (long)obj, tmpptr->flag);
220 #endif
221                                 enqueueObject_I(obj, queues, 1);
222 #ifdef DEBUG                             
223                                 BAMBOO_DEBUGPRINT_REG(hashsize(activetasks));
224 #endif
225                         } // for(k = 0; k < objInfo->length; ++k)
226                         releasewritelock_I(obj);
227                         RUNFREE(objInfo->queues);
228                         RUNFREE(objInfo);
229                 } else {
230                         // can not get lock
231                         // put it at the end of the queue if no update version in the queue
232                         struct QueueItem * qitem = getHead(&objqueue);
233                         struct QueueItem * prev = NULL;
234                         while(qitem != NULL) {
235                                 struct transObjInfo * tmpinfo = 
236                                         (struct transObjInfo *)(qitem->objectptr);
237                                 if(tmpinfo->objptr == obj) {
238                                         // the same object in the queue, which should be enqueued
239                                         // recently. Current one is outdate, do not re-enqueue it
240                                         RUNFREE(objInfo->queues);
241                                         RUNFREE(objInfo);
242                                         goto objqueuebreak;
243                                 } else {
244                                         prev = qitem;
245                                 } // if(tmpinfo->objptr == obj)
246                                 qitem = getNextQueueItem(prev);
247                         } // while(qitem != NULL)
248                         // try to execute active tasks already enqueued first
249                         addNewItem_I(&objqueue, objInfo);
250 #ifdef PROFILE
251                         //isInterrupt = true;
252 #endif
253 objqueuebreak:
254                         BAMBOO_CLOSE_CRITICAL_SECTION_OBJ_QUEUE();
255 #ifdef DEBUG
256                         BAMBOO_DEBUGPRINT(0xf000);
257 #endif
258                         break;
259                 } // if(grount == 1)
260                 BAMBOO_CLOSE_CRITICAL_SECTION_OBJ_QUEUE();
261 #ifdef DEBUG
262                 BAMBOO_DEBUGPRINT(0xf000);
263 #endif
264         } // while(!isEmpty(&objqueue))
265
266 #ifdef PROFILE
267 #ifdef ACCURATEPROFILE
268         if(isChecking) {
269                 profileTaskEnd();
270         } // if(isChecking)
271 #endif
272 #endif
273
274 #ifdef DEBUG
275         BAMBOO_DEBUGPRINT(0xee02);
276 #endif
277         return rflag;
278 }
279
280 inline __attribute__((always_inline))
281 void checkCoreStatus() {
282         bool allStall = false;
283         int i = 0;
284         int sumsendobj = 0;
285         if((!waitconfirm) || 
286                         (waitconfirm && (numconfirm == 0))) {
287 #ifdef DEBUG
288                 BAMBOO_DEBUGPRINT(0xee04);
289                 BAMBOO_DEBUGPRINT_REG(waitconfirm);
290 #endif
291                 BAMBOO_START_CRITICAL_SECTION_STATUS();
292 #ifdef DEBUG
293                 BAMBOO_DEBUGPRINT(0xf001);
294 #endif
295                 corestatus[BAMBOO_NUM_OF_CORE] = 0;
296                 numsendobjs[BAMBOO_NUM_OF_CORE] = self_numsendobjs;
297                 numreceiveobjs[BAMBOO_NUM_OF_CORE] = self_numreceiveobjs;
298                 // check the status of all cores
299                 allStall = true;
300 #ifdef DEBUG
301                 BAMBOO_DEBUGPRINT_REG(NUMCORES);
302 #endif
303                 for(i = 0; i < NUMCORES; ++i) {
304 #ifdef DEBUG
305                         BAMBOO_DEBUGPRINT(0xe000 + corestatus[i]);
306 #endif
307                         if(corestatus[i] != 0) {
308                                 allStall = false;
309                                 break;
310                         }
311                 } // for(i = 0; i < NUMCORES; ++i)
312                 if(allStall) {
313                         // check if the sum of send objs and receive obj are the same
314                         // yes->check if the info is the latest; no->go on executing
315                         sumsendobj = 0;
316                         for(i = 0; i < NUMCORES; ++i) {
317                                 sumsendobj += numsendobjs[i];
318 #ifdef DEBUG
319                                 BAMBOO_DEBUGPRINT(0xf000 + numsendobjs[i]);
320 #endif
321                         } // for(i = 0; i < NUMCORES; ++i)      
322                         for(i = 0; i < NUMCORES; ++i) {
323                                 sumsendobj -= numreceiveobjs[i];
324 #ifdef DEBUG
325                                 BAMBOO_DEBUGPRINT(0xf000 + numreceiveobjs[i]);
326 #endif
327                         } // for(i = 0; i < NUMCORES; ++i)
328                         if(0 == sumsendobj) {
329                                 if(!waitconfirm) {
330                                         // the first time found all cores stall
331                                         // send out status confirm msg to all other cores
332                                         // reset the corestatus array too
333 #ifdef DEBUG
334                                         BAMBOO_DEBUGPRINT(0xee05);
335 #endif
336                                         corestatus[BAMBOO_NUM_OF_CORE] = 1;
337                                         for(i = 1; i < NUMCORES; ++i) { 
338                                                 corestatus[i] = 1;
339                                                 // send status confirm msg to core i
340                                                 send_msg_1(i, STATUSCONFIRM);
341                                         } // for(i = 1; i < NUMCORES; ++i)
342                                         waitconfirm = true;
343                                         numconfirm = NUMCORES - 1;
344                                 } else {
345                                         // all the core status info are the latest
346                                         // terminate; for profiling mode, send request to all
347                                         // other cores to pour out profiling data
348 #ifdef DEBUG
349                                         BAMBOO_DEBUGPRINT(0xee06);
350 #endif                                            
351                          
352 #ifdef USEIO
353                                         totalexetime = BAMBOO_GET_EXE_TIME();
354 #else
355                                         BAMBOO_DEBUGPRINT(BAMBOO_GET_EXE_TIME());
356                                         BAMBOO_DEBUGPRINT_REG(total_num_t6); // TODO for test
357                                         BAMBOO_DEBUGPRINT(0xbbbbbbbb);
358 #endif
359                                         // profile mode, send msgs to other cores to request pouring
360                                         // out progiling data
361 #ifdef PROFILE
362                                         BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
363 #ifdef DEBUG
364                                         BAMBOO_DEBUGPRINT(0xf000);
365 #endif
366                                         for(i = 1; i < NUMCORES; ++i) {
367                                                 // send profile request msg to core i
368                                                 send_msg_2(i, PROFILEOUTPUT, totalexetime);
369                                         } // for(i = 1; i < NUMCORES; ++i)
370                                         // pour profiling data on startup core
371                                         outputProfileData();
372                                         while(true) {
373                                                 BAMBOO_START_CRITICAL_SECTION_STATUS();
374 #ifdef DEBUG
375                                                 BAMBOO_DEBUGPRINT(0xf001);
376 #endif
377                                                 profilestatus[BAMBOO_NUM_OF_CORE] = 0;
378                                                 // check the status of all cores
379                                                 allStall = true;
380 #ifdef DEBUG
381                                                 BAMBOO_DEBUGPRINT_REG(NUMCORES);
382 #endif  
383                                                 for(i = 0; i < NUMCORES; ++i) {
384 #ifdef DEBUG
385                                                         BAMBOO_DEBUGPRINT(0xe000 + profilestatus[i]);
386 #endif
387                                                         if(profilestatus[i] != 0) {
388                                                                 allStall = false;
389                                                                 break;
390                                                         }
391                                                 }  // for(i = 0; i < NUMCORES; ++i)
392                                                 if(!allStall) {
393                                                         int halt = 100;
394                                                         BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
395 #ifdef DEBUG
396                                                         BAMBOO_DEBUGPRINT(0xf000);
397 #endif
398                                                         while(halt--) {
399                                                         }
400                                                 } else {
401                                                         break;
402                                                 } // if(!allStall)
403                                         } // while(true)
404 #endif
405                                         disruntimedata();
406                                         terminate(); // All done.
407                                 } // if(!waitconfirm)
408                         } else {
409                                 // still some objects on the fly on the network
410                                 // reset the waitconfirm and numconfirm
411 #ifdef DEBUG
412                                         BAMBOO_DEBUGPRINT(0xee07);
413 #endif
414                                 waitconfirm = false;
415                                 numconfirm = 0;
416                         } //  if(0 == sumsendobj)
417                 } else {
418                         // not all cores are stall, keep on waiting
419 #ifdef DEBUG
420                         BAMBOO_DEBUGPRINT(0xee08);
421 #endif
422                         waitconfirm = false;
423                         numconfirm = 0;
424                 } //  if(allStall)
425                 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
426 #ifdef DEBUG
427                 BAMBOO_DEBUGPRINT(0xf000);
428 #endif
429         } // if((!waitconfirm) ||
430 }
431
432 // main function for each core
433 inline void run(void * arg) {
434   int i = 0;
435   int argc = 1;
436   char ** argv = NULL;
437   bool sendStall = false;
438   bool isfirst = true;
439   bool tocontinue = false;
440
441   corenum = BAMBOO_GET_NUM_OF_CORE();
442 #ifdef DEBUG
443   BAMBOO_DEBUGPRINT(0xeeee);
444   BAMBOO_DEBUGPRINT_REG(corenum);
445   BAMBOO_DEBUGPRINT(STARTUPCORE);
446 #endif
447
448         // initialize runtime data structures
449         initruntimedata();
450
451   // other architecture related initialization
452   initialization();
453   initCommunication();
454
455   initializeexithandler();
456
457   // main process of the execution module
458   if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
459         // non-executing cores, only processing communications
460     activetasks = NULL;
461 /*#ifdef PROFILE
462         BAMBOO_DEBUGPRINT(0xee01);
463         BAMBOO_DEBUGPRINT_REG(taskInfoIndex);
464         BAMBOO_DEBUGPRINT_REG(taskInfoOverflow);
465                 profileTaskStart("msg handling");
466         }
467  #endif*/
468 #ifdef PROFILE
469     //isInterrupt = false;
470 #endif
471                 fakeExecution();
472   } else {
473           /* Create queue of active tasks */
474           activetasks=
475                         genallocatehashtable((unsigned int(*) (void *)) &hashCodetpd,
476                            (int(*) (void *,void *)) &comparetpd);
477           
478           /* Process task information */
479           processtasks();
480           
481           if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
482                   /* Create startup object */
483                   createstartupobject(argc, argv);
484           }
485
486 #ifdef DEBUG
487           BAMBOO_DEBUGPRINT(0xee00);
488 #endif
489
490           while(true) {
491 #ifdef MULTICORE_GC
492                         // check if need to do GC
493                         gc(NULL);
494 #endif
495
496                   // check if there are new active tasks can be executed
497                   executetasks();
498                         if(busystatus) {
499                                 sendStall = false;
500                         }
501
502 #ifndef INTERRUPT
503                   while(receiveObject() != -1) {
504                   }
505 #endif  
506
507 #ifdef DEBUG
508                   BAMBOO_DEBUGPRINT(0xee01);
509 #endif  
510                   
511                   // check if there are some pending objects, 
512                         // if yes, enqueue them and executetasks again
513                   tocontinue = checkObjQueue();
514
515                   if(!tocontinue) {
516                           // check if stop
517                           if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
518                                   if(isfirst) {
519 #ifdef DEBUG
520                                           BAMBOO_DEBUGPRINT(0xee03);
521 #endif
522                                           isfirst = false;
523                                   }
524                                         checkCoreStatus();
525                           } else {
526                                   if(!sendStall) {
527 #ifdef DEBUG
528                                           BAMBOO_DEBUGPRINT(0xee09);
529 #endif
530 #ifdef PROFILE
531                                           if(!stall) {
532 #endif
533                                                   if(isfirst) {
534                                                           // wait for some time
535                                                           int halt = 10000;
536 #ifdef DEBUG
537                                                           BAMBOO_DEBUGPRINT(0xee0a);
538 #endif
539                                                           while(halt--) {
540                                                           }
541                                                           isfirst = false;
542                                                   } else {
543                                                           // send StallMsg to startup core
544 #ifdef DEBUG
545                                                           BAMBOO_DEBUGPRINT(0xee0b);
546 #endif
547                                                           // send stall msg
548                                                           send_msg_4(STARTUPCORE, TRANSTALL, BAMBOO_NUM_OF_CORE, 
549                                                                                        self_numsendobjs, self_numreceiveobjs);
550                                                           sendStall = true;
551                                                           isfirst = true;
552                                                           busystatus = false;
553                                                   }
554 #ifdef PROFILE
555                                           }
556 #endif
557                                   } else {
558                                           isfirst = true;
559                                           busystatus = false;
560 #ifdef DEBUG
561                                           BAMBOO_DEBUGPRINT(0xee0c);
562 #endif
563                                   } // if(!sendStall)
564                           } // if(STARTUPCORE == BAMBOO_NUM_OF_CORE) 
565                   } // if(!tocontinue)
566           } // while(true) 
567   } // if(BAMBOO_NUM_OF_CORE > NUMCORES - 1)
568
569 } // run()
570
571 struct ___createstartupobject____I_locals {
572   INTPTR size;
573   void * next;
574   struct  ___StartupObject___ * ___startupobject___;
575   struct ArrayObject * ___stringarray___;
576 }; // struct ___createstartupobject____I_locals
577
578 void createstartupobject(int argc, 
579                                      char ** argv) {
580   int i;
581
582   /* Allocate startup object     */
583 #ifdef MULTICORE_GC
584         struct ___createstartupobject____I_locals ___locals___={2, NULL, NULL, NULL};
585   struct ___StartupObject___ *startupobject=
586                 (struct ___StartupObject___*) allocate_new(&___locals___, STARTUPTYPE);
587         ___locals___.___startupobject___ = startupobject;
588   struct ArrayObject * stringarray=
589                 allocate_newarray(&___locals___, STRINGARRAYTYPE, argc-1);
590         ___locals___.___stringarray___ = stringarray;
591 #else
592   struct ___StartupObject___ *startupobject=
593                 (struct ___StartupObject___*) allocate_new(STARTUPTYPE);
594   struct ArrayObject * stringarray=
595                 allocate_newarray(STRINGARRAYTYPE, argc-1);
596 #endif
597   /* Build array of strings */
598   startupobject->___parameters___=stringarray;
599   for(i=1; i<argc; i++) {
600     int length=strlen(argv[i]);
601 #ifdef MULTICORE_GC
602     struct ___String___ *newstring=NewString(&___locals___, argv[i],length);
603 #else
604     struct ___String___ *newstring=NewString(argv[i],length);
605 #endif
606     ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=
607                         newstring;
608   }
609
610   startupobject->version = 0;
611   startupobject->lock = NULL;
612
613   /* Set initialized flag for startup object */
614   flagorandinit(startupobject,1,0xFFFFFFFF);
615   enqueueObject(startupobject, NULL, 0);
616 #ifdef CACHEFLUSH
617   BAMBOO_CACHE_FLUSH_ALL();
618 #endif
619 }
620
621 int hashCodetpd(struct taskparamdescriptor *ftd) {
622   int hash=(int)ftd->task;
623   int i;
624   for(i=0; i<ftd->numParameters; i++) {
625     hash^=(int)ftd->parameterArray[i];
626   }
627   return hash;
628 }
629
630 int comparetpd(struct taskparamdescriptor *ftd1, 
631                            struct taskparamdescriptor *ftd2) {
632   int i;
633   if (ftd1->task!=ftd2->task)
634     return 0;
635   for(i=0; i<ftd1->numParameters; i++)
636     if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
637       return 0;
638   return 1;
639 }
640
641 /* This function sets a tag. */
642 #ifdef MULTICORE_GC
643 void tagset(void *ptr, 
644                         struct ___Object___ * obj, 
645                                                 struct ___TagDescriptor___ * tagd) {
646 #else
647 void tagset(struct ___Object___ * obj, 
648                         struct ___TagDescriptor___ * tagd) {
649 #endif
650   struct ArrayObject * ao=NULL;
651   struct ___Object___ * tagptr=obj->___tags___;
652   if (tagptr==NULL) {
653     obj->___tags___=(struct ___Object___ *)tagd;
654   } else {
655     /* Have to check if it is already set */
656     if (tagptr->type==TAGTYPE) {
657       struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
658       if (td==tagd) {
659         return;
660       }
661 #ifdef MULTICORE_GC
662       int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
663       struct ArrayObject * ao=
664                                 allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
665       obj=(struct ___Object___ *)ptrarray[2];
666       tagd=(struct ___TagDescriptor___ *)ptrarray[3];
667       td=(struct ___TagDescriptor___ *) obj->___tags___;
668 #else
669       ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
670 #endif
671
672       ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
673       ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
674       obj->___tags___=(struct ___Object___ *) ao;
675       ao->___cachedCode___=2;
676     } else {
677       /* Array Case */
678       int i;
679       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
680       for(i=0; i<ao->___cachedCode___; i++) {
681         struct ___TagDescriptor___ * td=
682                 ARRAYGET(ao, struct ___TagDescriptor___*, i);
683         if (td==tagd) {
684           return;
685         }
686       }
687       if (ao->___cachedCode___<ao->___length___) {
688         ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
689         ao->___cachedCode___++;
690       } else {
691 #ifdef MULTICORE_GC
692         int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
693         struct ArrayObject * aonew=
694                 allocate_newarray(&ptrarray,TAGARRAYTYPE,
695                                               TAGARRAYINTERVAL+ao->___length___);
696         obj=(struct ___Object___ *)ptrarray[2];
697         tagd=(struct ___TagDescriptor___ *) ptrarray[3];
698         ao=(struct ArrayObject *)obj->___tags___;
699 #else
700         struct ArrayObject * aonew=
701                 allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
702 #endif
703
704         aonew->___cachedCode___=ao->___length___+1;
705         for(i=0; i<ao->___length___; i++) {
706           ARRAYSET(aonew, struct ___TagDescriptor___*, i, 
707                                      ARRAYGET(ao, struct ___TagDescriptor___*, i));
708         }
709         ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
710       }
711     }
712   }
713
714   {
715     struct ___Object___ * tagset=tagd->flagptr;
716     if(tagset==NULL) {
717       tagd->flagptr=obj;
718     } else if (tagset->type!=OBJECTARRAYTYPE) {
719 #ifdef MULTICORE_GC
720       int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
721       struct ArrayObject * ao=
722                                 allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
723       obj=(struct ___Object___ *)ptrarray[2];
724       tagd=(struct ___TagDescriptor___ *)ptrarray[3];
725 #else
726       struct ArrayObject * ao=
727                                 allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
728 #endif
729       ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
730       ARRAYSET(ao, struct ___Object___ *, 1, obj);
731       ao->___cachedCode___=2;
732       tagd->flagptr=(struct ___Object___ *)ao;
733     } else {
734       struct ArrayObject *ao=(struct ArrayObject *) tagset;
735       if (ao->___cachedCode___<ao->___length___) {
736         ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
737       } else {
738         int i;
739 #ifdef MULTICORE_GC
740         int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
741         struct ArrayObject * aonew=
742                 allocate_newarray(&ptrarray,OBJECTARRAYTYPE,
743                                               OBJECTARRAYINTERVAL+ao->___length___);
744         obj=(struct ___Object___ *)ptrarray[2];
745         tagd=(struct ___TagDescriptor___ *)ptrarray[3];
746         ao=(struct ArrayObject *)tagd->flagptr;
747 #else
748         struct ArrayObject * aonew=
749                 allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
750 #endif
751         aonew->___cachedCode___=ao->___cachedCode___+1;
752         for(i=0; i<ao->___length___; i++) {
753           ARRAYSET(aonew, struct ___Object___*, i, 
754                                      ARRAYGET(ao, struct ___Object___*, i));
755         }
756         ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
757         tagd->flagptr=(struct ___Object___ *) aonew;
758       }
759     }
760   }
761 }
762
763 /* This function clears a tag. */
764 #ifdef MULTICORE_GC
765 void tagclear(void *ptr, 
766                           struct ___Object___ * obj, 
767                                                         struct ___TagDescriptor___ * tagd) {
768 #else
769 void tagclear(struct ___Object___ * obj, 
770                           struct ___TagDescriptor___ * tagd) {
771 #endif
772   /* We'll assume that tag is alway there.
773      Need to statically check for this of course. */
774   struct ___Object___ * tagptr=obj->___tags___;
775
776   if (tagptr->type==TAGTYPE) {
777     if ((struct ___TagDescriptor___ *)tagptr==tagd)
778       obj->___tags___=NULL;
779   } else {
780     struct ArrayObject *ao=(struct ArrayObject *) tagptr;
781     int i;
782     for(i=0; i<ao->___cachedCode___; i++) {
783       struct ___TagDescriptor___ * td=
784                                 ARRAYGET(ao, struct ___TagDescriptor___ *, i);
785       if (td==tagd) {
786         ao->___cachedCode___--;
787         if (i<ao->___cachedCode___)
788           ARRAYSET(ao, struct ___TagDescriptor___ *, i, 
789                                 ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
790         ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
791         if (ao->___cachedCode___==0)
792           obj->___tags___=NULL;
793         goto PROCESSCLEAR;
794       }
795     }
796   }
797 PROCESSCLEAR:
798   {
799     struct ___Object___ *tagset=tagd->flagptr;
800     if (tagset->type!=OBJECTARRAYTYPE) {
801       if (tagset==obj)
802         tagd->flagptr=NULL;
803     } else {
804       struct ArrayObject *ao=(struct ArrayObject *) tagset;
805       int i;
806       for(i=0; i<ao->___cachedCode___; i++) {
807         struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
808         if (tobj==obj) {
809           ao->___cachedCode___--;
810           if (i<ao->___cachedCode___)
811             ARRAYSET(ao, struct ___Object___ *, i, 
812                                         ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
813           ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
814           if (ao->___cachedCode___==0)
815             tagd->flagptr=NULL;
816           goto ENDCLEAR;
817         }
818       }
819     }
820   }
821 ENDCLEAR:
822   return;
823 }
824
825 /* This function allocates a new tag. */
826 #ifdef MULTICORE_GC
827 struct ___TagDescriptor___ * allocate_tag(void *ptr, 
828                                                       int index) {
829   struct ___TagDescriptor___ * v=
830                 (struct ___TagDescriptor___ *) FREEMALLOC((struct garbagelist *) ptr, 
831                                                                       classsize[TAGTYPE]);
832 #else
833 struct ___TagDescriptor___ * allocate_tag(int index) {
834   struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
835 #endif
836   v->type=TAGTYPE;
837   v->flag=index;
838   return v;
839 }
840
841
842
843 /* This function updates the flag for object ptr.  It or's the flag
844    with the or mask and and's it with the andmask. */
845
846 void flagbody(struct ___Object___ *ptr, 
847                           int flag, 
848                                                         struct parameterwrapper ** queues, 
849                                                         int length, 
850                                                         bool isnew);
851
852 int flagcomp(const int *val1, const int *val2) {
853   return (*val1)-(*val2);
854 }
855
856 void flagorand(void * ptr, 
857                            int ormask, 
858                                                          int andmask, 
859                                                          struct parameterwrapper ** queues, 
860                                                          int length) {
861   {
862     int oldflag=((int *)ptr)[1];
863     int flag=ormask|oldflag;
864     flag&=andmask;
865     flagbody(ptr, flag, queues, length, false);
866   }
867 }
868
869 bool intflagorand(void * ptr, 
870                               int ormask, 
871                                                                         int andmask) {
872   {
873     int oldflag=((int *)ptr)[1];
874     int flag=ormask|oldflag;
875     flag&=andmask;
876     if (flag==oldflag)   /* Don't do anything */
877       return false;
878     else {
879       flagbody(ptr, flag, NULL, 0, false);
880       return true;
881     }
882   }
883 }
884
885 void flagorandinit(void * ptr, 
886                                int ormask, 
887                                                                          int andmask) {
888   int oldflag=((int *)ptr)[1];
889   int flag=ormask|oldflag;
890   flag&=andmask;
891   flagbody(ptr,flag,NULL,0,true);
892 }
893
894 void flagbody(struct ___Object___ *ptr, 
895                           int flag, 
896                                                         struct parameterwrapper ** vqueues, 
897                                                         int vlength, 
898                                                         bool isnew) {
899   struct parameterwrapper * flagptr = NULL;
900   int i = 0;
901   struct parameterwrapper ** queues = vqueues;
902   int length = vlength;
903   int next;
904   int UNUSED, UNUSED2;
905   int * enterflags = NULL;
906   if((!isnew) && (queues == NULL)) {
907     if(BAMBOO_NUM_OF_CORE < NUMCORES) {
908                 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
909                 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
910         } else {
911                 return;
912         }
913   }
914   ptr->flag=flag;
915
916   /*Remove object from all queues */
917   for(i = 0; i < length; ++i) {
918     flagptr = queues[i];
919     ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next, 
920                                           (int *) &enterflags, &UNUSED, &UNUSED2);
921     ObjectHashremove(flagptr->objectset, (int)ptr);
922     if (enterflags!=NULL)
923       RUNFREE(enterflags);
924   }
925 }
926
927 void enqueueObject(void * vptr, 
928                                struct parameterwrapper ** vqueues, 
929                                                                          int vlength) {
930         struct ___Object___ *ptr = (struct ___Object___ *)vptr;
931         
932         {
933                 //struct QueueItem *tmpptr;
934                 struct parameterwrapper * parameter=NULL;
935                 int j;
936                 int i;
937                 struct parameterwrapper * prevptr=NULL;
938                 struct ___Object___ *tagptr=NULL;
939                 struct parameterwrapper ** queues = vqueues;
940                 int length = vlength;
941                 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
942                         return;
943                 }
944                 if(queues == NULL) {
945                         queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
946                         length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
947                 }
948                 tagptr=ptr->___tags___;
949
950                 /* Outer loop iterates through all parameter queues an object of
951                    this type could be in.  */
952                 for(j = 0; j < length; ++j) {
953                         parameter = queues[j];     
954                         /* Check tags */
955                         if (parameter->numbertags>0) {
956                                 if (tagptr==NULL)
957                                         goto nextloop; //that means the object has no tag 
958                                                  //but that param needs tag
959                                 else if(tagptr->type==TAGTYPE) { //one tag
960                                         //struct ___TagDescriptor___ * tag=
961                                         //(struct ___TagDescriptor___*) tagptr;  
962                                         for(i=0; i<parameter->numbertags; i++) {
963                                                 //slotid is parameter->tagarray[2*i];
964                                                 int tagid=parameter->tagarray[2*i+1];
965                                                 if (tagid!=tagptr->flag)
966                                                         goto nextloop; /*We don't have this tag */
967                                         }
968                                 } else { //multiple tags
969                                         struct ArrayObject * ao=(struct ArrayObject *) tagptr;
970                                         for(i=0; i<parameter->numbertags; i++) {
971                                                 //slotid is parameter->tagarray[2*i];
972                                                 int tagid=parameter->tagarray[2*i+1];
973                                                 int j;
974                                                 for(j=0; j<ao->___cachedCode___; j++) {
975                                                         if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
976                                                                 goto foundtag;
977                                                 }
978                                                 goto nextloop;
979 foundtag:
980                                                 ;
981                                         }
982                                 }
983                         }
984         
985                         /* Check flags */
986                         for(i=0; i<parameter->numberofterms; i++) {
987                                 int andmask=parameter->intarray[i*2];
988                                 int checkmask=parameter->intarray[i*2+1];
989                                 if ((ptr->flag&andmask)==checkmask) {
990                                         enqueuetasks(parameter, prevptr, ptr, NULL, 0);
991                                         prevptr=parameter;
992                                         break;
993                                 }
994                         }
995 nextloop:
996                         ;
997                 }
998         }
999 }
1000
1001 void enqueueObject_I(void * vptr, 
1002                                  struct parameterwrapper ** vqueues, 
1003                                                                                  int vlength) {
1004         struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1005         
1006         {
1007                 //struct QueueItem *tmpptr;
1008                 struct parameterwrapper * parameter=NULL;
1009                 int j;
1010                 int i;
1011                 struct parameterwrapper * prevptr=NULL;
1012                 struct ___Object___ *tagptr=NULL;
1013                 struct parameterwrapper ** queues = vqueues;
1014                 int length = vlength;
1015                 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1016                         return;
1017                 }
1018                 if(queues == NULL) {
1019                         queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
1020                         length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
1021                 }
1022                 tagptr=ptr->___tags___;
1023
1024                 /* Outer loop iterates through all parameter queues an object of
1025                    this type could be in.  */
1026                 for(j = 0; j < length; ++j) {
1027                         parameter = queues[j];     
1028                         /* Check tags */
1029                         if (parameter->numbertags>0) {
1030                                 if (tagptr==NULL)
1031                                         goto nextloop; //that means the object has no tag 
1032                                                  //but that param needs tag
1033                                 else if(tagptr->type==TAGTYPE) { //one tag
1034                                         //struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;         
1035                                         for(i=0; i<parameter->numbertags; i++) {
1036                                                 //slotid is parameter->tagarray[2*i];
1037                                                 int tagid=parameter->tagarray[2*i+1];
1038                                                 if (tagid!=tagptr->flag)
1039                                                         goto nextloop; /*We don't have this tag */
1040                                         }
1041                                 } else { //multiple tags
1042                                         struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1043                                         for(i=0; i<parameter->numbertags; i++) {
1044                                                 //slotid is parameter->tagarray[2*i];
1045                                                 int tagid=parameter->tagarray[2*i+1];
1046                                                 int j;
1047                                                 for(j=0; j<ao->___cachedCode___; j++) {
1048                                                         if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
1049                                                                 goto foundtag;
1050                                                 }
1051                                                 goto nextloop;
1052 foundtag:
1053                                                 ;
1054                                         }
1055                                 }
1056                         }
1057
1058                         /* Check flags */
1059                         for(i=0; i<parameter->numberofterms; i++) {
1060                                 int andmask=parameter->intarray[i*2];
1061                                 int checkmask=parameter->intarray[i*2+1];
1062                                 if ((ptr->flag&andmask)==checkmask) {
1063                                         enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
1064                                         prevptr=parameter;
1065                                         break;
1066                                 }
1067                         }
1068 nextloop:
1069                         ;
1070                 }
1071         }
1072 }
1073
1074
1075 int * getAliasLock(void ** ptrs, 
1076                                int length, 
1077                                                                          struct RuntimeHash * tbl) {
1078         if(length == 0) {
1079                 return (int*)(RUNMALLOC(sizeof(int)));
1080         } else {
1081                 int i = 0;
1082                 int locks[length];
1083                 int locklen = 0;
1084                 bool redirect = false;
1085                 int redirectlock = 0;
1086                 for(; i < length; i++) {
1087                         struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
1088                         int lock = 0;
1089                         int j = 0;
1090                         if(ptr->lock == NULL) {
1091                                 lock = (int)(ptr);
1092                         } else {
1093                                 lock = (int)(ptr->lock);
1094                         }
1095                         if(redirect) {
1096                                 if(lock != redirectlock) {
1097                                         RuntimeHashadd(tbl, lock, redirectlock);
1098                                 }
1099                         } else {
1100                                 if(RuntimeHashcontainskey(tbl, lock)) {
1101                                         // already redirected
1102                                         redirect = true;
1103                                         RuntimeHashget(tbl, lock, &redirectlock);
1104                                         for(; j < locklen; j++) {
1105                                                 if(locks[j] != redirectlock) {
1106                                                         RuntimeHashadd(tbl, locks[j], redirectlock);
1107                                                 }
1108                                         }
1109                                 } else {
1110                                         bool insert = true;
1111                                         for(j = 0; j < locklen; j++) {
1112                                                 if(locks[j] == lock) {
1113                                                         insert = false;
1114                                                         break;
1115                                                 } else if(locks[j] > lock) {
1116                                                         break;
1117                                                 }
1118                                         }
1119                                         if(insert) {
1120                                                 int h = locklen;
1121                                                 for(; h > j; h--) {
1122                                                         locks[h] = locks[h-1];
1123                                                 }       
1124                                                 locks[j] = lock;
1125                                                 locklen++;
1126                                         }
1127                                 }
1128                         }
1129                 }
1130                 if(redirect) {
1131                         return (int *)redirectlock;
1132                 } else {
1133                         return (int *)(locks[0]);
1134                 }
1135         }
1136 }
1137
1138 void addAliasLock(void * ptr, 
1139                               int lock) {
1140   struct ___Object___ * obj = (struct ___Object___ *)ptr;
1141   if(((int)ptr != lock) && (obj->lock != (int*)lock)) {
1142     // originally no alias lock associated or have a different alias lock
1143     // flush it as the new one
1144     obj->lock = (int *)lock;
1145   }
1146 }
1147
1148 #ifdef PROFILE
1149 inline void setTaskExitIndex(int index) {
1150         taskInfoArray[taskInfoIndex]->exitIndex = index;
1151 }
1152
1153 inline void addNewObjInfo(void * nobj) {
1154         if(taskInfoArray[taskInfoIndex]->newObjs == NULL) {
1155                 taskInfoArray[taskInfoIndex]->newObjs = createQueue();
1156         }
1157         addNewItem(taskInfoArray[taskInfoIndex]->newObjs, nobj);
1158 }
1159 #endif
1160
1161 void * smemalloc(int size, 
1162                              int * allocsize) {
1163         void * mem = NULL;
1164 #ifdef MULTICORE_GC
1165         // go through free mem list for suitable blocks
1166         struct freeMemItem * freemem = bamboo_free_mem_list->head;
1167         struct freeMemItem * prev = NULL;
1168         do {
1169                 if(freemem->size >= size) {
1170                         // found one
1171                         break;
1172                 }
1173                 prev = freemem;
1174                 freemem = freemem->next;
1175         } while(freemem != NULL);
1176         if(freemem != NULL) {
1177                 mem = (void *)(freemem->ptr);
1178                 *allocsize = size;
1179                 freemem->ptr = ((void*)freemem->ptr) + size;
1180                 freemem->size -= size;
1181                 // check how many blocks it acrosses
1182                 int b = 0;
1183                 BLOCKINDEX(mem, &b);
1184                 // check the remaining space in this block
1185                 int remain = (b < NUMCORES? (b+1)*BAMBOO_SMEM_SIZE_L  
1186                                         : BAMBOO_LARGE_SMEM_BOUND+(b-NUMCORES+1)*BAMBOO_SMEM_SIZE)
1187                                   -((int)mem-BAMBOO_BASE_VA);
1188                 if(remain < size) {
1189                         // this object acrosses blocks
1190                         int tmpsbs = 1+(size-remain-1)/BAMBOO_SMEM_SIZE;
1191                         for(int k = 0; k < tmpsbs-1; k++) {
1192                                 gcsbstarttbl[k+b] = (INTPTR)(-1);
1193                         }
1194                         if((size-remain)%BAMBOO_SMEM_SIZE == 0) {
1195                                 gcsbstarttbl[b+tmpsbs-1] = (INTPTR)(-1);
1196                         } else {
1197                                 gcsbstarttbl[b+tmpsbs-1] = (INTPTR)(mem+size);
1198                         }
1199                 }
1200         } else {
1201 #else
1202         mem = mspace_calloc(bamboo_free_msp, 1, size);
1203         *allocsize = size;
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 GCSTART: {
1690                 // receive a start GC msg
1691 #ifdef DEBUG
1692 #ifndef TILERA
1693           BAMBOO_DEBUGPRINT(0xe88c);
1694 #endif
1695 #endif
1696           // set the GC flag
1697                 gcflag = true;
1698                 gcphase = MARKPHASE;
1699                 if(!smemflag) {
1700                         // is waiting for response of mem request
1701                         // let it return NULL and start gc
1702                         bamboo_smem_size = 0;
1703                         bamboo_cur_msp = NULL;
1704                         smemflag = true;
1705                 }
1706           break;
1707         }
1708
1709         case GCSTARTCOMPACT: {
1710                 // a compact phase start msg
1711                 gcblock2fill = msgdata[1];
1712                 gcphase = COMPACTPHASE;
1713                 break;
1714         }
1715
1716         case GCSTARTFLUSH: {
1717                 // received a flush phase start msg
1718                 gcphase = FLUSHPHASE;
1719                 break;
1720         }
1721
1722         case GCFINISHMARK: {
1723                 // received a mark phase finish msg
1724                 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1725                   // non startup core can not receive this msg
1726 #ifndef TILERA
1727                   BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1728 #endif
1729                   BAMBOO_EXIT(0xb001);
1730                 } 
1731                 if(msgdata[1] < NUMCORES) {
1732                         gccorestatus[msgdata[1]] = 0;
1733                         gcnumsendobjs[msgdata[1]] = msgdata[2];
1734                         gcnumreceiveobjs[msgdata[1]] = msgdata[3];
1735                 }
1736           break;
1737         }
1738         
1739         case GCFINISHCOMPACT: {
1740                 // received a compact phase finish msg
1741                 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1742                   // non startup core can not receive this msg
1743                   // return -1
1744 #ifndef TILERA
1745                   BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1746 #endif
1747                   BAMBOO_EXIT(0xb002);
1748                 }
1749                 int cnum = msgdata[1];
1750                 int filledblocks = msgdata[2];
1751                 int heaptop = msgdata[3];
1752                 int data4 = msgdata[4];
1753                 if(cnum < NUMCORES) {
1754                         if(COMPACTPHASE == gcphase) {
1755                                 gcfilledblocks[cnum] = filledblocks;
1756                                 gcloads[cnum] = heaptop;
1757                         }
1758                         if(data4 > 0) {
1759                                 // ask for more mem
1760                                 int startaddr = 0;
1761                                 int tomove = 0;
1762                                 int dstcore = 0;
1763                                 if(gcfindSpareMem(&startaddr, &tomove, &dstcore, data4, cnum)) {
1764                                         send_msg_4(cnum, GCMOVESTART, dstcore, startaddr, tomove);
1765                                 }
1766                         } else {
1767                                 gccorestatus[cnum] = 0;
1768                                 // check if there is pending move request
1769                                 if(gcmovepending > 0) {
1770                                         int j;
1771                                         for(j = 0; j < NUMCORES; j++) {
1772                                                 if(gcrequiredmems[j]>0) {
1773                                                         break;
1774                                                 }
1775                                         }
1776                                         if(j < NUMCORES) {
1777                                                 // find match
1778                                                 int tomove = 0;
1779                                                 int startaddr = 0;
1780                                                 gcrequiredmems[j] = assignSpareMem(cnum, 
1781                                                                                                                                                                                          gcrequiredmems[j], 
1782                                                                                                                                                                                          &tomove, 
1783                                                                                                                                                                                          &startaddr);
1784                                                 if(STARTUPCORE == j) {
1785                                                         gcdstcore = cnum;
1786                                                         gctomove = true;
1787                                                         gcmovestartaddr = startaddr;
1788                                                         gcblock2fill = tomove;
1789                                                 } else {
1790                                                         send_msg_4(j, GCMOVESTART, cnum, startaddr, tomove);
1791                                                 } // if(STARTUPCORE == j)
1792                                                 if(gcrequiredmems[j] == 0) {
1793                                                         gcmovepending--;
1794                                                 }
1795                                         } // if(j < NUMCORES)
1796                                 } // if(gcmovepending > 0)
1797                         } // if(flag == 0)
1798                 } // if(cnum < NUMCORES)
1799           break;
1800         }
1801
1802         case GCFINISHFLUSH: {
1803                 // received a flush phase finish msg
1804                 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1805                   // non startup core can not receive this msg
1806                   // return -1
1807 #ifndef TILERA
1808                   BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1809 #endif
1810                   BAMBOO_EXIT(0xb003);
1811                 } 
1812                 if(msgdata[1] < NUMCORES) {
1813                   gccorestatus[msgdata[1]] = 0;
1814                 }
1815           break;
1816         }
1817
1818         case GCFINISH: {
1819                 // received a GC finish msg
1820                 gcphase = FINISHPHASE;
1821                 break;
1822         }
1823
1824         case GCMARKCONFIRM: {
1825                 // received a marked phase finish confirm request msg
1826                 if((BAMBOO_NUM_OF_CORE == STARTUPCORE) 
1827                                 || (BAMBOO_NUM_OF_CORE > NUMCORES - 1)) {
1828                   // wrong core to receive such msg
1829                   BAMBOO_EXIT(0xb004);
1830                 } else {
1831                   // send response msg
1832                   if(isMsgSending) {
1833                           cache_msg_5(STARTUPCORE, GCMARKREPORT, BAMBOO_NUM_OF_CORE, 
1834                                                         gcbusystatus, gcself_numsendobjs, 
1835                                                                                 gcself_numreceiveobjs);
1836                   } else {
1837                           send_msg_5(STARTUPCORE, GCMARKREPORT, BAMBOO_NUM_OF_CORE, 
1838                                                        gcbusystatus, gcself_numsendobjs, gcself_numreceiveobjs);
1839                   }
1840                 }
1841           break;
1842         }
1843
1844         case GCMARKREPORT: {
1845                 // received a marked phase finish confirm response msg
1846                 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1847                   // wrong core to receive such msg
1848 #ifndef TILERA
1849                   BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1850 #endif
1851                   BAMBOO_EXIT(0xb005);
1852                 } else {
1853                   if(waitconfirm) {
1854                           numconfirm--;
1855                   }
1856                   gccorestatus[msgdata[1]] = msgdata[2];
1857                   gcnumsendobjs[msgdata[1]] = msgdata[3];
1858                   gcnumreceiveobjs[msgdata[1]] = msgdata[4];
1859                 }
1860           break;
1861         }
1862
1863         case GCMARKEDOBJ: {
1864                 // received a markedObj msg
1865                 gc_enqueue(msgdata[1]);
1866                 gcself_numreceiveobjs++;
1867                 gcbusystatus = true;
1868                 break;
1869         }
1870
1871         case GCMOVESTART: {
1872                 // received a start moving objs msg
1873                 gctomove = true;
1874                 gcdstcore = msgdata[1];
1875                 gcmovestartaddr = msgdata[2];
1876                 gcblock2fill = msgdata[3];
1877                 break;
1878         }
1879         
1880         case GCMAPREQUEST: {
1881                 // received a mapping info request msg
1882                 void * dstptr = NULL;
1883                 RuntimeHashget(gcpointertbl, msgdata[1], &dstptr);
1884                 if(NULL == dstptr) {
1885                         // no such pointer in this core, something is wrong
1886                         BAMBOO_EXIT(0xb006);
1887                 } else {
1888                         // send back the mapping info
1889                         if(isMsgSending) {
1890                                 cache_msg_3(msgdata[2], GCMAPINFO, msgdata[1], (int)dstptr);
1891                         } else {
1892                                 send_msg_3(msgdata[2], GCMAPINFO, msgdata[1], (int)dstptr);
1893                         }
1894                 }
1895                 break;
1896         }
1897
1898         case GCMAPINFO: {
1899                 // received a mapping info response msg
1900                 if(msgdata[1] != gcobj2map) {
1901                         // obj not matched, something is wrong
1902                         BAMBOO_EXIT(0xb007);
1903                 } else {
1904                         gcmappedobj = msgdata[2];
1905                         RuntimeHashadd(gcpointertbl, gcobj2map, gcmappedobj);
1906                 }
1907                 gcismapped = true;
1908                 break;
1909         }
1910
1911         case GCLOBJREQUEST: {
1912                 // received a large objs info request msg
1913                 transferMarkResults();
1914                 break;
1915         }
1916
1917         case GCLOBJINFO: {
1918                 // received a large objs info response msg
1919                 waitconfirm--;
1920
1921                 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1922 #ifndef TILERA
1923                         BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1924 #endif
1925                         BAMBOO_EXIT(0xb008);
1926                 } 
1927                 // store the mark result info 
1928                 int cnum = msgdata[2];
1929                 gcloads[cnum] = msgdata[3];
1930                 if(gcheaptop < msgdata[4]) {
1931                         gcheaptop = msgdata[4];
1932                 }
1933                 // large obj info here
1934           for(int k = 5; k < msgdata[1];) {
1935                         gc_lobjenqueue(msgdata[k++], msgdata[k++], cnum);
1936                 } // for(int k = 5; k < msgdata[1];)
1937                 break;
1938         }
1939         
1940         case GCLOBJMAPPING: {
1941                 // received a large obj mapping info msg
1942                 RuntimeHashadd(gcpointertbl, msgdata[1], msgdata[2]);
1943                 break;
1944         }
1945
1946 #endif
1947
1948         default:
1949                 break;
1950         }
1951         for(msgdataindex--; msgdataindex > 0; --msgdataindex) {
1952                 msgdata[msgdataindex] = -1;
1953         }
1954         msgtype = -1;
1955         msglength = 30;
1956 #ifdef DEBUG
1957 #ifndef TILERA
1958         BAMBOO_DEBUGPRINT(0xe88d);
1959 #endif
1960 #endif
1961
1962         if(BAMBOO_MSG_AVAIL() != 0) {
1963                 goto msg;
1964         }
1965 #ifdef PROFILE
1966 /*if(isInterrupt) {
1967                 profileTaskEnd();
1968         }*/
1969 #endif
1970         return (int)type;
1971 } else {
1972         // not a whole msg
1973 #ifdef DEBUG
1974 #ifndef TILERA
1975         BAMBOO_DEBUGPRINT(0xe88e);
1976 #endif
1977 #endif
1978 #ifdef PROFILE
1979 /*  if(isInterrupt) {
1980                   profileTaskEnd();
1981                 }*/
1982 #endif
1983     return -2;
1984   }
1985 }
1986
1987 int enqueuetasks(struct parameterwrapper *parameter, 
1988                              struct parameterwrapper *prevptr, 
1989                                                                  struct ___Object___ *ptr, 
1990                                                                  int * enterflags, 
1991                                                                  int numenterflags) {
1992   void * taskpointerarray[MAXTASKPARAMS];
1993   int j;
1994   //int numparams=parameter->task->numParameters;
1995   int numiterators=parameter->task->numTotal-1;
1996   int retval=1;
1997
1998   struct taskdescriptor * task=parameter->task;
1999
2000    //this add the object to parameterwrapper
2001    ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags, 
2002                                    numenterflags, enterflags==NULL);
2003
2004   /* Add enqueued object to parameter vector */
2005   taskpointerarray[parameter->slot]=ptr;
2006
2007   /* Reset iterators */
2008   for(j=0; j<numiterators; j++) {
2009     toiReset(&parameter->iterators[j]);
2010   }
2011
2012   /* Find initial state */
2013   for(j=0; j<numiterators; j++) {
2014 backtrackinit:
2015     if(toiHasNext(&parameter->iterators[j],taskpointerarray OPTARG(failed)))
2016       toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
2017     else if (j>0) {
2018       /* Need to backtrack */
2019       toiReset(&parameter->iterators[j]);
2020       j--;
2021       goto backtrackinit;
2022     } else {
2023       /* Nothing to enqueue */
2024       return retval;
2025     }
2026   }
2027
2028   while(1) {
2029     /* Enqueue current state */
2030     //int launch = 0;
2031     struct taskparamdescriptor *tpd=
2032                         RUNMALLOC(sizeof(struct taskparamdescriptor));
2033     tpd->task=task;
2034     tpd->numParameters=numiterators+1;
2035     tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
2036
2037     for(j=0; j<=numiterators; j++) {
2038                         //store the actual parameters
2039       tpd->parameterArray[j]=taskpointerarray[j]; 
2040     }
2041     /* Enqueue task */
2042     if ((/*!gencontains(failedtasks, tpd)&&*/ 
2043                                         !gencontains(activetasks,tpd))) {
2044                 genputtable(activetasks, tpd, tpd);
2045     } else {
2046       RUNFREE(tpd->parameterArray);
2047       RUNFREE(tpd);
2048     }
2049
2050     /* This loop iterates to the next parameter combination */
2051     if (numiterators==0)
2052       return retval;
2053
2054     for(j=numiterators-1; j<numiterators; j++) {
2055 backtrackinc:
2056       if(toiHasNext(&parameter->iterators[j],taskpointerarray OPTARG(failed)))
2057         toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
2058       else if (j>0) {
2059         /* Need to backtrack */
2060         toiReset(&parameter->iterators[j]);
2061         j--;
2062         goto backtrackinc;
2063       } else {
2064         /* Nothing more to enqueue */
2065         return retval;
2066       }
2067     }
2068   }
2069   return retval;
2070 }
2071
2072 int enqueuetasks_I(struct parameterwrapper *parameter, 
2073                                struct parameterwrapper *prevptr, 
2074                                                                          struct ___Object___ *ptr, 
2075                                                                          int * enterflags, 
2076                                                                          int numenterflags) {
2077   void * taskpointerarray[MAXTASKPARAMS];
2078   int j;
2079   //int numparams=parameter->task->numParameters;
2080   int numiterators=parameter->task->numTotal-1;
2081   int retval=1;
2082   //int addnormal=1;
2083   //int adderror=1;
2084
2085   struct taskdescriptor * task=parameter->task;
2086
2087    //this add the object to parameterwrapper
2088    ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags, 
2089                                      numenterflags, enterflags==NULL);  
2090
2091   /* Add enqueued object to parameter vector */
2092   taskpointerarray[parameter->slot]=ptr;
2093
2094   /* Reset iterators */
2095   for(j=0; j<numiterators; j++) {
2096     toiReset(&parameter->iterators[j]);
2097   }
2098
2099   /* Find initial state */
2100   for(j=0; j<numiterators; j++) {
2101 backtrackinit:
2102     if(toiHasNext(&parameter->iterators[j],taskpointerarray OPTARG(failed)))
2103       toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
2104     else if (j>0) {
2105       /* Need to backtrack */
2106       toiReset(&parameter->iterators[j]);
2107       j--;
2108       goto backtrackinit;
2109     } else {
2110       /* Nothing to enqueue */
2111       return retval;
2112     }
2113   }
2114
2115   while(1) {
2116     /* Enqueue current state */
2117     //int launch = 0;
2118     struct taskparamdescriptor *tpd=
2119                         RUNMALLOC_I(sizeof(struct taskparamdescriptor));
2120     tpd->task=task;
2121     tpd->numParameters=numiterators+1;
2122     tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
2123
2124     for(j=0; j<=numiterators; j++) {
2125                         //store the actual parameters
2126       tpd->parameterArray[j]=taskpointerarray[j]; 
2127     }
2128     /* Enqueue task */
2129     if ((/*!gencontains(failedtasks, tpd)&&*/ 
2130                                         !gencontains(activetasks,tpd))) {
2131                 genputtable_I(activetasks, tpd, tpd);
2132     } else {
2133       RUNFREE(tpd->parameterArray);
2134       RUNFREE(tpd);
2135     }
2136
2137     /* This loop iterates to the next parameter combination */
2138     if (numiterators==0)
2139       return retval;
2140
2141     for(j=numiterators-1; j<numiterators; j++) {
2142 backtrackinc:
2143       if(toiHasNext(&parameter->iterators[j], taskpointerarray OPTARG(failed)))
2144         toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
2145       else if (j>0) {
2146         /* Need to backtrack */
2147         toiReset(&parameter->iterators[j]);
2148         j--;
2149         goto backtrackinc;
2150       } else {
2151         /* Nothing more to enqueue */
2152         return retval;
2153       }
2154     }
2155   }
2156   return retval;
2157 }
2158
2159 #ifdef MULTICORE_GC
2160 #define OFFSET 2
2161 #else
2162 #define OFFSET 0
2163 #endif
2164
2165 int containstag(struct ___Object___ *ptr, 
2166                             struct ___TagDescriptor___ *tag);
2167
2168 #ifndef MULTICORE_GC
2169 void releasewritelock_r(void * lock, void * redirectlock) {
2170   int targetcore = 0;
2171   int reallock = (int)lock;
2172   targetcore = (reallock >> 5) % BAMBOO_TOTALCORE;
2173
2174 #ifdef DEBUG
2175   BAMBOO_DEBUGPRINT(0xe671);
2176   BAMBOO_DEBUGPRINT_REG((int)lock);
2177   BAMBOO_DEBUGPRINT_REG(reallock);
2178   BAMBOO_DEBUGPRINT_REG(targetcore);
2179 #endif
2180
2181   if(targetcore == BAMBOO_NUM_OF_CORE) {
2182         BAMBOO_START_CRITICAL_SECTION_LOCK();
2183 #ifdef DEBUG
2184         BAMBOO_DEBUGPRINT(0xf001);
2185 #endif
2186     // reside on this core
2187     if(!RuntimeHashcontainskey(locktbl, reallock)) {
2188       // no locks for this object, something is wrong
2189       BAMBOO_EXIT(0xa011);
2190     } else {
2191       int rwlock_obj = 0;
2192           struct LockValue * lockvalue = NULL;
2193 #ifdef DEBUG
2194       BAMBOO_DEBUGPRINT(0xe672);
2195 #endif
2196       RuntimeHashget(locktbl, reallock, &rwlock_obj);
2197           lockvalue = (struct LockValue *)rwlock_obj;
2198 #ifdef DEBUG
2199       BAMBOO_DEBUGPRINT_REG(lockvalue->value);
2200 #endif
2201       lockvalue->value++;
2202           lockvalue->redirectlock = (int)redirectlock;
2203 #ifdef DEBUG
2204       BAMBOO_DEBUGPRINT_REG(lockvalue->value);
2205 #endif
2206     }
2207         BAMBOO_CLOSE_CRITICAL_SECTION_LOCK();
2208 #ifdef DEBUG
2209         BAMBOO_DEBUGPRINT(0xf000);
2210 #endif
2211     return;
2212   } else {
2213           // send lock release with redirect info msg
2214           // for 32 bit machine, the size is always 4 words
2215           send_msg_4(targetcore, REDIRECTRELEASE, 1, (int)lock, (int)redirectlock);
2216   }
2217 }
2218 #endif
2219
2220 void executetasks() {
2221   void * taskpointerarray[MAXTASKPARAMS+OFFSET];
2222   int numparams=0;
2223   int numtotal=0;
2224   struct ___Object___ * tmpparam = NULL;
2225   struct parameterdescriptor * pd=NULL;
2226   struct parameterwrapper *pw=NULL;
2227   int j = 0;
2228   int x = 0;
2229   bool islock = true;
2230
2231   struct LockValue locks[MAXTASKPARAMS];
2232   int locklen = 0;
2233   int grount = 0;
2234   int andmask=0;
2235   int checkmask=0;
2236
2237
2238 newtask:
2239   while(hashsize(activetasks)>0) {
2240 #ifdef MULTICORE_GC
2241                 gc(NULL);
2242 #endif
2243 #ifdef DEBUG
2244     BAMBOO_DEBUGPRINT(0xe990);
2245 #endif
2246
2247     /* See if there are any active tasks */
2248     if (hashsize(activetasks)>0) {
2249       int i;
2250 #ifdef PROFILE
2251 #ifdef ACCURATEPROFILE
2252           profileTaskStart("tpd checking");
2253 #endif
2254 #endif
2255           busystatus = true;
2256       currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
2257       genfreekey(activetasks, currtpd);
2258
2259       numparams=currtpd->task->numParameters;
2260       numtotal=currtpd->task->numTotal;
2261
2262           // clear the lockRedirectTbl 
2263                 // (TODO, this table should be empty after all locks are released)
2264           // reset all locks
2265           for(j = 0; j < MAXTASKPARAMS; j++) {
2266                   locks[j].redirectlock = 0;
2267                   locks[j].value = 0;
2268           }
2269           // get all required locks
2270           locklen = 0;
2271           // check which locks are needed
2272           for(i = 0; i < numparams; i++) {
2273                   void * param = currtpd->parameterArray[i];
2274                   int tmplock = 0;
2275                   int j = 0;
2276                   bool insert = true;
2277                   if(((struct ___Object___ *)param)->type == STARTUPTYPE) {
2278                           islock = false;
2279                           taskpointerarray[i+OFFSET]=param;
2280                           goto execute;
2281                   }
2282                   if(((struct ___Object___ *)param)->lock == NULL) {
2283                           tmplock = (int)param;
2284                   } else {
2285                           tmplock = (int)(((struct ___Object___ *)param)->lock);
2286                   }
2287                   // insert into the locks array
2288                   for(j = 0; j < locklen; j++) {
2289                           if(locks[j].value == tmplock) {
2290                                   insert = false;
2291                                   break;
2292                           } else if(locks[j].value > tmplock) {
2293                                   break;
2294                           }
2295                   }
2296                   if(insert) {
2297                           int h = locklen;
2298                           for(; h > j; h--) {
2299                                   locks[h].redirectlock = locks[h-1].redirectlock;
2300                                   locks[h].value = locks[h-1].value;
2301                           }
2302                           locks[j].value = tmplock;
2303                           locks[j].redirectlock = (int)param;
2304                           locklen++;
2305                   }               
2306           } // line 2713: for(i = 0; i < numparams; i++) 
2307           // grab these required locks
2308 #ifdef DEBUG
2309           BAMBOO_DEBUGPRINT(0xe991);
2310 #endif
2311           for(i = 0; i < locklen; i++) {
2312                   int * lock = (int *)(locks[i].redirectlock);
2313                   islock = true;
2314                   // require locks for this parameter if it is not a startup object
2315 #ifdef DEBUG
2316                   BAMBOO_DEBUGPRINT_REG((int)lock);
2317                   BAMBOO_DEBUGPRINT_REG((int)(locks[i].value));
2318 #endif
2319                   getwritelock(lock);
2320                   BAMBOO_START_CRITICAL_SECTION();
2321 #ifdef DEBUG
2322                   BAMBOO_DEBUGPRINT(0xf001);
2323 #endif
2324 #ifdef PROFILE
2325                   //isInterrupt = false;
2326 #endif 
2327                   while(!lockflag) { 
2328                           BAMBOO_WAITING_FOR_LOCK();
2329                   }
2330 #ifndef INTERRUPT
2331                   if(reside) {
2332                           while(BAMBOO_WAITING_FOR_LOCK() != -1) {
2333                           }
2334                   }
2335 #endif
2336                   grount = lockresult;
2337
2338                   lockresult = 0;
2339                   lockobj = 0;
2340                   lock2require = 0;
2341                   lockflag = false;
2342 #ifndef INTERRUPT
2343                   reside = false;
2344 #endif
2345 #ifdef PROFILE
2346                   //isInterrupt = true;
2347 #endif
2348                   BAMBOO_CLOSE_CRITICAL_SECTION();
2349 #ifdef DEBUG
2350                   BAMBOO_DEBUGPRINT(0xf000);
2351 #endif
2352
2353                   if(grount == 0) {
2354                           int j = 0;
2355 #ifdef DEBUG
2356                           BAMBOO_DEBUGPRINT(0xe992);
2357 #endif
2358                           // can not get the lock, try later
2359                           // releas all grabbed locks for previous parameters
2360                           for(j = 0; j < i; ++j) {
2361                                   lock = (int*)(locks[j].redirectlock);
2362                                   releasewritelock(lock);
2363                           }
2364                           genputtable(activetasks, currtpd, currtpd);
2365                           if(hashsize(activetasks) == 1) {
2366                                   // only one task right now, wait a little while before next try
2367                                   int halt = 10000;
2368                                   while(halt--) {
2369                                   }
2370                           }
2371 #ifdef PROFILE
2372 #ifdef ACCURATEPROFILE
2373                           // fail, set the end of the checkTaskInfo
2374                           profileTaskEnd();
2375 #endif
2376 #endif
2377                           goto newtask;
2378                   } // line 2794: if(grount == 0)
2379           } // line 2752:  for(i = 0; i < locklen; i++)
2380
2381 #ifdef DEBUG
2382         BAMBOO_DEBUGPRINT(0xe993);
2383 #endif
2384       /* Make sure that the parameters are still in the queues */
2385       for(i=0; i<numparams; i++) {
2386         void * parameter=currtpd->parameterArray[i];
2387
2388         // flush the object
2389 #ifdef CACHEFLUSH
2390         BAMBOO_CACHE_FLUSH_RANGE((int)parameter, 
2391                         classsize[((struct ___Object___ *)parameter)->type]);
2392 #endif
2393         tmpparam = (struct ___Object___ *)parameter;
2394         pd=currtpd->task->descriptorarray[i];
2395         pw=(struct parameterwrapper *) pd->queue;
2396         /* Check that object is still in queue */
2397         {
2398           if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
2399 #ifdef DEBUG
2400             BAMBOO_DEBUGPRINT(0xe994);
2401 #endif
2402             // release grabbed locks
2403             for(j = 0; j < locklen; ++j) {
2404                 int * lock = (int *)(locks[j].redirectlock);
2405                 releasewritelock(lock);
2406             }
2407             RUNFREE(currtpd->parameterArray);
2408             RUNFREE(currtpd);
2409             goto newtask;
2410           }
2411         } // line2865
2412         /* Check if the object's flags still meets requirements */
2413         {
2414           int tmpi = 0;
2415           bool ismet = false;
2416           for(tmpi = 0; tmpi < pw->numberofterms; ++tmpi) {
2417             andmask=pw->intarray[tmpi*2];
2418             checkmask=pw->intarray[tmpi*2+1];
2419             if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
2420               ismet = true;
2421               break;
2422             }
2423           }
2424           if (!ismet) {
2425             // flags are never suitable
2426             // remove this obj from the queue
2427             int next;
2428             int UNUSED, UNUSED2;
2429             int * enterflags;
2430 #ifdef DEBUG
2431             BAMBOO_DEBUGPRINT(0xe995);
2432 #endif
2433             ObjectHashget(pw->objectset, (int) parameter, (int *) &next, 
2434                                                   (int *) &enterflags, &UNUSED, &UNUSED2);
2435             ObjectHashremove(pw->objectset, (int)parameter);
2436             if (enterflags!=NULL)
2437               RUNFREE(enterflags);
2438             // release grabbed locks
2439             for(j = 0; j < locklen; ++j) {
2440                  int * lock = (int *)(locks[j].redirectlock);
2441                 releasewritelock(lock);
2442             }
2443             RUNFREE(currtpd->parameterArray);
2444             RUNFREE(currtpd);
2445 #ifdef PROFILE
2446 #ifdef ACCURATEPROFILE
2447             // fail, set the end of the checkTaskInfo
2448                 profileTaskEnd();
2449 #endif
2450 #endif
2451             goto newtask;
2452           } // line 2878: if (!ismet)
2453         } // line 2867
2454 parameterpresent:
2455         ;
2456         /* Check that object still has necessary tags */
2457         for(j=0; j<pd->numbertags; j++) {
2458           int slotid=pd->tagarray[2*j]+numparams;
2459           struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
2460           if (!containstag(parameter, tagd)) {
2461 #ifdef DEBUG
2462             BAMBOO_DEBUGPRINT(0xe996);
2463 #endif
2464                 {
2465                 // release grabbed locks
2466                 int tmpj = 0;
2467             for(tmpj = 0; tmpj < locklen; ++tmpj) {
2468                  int * lock = (int *)(locks[tmpj].redirectlock);
2469                 releasewritelock(lock);
2470             }
2471                 }
2472             RUNFREE(currtpd->parameterArray);
2473             RUNFREE(currtpd);
2474             goto newtask;
2475           } // line2911: if (!containstag(parameter, tagd))
2476         } // line 2808: for(j=0; j<pd->numbertags; j++)
2477
2478         taskpointerarray[i+OFFSET]=parameter;
2479       } // line 2824: for(i=0; i<numparams; i++)
2480       /* Copy the tags */
2481       for(; i<numtotal; i++) {
2482         taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
2483       }
2484
2485       {
2486           /* Actually call task */
2487 #ifdef MULTICORE_GC
2488           ((int *)taskpointerarray)[0]=currtpd->numParameters;
2489           taskpointerarray[1]=NULL;
2490 #endif
2491 execute:
2492 #ifdef PROFILE
2493 #ifdef ACCURATEPROFILE
2494           // check finish, set the end of the checkTaskInfo
2495           profileTaskEnd();
2496 #endif
2497           profileTaskStart(currtpd->task->name);
2498 #endif
2499
2500 #ifdef DEBUG
2501                 BAMBOO_DEBUGPRINT(0xe997);
2502 #endif
2503                 ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
2504 #ifdef PROFILE
2505 #ifdef ACCURATEPROFILE
2506           // task finish, set the end of the checkTaskInfo
2507           profileTaskEnd();
2508           // new a PostTaskInfo for the post-task execution
2509           profileTaskStart("post task execution");
2510 #endif
2511 #endif
2512 #ifdef DEBUG
2513           BAMBOO_DEBUGPRINT(0xe998);
2514           BAMBOO_DEBUGPRINT_REG(islock);
2515 #endif
2516
2517           if(islock) {
2518 #ifdef DEBUG
2519                   BAMBOO_DEBUGPRINT(0xe999);
2520 #endif
2521             for(i = 0; i < locklen; ++i) {
2522                                 void * ptr = (void *)(locks[i].redirectlock);
2523               int * lock = (int *)(locks[i].value);
2524 #ifdef DEBUG
2525                   BAMBOO_DEBUGPRINT_REG((int)ptr);
2526                   BAMBOO_DEBUGPRINT_REG((int)lock);
2527 #endif
2528 #ifndef MULTICORE_GC
2529                   if(RuntimeHashcontainskey(lockRedirectTbl, (int)lock)) {
2530                           int redirectlock;
2531                           RuntimeHashget(lockRedirectTbl, (int)lock, &redirectlock);
2532                           RuntimeHashremovekey(lockRedirectTbl, (int)lock);
2533                           releasewritelock_r(lock, (int *)redirectlock);
2534                   } else {
2535 #else
2536                                 {
2537 #endif
2538                 releasewritelock(ptr);
2539                   }
2540             }
2541           } // line 3015: if(islock)
2542
2543 #ifdef PROFILE
2544           // post task execution finish, set the end of the postTaskInfo
2545           profileTaskEnd();
2546 #endif
2547
2548           // Free up task parameter descriptor
2549           RUNFREE(currtpd->parameterArray);
2550           RUNFREE(currtpd);
2551 #ifdef DEBUG
2552           BAMBOO_DEBUGPRINT(0xe99a);
2553 #endif
2554       } //  
2555     } //  if (hashsize(activetasks)>0)  
2556   } //  while(hashsize(activetasks)>0)
2557 #ifdef DEBUG
2558   BAMBOO_DEBUGPRINT(0xe99b);
2559 #endif
2560 }
2561
2562 /* This function processes an objects tags */
2563 void processtags(struct parameterdescriptor *pd, 
2564                              int index, 
2565                                                                  struct parameterwrapper *parameter, 
2566                                                                  int * iteratorcount, 
2567                                                                  int *statusarray, 
2568                                                                  int numparams) {
2569   int i;
2570
2571   for(i=0; i<pd->numbertags; i++) {
2572     int slotid=pd->tagarray[2*i];
2573     int tagid=pd->tagarray[2*i+1];
2574
2575     if (statusarray[slotid+numparams]==0) {
2576       parameter->iterators[*iteratorcount].istag=1;
2577       parameter->iterators[*iteratorcount].tagid=tagid;
2578       parameter->iterators[*iteratorcount].slot=slotid+numparams;
2579       parameter->iterators[*iteratorcount].tagobjectslot=index;
2580       statusarray[slotid+numparams]=1;
2581       (*iteratorcount)++;
2582     }
2583   }
2584 }
2585
2586
2587 void processobject(struct parameterwrapper *parameter, 
2588                                int index, 
2589                                                                          struct parameterdescriptor *pd, 
2590                                                                          int *iteratorcount, 
2591                                                                          int * statusarray, 
2592                                                                          int numparams) {
2593   int i;
2594   int tagcount=0;
2595   struct ObjectHash * objectset=
2596                 ((struct parameterwrapper *)pd->queue)->objectset;
2597
2598   parameter->iterators[*iteratorcount].istag=0;
2599   parameter->iterators[*iteratorcount].slot=index;
2600   parameter->iterators[*iteratorcount].objectset=objectset;
2601   statusarray[index]=1;
2602
2603   for(i=0; i<pd->numbertags; i++) {
2604     int slotid=pd->tagarray[2*i];
2605     //int tagid=pd->tagarray[2*i+1];
2606     if (statusarray[slotid+numparams]!=0) {
2607       /* This tag has already been enqueued, use it to narrow search */
2608       parameter->iterators[*iteratorcount].tagbindings[tagcount]=
2609                                 slotid+numparams;
2610       tagcount++;
2611     }
2612   }
2613   parameter->iterators[*iteratorcount].numtags=tagcount;
2614
2615   (*iteratorcount)++;
2616 }
2617
2618 /* This function builds the iterators for a task & parameter */
2619
2620 void builditerators(struct taskdescriptor * task, 
2621                                 int index, 
2622                                                                                 struct parameterwrapper * parameter) {
2623   int statusarray[MAXTASKPARAMS];
2624   int i;
2625   int numparams=task->numParameters;
2626   int iteratorcount=0;
2627   for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
2628
2629   statusarray[index]=1; /* Initial parameter */
2630   /* Process tags for initial iterator */
2631
2632   processtags(task->descriptorarray[index], index, parameter, 
2633                                 &iteratorcount, statusarray, numparams);
2634
2635   while(1) {
2636 loopstart:
2637     /* Check for objects with existing tags */
2638     for(i=0; i<numparams; i++) {
2639       if (statusarray[i]==0) {
2640         struct parameterdescriptor *pd=task->descriptorarray[i];
2641         int j;
2642         for(j=0; j<pd->numbertags; j++) {
2643           int slotid=pd->tagarray[2*j];
2644           if(statusarray[slotid+numparams]!=0) {
2645             processobject(parameter, i, pd, &iteratorcount, statusarray, 
2646                                                   numparams);
2647             processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2648             goto loopstart;
2649           }
2650         }
2651       }
2652     }
2653
2654     /* Next do objects w/ unbound tags*/
2655
2656     for(i=0; i<numparams; i++) {
2657       if (statusarray[i]==0) {
2658         struct parameterdescriptor *pd=task->descriptorarray[i];
2659         if (pd->numbertags>0) {
2660           processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2661           processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2662           goto loopstart;
2663         }
2664       }
2665     }
2666
2667     /* Nothing with a tag enqueued */
2668
2669     for(i=0; i<numparams; i++) {
2670       if (statusarray[i]==0) {
2671         struct parameterdescriptor *pd=task->descriptorarray[i];
2672         processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2673         processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2674         goto loopstart;
2675       }
2676     }
2677
2678     /* Nothing left */
2679     return;
2680   }
2681 }
2682
2683 void printdebug() {
2684   int i;
2685   int j;
2686   if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
2687     return;
2688   }
2689   for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
2690     struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
2691 #ifndef RAW 
2692         printf("%s\n", task->name);
2693 #endif
2694     for(j=0; j<task->numParameters; j++) {
2695       struct parameterdescriptor *param=task->descriptorarray[j];
2696       struct parameterwrapper *parameter=param->queue;
2697       struct ObjectHash * set=parameter->objectset;
2698       struct ObjectIterator objit;
2699 #ifndef RAW
2700           printf("  Parameter %d\n", j);
2701 #endif
2702       ObjectHashiterator(set, &objit);
2703       while(ObjhasNext(&objit)) {
2704         struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
2705         struct ___Object___ * tagptr=obj->___tags___;
2706         int nonfailed=Objdata4(&objit);
2707         int numflags=Objdata3(&objit);
2708         int flags=Objdata2(&objit);
2709         Objnext(&objit);
2710 #ifndef RAW
2711         printf("    Contains %lx\n", obj);
2712         printf("      flag=%d\n", obj->flag);
2713 #endif
2714         if (tagptr==NULL) {
2715         } else if (tagptr->type==TAGTYPE) {
2716 #ifndef RAW
2717           printf("      tag=%lx\n",tagptr);
2718 #else
2719           ;
2720 #endif
2721         } else {
2722           int tagindex=0;
2723           struct ArrayObject *ao=(struct ArrayObject *)tagptr;
2724           for(; tagindex<ao->___cachedCode___; tagindex++) {
2725 #ifndef RAW
2726                   printf("      tag=%lx\n",ARRAYGET(ao, struct ___TagDescriptor___*, 
2727                                                  tagindex));
2728 #else
2729                   ;
2730 #endif
2731           }
2732         }
2733       }
2734     }
2735   }
2736 }
2737
2738
2739 /* This function processes the task information to create queues for
2740    each parameter type. */
2741
2742 void processtasks() {
2743   int i;
2744   if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
2745     return;
2746   }
2747   for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
2748     struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
2749     int j;
2750
2751     /* Build objectsets */
2752     for(j=0; j<task->numParameters; j++) {
2753       struct parameterdescriptor *param=task->descriptorarray[j];
2754       struct parameterwrapper *parameter=param->queue;
2755       parameter->objectset=allocateObjectHash(10);
2756       parameter->task=task;
2757     }
2758
2759     /* Build iterators for parameters */
2760     for(j=0; j<task->numParameters; j++) {
2761       struct parameterdescriptor *param=task->descriptorarray[j];
2762       struct parameterwrapper *parameter=param->queue;
2763       builditerators(task, j, parameter);
2764     }
2765   }
2766 }
2767
2768 void toiReset(struct tagobjectiterator * it) {
2769   if (it->istag) {
2770     it->tagobjindex=0;
2771   } else if (it->numtags>0) {
2772     it->tagobjindex=0;
2773   } else {
2774     ObjectHashiterator(it->objectset, &it->it);
2775   }
2776 }
2777
2778 int toiHasNext(struct tagobjectiterator *it, 
2779                            void ** objectarray OPTARG(int * failed)) {
2780   if (it->istag) {
2781     /* Iterate tag */
2782     /* Get object with tags */
2783     struct ___Object___ *obj=objectarray[it->tagobjectslot];
2784     struct ___Object___ *tagptr=obj->___tags___;
2785     if (tagptr->type==TAGTYPE) {
2786       if ((it->tagobjindex==0)&& /* First object */
2787           (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
2788         return 1;
2789       else
2790         return 0;
2791     } else {
2792       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
2793       int tagindex=it->tagobjindex;
2794       for(; tagindex<ao->___cachedCode___; tagindex++) {
2795         struct ___TagDescriptor___ *td=
2796                 ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
2797         if (td->flag==it->tagid) {
2798           it->tagobjindex=tagindex; /* Found right type of tag */
2799           return 1;
2800         }
2801       }
2802       return 0;
2803     }
2804   } else if (it->numtags>0) {
2805     /* Use tags to locate appropriate objects */
2806     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
2807     struct ___Object___ *objptr=tag->flagptr;
2808     int i;
2809     if (objptr->type!=OBJECTARRAYTYPE) {
2810       if (it->tagobjindex>0)
2811         return 0;
2812       if (!ObjectHashcontainskey(it->objectset, (int) objptr))
2813         return 0;
2814       for(i=1; i<it->numtags; i++) {
2815         struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
2816         if (!containstag(objptr,tag2))
2817           return 0;
2818       }
2819       return 1;
2820     } else {
2821       struct ArrayObject *ao=(struct ArrayObject *) objptr;
2822       int tagindex;
2823       int i;
2824       for(tagindex=it->tagobjindex;tagindex<ao->___cachedCode___;tagindex++) {
2825         struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
2826         if (!ObjectHashcontainskey(it->objectset, (int) objptr))
2827           continue;
2828         for(i=1; i<it->numtags; i++) {
2829           struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
2830           if (!containstag(objptr,tag2))
2831             goto nexttag;
2832         }
2833         it->tagobjindex=tagindex;
2834         return 1;
2835 nexttag:
2836         ;
2837       }
2838       it->tagobjindex=tagindex;
2839       return 0;
2840     }
2841   } else {
2842     return ObjhasNext(&it->it);
2843   }
2844 }
2845
2846 int containstag(struct ___Object___ *ptr, 
2847                             struct ___TagDescriptor___ *tag) {
2848   int j;
2849   struct ___Object___ * objptr=tag->flagptr;
2850   if (objptr->type==OBJECTARRAYTYPE) {
2851     struct ArrayObject *ao=(struct ArrayObject *)objptr;
2852     for(j=0; j<ao->___cachedCode___; j++) {
2853       if (ptr==ARRAYGET(ao, struct ___Object___*, j))
2854         return 1;
2855     }
2856     return 0;
2857   } else
2858     return objptr==ptr;
2859 }
2860
2861 void toiNext(struct tagobjectiterator *it, 
2862                          void ** objectarray OPTARG(int * failed)) {
2863   /* hasNext has all of the intelligence */
2864   if(it->istag) {
2865     /* Iterate tag */
2866     /* Get object with tags */
2867     struct ___Object___ *obj=objectarray[it->tagobjectslot];
2868     struct ___Object___ *tagptr=obj->___tags___;
2869     if (tagptr->type==TAGTYPE) {
2870       it->tagobjindex++;
2871       objectarray[it->slot]=tagptr;
2872     } else {
2873       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
2874       objectarray[it->slot]=
2875                                 ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
2876     }
2877   } else if (it->numtags>0) {
2878     /* Use tags to locate appropriate objects */
2879     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
2880     struct ___Object___ *objptr=tag->flagptr;
2881     if (objptr->type!=OBJECTARRAYTYPE) {
2882       it->tagobjindex++;
2883       objectarray[it->slot]=objptr;
2884     } else {
2885       struct ArrayObject *ao=(struct ArrayObject *) objptr;
2886       objectarray[it->slot]=
2887                                 ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
2888     }
2889   } else {
2890     /* Iterate object */
2891     objectarray[it->slot]=(void *)Objkey(&it->it);
2892     Objnext(&it->it);
2893   }
2894 }
2895 #endif