3 #include "multicoreruntime.h"
4 #include "runtime_arch.h"
5 #include "GenericHashtable.h"
8 extern int injectfailures;
9 extern float failurechance;
14 void * curr_heapbase=0;
15 void * curr_heaptop=0;
18 #include "instrument.h"
20 #endif // if 0: for recovery
22 // data structures for task invocation
23 struct genhashtable * activetasks;
24 //struct genhashtable * failedtasks; // for recovery
25 struct taskparamdescriptor * currtpd;
27 struct RuntimeHash * forward;
28 struct RuntimeHash * reverse;
29 #endif // if 0: for recovery
31 // specific functions used inside critical sections
32 void enqueueObject_I(void * ptr, struct parameterwrapper ** queues, int length);
33 int enqueuetasks_I(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr, int * enterflags, int numenterflags);
35 // main function for each core
36 inline void run(void * arg) {
40 bool sendStall = false;
42 bool tocontinue = false;
43 struct transObjInfo * objInfo = NULL;
48 corenum = BAMBOO_GET_NUM_OF_CORE();
50 BAMBOO_DEBUGPRINT(0xeeee);
51 BAMBOO_DEBUGPRINT_REG(corenum);
52 BAMBOO_DEBUGPRINT(STARTUPCORE);
55 // initialize the arrays
56 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
57 // startup core to initialize corestatus[]
58 for(i = 0; i < NUMCORES; ++i) {
60 numsendobjs[i] = 0; // assume all variables are local variables! MAY BE WRONG!!!
61 numreceiveobjs[i] = 0;
66 // initialize the profile data arrays
67 for(i = 0; i < NUMCORES; ++i) {
76 self_numreceiveobjs = 0;
78 for(i = 0; i < 30; ++i) {
84 for(i = 0; i < 30; ++i) {
94 bamboo_cur_msp = NULL;
97 // create the lock table, lockresult table and obj queue
99 locktable.bucket = (struct RuntimeNode **) RUNMALLOC_I(sizeof(struct RuntimeNode *)*20);
100 /* Set allocation blocks*/
101 locktable.listhead=NULL;
102 locktable.listtail=NULL;
104 locktable.numelements = 0;
112 objqueue.head = NULL;
113 objqueue.tail = NULL;
114 lockRedirectTbl = allocateRuntimeHash(20);
115 objRedirectLockTbl = allocateRuntimeHash(20);
119 //isInterrupt = true;
122 taskInfoOverflow = false;
123 /*interruptInfoIndex = 0;
124 interruptInfoOverflow = false;*/
127 // other architecture related initialization
134 GC_init(); // Initialize the garbage collector
140 #endif // #if 0: for recovery and garbage collection
141 initializeexithandler();
143 // main process of the execution module
144 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
145 // non-executing cores, only processing communications
146 //failedtasks = NULL;
149 BAMBOO_DEBUGPRINT(0xee01);
150 BAMBOO_DEBUGPRINT_REG(taskInfoIndex);
151 BAMBOO_DEBUGPRINT_REG(taskInfoOverflow);
152 profileTaskStart("msg handling");
156 //isInterrupt = false;
160 /* Create table for failed tasks */
162 failedtasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd,
163 (int (*)(void *,void *)) &comparetpd);
164 #endif // #if 0: for recovery
165 /* Create queue of active tasks */
166 activetasks=genallocatehashtable((unsigned int(*) (void *)) &hashCodetpd,
167 (int(*) (void *,void *)) &comparetpd);
169 /* Process task information */
172 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
173 /* Create startup object */
174 createstartupobject(argc, argv);
178 BAMBOO_DEBUGPRINT(0xee00);
182 // check if there are new active tasks can be executed
186 while(receiveObject() != -1) {
191 BAMBOO_DEBUGPRINT(0xee01);
194 // check if there are some pending objects, if yes, enqueue them and executetasks again
197 #ifdef ACCURATEPROFILE
199 bool isChecking = false;
200 if(!isEmpty(&objqueue)) {
201 profileTaskStart("objqueue checking");
206 while(!isEmpty(&objqueue)) {
208 BAMBOO_START_CRITICAL_SECTION_OBJ_QUEUE();
210 BAMBOO_DEBUGPRINT(0xf001);
213 //isInterrupt = false;
216 BAMBOO_DEBUGPRINT(0xeee1);
220 objInfo = (struct transObjInfo *)getItem(&objqueue);
221 obj = objInfo->objptr;
223 BAMBOO_DEBUGPRINT_REG((int)obj);
225 // grab lock and flush the obj
229 BAMBOO_WAITING_FOR_LOCK();
233 BAMBOO_DEBUGPRINT_REG(grount);
248 BAMBOO_CACHE_FLUSH_RANGE((int)obj,sizeof(int));
249 BAMBOO_CACHE_FLUSH_RANGE((int)obj, classsize[((struct ___Object___ *)obj)->type]);
251 // enqueue the object
252 for(k = 0; k < objInfo->length; ++k) {
253 int taskindex = objInfo->queues[2 * k];
254 int paramindex = objInfo->queues[2 * k + 1];
255 struct parameterwrapper ** queues = &(paramqueues[BAMBOO_NUM_OF_CORE][taskindex][paramindex]);
257 BAMBOO_DEBUGPRINT_REG(taskindex);
258 BAMBOO_DEBUGPRINT_REG(paramindex);
259 struct ___Object___ * tmpptr = (struct ___Object___ *)obj;
260 tprintf("Process %x(%d): receive obj %x(%lld), ptrflag %x\n", BAMBOO_NUM_OF_CORE, BAMBOO_NUM_OF_CORE, (int)obj, (long)obj, tmpptr->flag);
262 enqueueObject_I(obj, queues, 1);
264 BAMBOO_DEBUGPRINT_REG(hashsize(activetasks));
267 releasewritelock_I(obj);
268 RUNFREE(objInfo->queues);
272 // put it at the end of the queue if no update version in the queue
273 struct QueueItem * qitem = getHead(&objqueue);
274 struct QueueItem * prev = NULL;
275 while(qitem != NULL) {
276 struct transObjInfo * tmpinfo = (struct transObjInfo *)(qitem->objectptr);
277 if(tmpinfo->objptr == obj) {
278 // the same object in the queue, which should be enqueued
279 // recently. Current one is outdate, do not re-enqueue it
280 RUNFREE(objInfo->queues);
286 qitem = getNextQueueItem(prev);
288 // try to execute active tasks already enqueued first
289 addNewItem_I(&objqueue, objInfo);
291 //isInterrupt = true;
294 BAMBOO_CLOSE_CRITICAL_SECTION_OBJ_QUEUE();
296 BAMBOO_DEBUGPRINT(0xf000);
300 BAMBOO_CLOSE_CRITICAL_SECTION_OBJ_QUEUE();
302 BAMBOO_DEBUGPRINT(0xf000);
306 #ifdef ACCURATEPROFILE
314 BAMBOO_DEBUGPRINT(0xee02);
319 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
322 BAMBOO_DEBUGPRINT(0xee03);
327 (waitconfirm && (numconfirm == 0))) {
329 BAMBOO_DEBUGPRINT(0xee04);
330 BAMBOO_DEBUGPRINT_REG(waitconfirm);
332 BAMBOO_START_CRITICAL_SECTION_STATUS();
334 BAMBOO_DEBUGPRINT(0xf001);
336 corestatus[BAMBOO_NUM_OF_CORE] = 0;
337 numsendobjs[BAMBOO_NUM_OF_CORE] = self_numsendobjs;
338 numreceiveobjs[BAMBOO_NUM_OF_CORE] = self_numreceiveobjs;
339 // check the status of all cores
342 BAMBOO_DEBUGPRINT_REG(NUMCORES);
344 for(i = 0; i < NUMCORES; ++i) {
346 BAMBOO_DEBUGPRINT(0xe000 + corestatus[i]);
348 if(corestatus[i] != 0) {
354 // check if the sum of send objs and receive obj are the same
355 // yes->check if the info is the latest; no->go on executing
357 for(i = 0; i < NUMCORES; ++i) {
358 sumsendobj += numsendobjs[i];
360 BAMBOO_DEBUGPRINT(0xf000 + numsendobjs[i]);
363 for(i = 0; i < NUMCORES; ++i) {
364 sumsendobj -= numreceiveobjs[i];
366 BAMBOO_DEBUGPRINT(0xf000 + numreceiveobjs[i]);
369 if(0 == sumsendobj) {
371 // the first time found all cores stall
372 // send out status confirm msg to all other cores
373 // reset the corestatus array too
375 BAMBOO_DEBUGPRINT(0xee05);
377 corestatus[BAMBOO_NUM_OF_CORE] = 1;
378 for(i = 1; i < NUMCORES; ++i) {
380 // send status confirm msg to core i
381 send_msg_1(i, STATUSCONFIRM);
384 numconfirm = NUMCORES - 1;
386 // all the core status info are the latest
387 // terminate; for profiling mode, send request to all
388 // other cores to pour out profiling data
390 BAMBOO_DEBUGPRINT(0xee06);
394 totalexetime = BAMBOO_GET_EXE_TIME();
396 BAMBOO_DEBUGPRINT(BAMBOO_GET_EXE_TIME());
397 BAMBOO_DEBUGPRINT_REG(total_num_t6); // TODO for test
398 BAMBOO_DEBUGPRINT(0xbbbbbbbb);
400 // profile mode, send msgs to other cores to request pouring
401 // out progiling data
403 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
405 BAMBOO_DEBUGPRINT(0xf000);
407 for(i = 1; i < NUMCORES; ++i) {
408 // send profile request msg to core i
409 send_msg_2(i, PROFILEOUTPUT, totalexetime);
411 // pour profiling data on startup core
414 BAMBOO_START_CRITICAL_SECTION_STATUS();
416 BAMBOO_DEBUGPRINT(0xf001);
418 profilestatus[BAMBOO_NUM_OF_CORE] = 0;
419 // check the status of all cores
422 BAMBOO_DEBUGPRINT_REG(NUMCORES);
424 for(i = 0; i < NUMCORES; ++i) {
426 BAMBOO_DEBUGPRINT(0xe000 + profilestatus[i]);
428 if(profilestatus[i] != 0) {
435 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
437 BAMBOO_DEBUGPRINT(0xf000);
446 terminate(); // All done.
447 } // if-else of line 364: if(!waitconfirm)
449 // still some objects on the fly on the network
450 // reset the waitconfirm and numconfirm
452 BAMBOO_DEBUGPRINT(0xee07);
456 } // if-else of line 363: if(0 == sumsendobj)
458 // not all cores are stall, keep on waiting
460 BAMBOO_DEBUGPRINT(0xee08);
464 } // if-else of line 347: if(allStall)
465 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
467 BAMBOO_DEBUGPRINT(0xf000);
469 } // if-else of line 320: if((!waitconfirm) ||
473 BAMBOO_DEBUGPRINT(0xee09);
479 // wait for some time
482 BAMBOO_DEBUGPRINT(0xee0a);
488 // send StallMsg to startup core
490 BAMBOO_DEBUGPRINT(0xee0b);
493 send_msg_4(STARTUPCORE, 1, BAMBOO_NUM_OF_CORE, self_numsendobjs, self_numreceiveobjs);
505 BAMBOO_DEBUGPRINT(0xee0c);
507 } // if-else of line 464: if(!sendStall)
508 } // if-else of line 313: if(STARTUPCORE == BAMBOO_NUM_OF_CORE)
509 } // if-else of line 311: if(!tocontinue)
510 } // line 193: while(true)
511 } // right-bracket for if-else of line 153: if(BAMBOO_NUM_OF_CORE > NUMCORES - 1)
515 void createstartupobject(int argc, char ** argv) {
518 /* Allocate startup object */
521 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(NULL, STARTUPTYPE);
522 struct ArrayObject * stringarray=allocate_newarray(NULL, STRINGARRAYTYPE, argc-1);
524 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
525 struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1);
527 #endif // #if 0: for garbage collection
528 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
529 struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1);
530 /* Build array of strings */
531 startupobject->___parameters___=stringarray;
532 for(i=1; i<argc; i++) {
533 int length=strlen(argv[i]);
536 struct ___String___ *newstring=NewString(NULL, argv[i],length);
538 struct ___String___ *newstring=NewString(argv[i],length);
540 #endif // #if 0: for garbage collection
541 struct ___String___ *newstring=NewString(argv[i],length);
542 ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=newstring;
545 startupobject->version = 0;
546 startupobject->lock = NULL;
548 /* Set initialized flag for startup object */
549 flagorandinit(startupobject,1,0xFFFFFFFF);
550 enqueueObject(startupobject, NULL, 0);
552 BAMBOO_CACHE_FLUSH_ALL();
556 int hashCodetpd(struct taskparamdescriptor *ftd) {
557 int hash=(int)ftd->task;
559 for(i=0; i<ftd->numParameters; i++) {
560 hash^=(int)ftd->parameterArray[i];
565 int comparetpd(struct taskparamdescriptor *ftd1, struct taskparamdescriptor *ftd2) {
567 if (ftd1->task!=ftd2->task)
569 for(i=0; i<ftd1->numParameters; i++)
570 if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
575 /* This function sets a tag. */
578 void tagset(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
580 void tagset(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
582 #endif // #if 0: for garbage collection
583 void tagset(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
584 struct ArrayObject * ao=NULL;
585 struct ___Object___ * tagptr=obj->___tags___;
587 obj->___tags___=(struct ___Object___ *)tagd;
589 /* Have to check if it is already set */
590 if (tagptr->type==TAGTYPE) {
591 struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
597 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
598 struct ArrayObject * ao=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
599 obj=(struct ___Object___ *)ptrarray[2];
600 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
601 td=(struct ___TagDescriptor___ *) obj->___tags___;
603 ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
605 #endif // #if 0: for garbage collection
606 ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
608 ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
609 ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
610 obj->___tags___=(struct ___Object___ *) ao;
611 ao->___cachedCode___=2;
615 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
616 for(i=0; i<ao->___cachedCode___; i++) {
617 struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___*, i);
622 if (ao->___cachedCode___<ao->___length___) {
623 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
624 ao->___cachedCode___++;
628 int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
629 struct ArrayObject * aonew=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
630 obj=(struct ___Object___ *)ptrarray[2];
631 tagd=(struct ___TagDescriptor___ *) ptrarray[3];
632 ao=(struct ArrayObject *)obj->___tags___;
634 struct ArrayObject * aonew=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
636 #endif // #if 0: for garbage collection
637 struct ArrayObject * aonew=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
639 aonew->___cachedCode___=ao->___length___+1;
640 for(i=0; i<ao->___length___; i++) {
641 ARRAYSET(aonew, struct ___TagDescriptor___*, i, ARRAYGET(ao, struct ___TagDescriptor___*, i));
643 ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
649 struct ___Object___ * tagset=tagd->flagptr;
652 } else if (tagset->type!=OBJECTARRAYTYPE) {
655 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
656 struct ArrayObject * ao=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
657 obj=(struct ___Object___ *)ptrarray[2];
658 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
660 struct ArrayObject * ao=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
662 #endif // #if 0: for garbage collection
663 struct ArrayObject * ao=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
664 ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
665 ARRAYSET(ao, struct ___Object___ *, 1, obj);
666 ao->___cachedCode___=2;
667 tagd->flagptr=(struct ___Object___ *)ao;
669 struct ArrayObject *ao=(struct ArrayObject *) tagset;
670 if (ao->___cachedCode___<ao->___length___) {
671 ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
676 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
677 struct ArrayObject * aonew=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL+ao->___length___);
678 obj=(struct ___Object___ *)ptrarray[2];
679 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
680 ao=(struct ArrayObject *)tagd->flagptr;
682 struct ArrayObject * aonew=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
684 #endif // #if 0: for garbage collection
685 struct ArrayObject * aonew=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
686 aonew->___cachedCode___=ao->___cachedCode___+1;
687 for(i=0; i<ao->___length___; i++) {
688 ARRAYSET(aonew, struct ___Object___*, i, ARRAYGET(ao, struct ___Object___*, i));
690 ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
691 tagd->flagptr=(struct ___Object___ *) aonew;
697 /* This function clears a tag. */
700 void tagclear(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
702 void tagclear(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
704 #endif // #if 0: for garbage collection
705 void tagclear(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
706 /* We'll assume that tag is alway there.
707 Need to statically check for this of course. */
708 struct ___Object___ * tagptr=obj->___tags___;
710 if (tagptr->type==TAGTYPE) {
711 if ((struct ___TagDescriptor___ *)tagptr==tagd)
712 obj->___tags___=NULL;
715 printf("ERROR 1 in tagclear\n");
720 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
722 for(i=0; i<ao->___cachedCode___; i++) {
723 struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___ *, i);
725 ao->___cachedCode___--;
726 if (i<ao->___cachedCode___)
727 ARRAYSET(ao, struct ___TagDescriptor___ *, i, ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
728 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
729 if (ao->___cachedCode___==0)
730 obj->___tags___=NULL;
735 printf("ERROR 2 in tagclear\n");
740 struct ___Object___ *tagset=tagd->flagptr;
741 if (tagset->type!=OBJECTARRAYTYPE) {
746 printf("ERROR 3 in tagclear\n");
751 struct ArrayObject *ao=(struct ArrayObject *) tagset;
753 for(i=0; i<ao->___cachedCode___; i++) {
754 struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
756 ao->___cachedCode___--;
757 if (i<ao->___cachedCode___)
758 ARRAYSET(ao, struct ___Object___ *, i, ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
759 ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
760 if (ao->___cachedCode___==0)
766 printf("ERROR 4 in tagclear\n");
775 /* This function allocates a new tag. */
777 struct ___TagDescriptor___ * allocate_tag(void *ptr, int index) {
778 struct ___TagDescriptor___ * v=(struct ___TagDescriptor___ *) mygcmalloc((struct garbagelist *) ptr, classsize[TAGTYPE]);
780 struct ___TagDescriptor___ * allocate_tag(int index) {
781 struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
783 #endif // #if 0: for garbage collection
784 struct ___TagDescriptor___ * allocate_tag(int index) {
785 struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
793 /* This function updates the flag for object ptr. It or's the flag
794 with the or mask and and's it with the andmask. */
796 void flagbody(struct ___Object___ *ptr, int flag, struct parameterwrapper ** queues, int length, bool isnew);
798 int flagcomp(const int *val1, const int *val2) {
799 return (*val1)-(*val2);
802 void flagorand(void * ptr, int ormask, int andmask, struct parameterwrapper ** queues, int length) {
804 int oldflag=((int *)ptr)[1];
805 int flag=ormask|oldflag;
807 flagbody(ptr, flag, queues, length, false);
811 bool intflagorand(void * ptr, int ormask, int andmask) {
813 int oldflag=((int *)ptr)[1];
814 int flag=ormask|oldflag;
816 if (flag==oldflag) /* Don't do anything */
819 flagbody(ptr, flag, NULL, 0, false);
825 void flagorandinit(void * ptr, int ormask, int andmask) {
826 int oldflag=((int *)ptr)[1];
827 int flag=ormask|oldflag;
829 flagbody(ptr,flag,NULL,0,true);
832 void flagbody(struct ___Object___ *ptr, int flag, struct parameterwrapper ** vqueues, int vlength, bool isnew) {
833 struct parameterwrapper * flagptr = NULL;
835 struct parameterwrapper ** queues = vqueues;
836 int length = vlength;
839 int * enterflags = NULL;
840 if((!isnew) && (queues == NULL)) {
841 if(BAMBOO_NUM_OF_CORE < NUMCORES) {
842 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
843 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
850 /*Remove object from all queues */
851 for(i = 0; i < length; ++i) {
853 ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
854 ObjectHashremove(flagptr->objectset, (int)ptr);
855 if (enterflags!=NULL)
860 void enqueueObject(void * vptr, struct parameterwrapper ** vqueues, int vlength) {
861 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
864 //struct QueueItem *tmpptr;
865 struct parameterwrapper * parameter=NULL;
868 struct parameterwrapper * prevptr=NULL;
869 struct ___Object___ *tagptr=NULL;
870 struct parameterwrapper ** queues = vqueues;
871 int length = vlength;
872 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
876 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
877 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
879 tagptr=ptr->___tags___;
881 /* Outer loop iterates through all parameter queues an object of
882 this type could be in. */
883 for(j = 0; j < length; ++j) {
884 parameter = queues[j];
886 if (parameter->numbertags>0) {
888 goto nextloop; //that means the object has no tag but that param needs tag
889 else if(tagptr->type==TAGTYPE) { //one tag
890 //struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
891 for(i=0; i<parameter->numbertags; i++) {
892 //slotid is parameter->tagarray[2*i];
893 int tagid=parameter->tagarray[2*i+1];
894 if (tagid!=tagptr->flag)
895 goto nextloop; /*We don't have this tag */
897 } else { //multiple tags
898 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
899 for(i=0; i<parameter->numbertags; i++) {
900 //slotid is parameter->tagarray[2*i];
901 int tagid=parameter->tagarray[2*i+1];
903 for(j=0; j<ao->___cachedCode___; j++) {
904 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
915 for(i=0; i<parameter->numberofterms; i++) {
916 int andmask=parameter->intarray[i*2];
917 int checkmask=parameter->intarray[i*2+1];
918 if ((ptr->flag&andmask)==checkmask) {
919 enqueuetasks(parameter, prevptr, ptr, NULL, 0);
930 void enqueueObject_I(void * vptr, struct parameterwrapper ** vqueues, int vlength) {
931 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
934 //struct QueueItem *tmpptr;
935 struct parameterwrapper * parameter=NULL;
938 struct parameterwrapper * prevptr=NULL;
939 struct ___Object___ *tagptr=NULL;
940 struct parameterwrapper ** queues = vqueues;
941 int length = vlength;
942 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
946 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
947 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
949 tagptr=ptr->___tags___;
951 /* Outer loop iterates through all parameter queues an object of
952 this type could be in. */
953 for(j = 0; j < length; ++j) {
954 parameter = queues[j];
956 if (parameter->numbertags>0) {
958 goto nextloop; //that means the object has no tag but that param needs tag
959 else if(tagptr->type==TAGTYPE) { //one tag
960 //struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
961 for(i=0; i<parameter->numbertags; i++) {
962 //slotid is parameter->tagarray[2*i];
963 int tagid=parameter->tagarray[2*i+1];
964 if (tagid!=tagptr->flag)
965 goto nextloop; /*We don't have this tag */
967 } else { //multiple tags
968 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
969 for(i=0; i<parameter->numbertags; i++) {
970 //slotid is parameter->tagarray[2*i];
971 int tagid=parameter->tagarray[2*i+1];
973 for(j=0; j<ao->___cachedCode___; j++) {
974 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
985 for(i=0; i<parameter->numberofterms; i++) {
986 int andmask=parameter->intarray[i*2];
987 int checkmask=parameter->intarray[i*2+1];
988 if ((ptr->flag&andmask)==checkmask) {
989 enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
1001 int * getAliasLock(void ** ptrs, int length, struct RuntimeHash * tbl) {
1003 return (int*)(RUNMALLOC(sizeof(int)));
1008 bool redirect = false;
1009 int redirectlock = 0;
1010 for(; i < length; i++) {
1011 struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
1014 if(ptr->lock == NULL) {
1017 lock = (int)(ptr->lock);
1020 if(lock != redirectlock) {
1021 RuntimeHashadd(tbl, lock, redirectlock);
1024 if(RuntimeHashcontainskey(tbl, lock)) {
1025 // already redirected
1027 RuntimeHashget(tbl, lock, &redirectlock);
1028 for(; j < locklen; j++) {
1029 if(locks[j] != redirectlock) {
1030 RuntimeHashadd(tbl, locks[j], redirectlock);
1035 for(j = 0; j < locklen; j++) {
1036 if(locks[j] == lock) {
1039 } else if(locks[j] > lock) {
1046 locks[h] = locks[h-1];
1055 return (int *)redirectlock;
1057 return (int *)(locks[0]);
1062 void addAliasLock(void * ptr, int lock) {
1063 struct ___Object___ * obj = (struct ___Object___ *)ptr;
1064 if(((int)ptr != lock) && (obj->lock != (int*)lock)) {
1065 // originally no alias lock associated or have a different alias lock
1066 // flush it as the new one
1067 obj->lock = (int *)lock;
1072 inline void setTaskExitIndex(int index) {
1073 taskInfoArray[taskInfoIndex]->exitIndex = index;
1076 inline void addNewObjInfo(void * nobj) {
1077 if(taskInfoArray[taskInfoIndex]->newObjs == NULL) {
1078 taskInfoArray[taskInfoIndex]->newObjs = createQueue();
1080 addNewItem(taskInfoArray[taskInfoIndex]->newObjs, nobj);
1084 // receive object transferred from other cores
1085 // or the terminate message from other cores
1086 // Should be invoked in critical sections!!
1087 // NOTICE: following format is for threadsimulate version only
1088 // RAW version please see previous description
1089 // format: type + object
1090 // type: -1--stall msg
1092 // return value: 0--received an object
1093 // 1--received nothing
1094 // 2--received a Stall Msg
1095 // 3--received a lock Msg
1096 // RAW version: -1 -- received nothing
1097 // otherwise -- received msg type
1098 int receiveObject() {
1102 if(receiveMsg() == -1) {
1106 if(msgdataindex == msglength) {
1107 // received a whole msg
1109 int data1; // will receive at least 2 words including type
1114 // receive a object transfer msg
1115 struct transObjInfo * transObj = RUNMALLOC_I(sizeof(struct transObjInfo));
1119 BAMBOO_DEBUGPRINT(0xe880);
1122 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1124 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1126 BAMBOO_EXIT(0xa005);
1128 // store the object and its corresponding queue info, enqueue it later
1129 transObj->objptr = (void *)msgdata[2]; // data1 is now size of the msg
1130 transObj->length = (msglength - 3) / 2;
1131 transObj->queues = RUNMALLOC_I(sizeof(int)*(msglength - 3));
1132 for(k = 0; k < transObj->length; ++k) {
1133 transObj->queues[2*k] = msgdata[3+2*k];
1136 BAMBOO_DEBUGPRINT_REG(transObj->queues[2*k]);
1139 transObj->queues[2*k+1] = msgdata[3+2*k+1];
1142 BAMBOO_DEBUGPRINT_REG(transObj->queues[2*k+1]);
1146 // check if there is an existing duplicate item
1148 struct QueueItem * qitem = getHead(&objqueue);
1149 struct QueueItem * prev = NULL;
1150 while(qitem != NULL) {
1151 struct transObjInfo * tmpinfo =
1152 (struct transObjInfo *)(qitem->objectptr);
1153 if(tmpinfo->objptr == transObj->objptr) {
1154 // the same object, remove outdate one
1155 removeItem(&objqueue, qitem);
1161 qitem = getHead(&objqueue);
1163 qitem = getNextQueueItem(prev);
1166 addNewItem_I(&objqueue, (void *)transObj);
1168 ++(self_numreceiveobjs);
1173 // receive a stall msg
1174 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1175 // non startup core can not receive stall msg
1177 BAMBOO_DEBUGPRINT_REG(data1);
1179 BAMBOO_EXIT(0xa006);
1181 if(data1 < NUMCORES) {
1184 BAMBOO_DEBUGPRINT(0xe881);
1187 corestatus[data1] = 0;
1188 numsendobjs[data1] = msgdata[2];
1189 numreceiveobjs[data1] = msgdata[3];
1195 // receive lock request msg, handle it right now
1196 // check to see if there is a lock exist for the required obj
1197 // data1 -> lock type
1198 int data2 = msgdata[2]; // obj pointer
1199 int data3 = msgdata[3]; // lock
1200 int data4 = msgdata[4]; // request core
1201 deny = processlockrequest(data1, data3, data2, data4, data4, true); // -1: redirected, 0: approved, 1: denied
1203 // this lock request is redirected
1206 // send response msg
1207 // for 32 bit machine, the size is always 4 words
1208 int tmp = deny==1?LOCKDENY:LOCKGROUNT;
1210 cache_msg_4(data4, tmp, data1, data2, data3);
1212 send_msg_4(data4, tmp, data1, data2, data3);
1219 // receive lock grount msg
1220 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1222 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1224 BAMBOO_EXIT(0xa007);
1226 if((lockobj == msgdata[2]) && (lock2require == msgdata[3])) {
1229 BAMBOO_DEBUGPRINT(0xe882);
1238 // conflicts on lockresults
1240 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1242 BAMBOO_EXIT(0xa008);
1248 // receive lock deny msg
1249 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1251 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1253 BAMBOO_EXIT(0xa009);
1255 if((lockobj == msgdata[2]) && (lock2require == msgdata[3])) {
1258 BAMBOO_DEBUGPRINT(0xe883);
1267 // conflicts on lockresults
1269 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1271 BAMBOO_EXIT(0xa00a);
1277 // receive lock release msg
1278 processlockrelease(data1, msgdata[2], 0, false);
1283 case PROFILEOUTPUT: {
1284 // receive an output profile data request msg
1285 if(BAMBOO_NUM_OF_CORE == STARTUPCORE) {
1286 // startup core can not receive profile output finish msg
1287 BAMBOO_EXIT(0xa00c);
1291 BAMBOO_DEBUGPRINT(0xe885);
1295 totalexetime = data1;
1296 outputProfileData();
1298 cache_msg_2(STARTUPCORE, PROFILEFINISH, BAMBOO_NUM_OF_CORE);
1300 send_msg_2(STARTUPCORE, PROFILEFINISH, BAMBOO_NUM_OF_CORE);
1305 case PROFILEFINISH: {
1306 // receive a profile output finish msg
1307 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1308 // non startup core can not receive profile output finish msg
1310 BAMBOO_DEBUGPRINT_REG(data1);
1312 BAMBOO_EXIT(0xa00d);
1316 BAMBOO_DEBUGPRINT(0xe886);
1319 profilestatus[data1] = 0;
1324 case REDIRECTLOCK: {
1325 // receive a redirect lock request msg, handle it right now
1326 // check to see if there is a lock exist for the required obj
1327 // data1 -> lock type
1328 int data2 = msgdata[2]; // obj pointer
1329 int data3 = msgdata[3]; // redirect lock
1330 int data4 = msgdata[4]; // root request core
1331 int data5 = msgdata[5]; // request core
1332 deny = processlockrequest(data1, data3, data2, data5, data4, true);
1334 // this lock request is redirected
1337 // send response msg
1338 // for 32 bit machine, the size is always 4 words
1340 cache_msg_4(data4, deny==1?REDIRECTDENY:REDIRECTGROUNT,
1341 data1, data2, data3);
1343 send_msg_4(data4, deny==1?REDIRECTDENY:REDIRECTGROUNT,
1344 data1, data2, data3);
1350 case REDIRECTGROUNT: {
1351 // receive a lock grant msg with redirect info
1352 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1354 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1356 BAMBOO_EXIT(0xa00e);
1358 if(lockobj == msgdata[2]) {
1361 BAMBOO_DEBUGPRINT(0xe891);
1366 RuntimeHashadd_I(objRedirectLockTbl, lockobj, msgdata[3]);
1371 // conflicts on lockresults
1373 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1375 BAMBOO_EXIT(0xa00f);
1380 case REDIRECTDENY: {
1381 // receive a lock deny msg with redirect info
1382 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1384 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1386 BAMBOO_EXIT(0xa010);
1388 if(lockobj == msgdata[2]) {
1391 BAMBOO_DEBUGPRINT(0xe892);
1400 // conflicts on lockresults
1402 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1404 BAMBOO_EXIT(0xa011);
1409 case REDIRECTRELEASE: {
1410 // receive a lock release msg with redirect info
1411 processlockrelease(data1, msgdata[2], msgdata[3], true);
1415 case STATUSCONFIRM: {
1416 // receive a status confirm info
1417 if((BAMBOO_NUM_OF_CORE == STARTUPCORE)
1418 || (BAMBOO_NUM_OF_CORE > NUMCORES - 1)) {
1419 // wrong core to receive such msg
1420 BAMBOO_EXIT(0xa013);
1422 // send response msg
1425 BAMBOO_DEBUGPRINT(0xe887);
1429 cache_msg_3(STARTUPCORE, STATUSREPORT,
1430 busystatus?1:0, BAMBOO_NUM_OF_CORE);
1432 send_msg_3(STARTUPCORE, STATUSREPORT,
1433 busystatus?1:0, BAMBOO_NUM_OF_CORE);
1439 case STATUSREPORT: {
1440 // receive a status confirm info
1441 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1442 // wrong core to receive such msg
1444 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1446 BAMBOO_EXIT(0xa014);
1450 BAMBOO_DEBUGPRINT(0xe888);
1456 corestatus[msgdata[2]] = msgdata[1];
1462 // receive a terminate msg
1465 BAMBOO_DEBUGPRINT(0xe889);
1473 // receive a shared memory request msg
1474 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1475 // wrong core to receive such msg
1477 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1479 BAMBOO_EXIT(0xa015);
1483 BAMBOO_DEBUGPRINT(0xe88a);
1486 // TODO change for GC
1487 void * mem = mspace_calloc(bamboo_free_msp, 1, msgdata[1]);
1489 BAMBOO_DEBUGPRINT(0xa016);
1490 BAMBOO_EXIT(0xa016);
1492 // send the start_va to request core
1494 cache_msg_3(msgdata[2], MEMRESPONSE, mem, msgdata[1]);
1496 send_msg_3( msgdata[2], MEMRESPONSE, mem, msgdata[1]);
1503 // receive a shared memory response msg
1506 BAMBOO_DEBUGPRINT(0xe88b);
1509 if(msgdata[2] == 0) {
1510 bamboo_smem_size = 0;
1511 bamboo_cur_msp = NULL;
1513 bamboo_smem_size = msgdata[2];
1514 bamboo_cur_msp = create_mspace_with_base((void*)msgdata[1], msgdata[2], 0);
1523 // receive a start GC msg
1526 BAMBOO_DEBUGPRINT(0xe88c);
1534 case GCSTARTCOMPACT: {
1535 // a compact phase start msg
1536 if(cinstruction == NULL) {
1538 (struct compactInstr *)RUNMALLOC(sizeof(struct compactInstr));
1540 // clean up out of data info
1541 if(cinstruction->tomoveobjs != NULL) {
1542 RUNFREE(cinstruction->tomoveobjs->starts);
1543 RUNFREE(cinstruction->tomoveobjs->ends);
1544 RUNFREE(cinstruction->tomoveobjs->dststarts);
1545 RUNFREE(cinstruction->tomoveobjs->dsts);
1546 RUNFREE(cinstruction->tomoveobjs);
1547 cinstruction->tomoveobjs = NULL;
1549 if(cinstruction->incomingobjs != NULL) {
1551 RUNFREE(cinstruction->incomingobjs->starts);
1552 RUNFREE(cinstruction->incomingobjs->dsts);
1553 RUNFREE(cinstruction->incomingobjs);
1554 cinstruction->incomingobjs = NULL;
1556 // largeobj items should have been freed when processed
1557 if(cinstruction->largeobjs != NULL) {
1558 BAMBOO_EXIT(0xb005);
1562 // have objs to move etc.
1564 // process objs to move
1565 int num = msgdata[startindex++];
1567 cinstruction->tomoveobjs =
1568 (struct moveObj *)RUNMALLOC(sizeof(struct moveObj));
1569 cinstruction->tomoveobjs->length = num;
1570 cinstruction->tomoveobjs->starts =
1571 (INTPTR *)RUNMALLOC(num * sizeof(INTPTR));
1572 cinstruction->tomoveobjs->ends =
1573 (INTPTR *)RUNMALLOC(num * sizeof(INTPTR));
1574 cinstruction->tomoveobjs->dststarts =
1575 (INTPTR *)RUNMALLOC(num * sizeof(INTPTR));
1576 cinstruction->tomoveobjs->dsts =
1577 (INTPTR *)RUNMALLOC(num * sizeof(INTPTR));
1578 for(i = 0; i < num; i++) {
1579 cinstruction->tomoveobjs->starts[i] = msgdata[startindex++];
1580 cinstruction->tomoveobjs->ends[i] = msgdata[startindex++];
1581 cinstruction->tomoveobjs->dsts[i] = msgdata[startindex++];
1582 cinstruction->tomoveobjs->dststarts[i] = msgdata[startindex++];
1585 // process incoming objs
1586 num = msgdata[startindex++];
1588 cinstruction->incomingobjs =
1589 (struct moveObj *)RUNMALLOC(sizeof(struct moveObj));
1590 cinstruction->incomingobjs->length = num;
1591 cinstruction->incomingobjs->starts =
1592 (INTPTR *)RUNMALLOC(num * sizeof(INTPTR));
1593 cinstruction->incomingobjs->dsts =
1594 (INTPTR *)RUNMALLOC(num * sizeof(INTPTR));
1595 for(i = 0; i < num; i++) {
1596 cinstruction->incomingobjs->starts[i] = msgdata[startindex++];
1597 cinstruction->incomingobjs->dsts[i] = msgdata[startindex++];
1600 // process large objs
1601 num = msgdata[startindex++];
1602 for(i = 0; i < num; i++) {
1603 struct largeObjItem * loi =
1604 (struct largeObjItem *)RUNMALLOC(sizeof(struct largeObjItem ));
1605 loi->orig = msgdata[startindex++];
1606 loi->length = msgdata[startindex++];
1607 loi->dst = msgdata[startindex++];
1610 cinstruction->largeobjs->next = loi;
1612 cinstruction->largeobjs = loi;
1615 gcphase = COMPACTPHASE;
1619 case GCSTARTFLUSH: {
1620 // received a flush phase start msg
1621 gcphase = FLUSHPHASE;
1625 case GCFINISHMARK: {
1626 // received a mark phase finish msg
1627 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1628 // non startup core can not receive this msg
1630 BAMBOO_DEBUGPRINT_REG(data1);
1632 BAMBOO_EXIT(0xb006);
1634 if(data1 < NUMCORES) {
1635 gccorestatus[data1] = 0;
1636 gcnumsendobjs[data1] = gcmsgdata[2];
1637 gcnumreceiveobjs[data1] = gcmsgdata[3];
1642 case GCFINISHCOMPACT: {
1643 // received a compact phase finish msg
1644 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1645 // non startup core can not receive this msg
1648 BAMBOO_DEBUGPRINT_REG(data1);
1650 BAMBOO_EXIT(0xb006);
1652 if(data1 < NUMCORES) {
1653 gccorestatus[data1] = 0;
1658 case GCFINISHFLUSH: {
1659 // received a flush phase finish msg
1660 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1661 // non startup core can not receive this msg
1664 BAMBOO_DEBUGPRINT_REG(data1);
1666 BAMBOO_EXIT(0xb006);
1668 if(data1 < NUMCORES) {
1669 gccorestatus[data1] = 0;
1675 // received a GC finish msg
1676 gcphase = FINISHPHASE;
1680 case GCMARKCONFIRM: {
1681 // received a marked phase finish confirm request msg
1682 if((BAMBOO_NUM_OF_CORE == STARTUPCORE)
1683 || (BAMBOO_NUM_OF_CORE > NUMCORES - 1)) {
1684 // wrong core to receive such msg
1685 BAMBOO_EXIT(0xa013);
1687 // send response msg
1689 cache_msg_5(STARTUPCORE, GCMARKREPORT, BAMBOO_NUM_OF_CORE,
1690 gcbusystatus, gcself_numsendobjs, gcself_numreceiveobjs);
1692 send_msg_5(STARTUPCORE, GCMARKREPORT, BAMBOO_NUM_OF_CORE,
1693 gcbusystatus, gcself_numsendobjs, gcself_numreceiveobjs);
1699 case GCMARKREPORT: {
1700 // received a marked phase finish confirm response msg
1701 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1702 // wrong core to receive such msg
1704 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1706 BAMBOO_EXIT(0xb014);
1711 gccorestatus[data1] = gcmsgdata[2];
1712 gcnumsendobjs[data1] = gcmsgdata[3];
1713 gcnumreceiveobjs[data1] = gcmsgdata[4];
1719 // received a markedObj msg
1720 addNewItem(gctomark, data1);
1721 gcself_numreceiveobjs++;
1722 gcbusystatus = true;
1727 // received a start moving objs msg
1728 addNewItem_I(gcdsts, data1);
1733 case GCMAPREQUEST: {
1734 // received a mapping info request msg
1735 void * dstptr = gengettable(pointertbl, data1);
1736 if(NULL == dstptr) {
1737 // no such pointer in this core, something is wrong
1738 BAMBOO_EXIT(0xb008);
1740 // send back the mapping info
1742 cache_msg_3(msgdata[2], GCMAPINFO, data1, dstptr);
1744 send_msg_3(msgdata[2], GCMAPINFO,data1, dstptr);
1751 // received a mapping info response msg
1752 if(data1 != obj2map) {
1753 // obj not matched, something is wrong
1754 BAMBOO_EXIT(0xb009);
1756 mappedobj = msgdata[2];
1757 genputtable(pointertbl, obj2map, mappedobj);
1763 case GCLOBJREQUEST: {
1764 // received a large objs info request msg
1765 transferMarkResults();
1770 // received a large objs info response msg
1780 for(msgdataindex--; msgdataindex > 0; --msgdataindex) {
1781 msgdata[msgdataindex] = -1;
1787 BAMBOO_DEBUGPRINT(0xe88d);
1791 if(BAMBOO_MSG_AVAIL() != 0) {
1804 BAMBOO_DEBUGPRINT(0xe88e);
1808 /* if(isInterrupt) {
1817 ent enqueuetasks(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr, int * enterflags, int numenterflags) {
1818 void * taskpointerarray[MAXTASKPARAMS];
1820 //int numparams=parameter->task->numParameters;
1821 int numiterators=parameter->task->numTotal-1;
1826 struct taskdescriptor * task=parameter->task;
1828 //this add the object to parameterwrapper
1829 ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags, numenterflags, enterflags==NULL);
1831 /* Add enqueued object to parameter vector */
1832 taskpointerarray[parameter->slot]=ptr;
1834 /* Reset iterators */
1835 for(j=0; j<numiterators; j++) {
1836 toiReset(¶meter->iterators[j]);
1839 /* Find initial state */
1840 for(j=0; j<numiterators; j++) {
1842 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
1843 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
1845 /* Need to backtrack */
1846 toiReset(¶meter->iterators[j]);
1850 /* Nothing to enqueue */
1856 /* Enqueue current state */
1858 struct taskparamdescriptor *tpd=RUNMALLOC(sizeof(struct taskparamdescriptor));
1860 tpd->numParameters=numiterators+1;
1861 tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
1863 for(j=0; j<=numiterators; j++) {
1864 tpd->parameterArray[j]=taskpointerarray[j]; //store the actual parameters
1867 if ((/*!gencontains(failedtasks, tpd)&&*/ !gencontains(activetasks,tpd))) {
1868 genputtable(activetasks, tpd, tpd);
1870 RUNFREE(tpd->parameterArray);
1874 /* This loop iterates to the next parameter combination */
1875 if (numiterators==0)
1878 for(j=numiterators-1; j<numiterators; j++) {
1880 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
1881 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
1883 /* Need to backtrack */
1884 toiReset(¶meter->iterators[j]);
1888 /* Nothing more to enqueue */
1896 int enqueuetasks_I(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr, int * enterflags, int numenterflags) {
1897 void * taskpointerarray[MAXTASKPARAMS];
1899 //int numparams=parameter->task->numParameters;
1900 int numiterators=parameter->task->numTotal-1;
1905 struct taskdescriptor * task=parameter->task;
1907 //this add the object to parameterwrapper
1908 ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags, numenterflags, enterflags==NULL);
1910 /* Add enqueued object to parameter vector */
1911 taskpointerarray[parameter->slot]=ptr;
1913 /* Reset iterators */
1914 for(j=0; j<numiterators; j++) {
1915 toiReset(¶meter->iterators[j]);
1918 /* Find initial state */
1919 for(j=0; j<numiterators; j++) {
1921 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
1922 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
1924 /* Need to backtrack */
1925 toiReset(¶meter->iterators[j]);
1929 /* Nothing to enqueue */
1935 /* Enqueue current state */
1937 struct taskparamdescriptor *tpd=RUNMALLOC_I(sizeof(struct taskparamdescriptor));
1939 tpd->numParameters=numiterators+1;
1940 tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
1942 for(j=0; j<=numiterators; j++) {
1943 tpd->parameterArray[j]=taskpointerarray[j]; //store the actual parameters
1946 if ((/*!gencontains(failedtasks, tpd)&&*/ !gencontains(activetasks,tpd))) {
1947 genputtable_I(activetasks, tpd, tpd);
1949 RUNFREE(tpd->parameterArray);
1953 /* This loop iterates to the next parameter combination */
1954 if (numiterators==0)
1957 for(j=numiterators-1; j<numiterators; j++) {
1959 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
1960 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
1962 /* Need to backtrack */
1963 toiReset(¶meter->iterators[j]);
1967 /* Nothing more to enqueue */
1975 /* Handler for signals. The signals catch null pointer errors and
1976 arithmatic errors. */
1978 void myhandler(int sig, siginfo_t *info, void *uap) {
1981 printf("sig=%d\n",sig);
1984 sigemptyset(&toclear);
1985 sigaddset(&toclear, sig);
1986 sigprocmask(SIG_UNBLOCK, &toclear,NULL);
1987 longjmp(error_handler,1);
1994 struct RuntimeHash *fdtoobject;
1996 void addreadfd(int fd) {
1999 FD_SET(fd, &readfds);
2002 void removereadfd(int fd) {
2003 FD_CLR(fd, &readfds);
2004 if (maxreadfd==(fd+1)) {
2006 while(maxreadfd>0&&!FD_ISSET(maxreadfd-1, &readfds))
2018 int containstag(struct ___Object___ *ptr, struct ___TagDescriptor___ *tag);
2020 void executetasks() {
2021 void * taskpointerarray[MAXTASKPARAMS+OFFSET];
2024 struct ___Object___ * tmpparam = NULL;
2025 struct parameterdescriptor * pd=NULL;
2026 struct parameterwrapper *pw=NULL;
2031 struct LockValue locks[MAXTASKPARAMS];
2038 /* Set up signal handlers */
2039 struct sigaction sig;
2040 sig.sa_sigaction=&myhandler;
2041 sig.sa_flags=SA_SIGINFO;
2042 sigemptyset(&sig.sa_mask);
2044 /* Catch bus errors, segmentation faults, and floating point exceptions*/
2045 sigaction(SIGBUS,&sig,0);
2046 sigaction(SIGSEGV,&sig,0);
2047 sigaction(SIGFPE,&sig,0);
2048 sigaction(SIGPIPE,&sig,0);
2049 #endif // #if 0: non-multicore
2059 fdtoobject=allocateRuntimeHash(100);
2063 /* Map first block of memory to protected, anonymous page */
2064 mmap(0, 0x1000, 0, MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
2069 while(hashsize(activetasks)>0) {
2071 while((hashsize(activetasks)>0)||(maxreadfd>0)) {
2074 BAMBOO_DEBUGPRINT(0xe990);
2077 /* Check if any filedescriptors have IO pending */
2080 struct timeval timeout={0,0};
2084 numselect=select(maxreadfd, &tmpreadfds, NULL, NULL, &timeout);
2086 /* Process ready fd's */
2088 for(fd=0; fd<maxreadfd; fd++) {
2089 if (FD_ISSET(fd, &tmpreadfds)) {
2090 /* Set ready flag on object */
2092 // printf("Setting fd %d\n",fd);
2093 if (RuntimeHashget(fdtoobject, fd,(int *) &objptr)) {
2094 if(intflagorand(objptr,1,0xFFFFFFFF)) { /* Set the first flag to 1 */
2095 enqueueObject(objptr, NULL, 0);
2104 /* See if there are any active tasks */
2105 if (hashsize(activetasks)>0) {
2108 #ifdef ACCURATEPROFILE
2109 profileTaskStart("tpd checking");
2113 currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
2114 genfreekey(activetasks, currtpd);
2116 numparams=currtpd->task->numParameters;
2117 numtotal=currtpd->task->numTotal;
2119 // clear the lockRedirectTbl (TODO, this table should be empty after all locks are released)
2121 for(j = 0; j < MAXTASKPARAMS; j++) {
2122 locks[j].redirectlock = 0;
2125 // get all required locks
2127 // check which locks are needed
2128 for(i = 0; i < numparams; i++) {
2129 void * param = currtpd->parameterArray[i];
2133 if(((struct ___Object___ *)param)->type == STARTUPTYPE) {
2135 taskpointerarray[i+OFFSET]=param;
2138 if(((struct ___Object___ *)param)->lock == NULL) {
2139 tmplock = (int)param;
2141 tmplock = (int)(((struct ___Object___ *)param)->lock);
2143 // insert into the locks array
2144 for(j = 0; j < locklen; j++) {
2145 if(locks[j].value == tmplock) {
2148 } else if(locks[j].value > tmplock) {
2155 locks[h].redirectlock = locks[h-1].redirectlock;
2156 locks[h].value = locks[h-1].value;
2158 locks[j].value = tmplock;
2159 locks[j].redirectlock = (int)param;
2162 } // line 2713: for(i = 0; i < numparams; i++)
2163 // grab these required locks
2165 BAMBOO_DEBUGPRINT(0xe991);
2167 for(i = 0; i < locklen; i++) {
2168 int * lock = (int *)(locks[i].redirectlock);
2170 // require locks for this parameter if it is not a startup object
2172 BAMBOO_DEBUGPRINT_REG((int)lock);
2173 BAMBOO_DEBUGPRINT_REG((int)(locks[i].value));
2176 BAMBOO_START_CRITICAL_SECTION();
2178 BAMBOO_DEBUGPRINT(0xf001);
2181 //isInterrupt = false;
2184 BAMBOO_WAITING_FOR_LOCK();
2188 while(BAMBOO_WAITING_FOR_LOCK() != -1) {
2192 grount = lockresult;
2202 //isInterrupt = true;
2204 BAMBOO_CLOSE_CRITICAL_SECTION();
2206 BAMBOO_DEBUGPRINT(0xf000);
2212 BAMBOO_DEBUGPRINT(0xe992);
2214 // can not get the lock, try later
2215 // releas all grabbed locks for previous parameters
2216 for(j = 0; j < i; ++j) {
2217 lock = (int*)(locks[j].redirectlock);
2218 releasewritelock(lock);
2220 genputtable(activetasks, currtpd, currtpd);
2221 if(hashsize(activetasks) == 1) {
2222 // only one task right now, wait a little while before next try
2228 #ifdef ACCURATEPROFILE
2229 // fail, set the end of the checkTaskInfo
2234 } // line 2794: if(grount == 0)
2235 } // line 2752: for(i = 0; i < locklen; i++)
2238 BAMBOO_DEBUGPRINT(0xe993);
2240 /* Make sure that the parameters are still in the queues */
2241 for(i=0; i<numparams; i++) {
2242 void * parameter=currtpd->parameterArray[i];
2246 BAMBOO_CACHE_FLUSH_RANGE((int)parameter, classsize[((struct ___Object___ *)parameter)->type]);
2248 BAMBOO_START_CRITICAL_SECTION_LOCK();
2250 BAMBOO_DEBUGPRINT(0xf001);
2252 if(RuntimeHashcontainskey(objRedirectLockTbl, (int)parameter)) {
2253 int redirectlock_r = 0;
2254 RuntimeHashget(objRedirectLockTbl, (int)parameter, &redirectlock_r);
2255 ((struct ___Object___ *)parameter)->lock = redirectlock_r;
2256 RuntimeHashremovekey(objRedirectLockTbl, (int)parameter);
2258 BAMBOO_CLOSE_CRITICAL_SECTION_LOCK();
2260 BAMBOO_DEBUGPRINT(0xf000);
2264 tmpparam = (struct ___Object___ *)parameter;
2265 pd=currtpd->task->descriptorarray[i];
2266 pw=(struct parameterwrapper *) pd->queue;
2267 /* Check that object is still in queue */
2269 if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
2271 BAMBOO_DEBUGPRINT(0xe994);
2273 // release grabbed locks
2274 for(j = 0; j < locklen; ++j) {
2275 int * lock = (int *)(locks[j].redirectlock);
2276 releasewritelock(lock);
2278 RUNFREE(currtpd->parameterArray);
2283 /* Check if the object's flags still meets requirements */
2287 for(tmpi = 0; tmpi < pw->numberofterms; ++tmpi) {
2288 andmask=pw->intarray[tmpi*2];
2289 checkmask=pw->intarray[tmpi*2+1];
2290 if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
2296 // flags are never suitable
2297 // remove this obj from the queue
2299 int UNUSED, UNUSED2;
2302 BAMBOO_DEBUGPRINT(0xe995);
2304 ObjectHashget(pw->objectset, (int) parameter, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
2305 ObjectHashremove(pw->objectset, (int)parameter);
2306 if (enterflags!=NULL)
2307 RUNFREE(enterflags);
2308 // release grabbed locks
2309 for(j = 0; j < locklen; ++j) {
2310 int * lock = (int *)(locks[j].redirectlock);
2311 releasewritelock(lock);
2313 RUNFREE(currtpd->parameterArray);
2316 #ifdef ACCURATEPROFILE
2317 // fail, set the end of the checkTaskInfo
2322 } // line 2878: if (!ismet)
2326 /* Check that object still has necessary tags */
2327 for(j=0; j<pd->numbertags; j++) {
2328 int slotid=pd->tagarray[2*j]+numparams;
2329 struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
2330 if (!containstag(parameter, tagd)) {
2332 BAMBOO_DEBUGPRINT(0xe996);
2335 // release grabbed locks
2337 for(tmpj = 0; tmpj < locklen; ++tmpj) {
2338 int * lock = (int *)(locks[tmpj].redirectlock);
2339 releasewritelock(lock);
2342 RUNFREE(currtpd->parameterArray);
2345 } // line2911: if (!containstag(parameter, tagd))
2346 } // line 2808: for(j=0; j<pd->numbertags; j++)
2348 taskpointerarray[i+OFFSET]=parameter;
2349 } // line 2824: for(i=0; i<numparams; i++)
2351 for(; i<numtotal; i++) {
2352 taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
2358 /* Checkpoint the state */
2359 forward=allocateRuntimeHash(100);
2360 reverse=allocateRuntimeHash(100);
2361 //void ** checkpoint=makecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, forward, reverse);
2363 #endif // #if 0: for recovery
2365 if (x=setjmp(error_handler)) {
2370 printf("Fatal Error=%d, Recovering!\n",x);
2374 genputtable(failedtasks,currtpd,currtpd);
2375 //restorecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, checkpoint, forward, reverse);
2377 freeRuntimeHash(forward);
2378 freeRuntimeHash(reverse);
2382 #endif // #if 0: for recovery
2383 BAMBOO_DEBUGPRINT_REG(x);
2384 BAMBOO_EXIT(0xa022);
2386 #endif // #ifndef MULTICORE
2388 if (injectfailures) {
2389 if ((((double)random())/RAND_MAX)<failurechance) {
2390 printf("\nINJECTING TASK FAILURE to %s\n", currtpd->task->name);
2391 longjmp(error_handler,10);
2394 #endif // #if 0: for recovery
2395 /* Actually call task */
2398 ((int *)taskpointerarray)[0]=currtpd->numParameters;
2399 taskpointerarray[1]=NULL;
2401 #endif // #if 0: for garbage collection
2404 #ifdef ACCURATEPROFILE
2405 // check finish, set the end of the checkTaskInfo
2408 profileTaskStart(currtpd->task->name);
2413 printf("ENTER %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
2415 ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
2417 printf("EXIT %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
2421 BAMBOO_DEBUGPRINT(0xe997);
2423 ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
2424 } // line 2990: if(debugtask)
2426 #ifdef ACCURATEPROFILE
2427 // task finish, set the end of the checkTaskInfo
2429 // new a PostTaskInfo for the post-task execution
2430 profileTaskStart("post task execution");
2434 BAMBOO_DEBUGPRINT(0xe998);
2435 BAMBOO_DEBUGPRINT_REG(islock);
2440 BAMBOO_DEBUGPRINT(0xe999);
2442 for(i = 0; i < locklen; ++i) {
2443 void * ptr = (void *)(locks[i].redirectlock);
2444 int * lock = (int *)(locks[i].value);
2446 BAMBOO_DEBUGPRINT_REG((int)ptr);
2447 BAMBOO_DEBUGPRINT_REG((int)lock);
2449 if(RuntimeHashcontainskey(lockRedirectTbl, (int)lock)) {
2451 RuntimeHashget(lockRedirectTbl, (int)lock, &redirectlock);
2452 RuntimeHashremovekey(lockRedirectTbl, (int)lock);
2453 releasewritelock_r(lock, (int *)redirectlock);
2455 releasewritelock(ptr);
2458 } // line 3015: if(islock)
2461 // post task execution finish, set the end of the postTaskInfo
2466 freeRuntimeHash(forward);
2467 freeRuntimeHash(reverse);
2470 // Free up task parameter descriptor
2471 RUNFREE(currtpd->parameterArray);
2478 BAMBOO_DEBUGPRINT(0xe99a);
2479 //BAMBOO_DEBUGPRINT_REG(hashsize(activetasks));
2482 } // line 2946: if (x=setjmp(error_handler))
2485 } // line 2697: if (hashsize(activetasks)>0)
2486 } // line 2659: while(hashsize(activetasks)>0)
2488 BAMBOO_DEBUGPRINT(0xe99b);
2492 /* This function processes an objects tags */
2493 void processtags(struct parameterdescriptor *pd, int index, struct parameterwrapper *parameter, int * iteratorcount, int *statusarray, int numparams) {
2496 for(i=0; i<pd->numbertags; i++) {
2497 int slotid=pd->tagarray[2*i];
2498 int tagid=pd->tagarray[2*i+1];
2500 if (statusarray[slotid+numparams]==0) {
2501 parameter->iterators[*iteratorcount].istag=1;
2502 parameter->iterators[*iteratorcount].tagid=tagid;
2503 parameter->iterators[*iteratorcount].slot=slotid+numparams;
2504 parameter->iterators[*iteratorcount].tagobjectslot=index;
2505 statusarray[slotid+numparams]=1;
2512 void processobject(struct parameterwrapper *parameter, int index, struct parameterdescriptor *pd, int *iteratorcount, int * statusarray, int numparams) {
2515 struct ObjectHash * objectset=((struct parameterwrapper *)pd->queue)->objectset;
2517 parameter->iterators[*iteratorcount].istag=0;
2518 parameter->iterators[*iteratorcount].slot=index;
2519 parameter->iterators[*iteratorcount].objectset=objectset;
2520 statusarray[index]=1;
2522 for(i=0; i<pd->numbertags; i++) {
2523 int slotid=pd->tagarray[2*i];
2524 //int tagid=pd->tagarray[2*i+1];
2525 if (statusarray[slotid+numparams]!=0) {
2526 /* This tag has already been enqueued, use it to narrow search */
2527 parameter->iterators[*iteratorcount].tagbindings[tagcount]=slotid+numparams;
2531 parameter->iterators[*iteratorcount].numtags=tagcount;
2536 /* This function builds the iterators for a task & parameter */
2538 void builditerators(struct taskdescriptor * task, int index, struct parameterwrapper * parameter) {
2539 int statusarray[MAXTASKPARAMS];
2541 int numparams=task->numParameters;
2542 int iteratorcount=0;
2543 for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
2545 statusarray[index]=1; /* Initial parameter */
2546 /* Process tags for initial iterator */
2548 processtags(task->descriptorarray[index], index, parameter, &iteratorcount, statusarray, numparams);
2552 /* Check for objects with existing tags */
2553 for(i=0; i<numparams; i++) {
2554 if (statusarray[i]==0) {
2555 struct parameterdescriptor *pd=task->descriptorarray[i];
2557 for(j=0; j<pd->numbertags; j++) {
2558 int slotid=pd->tagarray[2*j];
2559 if(statusarray[slotid+numparams]!=0) {
2560 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2561 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2568 /* Next do objects w/ unbound tags*/
2570 for(i=0; i<numparams; i++) {
2571 if (statusarray[i]==0) {
2572 struct parameterdescriptor *pd=task->descriptorarray[i];
2573 if (pd->numbertags>0) {
2574 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2575 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2581 /* Nothing with a tag enqueued */
2583 for(i=0; i<numparams; i++) {
2584 if (statusarray[i]==0) {
2585 struct parameterdescriptor *pd=task->descriptorarray[i];
2586 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2587 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2600 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
2603 for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
2604 struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
2606 printf("%s\n", task->name);
2608 for(j=0; j<task->numParameters; j++) {
2609 struct parameterdescriptor *param=task->descriptorarray[j];
2610 struct parameterwrapper *parameter=param->queue;
2611 struct ObjectHash * set=parameter->objectset;
2612 struct ObjectIterator objit;
2614 printf(" Parameter %d\n", j);
2616 ObjectHashiterator(set, &objit);
2617 while(ObjhasNext(&objit)) {
2618 struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
2619 struct ___Object___ * tagptr=obj->___tags___;
2620 int nonfailed=Objdata4(&objit);
2621 int numflags=Objdata3(&objit);
2622 int flags=Objdata2(&objit);
2625 printf(" Contains %lx\n", obj);
2626 printf(" flag=%d\n", obj->flag);
2629 } else if (tagptr->type==TAGTYPE) {
2631 printf(" tag=%lx\n",tagptr);
2637 struct ArrayObject *ao=(struct ArrayObject *)tagptr;
2638 for(; tagindex<ao->___cachedCode___; tagindex++) {
2640 printf(" tag=%lx\n",ARRAYGET(ao, struct ___TagDescriptor___*, tagindex));
2652 /* This function processes the task information to create queues for
2653 each parameter type. */
2655 void processtasks() {
2657 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
2660 for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
2661 struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
2664 /* Build objectsets */
2665 for(j=0; j<task->numParameters; j++) {
2666 struct parameterdescriptor *param=task->descriptorarray[j];
2667 struct parameterwrapper *parameter=param->queue;
2668 parameter->objectset=allocateObjectHash(10);
2669 parameter->task=task;
2672 /* Build iterators for parameters */
2673 for(j=0; j<task->numParameters; j++) {
2674 struct parameterdescriptor *param=task->descriptorarray[j];
2675 struct parameterwrapper *parameter=param->queue;
2676 builditerators(task, j, parameter);
2681 void toiReset(struct tagobjectiterator * it) {
2684 } else if (it->numtags>0) {
2687 ObjectHashiterator(it->objectset, &it->it);
2691 int toiHasNext(struct tagobjectiterator *it, void ** objectarray OPTARG(int * failed)) {
2694 /* Get object with tags */
2695 struct ___Object___ *obj=objectarray[it->tagobjectslot];
2696 struct ___Object___ *tagptr=obj->___tags___;
2697 if (tagptr->type==TAGTYPE) {
2698 if ((it->tagobjindex==0)&& /* First object */
2699 (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
2704 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
2705 int tagindex=it->tagobjindex;
2706 for(; tagindex<ao->___cachedCode___; tagindex++) {
2707 struct ___TagDescriptor___ *td=ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
2708 if (td->flag==it->tagid) {
2709 it->tagobjindex=tagindex; /* Found right type of tag */
2715 } else if (it->numtags>0) {
2716 /* Use tags to locate appropriate objects */
2717 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
2718 struct ___Object___ *objptr=tag->flagptr;
2720 if (objptr->type!=OBJECTARRAYTYPE) {
2721 if (it->tagobjindex>0)
2723 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
2725 for(i=1; i<it->numtags; i++) {
2726 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
2727 if (!containstag(objptr,tag2))
2732 struct ArrayObject *ao=(struct ArrayObject *) objptr;
2735 for(tagindex=it->tagobjindex; tagindex<ao->___cachedCode___; tagindex++) {
2736 struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
2737 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
2739 for(i=1; i<it->numtags; i++) {
2740 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
2741 if (!containstag(objptr,tag2))
2744 it->tagobjindex=tagindex;
2749 it->tagobjindex=tagindex;
2753 return ObjhasNext(&it->it);
2757 int containstag(struct ___Object___ *ptr, struct ___TagDescriptor___ *tag) {
2759 struct ___Object___ * objptr=tag->flagptr;
2760 if (objptr->type==OBJECTARRAYTYPE) {
2761 struct ArrayObject *ao=(struct ArrayObject *)objptr;
2762 for(j=0; j<ao->___cachedCode___; j++) {
2763 if (ptr==ARRAYGET(ao, struct ___Object___*, j))
2771 void toiNext(struct tagobjectiterator *it, void ** objectarray OPTARG(int * failed)) {
2772 /* hasNext has all of the intelligence */
2775 /* Get object with tags */
2776 struct ___Object___ *obj=objectarray[it->tagobjectslot];
2777 struct ___Object___ *tagptr=obj->___tags___;
2778 if (tagptr->type==TAGTYPE) {
2780 objectarray[it->slot]=tagptr;
2782 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
2783 objectarray[it->slot]=ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
2785 } else if (it->numtags>0) {
2786 /* Use tags to locate appropriate objects */
2787 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
2788 struct ___Object___ *objptr=tag->flagptr;
2789 if (objptr->type!=OBJECTARRAYTYPE) {
2791 objectarray[it->slot]=objptr;
2793 struct ArrayObject *ao=(struct ArrayObject *) objptr;
2794 objectarray[it->slot]=ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
2797 /* Iterate object */
2798 objectarray[it->slot]=(void *)Objkey(&it->it);