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