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