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