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