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