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