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