3 #include "multicoreruntime.h"
4 #include "runtime_arch.h"
5 #include "GenericHashtable.h"
7 // data structures for task invocation
8 struct genhashtable * activetasks;
9 struct taskparamdescriptor * currtpd;
11 // specific functions used inside critical sections
12 void enqueueObject_I(void * ptr,
13 struct parameterwrapper ** queues,
15 int enqueuetasks_I(struct parameterwrapper *parameter,
16 struct parameterwrapper *prevptr,
17 struct ___Object___ *ptr,
21 inline __attribute__((always_inline))
22 void initruntimedata() {
24 // initialize the arrays
25 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
26 // startup core to initialize corestatus[]
27 for(i = 0; i < NUMCORES; ++i) {
30 numreceiveobjs[i] = 0;
32 // initialize the profile data arrays
38 gcnumreceiveobjs[i] = 0;
40 gcrequiredmems[i] = 0;
42 gcfilledblocks[i] = 0;
44 } // for(i = 0; i < NUMCORES; ++i)
54 self_numreceiveobjs = 0;
56 for(i = 0; i < BAMBOO_MSG_BUF_LENGTH; ++i) {
61 msglength = BAMBOO_MSG_BUF_LENGTH;
62 for(i = 0; i < BAMBOO_OUT_BUF_LENGTH; ++i) {
72 bamboo_cur_msp = NULL;
74 totransobjqueue = createQueue();
79 gcphase = FINISHPHASE;
81 gcself_numsendobjs = 0;
82 gcself_numreceiveobjs = 0;
84 gcpointertbl = allocateRuntimeHash(20);
94 //gchead = gctail = gctail2 = NULL;
95 //gclobjhead = gclobjtail = gclobjtail2 = NULL;
96 //gcheadindex=gctailindex=gctailindex2 = 0;
97 //gclobjheadindex=gclobjtailindex=gclobjtailindex2 = 0;
101 // create the lock table, lockresult table and obj queue
104 (struct RuntimeNode **) RUNMALLOC_I(sizeof(struct RuntimeNode *)*20);
105 /* Set allocation blocks*/
106 locktable.listhead=NULL;
107 locktable.listtail=NULL;
109 locktable.numelements = 0;
114 lockRedirectTbl = allocateRuntimeHash(20);
115 objRedirectLockTbl = allocateRuntimeHash(20);
120 objqueue.head = NULL;
121 objqueue.tail = NULL;
127 //isInterrupt = true;
130 taskInfoOverflow = false;
131 /*interruptInfoIndex = 0;
132 interruptInfoOverflow = false;*/
136 inline __attribute__((always_inline))
137 void disruntimedata() {
139 freeRuntimeHash(gcpointertbl);
141 freeRuntimeHash(lockRedirectTbl);
142 freeRuntimeHash(objRedirectLockTbl);
143 RUNFREE(locktable.bucket);
145 genfreehashtable(activetasks);
146 if(currtpd != NULL) {
147 RUNFREE(currtpd->parameterArray);
153 inline __attribute__((always_inline))
154 bool checkObjQueue() {
156 struct transObjInfo * objInfo = NULL;
160 #ifdef ACCURATEPROFILE
161 bool isChecking = false;
162 if(!isEmpty(&objqueue)) {
163 profileTaskStart("objqueue checking");
165 } // if(!isEmpty(&objqueue))
169 while(!isEmpty(&objqueue)) {
171 BAMBOO_START_CRITICAL_SECTION_OBJ_QUEUE();
173 BAMBOO_DEBUGPRINT(0xf001);
176 //isInterrupt = false;
179 BAMBOO_DEBUGPRINT(0xeee1);
182 objInfo = (struct transObjInfo *)getItem(&objqueue);
183 obj = objInfo->objptr;
185 BAMBOO_DEBUGPRINT_REG((int)obj);
187 // grab lock and flush the obj
191 BAMBOO_WAITING_FOR_LOCK();
192 } // while(!lockflag)
195 BAMBOO_DEBUGPRINT_REG(grount);
210 BAMBOO_CACHE_FLUSH_RANGE((int)obj,sizeof(int));
211 BAMBOO_CACHE_FLUSH_RANGE((int)obj,
212 classsize[((struct ___Object___ *)obj)->type]);
214 // enqueue the object
215 for(k = 0; k < objInfo->length; ++k) {
216 int taskindex = objInfo->queues[2 * k];
217 int paramindex = objInfo->queues[2 * k + 1];
218 struct parameterwrapper ** queues =
219 &(paramqueues[BAMBOO_NUM_OF_CORE][taskindex][paramindex]);
221 BAMBOO_DEBUGPRINT_REG(taskindex);
222 BAMBOO_DEBUGPRINT_REG(paramindex);
223 struct ___Object___ * tmpptr = (struct ___Object___ *)obj;
224 tprintf("Process %x(%d): receive obj %x(%lld), ptrflag %x\n",
225 BAMBOO_NUM_OF_CORE, BAMBOO_NUM_OF_CORE, (int)obj,
226 (long)obj, tmpptr->flag);
228 enqueueObject_I(obj, queues, 1);
230 BAMBOO_DEBUGPRINT_REG(hashsize(activetasks));
232 } // for(k = 0; k < objInfo->length; ++k)
233 releasewritelock_I(obj);
234 RUNFREE(objInfo->queues);
238 // put it at the end of the queue if no update version in the queue
239 struct QueueItem * qitem = getHead(&objqueue);
240 struct QueueItem * prev = NULL;
241 while(qitem != NULL) {
242 struct transObjInfo * tmpinfo =
243 (struct transObjInfo *)(qitem->objectptr);
244 if(tmpinfo->objptr == obj) {
245 // the same object in the queue, which should be enqueued
246 // recently. Current one is outdate, do not re-enqueue it
247 RUNFREE(objInfo->queues);
252 } // if(tmpinfo->objptr == obj)
253 qitem = getNextQueueItem(prev);
254 } // while(qitem != NULL)
255 // try to execute active tasks already enqueued first
256 addNewItem_I(&objqueue, objInfo);
258 //isInterrupt = true;
261 BAMBOO_CLOSE_CRITICAL_SECTION_OBJ_QUEUE();
263 BAMBOO_DEBUGPRINT(0xf000);
267 BAMBOO_CLOSE_CRITICAL_SECTION_OBJ_QUEUE();
269 BAMBOO_DEBUGPRINT(0xf000);
271 } // while(!isEmpty(&objqueue))
274 #ifdef ACCURATEPROFILE
282 BAMBOO_DEBUGPRINT(0xee02);
287 inline __attribute__((always_inline))
288 void checkCoreStatus() {
289 bool allStall = false;
293 (waitconfirm && (numconfirm == 0))) {
295 BAMBOO_DEBUGPRINT(0xee04);
296 BAMBOO_DEBUGPRINT_REG(waitconfirm);
298 BAMBOO_START_CRITICAL_SECTION_STATUS();
300 BAMBOO_DEBUGPRINT(0xf001);
302 corestatus[BAMBOO_NUM_OF_CORE] = 0;
303 numsendobjs[BAMBOO_NUM_OF_CORE] = self_numsendobjs;
304 numreceiveobjs[BAMBOO_NUM_OF_CORE] = self_numreceiveobjs;
305 // check the status of all cores
308 BAMBOO_DEBUGPRINT_REG(NUMCORES);
310 for(i = 0; i < NUMCORES; ++i) {
312 BAMBOO_DEBUGPRINT(0xe000 + corestatus[i]);
314 if(corestatus[i] != 0) {
318 } // for(i = 0; i < NUMCORES; ++i)
320 // check if the sum of send objs and receive obj are the same
321 // yes->check if the info is the latest; no->go on executing
323 for(i = 0; i < NUMCORES; ++i) {
324 sumsendobj += numsendobjs[i];
326 BAMBOO_DEBUGPRINT(0xf000 + numsendobjs[i]);
328 } // for(i = 0; i < NUMCORES; ++i)
329 for(i = 0; i < NUMCORES; ++i) {
330 sumsendobj -= numreceiveobjs[i];
332 BAMBOO_DEBUGPRINT(0xf000 + numreceiveobjs[i]);
334 } // for(i = 0; i < NUMCORES; ++i)
335 if(0 == sumsendobj) {
337 // the first time found all cores stall
338 // send out status confirm msg to all other cores
339 // reset the corestatus array too
341 BAMBOO_DEBUGPRINT(0xee05);
343 corestatus[BAMBOO_NUM_OF_CORE] = 1;
344 for(i = 1; i < NUMCORES; ++i) {
346 // send status confirm msg to core i
347 send_msg_1(i, STATUSCONFIRM);
348 } // for(i = 1; i < NUMCORES; ++i)
350 numconfirm = NUMCORES - 1;
352 // all the core status info are the latest
353 // terminate; for profiling mode, send request to all
354 // other cores to pour out profiling data
356 BAMBOO_DEBUGPRINT(0xee06);
360 totalexetime = BAMBOO_GET_EXE_TIME();
362 BAMBOO_DEBUGPRINT(BAMBOO_GET_EXE_TIME());
363 BAMBOO_DEBUGPRINT_REG(total_num_t6); // TODO for test
364 BAMBOO_DEBUGPRINT(0xbbbbbbbb);
366 // profile mode, send msgs to other cores to request pouring
367 // out progiling data
369 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
371 BAMBOO_DEBUGPRINT(0xf000);
373 for(i = 1; i < NUMCORES; ++i) {
374 // send profile request msg to core i
375 send_msg_2(i, PROFILEOUTPUT, totalexetime);
376 } // for(i = 1; i < NUMCORES; ++i)
377 // pour profiling data on startup core
380 BAMBOO_START_CRITICAL_SECTION_STATUS();
382 BAMBOO_DEBUGPRINT(0xf001);
384 profilestatus[BAMBOO_NUM_OF_CORE] = 0;
385 // check the status of all cores
388 BAMBOO_DEBUGPRINT_REG(NUMCORES);
390 for(i = 0; i < NUMCORES; ++i) {
392 BAMBOO_DEBUGPRINT(0xe000 + profilestatus[i]);
394 if(profilestatus[i] != 0) {
398 } // for(i = 0; i < NUMCORES; ++i)
401 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
403 BAMBOO_DEBUGPRINT(0xf000);
413 terminate(); // All done.
414 } // if(!waitconfirm)
416 // still some objects on the fly on the network
417 // reset the waitconfirm and numconfirm
419 BAMBOO_DEBUGPRINT(0xee07);
423 } // if(0 == sumsendobj)
425 // not all cores are stall, keep on waiting
427 BAMBOO_DEBUGPRINT(0xee08);
432 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
434 BAMBOO_DEBUGPRINT(0xf000);
436 } // if((!waitconfirm) ||
439 // main function for each core
440 inline void run(void * arg) {
444 bool sendStall = false;
446 bool tocontinue = false;
448 corenum = BAMBOO_GET_NUM_OF_CORE();
450 BAMBOO_DEBUGPRINT(0xeeee);
451 BAMBOO_DEBUGPRINT_REG(corenum);
452 BAMBOO_DEBUGPRINT(STARTUPCORE);
455 // initialize runtime data structures
458 // other architecture related initialization
462 initializeexithandler();
464 // main process of the execution module
465 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
466 // non-executing cores, only processing communications
469 BAMBOO_DEBUGPRINT(0xee01);
470 BAMBOO_DEBUGPRINT_REG(taskInfoIndex);
471 BAMBOO_DEBUGPRINT_REG(taskInfoOverflow);
472 profileTaskStart("msg handling");
476 //isInterrupt = false;
480 /* Create queue of active tasks */
482 genallocatehashtable((unsigned int(*) (void *)) &hashCodetpd,
483 (int(*) (void *,void *)) &comparetpd);
485 /* Process task information */
488 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
489 /* Create startup object */
490 createstartupobject(argc, argv);
494 BAMBOO_DEBUGPRINT(0xee00);
499 // check if need to do GC
503 // check if there are new active tasks can be executed
510 while(receiveObject() != -1) {
515 BAMBOO_DEBUGPRINT(0xee01);
518 // check if there are some pending objects,
519 // if yes, enqueue them and executetasks again
520 tocontinue = checkObjQueue();
524 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
527 BAMBOO_DEBUGPRINT(0xee03);
535 BAMBOO_DEBUGPRINT(0xee09);
541 // wait for some time
544 BAMBOO_DEBUGPRINT(0xee0a);
550 // send StallMsg to startup core
552 BAMBOO_DEBUGPRINT(0xee0b);
555 send_msg_4(STARTUPCORE, TRANSTALL, BAMBOO_NUM_OF_CORE,
556 self_numsendobjs, self_numreceiveobjs);
568 BAMBOO_DEBUGPRINT(0xee0c);
571 } // if(STARTUPCORE == BAMBOO_NUM_OF_CORE)
574 } // if(BAMBOO_NUM_OF_CORE > NUMCORES - 1)
578 struct ___createstartupobject____I_locals {
581 struct ___StartupObject___ * ___startupobject___;
582 struct ArrayObject * ___stringarray___;
583 }; // struct ___createstartupobject____I_locals
585 void createstartupobject(int argc,
589 /* Allocate startup object */
591 struct ___createstartupobject____I_locals ___locals___={2, NULL, NULL, NULL};
592 struct ___StartupObject___ *startupobject=
593 (struct ___StartupObject___*) allocate_new(&___locals___, STARTUPTYPE);
594 ___locals___.___startupobject___ = startupobject;
595 struct ArrayObject * stringarray=
596 allocate_newarray(&___locals___, STRINGARRAYTYPE, argc-1);
597 ___locals___.___stringarray___ = stringarray;
599 struct ___StartupObject___ *startupobject=
600 (struct ___StartupObject___*) allocate_new(STARTUPTYPE);
601 struct ArrayObject * stringarray=
602 allocate_newarray(STRINGARRAYTYPE, argc-1);
604 /* Build array of strings */
605 startupobject->___parameters___=stringarray;
606 for(i=1; i<argc; i++) {
607 int length=strlen(argv[i]);
609 struct ___String___ *newstring=NewString(&___locals___, argv[i],length);
611 struct ___String___ *newstring=NewString(argv[i],length);
613 ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=
617 startupobject->version = 0;
618 startupobject->lock = NULL;
620 /* Set initialized flag for startup object */
621 flagorandinit(startupobject,1,0xFFFFFFFF);
622 enqueueObject(startupobject, NULL, 0);
624 BAMBOO_CACHE_FLUSH_ALL();
628 int hashCodetpd(struct taskparamdescriptor *ftd) {
629 int hash=(int)ftd->task;
631 for(i=0; i<ftd->numParameters; i++) {
632 hash^=(int)ftd->parameterArray[i];
637 int comparetpd(struct taskparamdescriptor *ftd1,
638 struct taskparamdescriptor *ftd2) {
640 if (ftd1->task!=ftd2->task)
642 for(i=0; i<ftd1->numParameters; i++)
643 if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
648 /* This function sets a tag. */
650 void tagset(void *ptr,
651 struct ___Object___ * obj,
652 struct ___TagDescriptor___ * tagd) {
654 void tagset(struct ___Object___ * obj,
655 struct ___TagDescriptor___ * tagd) {
657 struct ArrayObject * ao=NULL;
658 struct ___Object___ * tagptr=obj->___tags___;
660 obj->___tags___=(struct ___Object___ *)tagd;
662 /* Have to check if it is already set */
663 if (tagptr->type==TAGTYPE) {
664 struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
669 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
670 struct ArrayObject * ao=
671 allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
672 obj=(struct ___Object___ *)ptrarray[2];
673 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
674 td=(struct ___TagDescriptor___ *) obj->___tags___;
676 ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
679 ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
680 ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
681 obj->___tags___=(struct ___Object___ *) ao;
682 ao->___cachedCode___=2;
686 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
687 for(i=0; i<ao->___cachedCode___; i++) {
688 struct ___TagDescriptor___ * td=
689 ARRAYGET(ao, struct ___TagDescriptor___*, i);
694 if (ao->___cachedCode___<ao->___length___) {
695 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
696 ao->___cachedCode___++;
699 int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
700 struct ArrayObject * aonew=
701 allocate_newarray(&ptrarray,TAGARRAYTYPE,
702 TAGARRAYINTERVAL+ao->___length___);
703 obj=(struct ___Object___ *)ptrarray[2];
704 tagd=(struct ___TagDescriptor___ *) ptrarray[3];
705 ao=(struct ArrayObject *)obj->___tags___;
707 struct ArrayObject * aonew=
708 allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
711 aonew->___cachedCode___=ao->___length___+1;
712 for(i=0; i<ao->___length___; i++) {
713 ARRAYSET(aonew, struct ___TagDescriptor___*, i,
714 ARRAYGET(ao, struct ___TagDescriptor___*, i));
716 ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
722 struct ___Object___ * tagset=tagd->flagptr;
725 } else if (tagset->type!=OBJECTARRAYTYPE) {
727 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
728 struct ArrayObject * ao=
729 allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
730 obj=(struct ___Object___ *)ptrarray[2];
731 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
733 struct ArrayObject * ao=
734 allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
736 ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
737 ARRAYSET(ao, struct ___Object___ *, 1, obj);
738 ao->___cachedCode___=2;
739 tagd->flagptr=(struct ___Object___ *)ao;
741 struct ArrayObject *ao=(struct ArrayObject *) tagset;
742 if (ao->___cachedCode___<ao->___length___) {
743 ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
747 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
748 struct ArrayObject * aonew=
749 allocate_newarray(&ptrarray,OBJECTARRAYTYPE,
750 OBJECTARRAYINTERVAL+ao->___length___);
751 obj=(struct ___Object___ *)ptrarray[2];
752 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
753 ao=(struct ArrayObject *)tagd->flagptr;
755 struct ArrayObject * aonew=
756 allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
758 aonew->___cachedCode___=ao->___cachedCode___+1;
759 for(i=0; i<ao->___length___; i++) {
760 ARRAYSET(aonew, struct ___Object___*, i,
761 ARRAYGET(ao, struct ___Object___*, i));
763 ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
764 tagd->flagptr=(struct ___Object___ *) aonew;
770 /* This function clears a tag. */
772 void tagclear(void *ptr,
773 struct ___Object___ * obj,
774 struct ___TagDescriptor___ * tagd) {
776 void tagclear(struct ___Object___ * obj,
777 struct ___TagDescriptor___ * tagd) {
779 /* We'll assume that tag is alway there.
780 Need to statically check for this of course. */
781 struct ___Object___ * tagptr=obj->___tags___;
783 if (tagptr->type==TAGTYPE) {
784 if ((struct ___TagDescriptor___ *)tagptr==tagd)
785 obj->___tags___=NULL;
787 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
789 for(i=0; i<ao->___cachedCode___; i++) {
790 struct ___TagDescriptor___ * td=
791 ARRAYGET(ao, struct ___TagDescriptor___ *, i);
793 ao->___cachedCode___--;
794 if (i<ao->___cachedCode___)
795 ARRAYSET(ao, struct ___TagDescriptor___ *, i,
796 ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
797 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
798 if (ao->___cachedCode___==0)
799 obj->___tags___=NULL;
806 struct ___Object___ *tagset=tagd->flagptr;
807 if (tagset->type!=OBJECTARRAYTYPE) {
811 struct ArrayObject *ao=(struct ArrayObject *) tagset;
813 for(i=0; i<ao->___cachedCode___; i++) {
814 struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
816 ao->___cachedCode___--;
817 if (i<ao->___cachedCode___)
818 ARRAYSET(ao, struct ___Object___ *, i,
819 ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
820 ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
821 if (ao->___cachedCode___==0)
832 /* This function allocates a new tag. */
834 struct ___TagDescriptor___ * allocate_tag(void *ptr,
836 struct ___TagDescriptor___ * v=
837 (struct ___TagDescriptor___ *) FREEMALLOC((struct garbagelist *) ptr,
840 struct ___TagDescriptor___ * allocate_tag(int index) {
841 struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
850 /* This function updates the flag for object ptr. It or's the flag
851 with the or mask and and's it with the andmask. */
853 void flagbody(struct ___Object___ *ptr,
855 struct parameterwrapper ** queues,
859 int flagcomp(const int *val1, const int *val2) {
860 return (*val1)-(*val2);
863 void flagorand(void * ptr,
866 struct parameterwrapper ** queues,
869 int oldflag=((int *)ptr)[1];
870 int flag=ormask|oldflag;
872 flagbody(ptr, flag, queues, length, false);
876 bool intflagorand(void * ptr,
880 int oldflag=((int *)ptr)[1];
881 int flag=ormask|oldflag;
883 if (flag==oldflag) /* Don't do anything */
886 flagbody(ptr, flag, NULL, 0, false);
892 void flagorandinit(void * ptr,
895 int oldflag=((int *)ptr)[1];
896 int flag=ormask|oldflag;
898 flagbody(ptr,flag,NULL,0,true);
901 void flagbody(struct ___Object___ *ptr,
903 struct parameterwrapper ** vqueues,
906 struct parameterwrapper * flagptr = NULL;
908 struct parameterwrapper ** queues = vqueues;
909 int length = vlength;
912 int * enterflags = NULL;
913 if((!isnew) && (queues == NULL)) {
914 if(BAMBOO_NUM_OF_CORE < NUMCORES) {
915 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
916 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
923 /*Remove object from all queues */
924 for(i = 0; i < length; ++i) {
926 ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next,
927 (int *) &enterflags, &UNUSED, &UNUSED2);
928 ObjectHashremove(flagptr->objectset, (int)ptr);
929 if (enterflags!=NULL)
934 void enqueueObject(void * vptr,
935 struct parameterwrapper ** vqueues,
937 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
940 //struct QueueItem *tmpptr;
941 struct parameterwrapper * parameter=NULL;
944 struct parameterwrapper * prevptr=NULL;
945 struct ___Object___ *tagptr=NULL;
946 struct parameterwrapper ** queues = vqueues;
947 int length = vlength;
948 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
952 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
953 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
955 tagptr=ptr->___tags___;
957 /* Outer loop iterates through all parameter queues an object of
958 this type could be in. */
959 for(j = 0; j < length; ++j) {
960 parameter = queues[j];
962 if (parameter->numbertags>0) {
964 goto nextloop; //that means the object has no tag
965 //but that param needs tag
966 else if(tagptr->type==TAGTYPE) { //one tag
967 //struct ___TagDescriptor___ * tag=
968 //(struct ___TagDescriptor___*) tagptr;
969 for(i=0; i<parameter->numbertags; i++) {
970 //slotid is parameter->tagarray[2*i];
971 int tagid=parameter->tagarray[2*i+1];
972 if (tagid!=tagptr->flag)
973 goto nextloop; /*We don't have this tag */
975 } else { //multiple tags
976 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
977 for(i=0; i<parameter->numbertags; i++) {
978 //slotid is parameter->tagarray[2*i];
979 int tagid=parameter->tagarray[2*i+1];
981 for(j=0; j<ao->___cachedCode___; j++) {
982 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
993 for(i=0; i<parameter->numberofterms; i++) {
994 int andmask=parameter->intarray[i*2];
995 int checkmask=parameter->intarray[i*2+1];
996 if ((ptr->flag&andmask)==checkmask) {
997 enqueuetasks(parameter, prevptr, ptr, NULL, 0);
1008 void enqueueObject_I(void * vptr,
1009 struct parameterwrapper ** vqueues,
1011 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1014 //struct QueueItem *tmpptr;
1015 struct parameterwrapper * parameter=NULL;
1018 struct parameterwrapper * prevptr=NULL;
1019 struct ___Object___ *tagptr=NULL;
1020 struct parameterwrapper ** queues = vqueues;
1021 int length = vlength;
1022 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1025 if(queues == NULL) {
1026 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
1027 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
1029 tagptr=ptr->___tags___;
1031 /* Outer loop iterates through all parameter queues an object of
1032 this type could be in. */
1033 for(j = 0; j < length; ++j) {
1034 parameter = queues[j];
1036 if (parameter->numbertags>0) {
1038 goto nextloop; //that means the object has no tag
1039 //but that param needs tag
1040 else if(tagptr->type==TAGTYPE) { //one tag
1041 //struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1042 for(i=0; i<parameter->numbertags; i++) {
1043 //slotid is parameter->tagarray[2*i];
1044 int tagid=parameter->tagarray[2*i+1];
1045 if (tagid!=tagptr->flag)
1046 goto nextloop; /*We don't have this tag */
1048 } else { //multiple tags
1049 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1050 for(i=0; i<parameter->numbertags; i++) {
1051 //slotid is parameter->tagarray[2*i];
1052 int tagid=parameter->tagarray[2*i+1];
1054 for(j=0; j<ao->___cachedCode___; j++) {
1055 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
1066 for(i=0; i<parameter->numberofterms; i++) {
1067 int andmask=parameter->intarray[i*2];
1068 int checkmask=parameter->intarray[i*2+1];
1069 if ((ptr->flag&andmask)==checkmask) {
1070 enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
1082 int * getAliasLock(void ** ptrs,
1084 struct RuntimeHash * tbl) {
1086 return (int*)(RUNMALLOC(sizeof(int)));
1091 bool redirect = false;
1092 int redirectlock = 0;
1093 for(; i < length; i++) {
1094 struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
1097 if(ptr->lock == NULL) {
1100 lock = (int)(ptr->lock);
1103 if(lock != redirectlock) {
1104 RuntimeHashadd(tbl, lock, redirectlock);
1107 if(RuntimeHashcontainskey(tbl, lock)) {
1108 // already redirected
1110 RuntimeHashget(tbl, lock, &redirectlock);
1111 for(; j < locklen; j++) {
1112 if(locks[j] != redirectlock) {
1113 RuntimeHashadd(tbl, locks[j], redirectlock);
1118 for(j = 0; j < locklen; j++) {
1119 if(locks[j] == lock) {
1122 } else if(locks[j] > lock) {
1129 locks[h] = locks[h-1];
1138 return (int *)redirectlock;
1140 return (int *)(locks[0]);
1145 void addAliasLock(void * ptr,
1147 struct ___Object___ * obj = (struct ___Object___ *)ptr;
1148 if(((int)ptr != lock) && (obj->lock != (int*)lock)) {
1149 // originally no alias lock associated or have a different alias lock
1150 // flush it as the new one
1151 obj->lock = (int *)lock;
1156 inline void setTaskExitIndex(int index) {
1157 taskInfoArray[taskInfoIndex]->exitIndex = index;
1160 inline void addNewObjInfo(void * nobj) {
1161 if(taskInfoArray[taskInfoIndex]->newObjs == NULL) {
1162 taskInfoArray[taskInfoIndex]->newObjs = createQueue();
1164 addNewItem(taskInfoArray[taskInfoIndex]->newObjs, nobj);
1168 void * smemalloc(int size,
1173 // go through free mem list for suitable blocks
1174 struct freeMemItem * freemem = bamboo_free_mem_list->head;
1175 struct freeMemItem * prev = NULL;
1177 if(freemem->size >= isize) {
1182 freemem = freemem->next;
1183 } while(freemem != NULL);
1184 if(freemem != NULL) {
1185 mem = (void *)(freemem->ptr);
1186 // check the remaining space in this block
1187 int remain = (int)(mem-(BAMBOO_BASE_VA));
1188 int bound = (BAMBOO_SMEM_SIZE);
1189 if(remain < BAMBOO_LARGE_SMEM_BOUND) {
1190 bound = (BAMBOO_SMEM_SIZE_L);
1192 remain = bound - remain%bound;
1193 if(remain < isize) {
1194 // this object acrosses blocks
1195 // try to align the block if required a block
1196 if((isize == BAMBOO_SMEM_SIZE) && (freemem->size >= isize + remain)) {
1201 freemem->ptr = ((void*)freemem->ptr) + isize;
1202 freemem->size -= isize;
1205 mem = mspace_calloc(bamboo_free_msp, 1, isize);
1209 // no enough shared global memory
1215 BAMBOO_DEBUGPRINT(0xa001);
1216 BAMBOO_EXIT(0xa001);
1222 // receive object transferred from other cores
1223 // or the terminate message from other cores
1224 // Should be invoked in critical sections!!
1225 // NOTICE: following format is for threadsimulate version only
1226 // RAW version please see previous description
1227 // format: type + object
1228 // type: -1--stall msg
1230 // return value: 0--received an object
1231 // 1--received nothing
1232 // 2--received a Stall Msg
1233 // 3--received a lock Msg
1234 // RAW version: -1 -- received nothing
1235 // otherwise -- received msg type
1236 int receiveObject() {
1240 if(receiveMsg() == -1) {
1244 if(msgdataindex == msglength) {
1245 // received a whole msg
1250 // receive a object transfer msg
1251 struct transObjInfo * transObj =
1252 RUNMALLOC_I(sizeof(struct transObjInfo));
1256 BAMBOO_DEBUGPRINT(0xe880);
1259 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1261 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1263 BAMBOO_EXIT(0xa002);
1265 // store the object and its corresponding queue info, enqueue it later
1266 transObj->objptr = (void *)msgdata[2];
1267 transObj->length = (msglength - 3) / 2;
1268 transObj->queues = RUNMALLOC_I(sizeof(int)*(msglength - 3));
1269 for(k = 0; k < transObj->length; ++k) {
1270 transObj->queues[2*k] = msgdata[3+2*k];
1273 BAMBOO_DEBUGPRINT_REG(transObj->queues[2*k]);
1276 transObj->queues[2*k+1] = msgdata[3+2*k+1];
1279 BAMBOO_DEBUGPRINT_REG(transObj->queues[2*k+1]);
1283 // check if there is an existing duplicate item
1285 struct QueueItem * qitem = getHead(&objqueue);
1286 struct QueueItem * prev = NULL;
1287 while(qitem != NULL) {
1288 struct transObjInfo * tmpinfo =
1289 (struct transObjInfo *)(qitem->objectptr);
1290 if(tmpinfo->objptr == transObj->objptr) {
1291 // the same object, remove outdate one
1292 removeItem(&objqueue, qitem);
1298 qitem = getHead(&objqueue);
1300 qitem = getNextQueueItem(prev);
1303 addNewItem_I(&objqueue, (void *)transObj);
1305 ++(self_numreceiveobjs);
1310 // receive a stall msg
1311 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1312 // non startup core can not receive stall msg
1314 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1316 BAMBOO_EXIT(0xa003);
1318 if(msgdata[1] < NUMCORES) {
1321 BAMBOO_DEBUGPRINT(0xe881);
1324 corestatus[msgdata[1]] = 0;
1325 numsendobjs[msgdata[1]] = msgdata[2];
1326 numreceiveobjs[msgdata[1]] = msgdata[3];
1331 // GC version have no lock msgs
1332 #ifndef MULTICORE_GC
1334 // receive lock request msg, handle it right now
1335 // check to see if there is a lock exist for the required obj
1336 // msgdata[1] -> lock type
1337 int data2 = msgdata[2]; // obj pointer
1338 int data3 = msgdata[3]; // lock
1339 int data4 = msgdata[4]; // request core
1340 // -1: redirected, 0: approved, 1: denied
1341 deny = processlockrequest(msgdata[1], data3, data2,
1342 data4, data4, true);
1344 // this lock request is redirected
1347 // send response msg
1348 // for 32 bit machine, the size is always 4 words
1349 int tmp = deny==1?LOCKDENY:LOCKGROUNT;
1351 cache_msg_4(data4, tmp, msgdata[1], data2, data3);
1353 send_msg_4(data4, tmp, msgdata[1], data2, data3);
1360 // receive lock grount msg
1361 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1363 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1365 BAMBOO_EXIT(0xa004);
1367 if((lockobj == msgdata[2]) && (lock2require == msgdata[3])) {
1370 BAMBOO_DEBUGPRINT(0xe882);
1379 // conflicts on lockresults
1381 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1383 BAMBOO_EXIT(0xa005);
1389 // receive lock deny msg
1390 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1392 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1394 BAMBOO_EXIT(0xa006);
1396 if((lockobj == msgdata[2]) && (lock2require == msgdata[3])) {
1399 BAMBOO_DEBUGPRINT(0xe883);
1408 // conflicts on lockresults
1410 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1412 BAMBOO_EXIT(0xa007);
1418 // receive lock release msg
1419 processlockrelease(msgdata[1], msgdata[2], 0, false);
1425 case PROFILEOUTPUT: {
1426 // receive an output profile data request msg
1427 if(BAMBOO_NUM_OF_CORE == STARTUPCORE) {
1428 // startup core can not receive profile output finish msg
1429 BAMBOO_EXIT(0xa008);
1433 BAMBOO_DEBUGPRINT(0xe885);
1437 totalexetime = msgdata[1];
1438 outputProfileData();
1440 cache_msg_2(STARTUPCORE, PROFILEFINISH, BAMBOO_NUM_OF_CORE);
1442 send_msg_2(STARTUPCORE, PROFILEFINISH, BAMBOO_NUM_OF_CORE);
1447 case PROFILEFINISH: {
1448 // receive a profile output finish msg
1449 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1450 // non startup core can not receive profile output finish msg
1452 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1454 BAMBOO_EXIT(0xa009);
1458 BAMBOO_DEBUGPRINT(0xe886);
1461 profilestatus[msgdata[1]] = 0;
1466 // GC version has no lock msgs
1467 #ifndef MULTICORE_GC
1468 case REDIRECTLOCK: {
1469 // receive a redirect lock request msg, handle it right now
1470 // check to see if there is a lock exist for the required obj
1471 int data1 = msgdata[1]; // lock type
1472 int data2 = msgdata[2]; // obj pointer
1473 int data3 = msgdata[3]; // redirect lock
1474 int data4 = msgdata[4]; // root request core
1475 int data5 = msgdata[5]; // request core
1476 deny = processlockrequest(msgdata[1], data3, data2, data5, data4, true);
1478 // this lock request is redirected
1481 // send response msg
1482 // for 32 bit machine, the size is always 4 words
1484 cache_msg_4(data4, deny==1?REDIRECTDENY:REDIRECTGROUNT,
1485 data1, data2, data3);
1487 send_msg_4(data4, deny==1?REDIRECTDENY:REDIRECTGROUNT,
1488 data1, data2, data3);
1494 case REDIRECTGROUNT: {
1495 // receive a lock grant msg with redirect info
1496 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1498 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1500 BAMBOO_EXIT(0xa00a);
1502 if(lockobj == msgdata[2]) {
1505 BAMBOO_DEBUGPRINT(0xe891);
1510 RuntimeHashadd_I(objRedirectLockTbl, lockobj, msgdata[3]);
1515 // conflicts on lockresults
1517 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1519 BAMBOO_EXIT(0xa00b);
1524 case REDIRECTDENY: {
1525 // receive a lock deny msg with redirect info
1526 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1528 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1530 BAMBOO_EXIT(0xa00c);
1532 if(lockobj == msgdata[2]) {
1535 BAMBOO_DEBUGPRINT(0xe892);
1544 // conflicts on lockresults
1546 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1548 BAMBOO_EXIT(0xa00d);
1553 case REDIRECTRELEASE: {
1554 // receive a lock release msg with redirect info
1555 processlockrelease(msgdata[1], msgdata[2], msgdata[3], true);
1560 case STATUSCONFIRM: {
1561 // receive a status confirm info
1562 if((BAMBOO_NUM_OF_CORE == STARTUPCORE)
1563 || (BAMBOO_NUM_OF_CORE > NUMCORES - 1)) {
1564 // wrong core to receive such msg
1565 BAMBOO_EXIT(0xa00e);
1567 // send response msg
1570 BAMBOO_DEBUGPRINT(0xe887);
1574 cache_msg_5(STARTUPCORE, STATUSREPORT,
1575 busystatus?1:0, BAMBOO_NUM_OF_CORE,
1576 self_numsendobjs, self_numreceiveobjs);
1578 send_msg_5(STARTUPCORE, STATUSREPORT,
1579 busystatus?1:0, BAMBOO_NUM_OF_CORE,
1580 self_numsendobjs, self_numreceiveobjs);
1586 case STATUSREPORT: {
1587 // receive a status confirm info
1588 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1589 // wrong core to receive such msg
1591 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1593 BAMBOO_EXIT(0xa00f);
1597 BAMBOO_DEBUGPRINT(0xe888);
1603 corestatus[msgdata[2]] = msgdata[1];
1604 numsendobjs[msgdata[2]] = msgdata[3];
1605 numreceiveobjs[msgdata[2]] = msgdata[4];
1611 // receive a terminate msg
1614 BAMBOO_DEBUGPRINT(0xe889);
1623 // receive a shared memory request msg
1624 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1625 // wrong core to receive such msg
1627 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1629 BAMBOO_EXIT(0xa010);
1633 BAMBOO_DEBUGPRINT(0xe88a);
1638 // is currently doing gc, dump this msg
1643 void * mem = smemalloc(msgdata[1], &allocsize);
1647 // send the start_va to request core
1649 cache_msg_3(msgdata[2], MEMRESPONSE, mem, allocsize);
1651 send_msg_3( msgdata[2], MEMRESPONSE, mem, allocsize);
1658 // receive a shared memory response msg
1661 BAMBOO_DEBUGPRINT(0xe88b);
1666 // is currently doing gc, dump this msg
1670 if(msgdata[2] == 0) {
1671 bamboo_smem_size = 0;
1674 // fill header to store the size of this mem block
1675 (*((int*)msgdata[1])) = msgdata[2];
1676 bamboo_smem_size = msgdata[2] - BAMBOO_CACHE_LINE_SIZE;
1678 bamboo_cur_msp = msgdata[1] + BAMBOO_CACHE_LINE_SIZE;
1681 create_mspace_with_base((void*)(msgdata[1]+BAMBOO_CACHE_LINE_SIZE),
1682 msgdata[2]-BAMBOO_CACHE_LINE_SIZE,
1695 // is waiting for response of mem request
1696 // let it return NULL and start gc
1697 bamboo_smem_size = 0;
1698 bamboo_cur_msp = NULL;
1705 // receive a start GC msg
1708 BAMBOO_DEBUGPRINT(0xe88c);
1712 gcphase = MARKPHASE;
1716 case GCSTARTCOMPACT: {
1717 // a compact phase start msg
1718 gcblock2fill = msgdata[1];
1719 gcphase = COMPACTPHASE;
1723 case GCSTARTFLUSH: {
1724 // received a flush phase start msg
1725 gcphase = FLUSHPHASE;
1729 case GCFINISHINIT: {
1730 // received a init phase finish msg
1731 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1732 // non startup core can not receive this msg
1734 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1736 BAMBOO_EXIT(0xb001);
1738 if(msgdata[1] < NUMCORES) {
1739 gccorestatus[msgdata[1]] = 0;
1743 case GCFINISHMARK: {
1744 // received a mark phase finish msg
1745 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1746 // non startup core can not receive this msg
1748 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1750 BAMBOO_EXIT(0xb002);
1752 if(msgdata[1] < NUMCORES) {
1753 gccorestatus[msgdata[1]] = 0;
1754 gcnumsendobjs[msgdata[1]] = msgdata[2];
1755 gcnumreceiveobjs[msgdata[1]] = msgdata[3];
1760 case GCFINISHCOMPACT: {
1761 // received a compact phase finish msg
1762 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1763 // non startup core can not receive this msg
1766 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1768 BAMBOO_EXIT(0xb003);
1770 int cnum = msgdata[1];
1771 int filledblocks = msgdata[2];
1772 int heaptop = msgdata[3];
1773 int data4 = msgdata[4];
1774 if(cnum < NUMCORES) {
1775 if(COMPACTPHASE == gcphase) {
1776 gcfilledblocks[cnum] = filledblocks;
1777 gcloads[cnum] = heaptop;
1784 if(gcfindSpareMem_I(&startaddr, &tomove, &dstcore, data4, cnum)) {
1786 cache_msg_4(cnum, GCMOVESTART, dstcore, startaddr, tomove);
1788 send_msg_4(cnum, GCMOVESTART, dstcore, startaddr, tomove);
1792 gccorestatus[cnum] = 0;
1793 // check if there is pending move request
1794 if(gcmovepending > 0) {
1796 for(j = 0; j < NUMCORES; j++) {
1797 if(gcrequiredmems[j]>0) {
1805 gcrequiredmems[j] = assignSpareMem_I(cnum,
1809 if(STARTUPCORE == j) {
1812 gcmovestartaddr = startaddr;
1813 gcblock2fill = tomove;
1816 cache_msg_4(j, GCMOVESTART, cnum, startaddr, tomove);
1818 send_msg_4(j, GCMOVESTART, cnum, startaddr, tomove);
1820 } // if(STARTUPCORE == j)
1821 if(gcrequiredmems[j] == 0) {
1824 } // if(j < NUMCORES)
1825 } // if(gcmovepending > 0)
1827 } // if(cnum < NUMCORES)
1831 case GCFINISHFLUSH: {
1832 // received a flush phase finish msg
1833 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1834 // non startup core can not receive this msg
1837 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1839 BAMBOO_EXIT(0xb004);
1841 if(msgdata[1] < NUMCORES) {
1842 gccorestatus[msgdata[1]] = 0;
1848 // received a GC finish msg
1849 gcphase = FINISHPHASE;
1853 case GCMARKCONFIRM: {
1854 // received a marked phase finish confirm request msg
1855 if((BAMBOO_NUM_OF_CORE == STARTUPCORE)
1856 || (BAMBOO_NUM_OF_CORE > NUMCORES - 1)) {
1857 // wrong core to receive such msg
1858 BAMBOO_EXIT(0xb005);
1860 // send response msg
1862 cache_msg_5(STARTUPCORE, GCMARKREPORT, BAMBOO_NUM_OF_CORE,
1863 gcbusystatus, gcself_numsendobjs,
1864 gcself_numreceiveobjs);
1866 send_msg_5(STARTUPCORE, GCMARKREPORT, BAMBOO_NUM_OF_CORE,
1867 gcbusystatus, gcself_numsendobjs, gcself_numreceiveobjs);
1873 case GCMARKREPORT: {
1874 // received a marked phase finish confirm response msg
1875 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1876 // wrong core to receive such msg
1878 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1880 BAMBOO_EXIT(0xb006);
1885 gccorestatus[msgdata[1]] = msgdata[2];
1886 gcnumsendobjs[msgdata[1]] = msgdata[3];
1887 gcnumreceiveobjs[msgdata[1]] = msgdata[4];
1893 // received a markedObj msg
1894 gc_enqueue_I(msgdata[1]);
1895 gcself_numreceiveobjs++;
1896 gcbusystatus = true;
1901 // received a start moving objs msg
1903 gcdstcore = msgdata[1];
1904 gcmovestartaddr = msgdata[2];
1905 gcblock2fill = msgdata[3];
1909 case GCMAPREQUEST: {
1910 // received a mapping info request msg
1911 void * dstptr = NULL;
1912 RuntimeHashget(gcpointertbl, msgdata[1], &dstptr);
1913 if(NULL == dstptr) {
1914 // no such pointer in this core, something is wrong
1915 BAMBOO_EXIT(0xb007);
1917 // send back the mapping info
1919 cache_msg_3(msgdata[2], GCMAPINFO, msgdata[1], (int)dstptr);
1921 send_msg_3(msgdata[2], GCMAPINFO, msgdata[1], (int)dstptr);
1928 // received a mapping info response msg
1929 if(msgdata[1] != gcobj2map) {
1930 // obj not matched, something is wrong
1931 BAMBOO_EXIT(0xb008);
1933 gcmappedobj = msgdata[2];
1934 RuntimeHashadd_I(gcpointertbl, gcobj2map, gcmappedobj);
1940 case GCLOBJREQUEST: {
1941 // received a large objs info request msg
1942 transferMarkResults_I();
1947 // received a large objs info response msg
1950 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1952 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1954 BAMBOO_EXIT(0xb009);
1956 // store the mark result info
1957 int cnum = msgdata[2];
1958 gcloads[cnum] = msgdata[3];
1959 if(gcheaptop < msgdata[4]) {
1960 gcheaptop = msgdata[4];
1962 // large obj info here
1963 for(int k = 5; k < msgdata[1];) {
1964 gc_lobjenqueue_I(msgdata[k++], msgdata[k++], cnum);
1966 } // for(int k = 5; k < msgdata[1];)
1970 case GCLOBJMAPPING: {
1971 // received a large obj mapping info msg
1972 RuntimeHashadd_I(gcpointertbl, msgdata[1], msgdata[2]);
1981 for(msgdataindex--; msgdataindex > 0; --msgdataindex) {
1982 msgdata[msgdataindex] = -1;
1988 BAMBOO_DEBUGPRINT(0xe88d);
1992 if(BAMBOO_MSG_AVAIL() != 0) {
2005 BAMBOO_DEBUGPRINT(0xe88e);
2009 /* if(isInterrupt) {
2017 int enqueuetasks(struct parameterwrapper *parameter,
2018 struct parameterwrapper *prevptr,
2019 struct ___Object___ *ptr,
2021 int numenterflags) {
2022 void * taskpointerarray[MAXTASKPARAMS];
2024 //int numparams=parameter->task->numParameters;
2025 int numiterators=parameter->task->numTotal-1;
2028 struct taskdescriptor * task=parameter->task;
2030 //this add the object to parameterwrapper
2031 ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags,
2032 numenterflags, enterflags==NULL);
2034 /* Add enqueued object to parameter vector */
2035 taskpointerarray[parameter->slot]=ptr;
2037 /* Reset iterators */
2038 for(j=0; j<numiterators; j++) {
2039 toiReset(¶meter->iterators[j]);
2042 /* Find initial state */
2043 for(j=0; j<numiterators; j++) {
2045 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
2046 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2048 /* Need to backtrack */
2049 toiReset(¶meter->iterators[j]);
2053 /* Nothing to enqueue */
2059 /* Enqueue current state */
2061 struct taskparamdescriptor *tpd=
2062 RUNMALLOC(sizeof(struct taskparamdescriptor));
2064 tpd->numParameters=numiterators+1;
2065 tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
2067 for(j=0; j<=numiterators; j++) {
2068 //store the actual parameters
2069 tpd->parameterArray[j]=taskpointerarray[j];
2072 if ((/*!gencontains(failedtasks, tpd)&&*/
2073 !gencontains(activetasks,tpd))) {
2074 genputtable(activetasks, tpd, tpd);
2076 RUNFREE(tpd->parameterArray);
2080 /* This loop iterates to the next parameter combination */
2081 if (numiterators==0)
2084 for(j=numiterators-1; j<numiterators; j++) {
2086 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
2087 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2089 /* Need to backtrack */
2090 toiReset(¶meter->iterators[j]);
2094 /* Nothing more to enqueue */
2102 int enqueuetasks_I(struct parameterwrapper *parameter,
2103 struct parameterwrapper *prevptr,
2104 struct ___Object___ *ptr,
2106 int numenterflags) {
2107 void * taskpointerarray[MAXTASKPARAMS];
2109 //int numparams=parameter->task->numParameters;
2110 int numiterators=parameter->task->numTotal-1;
2115 struct taskdescriptor * task=parameter->task;
2117 //this add the object to parameterwrapper
2118 ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags,
2119 numenterflags, enterflags==NULL);
2121 /* Add enqueued object to parameter vector */
2122 taskpointerarray[parameter->slot]=ptr;
2124 /* Reset iterators */
2125 for(j=0; j<numiterators; j++) {
2126 toiReset(¶meter->iterators[j]);
2129 /* Find initial state */
2130 for(j=0; j<numiterators; j++) {
2132 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
2133 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2135 /* Need to backtrack */
2136 toiReset(¶meter->iterators[j]);
2140 /* Nothing to enqueue */
2146 /* Enqueue current state */
2148 struct taskparamdescriptor *tpd=
2149 RUNMALLOC_I(sizeof(struct taskparamdescriptor));
2151 tpd->numParameters=numiterators+1;
2152 tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
2154 for(j=0; j<=numiterators; j++) {
2155 //store the actual parameters
2156 tpd->parameterArray[j]=taskpointerarray[j];
2159 if ((/*!gencontains(failedtasks, tpd)&&*/
2160 !gencontains(activetasks,tpd))) {
2161 genputtable_I(activetasks, tpd, tpd);
2163 RUNFREE(tpd->parameterArray);
2167 /* This loop iterates to the next parameter combination */
2168 if (numiterators==0)
2171 for(j=numiterators-1; j<numiterators; j++) {
2173 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
2174 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2176 /* Need to backtrack */
2177 toiReset(¶meter->iterators[j]);
2181 /* Nothing more to enqueue */
2195 int containstag(struct ___Object___ *ptr,
2196 struct ___TagDescriptor___ *tag);
2198 #ifndef MULTICORE_GC
2199 void releasewritelock_r(void * lock, void * redirectlock) {
2201 int reallock = (int)lock;
2202 targetcore = (reallock >> 5) % BAMBOO_TOTALCORE;
2205 BAMBOO_DEBUGPRINT(0xe671);
2206 BAMBOO_DEBUGPRINT_REG((int)lock);
2207 BAMBOO_DEBUGPRINT_REG(reallock);
2208 BAMBOO_DEBUGPRINT_REG(targetcore);
2211 if(targetcore == BAMBOO_NUM_OF_CORE) {
2212 BAMBOO_START_CRITICAL_SECTION_LOCK();
2214 BAMBOO_DEBUGPRINT(0xf001);
2216 // reside on this core
2217 if(!RuntimeHashcontainskey(locktbl, reallock)) {
2218 // no locks for this object, something is wrong
2219 BAMBOO_EXIT(0xa011);
2222 struct LockValue * lockvalue = NULL;
2224 BAMBOO_DEBUGPRINT(0xe672);
2226 RuntimeHashget(locktbl, reallock, &rwlock_obj);
2227 lockvalue = (struct LockValue *)rwlock_obj;
2229 BAMBOO_DEBUGPRINT_REG(lockvalue->value);
2232 lockvalue->redirectlock = (int)redirectlock;
2234 BAMBOO_DEBUGPRINT_REG(lockvalue->value);
2237 BAMBOO_CLOSE_CRITICAL_SECTION_LOCK();
2239 BAMBOO_DEBUGPRINT(0xf000);
2243 // send lock release with redirect info msg
2244 // for 32 bit machine, the size is always 4 words
2245 send_msg_4(targetcore, REDIRECTRELEASE, 1, (int)lock, (int)redirectlock);
2250 void executetasks() {
2251 void * taskpointerarray[MAXTASKPARAMS+OFFSET];
2254 struct ___Object___ * tmpparam = NULL;
2255 struct parameterdescriptor * pd=NULL;
2256 struct parameterwrapper *pw=NULL;
2261 struct LockValue locks[MAXTASKPARAMS];
2269 while(hashsize(activetasks)>0) {
2274 BAMBOO_DEBUGPRINT(0xe990);
2277 /* See if there are any active tasks */
2278 if (hashsize(activetasks)>0) {
2281 #ifdef ACCURATEPROFILE
2282 profileTaskStart("tpd checking");
2286 currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
2287 genfreekey(activetasks, currtpd);
2289 numparams=currtpd->task->numParameters;
2290 numtotal=currtpd->task->numTotal;
2292 // clear the lockRedirectTbl
2293 // (TODO, this table should be empty after all locks are released)
2295 for(j = 0; j < MAXTASKPARAMS; j++) {
2296 locks[j].redirectlock = 0;
2299 // get all required locks
2301 // check which locks are needed
2302 for(i = 0; i < numparams; i++) {
2303 void * param = currtpd->parameterArray[i];
2307 if(((struct ___Object___ *)param)->type == STARTUPTYPE) {
2309 taskpointerarray[i+OFFSET]=param;
2312 if(((struct ___Object___ *)param)->lock == NULL) {
2313 tmplock = (int)param;
2315 tmplock = (int)(((struct ___Object___ *)param)->lock);
2317 // insert into the locks array
2318 for(j = 0; j < locklen; j++) {
2319 if(locks[j].value == tmplock) {
2322 } else if(locks[j].value > tmplock) {
2329 locks[h].redirectlock = locks[h-1].redirectlock;
2330 locks[h].value = locks[h-1].value;
2332 locks[j].value = tmplock;
2333 locks[j].redirectlock = (int)param;
2336 } // line 2713: for(i = 0; i < numparams; i++)
2337 // grab these required locks
2339 BAMBOO_DEBUGPRINT(0xe991);
2341 for(i = 0; i < locklen; i++) {
2342 int * lock = (int *)(locks[i].redirectlock);
2344 // require locks for this parameter if it is not a startup object
2346 BAMBOO_DEBUGPRINT_REG((int)lock);
2347 BAMBOO_DEBUGPRINT_REG((int)(locks[i].value));
2350 BAMBOO_START_CRITICAL_SECTION();
2352 BAMBOO_DEBUGPRINT(0xf001);
2355 //isInterrupt = false;
2358 BAMBOO_WAITING_FOR_LOCK();
2362 while(BAMBOO_WAITING_FOR_LOCK() != -1) {
2366 grount = lockresult;
2376 //isInterrupt = true;
2378 BAMBOO_CLOSE_CRITICAL_SECTION();
2380 BAMBOO_DEBUGPRINT(0xf000);
2386 BAMBOO_DEBUGPRINT(0xe992);
2388 // can not get the lock, try later
2389 // releas all grabbed locks for previous parameters
2390 for(j = 0; j < i; ++j) {
2391 lock = (int*)(locks[j].redirectlock);
2392 releasewritelock(lock);
2394 genputtable(activetasks, currtpd, currtpd);
2395 if(hashsize(activetasks) == 1) {
2396 // only one task right now, wait a little while before next try
2402 #ifdef ACCURATEPROFILE
2403 // fail, set the end of the checkTaskInfo
2408 } // line 2794: if(grount == 0)
2409 } // line 2752: for(i = 0; i < locklen; i++)
2412 BAMBOO_DEBUGPRINT(0xe993);
2414 /* Make sure that the parameters are still in the queues */
2415 for(i=0; i<numparams; i++) {
2416 void * parameter=currtpd->parameterArray[i];
2420 BAMBOO_CACHE_FLUSH_RANGE((int)parameter,
2421 classsize[((struct ___Object___ *)parameter)->type]);
2423 tmpparam = (struct ___Object___ *)parameter;
2424 pd=currtpd->task->descriptorarray[i];
2425 pw=(struct parameterwrapper *) pd->queue;
2426 /* Check that object is still in queue */
2428 if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
2430 BAMBOO_DEBUGPRINT(0xe994);
2432 // release grabbed locks
2433 for(j = 0; j < locklen; ++j) {
2434 int * lock = (int *)(locks[j].redirectlock);
2435 releasewritelock(lock);
2437 RUNFREE(currtpd->parameterArray);
2443 /* Check if the object's flags still meets requirements */
2447 for(tmpi = 0; tmpi < pw->numberofterms; ++tmpi) {
2448 andmask=pw->intarray[tmpi*2];
2449 checkmask=pw->intarray[tmpi*2+1];
2450 if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
2456 // flags are never suitable
2457 // remove this obj from the queue
2459 int UNUSED, UNUSED2;
2462 BAMBOO_DEBUGPRINT(0xe995);
2464 ObjectHashget(pw->objectset, (int) parameter, (int *) &next,
2465 (int *) &enterflags, &UNUSED, &UNUSED2);
2466 ObjectHashremove(pw->objectset, (int)parameter);
2467 if (enterflags!=NULL)
2468 RUNFREE(enterflags);
2469 // release grabbed locks
2470 for(j = 0; j < locklen; ++j) {
2471 int * lock = (int *)(locks[j].redirectlock);
2472 releasewritelock(lock);
2474 RUNFREE(currtpd->parameterArray);
2478 #ifdef ACCURATEPROFILE
2479 // fail, set the end of the checkTaskInfo
2484 } // line 2878: if (!ismet)
2488 /* Check that object still has necessary tags */
2489 for(j=0; j<pd->numbertags; j++) {
2490 int slotid=pd->tagarray[2*j]+numparams;
2491 struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
2492 if (!containstag(parameter, tagd)) {
2494 BAMBOO_DEBUGPRINT(0xe996);
2497 // release grabbed locks
2499 for(tmpj = 0; tmpj < locklen; ++tmpj) {
2500 int * lock = (int *)(locks[tmpj].redirectlock);
2501 releasewritelock(lock);
2504 RUNFREE(currtpd->parameterArray);
2508 } // line2911: if (!containstag(parameter, tagd))
2509 } // line 2808: for(j=0; j<pd->numbertags; j++)
2511 taskpointerarray[i+OFFSET]=parameter;
2512 } // line 2824: for(i=0; i<numparams; i++)
2514 for(; i<numtotal; i++) {
2515 taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
2520 /* Actually call task */
2522 ((int *)taskpointerarray)[0]=currtpd->numParameters;
2523 taskpointerarray[1]=NULL;
2526 #ifdef ACCURATEPROFILE
2527 // check finish, set the end of the checkTaskInfo
2530 profileTaskStart(currtpd->task->name);
2534 BAMBOO_DEBUGPRINT(0xe997);
2536 ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
2538 #ifdef ACCURATEPROFILE
2539 // task finish, set the end of the checkTaskInfo
2541 // new a PostTaskInfo for the post-task execution
2542 profileTaskStart("post task execution");
2546 BAMBOO_DEBUGPRINT(0xe998);
2547 BAMBOO_DEBUGPRINT_REG(islock);
2552 BAMBOO_DEBUGPRINT(0xe999);
2554 for(i = 0; i < locklen; ++i) {
2555 void * ptr = (void *)(locks[i].redirectlock);
2556 int * lock = (int *)(locks[i].value);
2558 BAMBOO_DEBUGPRINT_REG((int)ptr);
2559 BAMBOO_DEBUGPRINT_REG((int)lock);
2561 #ifndef MULTICORE_GC
2562 if(RuntimeHashcontainskey(lockRedirectTbl, (int)lock)) {
2564 RuntimeHashget(lockRedirectTbl, (int)lock, &redirectlock);
2565 RuntimeHashremovekey(lockRedirectTbl, (int)lock);
2566 releasewritelock_r(lock, (int *)redirectlock);
2571 releasewritelock(ptr);
2574 } // line 3015: if(islock)
2577 // post task execution finish, set the end of the postTaskInfo
2581 // Free up task parameter descriptor
2582 RUNFREE(currtpd->parameterArray);
2586 BAMBOO_DEBUGPRINT(0xe99a);
2589 } // if (hashsize(activetasks)>0)
2590 } // while(hashsize(activetasks)>0)
2592 BAMBOO_DEBUGPRINT(0xe99b);
2596 /* This function processes an objects tags */
2597 void processtags(struct parameterdescriptor *pd,
2599 struct parameterwrapper *parameter,
2600 int * iteratorcount,
2605 for(i=0; i<pd->numbertags; i++) {
2606 int slotid=pd->tagarray[2*i];
2607 int tagid=pd->tagarray[2*i+1];
2609 if (statusarray[slotid+numparams]==0) {
2610 parameter->iterators[*iteratorcount].istag=1;
2611 parameter->iterators[*iteratorcount].tagid=tagid;
2612 parameter->iterators[*iteratorcount].slot=slotid+numparams;
2613 parameter->iterators[*iteratorcount].tagobjectslot=index;
2614 statusarray[slotid+numparams]=1;
2621 void processobject(struct parameterwrapper *parameter,
2623 struct parameterdescriptor *pd,
2629 struct ObjectHash * objectset=
2630 ((struct parameterwrapper *)pd->queue)->objectset;
2632 parameter->iterators[*iteratorcount].istag=0;
2633 parameter->iterators[*iteratorcount].slot=index;
2634 parameter->iterators[*iteratorcount].objectset=objectset;
2635 statusarray[index]=1;
2637 for(i=0; i<pd->numbertags; i++) {
2638 int slotid=pd->tagarray[2*i];
2639 //int tagid=pd->tagarray[2*i+1];
2640 if (statusarray[slotid+numparams]!=0) {
2641 /* This tag has already been enqueued, use it to narrow search */
2642 parameter->iterators[*iteratorcount].tagbindings[tagcount]=
2647 parameter->iterators[*iteratorcount].numtags=tagcount;
2652 /* This function builds the iterators for a task & parameter */
2654 void builditerators(struct taskdescriptor * task,
2656 struct parameterwrapper * parameter) {
2657 int statusarray[MAXTASKPARAMS];
2659 int numparams=task->numParameters;
2660 int iteratorcount=0;
2661 for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
2663 statusarray[index]=1; /* Initial parameter */
2664 /* Process tags for initial iterator */
2666 processtags(task->descriptorarray[index], index, parameter,
2667 &iteratorcount, statusarray, numparams);
2671 /* Check for objects with existing tags */
2672 for(i=0; i<numparams; i++) {
2673 if (statusarray[i]==0) {
2674 struct parameterdescriptor *pd=task->descriptorarray[i];
2676 for(j=0; j<pd->numbertags; j++) {
2677 int slotid=pd->tagarray[2*j];
2678 if(statusarray[slotid+numparams]!=0) {
2679 processobject(parameter, i, pd, &iteratorcount, statusarray,
2681 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2688 /* Next do objects w/ unbound tags*/
2690 for(i=0; i<numparams; i++) {
2691 if (statusarray[i]==0) {
2692 struct parameterdescriptor *pd=task->descriptorarray[i];
2693 if (pd->numbertags>0) {
2694 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2695 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2701 /* Nothing with a tag enqueued */
2703 for(i=0; i<numparams; i++) {
2704 if (statusarray[i]==0) {
2705 struct parameterdescriptor *pd=task->descriptorarray[i];
2706 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2707 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2720 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
2723 for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
2724 struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
2726 printf("%s\n", task->name);
2728 for(j=0; j<task->numParameters; j++) {
2729 struct parameterdescriptor *param=task->descriptorarray[j];
2730 struct parameterwrapper *parameter=param->queue;
2731 struct ObjectHash * set=parameter->objectset;
2732 struct ObjectIterator objit;
2734 printf(" Parameter %d\n", j);
2736 ObjectHashiterator(set, &objit);
2737 while(ObjhasNext(&objit)) {
2738 struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
2739 struct ___Object___ * tagptr=obj->___tags___;
2740 int nonfailed=Objdata4(&objit);
2741 int numflags=Objdata3(&objit);
2742 int flags=Objdata2(&objit);
2745 printf(" Contains %lx\n", obj);
2746 printf(" flag=%d\n", obj->flag);
2749 } else if (tagptr->type==TAGTYPE) {
2751 printf(" tag=%lx\n",tagptr);
2757 struct ArrayObject *ao=(struct ArrayObject *)tagptr;
2758 for(; tagindex<ao->___cachedCode___; tagindex++) {
2760 printf(" tag=%lx\n",ARRAYGET(ao, struct ___TagDescriptor___*,
2773 /* This function processes the task information to create queues for
2774 each parameter type. */
2776 void processtasks() {
2778 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
2781 for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
2782 struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
2785 /* Build objectsets */
2786 for(j=0; j<task->numParameters; j++) {
2787 struct parameterdescriptor *param=task->descriptorarray[j];
2788 struct parameterwrapper *parameter=param->queue;
2789 parameter->objectset=allocateObjectHash(10);
2790 parameter->task=task;
2793 /* Build iterators for parameters */
2794 for(j=0; j<task->numParameters; j++) {
2795 struct parameterdescriptor *param=task->descriptorarray[j];
2796 struct parameterwrapper *parameter=param->queue;
2797 builditerators(task, j, parameter);
2802 void toiReset(struct tagobjectiterator * it) {
2805 } else if (it->numtags>0) {
2808 ObjectHashiterator(it->objectset, &it->it);
2812 int toiHasNext(struct tagobjectiterator *it,
2813 void ** objectarray OPTARG(int * failed)) {
2816 /* Get object with tags */
2817 struct ___Object___ *obj=objectarray[it->tagobjectslot];
2818 struct ___Object___ *tagptr=obj->___tags___;
2819 if (tagptr->type==TAGTYPE) {
2820 if ((it->tagobjindex==0)&& /* First object */
2821 (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
2826 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
2827 int tagindex=it->tagobjindex;
2828 for(; tagindex<ao->___cachedCode___; tagindex++) {
2829 struct ___TagDescriptor___ *td=
2830 ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
2831 if (td->flag==it->tagid) {
2832 it->tagobjindex=tagindex; /* Found right type of tag */
2838 } else if (it->numtags>0) {
2839 /* Use tags to locate appropriate objects */
2840 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
2841 struct ___Object___ *objptr=tag->flagptr;
2843 if (objptr->type!=OBJECTARRAYTYPE) {
2844 if (it->tagobjindex>0)
2846 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
2848 for(i=1; i<it->numtags; i++) {
2849 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
2850 if (!containstag(objptr,tag2))
2855 struct ArrayObject *ao=(struct ArrayObject *) objptr;
2858 for(tagindex=it->tagobjindex;tagindex<ao->___cachedCode___;tagindex++) {
2859 struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
2860 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
2862 for(i=1; i<it->numtags; i++) {
2863 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
2864 if (!containstag(objptr,tag2))
2867 it->tagobjindex=tagindex;
2872 it->tagobjindex=tagindex;
2876 return ObjhasNext(&it->it);
2880 int containstag(struct ___Object___ *ptr,
2881 struct ___TagDescriptor___ *tag) {
2883 struct ___Object___ * objptr=tag->flagptr;
2884 if (objptr->type==OBJECTARRAYTYPE) {
2885 struct ArrayObject *ao=(struct ArrayObject *)objptr;
2886 for(j=0; j<ao->___cachedCode___; j++) {
2887 if (ptr==ARRAYGET(ao, struct ___Object___*, j))
2895 void toiNext(struct tagobjectiterator *it,
2896 void ** objectarray OPTARG(int * failed)) {
2897 /* hasNext has all of the intelligence */
2900 /* Get object with tags */
2901 struct ___Object___ *obj=objectarray[it->tagobjectslot];
2902 struct ___Object___ *tagptr=obj->___tags___;
2903 if (tagptr->type==TAGTYPE) {
2905 objectarray[it->slot]=tagptr;
2907 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
2908 objectarray[it->slot]=
2909 ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
2911 } else if (it->numtags>0) {
2912 /* Use tags to locate appropriate objects */
2913 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
2914 struct ___Object___ *objptr=tag->flagptr;
2915 if (objptr->type!=OBJECTARRAYTYPE) {
2917 objectarray[it->slot]=objptr;
2919 struct ArrayObject *ao=(struct ArrayObject *) objptr;
2920 objectarray[it->slot]=
2921 ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
2924 /* Iterate object */
2925 objectarray[it->slot]=(void *)Objkey(&it->it);