3 #include "multicoreruntime.h"
4 #include "multicoretaskprofile.h"
5 #include "multicoretask.h"
8 #define INLINE inline __attribute__((always_inline))
11 // data structures for task invocation
12 struct genhashtable * activetasks;
13 struct taskparamdescriptor * currtpd;
14 struct LockValue runtime_locks[MAXTASKPARAMS];
17 // specific functions used inside critical sections
18 void enqueueObject_I(void * ptr,
19 struct parameterwrapper ** queues,
21 int enqueuetasks_I(struct parameterwrapper *parameter,
22 struct parameterwrapper *prevptr,
23 struct ___Object___ *ptr,
27 INLINE void initlocktable() {
31 // create the lock table, lockresult table and obj queue
34 (struct RuntimeNode **) RUNMALLOC_I(sizeof(struct RuntimeNode *)*20);
35 /* Set allocation blocks*/
36 locktable.listhead=NULL;
37 locktable.listtail=NULL;
39 locktable.numelements = 0;
44 lockRedirectTbl = allocateRuntimeHash_I(20);
45 objRedirectLockTbl = allocateRuntimeHash_I(20);
49 INLINE void dislocktable() {
53 freeRuntimeHash(lockRedirectTbl);
54 freeRuntimeHash(objRedirectLockTbl);
55 RUNFREE(locktable.bucket);
59 INLINE void inittaskdata() {
60 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
61 // startup core to initialize corestatus[]
62 total_num_t6 = 0; // TODO for test
64 totransobjqueue = createQueue_I();
68 for(int i = 0; i < MAXTASKPARAMS; i++) {
69 runtime_locks[i].redirectlock = 0;
70 runtime_locks[i].value = 0;
74 INIT_TASKPROFILE_DATA();
77 INLINE void distaskdata() {
78 if(activetasks != NULL) {
79 genfreehashtable(activetasks);
82 RUNFREE(currtpd->parameterArray);
89 INLINE bool checkObjQueue() {
91 struct transObjInfo * objInfo = NULL;
94 #ifdef ACCURATEPROFILE
95 PROFILE_TASK_START("objqueue checking");
98 while(!isEmpty(&objqueue)) {
100 BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
101 BAMBOO_DEBUGPRINT(0xf001);
102 BAMBOO_DEBUGPRINT(0xeee1);
104 objInfo = (struct transObjInfo *)getItem(&objqueue);
105 obj = objInfo->objptr;
106 BAMBOO_DEBUGPRINT_REG((int)obj);
107 // grab lock and flush the obj
109 struct ___Object___ * tmpobj = (struct ___Object___ *)obj;
110 while(tmpobj->lock != NULL) {
111 tmpobj = (struct ___Object___ *)(tmpobj->lock);
113 getwritelock_I(tmpobj);
115 BAMBOO_WAITING_FOR_LOCK(0);
118 BAMBOO_DEBUGPRINT_REG(grount);
131 BAMBOO_CACHE_FLUSH_RANGE((int)obj,sizeof(int));
132 BAMBOO_CACHE_FLUSH_RANGE((int)obj,
133 classsize[((struct ___Object___ *)obj)->type]);
134 // enqueue the object
135 for(k = 0; k < objInfo->length; ++k) {
136 int taskindex = objInfo->queues[2 * k];
137 int paramindex = objInfo->queues[2 * k + 1];
138 struct parameterwrapper ** queues =
139 &(paramqueues[BAMBOO_NUM_OF_CORE][taskindex][paramindex]);
140 BAMBOO_DEBUGPRINT_REG(taskindex);
141 BAMBOO_DEBUGPRINT_REG(paramindex);
142 enqueueObject_I(obj, queues, 1);
143 BAMBOO_DEBUGPRINT_REG(hashsize(activetasks));
145 releasewritelock_I(tmpobj);
146 RUNFREE_I(objInfo->queues);
150 // put it at the end of the queue if no update version in the queue
151 struct QueueItem * qitem = getHead(&objqueue);
152 struct QueueItem * prev = NULL;
153 while(qitem != NULL) {
154 struct transObjInfo * tmpinfo =
155 (struct transObjInfo *)(qitem->objectptr);
156 if(tmpinfo->objptr == obj) {
157 // the same object in the queue, which should be enqueued
158 // recently. Current one is outdate, do not re-enqueue it
159 RUNFREE_I(objInfo->queues);
165 qitem = getNextQueueItem(prev);
167 // try to execute active tasks already enqueued first
168 addNewItem_I(&objqueue, objInfo);
170 BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
171 BAMBOO_DEBUGPRINT(0xf000);
174 BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
175 BAMBOO_DEBUGPRINT(0xf000);
178 #ifdef ACCURATEPROFILE
182 BAMBOO_DEBUGPRINT(0xee02);
186 struct ___createstartupobject____I_locals {
189 struct ___StartupObject___ * ___startupobject___;
190 struct ArrayObject * ___stringarray___;
193 void createstartupobject(int argc,
197 /* Allocate startup object */
199 struct ___createstartupobject____I_locals ___locals___ =
200 {2, NULL, NULL, NULL};
201 struct ___StartupObject___ *startupobject=
202 (struct ___StartupObject___*) allocate_new(&___locals___, STARTUPTYPE);
203 ___locals___.___startupobject___ = startupobject;
204 struct ArrayObject * stringarray=
205 allocate_newarray(&___locals___, STRINGARRAYTYPE, argc-1);
206 ___locals___.___stringarray___ = stringarray;
208 struct ___StartupObject___ *startupobject=
209 (struct ___StartupObject___*) allocate_new(STARTUPTYPE);
210 struct ArrayObject * stringarray=
211 allocate_newarray(STRINGARRAYTYPE, argc-1);
213 /* Build array of strings */
214 startupobject->___parameters___=stringarray;
215 for(i=1; i<argc; i++) {
216 int length=strlen(argv[i]);
218 struct ___String___ *newstring=NewString(&___locals___, argv[i],length);
220 struct ___String___ *newstring=NewString(argv[i],length);
222 ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=
226 startupobject->version = 0;
227 startupobject->lock = NULL;
229 /* Set initialized flag for startup object */
230 flagorandinit(startupobject,1,0xFFFFFFFF);
231 enqueueObject(startupobject, NULL, 0);
232 BAMBOO_CACHE_FLUSH_ALL();
235 int hashCodetpd(struct taskparamdescriptor *ftd) {
236 int hash=(int)ftd->task;
238 for(i=0; i<ftd->numParameters; i++) {
239 hash^=(int)ftd->parameterArray[i];
244 int comparetpd(struct taskparamdescriptor *ftd1,
245 struct taskparamdescriptor *ftd2) {
247 if (ftd1->task!=ftd2->task)
249 for(i=0; i<ftd1->numParameters; i++)
250 if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
255 /* This function sets a tag. */
257 void tagset(void *ptr,
258 struct ___Object___ * obj,
259 struct ___TagDescriptor___ * tagd) {
261 void tagset(struct ___Object___ * obj,
262 struct ___TagDescriptor___ * tagd) {
264 struct ArrayObject * ao=NULL;
265 struct ___Object___ * tagptr=obj->___tags___;
267 obj->___tags___=(struct ___Object___ *)tagd;
269 /* Have to check if it is already set */
270 if (tagptr->type==TAGTYPE) {
271 struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
276 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
277 struct ArrayObject * ao=
278 allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
279 obj=(struct ___Object___ *)ptrarray[2];
280 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
281 td=(struct ___TagDescriptor___ *) obj->___tags___;
283 ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
286 ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
287 ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
288 obj->___tags___=(struct ___Object___ *) ao;
289 ao->___cachedCode___=2;
293 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
294 for(i=0; i<ao->___cachedCode___; i++) {
295 struct ___TagDescriptor___ * td=
296 ARRAYGET(ao, struct ___TagDescriptor___*, i);
301 if (ao->___cachedCode___<ao->___length___) {
302 ARRAYSET(ao, struct ___TagDescriptor___ *,ao->___cachedCode___,tagd);
303 ao->___cachedCode___++;
306 int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
307 struct ArrayObject * aonew=
308 allocate_newarray(&ptrarray,TAGARRAYTYPE,
309 TAGARRAYINTERVAL+ao->___length___);
310 obj=(struct ___Object___ *)ptrarray[2];
311 tagd=(struct ___TagDescriptor___ *) ptrarray[3];
312 ao=(struct ArrayObject *)obj->___tags___;
314 struct ArrayObject * aonew=
315 allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
318 aonew->___cachedCode___=ao->___length___+1;
319 for(i=0; i<ao->___length___; i++) {
320 ARRAYSET(aonew, struct ___TagDescriptor___*, i,
321 ARRAYGET(ao, struct ___TagDescriptor___*, i));
323 ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___,tagd);
329 struct ___Object___ * tagset=tagd->flagptr;
332 } else if (tagset->type!=OBJECTARRAYTYPE) {
334 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
335 struct ArrayObject * ao=
336 allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
337 obj=(struct ___Object___ *)ptrarray[2];
338 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
340 struct ArrayObject * ao=
341 allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
343 ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
344 ARRAYSET(ao, struct ___Object___ *, 1, obj);
345 ao->___cachedCode___=2;
346 tagd->flagptr=(struct ___Object___ *)ao;
348 struct ArrayObject *ao=(struct ArrayObject *) tagset;
349 if (ao->___cachedCode___<ao->___length___) {
350 ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
354 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
355 struct ArrayObject * aonew=
356 allocate_newarray(&ptrarray,OBJECTARRAYTYPE,
357 OBJECTARRAYINTERVAL+ao->___length___);
358 obj=(struct ___Object___ *)ptrarray[2];
359 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
360 ao=(struct ArrayObject *)tagd->flagptr;
362 struct ArrayObject * aonew=allocate_newarray(OBJECTARRAYTYPE,
363 OBJECTARRAYINTERVAL+ao->___length___);
365 aonew->___cachedCode___=ao->___cachedCode___+1;
366 for(i=0; i<ao->___length___; i++) {
367 ARRAYSET(aonew, struct ___Object___*, i,
368 ARRAYGET(ao, struct ___Object___*, i));
370 ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
371 tagd->flagptr=(struct ___Object___ *) aonew;
377 /* This function clears a tag. */
379 void tagclear(void *ptr,
380 struct ___Object___ * obj,
381 struct ___TagDescriptor___ * tagd) {
383 void tagclear(struct ___Object___ * obj,
384 struct ___TagDescriptor___ * tagd) {
386 /* We'll assume that tag is alway there.
387 Need to statically check for this of course. */
388 struct ___Object___ * tagptr=obj->___tags___;
390 if (tagptr->type==TAGTYPE) {
391 if ((struct ___TagDescriptor___ *)tagptr==tagd)
392 obj->___tags___=NULL;
394 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
396 for(i=0; i<ao->___cachedCode___; i++) {
397 struct ___TagDescriptor___ * td=
398 ARRAYGET(ao, struct ___TagDescriptor___ *, i);
400 ao->___cachedCode___--;
401 if (i<ao->___cachedCode___)
402 ARRAYSET(ao, struct ___TagDescriptor___ *, i,
403 ARRAYGET(ao,struct ___TagDescriptor___*,ao->___cachedCode___));
404 ARRAYSET(ao,struct ___TagDescriptor___ *,ao->___cachedCode___, NULL);
405 if (ao->___cachedCode___==0)
406 obj->___tags___=NULL;
413 struct ___Object___ *tagset=tagd->flagptr;
414 if (tagset->type!=OBJECTARRAYTYPE) {
418 struct ArrayObject *ao=(struct ArrayObject *) tagset;
420 for(i=0; i<ao->___cachedCode___; i++) {
421 struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
423 ao->___cachedCode___--;
424 if (i<ao->___cachedCode___)
425 ARRAYSET(ao, struct ___Object___ *, i,
426 ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
427 ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
428 if (ao->___cachedCode___==0)
439 /* This function allocates a new tag. */
441 struct ___TagDescriptor___ * allocate_tag(void *ptr,
443 struct ___TagDescriptor___ * v=
444 (struct ___TagDescriptor___ *) FREEMALLOC((struct garbagelist *) ptr,
447 struct ___TagDescriptor___ * allocate_tag(int index) {
448 struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
455 /* This function updates the flag for object ptr. It or's the flag
456 with the or mask and and's it with the andmask. */
458 void flagbody(struct ___Object___ *ptr,
460 struct parameterwrapper ** queues,
464 int flagcomp(const int *val1, const int *val2) {
465 return (*val1)-(*val2);
468 void flagorand(void * ptr,
471 struct parameterwrapper ** queues,
473 int oldflag=((int *)ptr)[2]; // the flag field is now the third one
474 int flag=ormask|oldflag;
476 flagbody(ptr, flag, queues, length, false);
479 bool intflagorand(void * ptr,
482 int oldflag=((int *)ptr)[2]; // the flag field is the third one
483 int flag=ormask|oldflag;
485 if (flag==oldflag) /* Don't do anything */
488 flagbody(ptr, flag, NULL, 0, false);
493 void flagorandinit(void * ptr,
496 int oldflag=((int *)ptr)[2]; // the flag field is the third one
497 int flag=ormask|oldflag;
499 flagbody(ptr,flag,NULL,0,true);
502 void flagbody(struct ___Object___ *ptr,
504 struct parameterwrapper ** vqueues,
507 struct parameterwrapper * flagptr = NULL;
509 struct parameterwrapper ** queues = vqueues;
510 int length = vlength;
513 int * enterflags = NULL;
514 if((!isnew) && (queues == NULL)) {
515 if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
516 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
517 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
524 /*Remove object from all queues */
525 for(i = 0; i < length; ++i) {
527 ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next,
528 (int *) &enterflags, &UNUSED, &UNUSED2);
529 ObjectHashremove(flagptr->objectset, (int)ptr);
530 if (enterflags!=NULL)
535 void enqueueObject(void * vptr,
536 struct parameterwrapper ** vqueues,
538 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
541 struct parameterwrapper * parameter=NULL;
544 struct parameterwrapper * prevptr=NULL;
545 struct ___Object___ *tagptr=NULL;
546 struct parameterwrapper ** queues = vqueues;
547 int length = vlength;
548 if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
552 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
553 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
555 tagptr=ptr->___tags___;
557 /* Outer loop iterates through all parameter queues an object of
558 this type could be in. */
559 for(j = 0; j < length; ++j) {
560 parameter = queues[j];
562 if (parameter->numbertags>0) {
564 goto nextloop; //that means the object has no tag
565 //but that param needs tag
566 else if(tagptr->type==TAGTYPE) { //one tag
567 for(i=0; i<parameter->numbertags; i++) {
568 //slotid is parameter->tagarray[2*i];
569 int tagid=parameter->tagarray[2*i+1];
570 if (tagid!=tagptr->flag)
571 goto nextloop; /*We don't have this tag */
573 } else { //multiple tags
574 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
575 for(i=0; i<parameter->numbertags; i++) {
576 //slotid is parameter->tagarray[2*i];
577 int tagid=parameter->tagarray[2*i+1];
579 for(j=0; j<ao->___cachedCode___; j++) {
580 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
591 for(i=0; i<parameter->numberofterms; i++) {
592 int andmask=parameter->intarray[i*2];
593 int checkmask=parameter->intarray[i*2+1];
594 if ((ptr->flag&andmask)==checkmask) {
595 enqueuetasks(parameter, prevptr, ptr, NULL, 0);
606 void enqueueObject_I(void * vptr,
607 struct parameterwrapper ** vqueues,
609 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
612 struct parameterwrapper * parameter=NULL;
615 struct parameterwrapper * prevptr=NULL;
616 struct ___Object___ *tagptr=NULL;
617 struct parameterwrapper ** queues = vqueues;
618 int length = vlength;
619 if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
623 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
624 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
626 tagptr=ptr->___tags___;
628 /* Outer loop iterates through all parameter queues an object of
629 this type could be in. */
630 for(j = 0; j < length; ++j) {
631 parameter = queues[j];
633 if (parameter->numbertags>0) {
635 goto nextloop; //that means the object has no tag
636 //but that param needs tag
637 else if(tagptr->type==TAGTYPE) { //one tag
638 for(i=0; i<parameter->numbertags; i++) {
639 //slotid is parameter->tagarray[2*i];
640 int tagid=parameter->tagarray[2*i+1];
641 if (tagid!=tagptr->flag)
642 goto nextloop; /*We don't have this tag */
644 } else { //multiple tags
645 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
646 for(i=0; i<parameter->numbertags; i++) {
647 //slotid is parameter->tagarray[2*i];
648 int tagid=parameter->tagarray[2*i+1];
650 for(j=0; j<ao->___cachedCode___; j++) {
651 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
662 for(i=0; i<parameter->numberofterms; i++) {
663 int andmask=parameter->intarray[i*2];
664 int checkmask=parameter->intarray[i*2+1];
665 if ((ptr->flag&andmask)==checkmask) {
666 enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
678 int * getAliasLock(void ** ptrs,
680 struct RuntimeHash * tbl) {
685 // sort all the locks required by the objs in the aliased set
686 for(; i < length; i++) {
687 struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
690 if(ptr->lock == NULL) {
693 lock = (int)(ptr->lock);
696 for(j = 0; j < locklen; j++) {
697 if(locks[j] == lock) {
700 } else if(locks[j] > lock) {
707 locks[h] = locks[h-1];
713 // use the smallest lock as the shared lock for the whole set
714 return (int *)(locks[0]);
716 // TODO possible bug here!!!
718 return (int*)(RUNMALLOC(sizeof(int)));
723 bool redirect = false;
724 int redirectlock = 0;
725 for(; i < length; i++) {
726 struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
729 if(ptr->lock == NULL) {
732 lock = (int)(ptr->lock);
735 if(lock != redirectlock) {
736 RuntimeHashadd(tbl, lock, redirectlock);
739 if(RuntimeHashcontainskey(tbl, lock)) {
740 // already redirected
742 RuntimeHashget(tbl, lock, &redirectlock);
743 for(; j < locklen; j++) {
744 if(locks[j] != redirectlock) {
745 RuntimeHashadd(tbl, locks[j], redirectlock);
750 for(j = 0; j < locklen; j++) {
751 if(locks[j] == lock) {
754 } else if(locks[j] > lock) {
761 locks[h] = locks[h-1];
770 return (int *)redirectlock;
772 // use the first lock as the shared lock
773 for(j = 1; j < locklen; j++) {
774 if(locks[j] != locks[0]) {
775 RuntimeHashadd(tbl, locks[j], locks[0]);
778 return (int *)(locks[0]);
784 void addAliasLock(void * ptr,
786 struct ___Object___ * obj = (struct ___Object___ *)ptr;
787 if(((int)ptr != lock) && (obj->lock != (int*)lock)) {
788 // originally no alias lock associated or have a different alias lock
789 // flush it as the new one
791 while(obj->lock != NULL) {
792 // previously have alias lock, trace the 'root' obj and redirect it
793 obj = (struct ___Object___ *)(obj->lock);
796 obj->lock = (int *)lock;
800 int enqueuetasks(struct parameterwrapper *parameter,
801 struct parameterwrapper *prevptr,
802 struct ___Object___ *ptr,
805 void * taskpointerarray[MAXTASKPARAMS];
807 int numiterators=parameter->task->numTotal-1;
810 struct taskdescriptor * task=parameter->task;
812 //this add the object to parameterwrapper
813 ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags,
814 numenterflags, enterflags==NULL);
816 /* Add enqueued object to parameter vector */
817 taskpointerarray[parameter->slot]=ptr;
819 /* Reset iterators */
820 for(j=0; j<numiterators; j++) {
821 toiReset(¶meter->iterators[j]);
824 /* Find initial state */
825 for(j=0; j<numiterators; j++) {
827 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
828 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
830 /* Need to backtrack */
831 toiReset(¶meter->iterators[j]);
835 /* Nothing to enqueue */
841 /* Enqueue current state */
843 struct taskparamdescriptor *tpd=
844 RUNMALLOC(sizeof(struct taskparamdescriptor));
846 tpd->numParameters=numiterators+1;
847 tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
849 for(j=0; j<=numiterators; j++) {
850 //store the actual parameters
851 tpd->parameterArray[j]=taskpointerarray[j];
854 if (!gencontains(activetasks,tpd)) {
855 genputtable(activetasks, tpd, tpd);
857 RUNFREE(tpd->parameterArray);
861 /* This loop iterates to the next parameter combination */
865 for(j=numiterators-1; j<numiterators; j++) {
867 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
868 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
870 /* Need to backtrack */
871 toiReset(¶meter->iterators[j]);
875 /* Nothing more to enqueue */
883 int enqueuetasks_I(struct parameterwrapper *parameter,
884 struct parameterwrapper *prevptr,
885 struct ___Object___ *ptr,
888 void * taskpointerarray[MAXTASKPARAMS];
890 int numiterators=parameter->task->numTotal-1;
893 struct taskdescriptor * task=parameter->task;
895 //this add the object to parameterwrapper
896 ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags,
897 numenterflags, enterflags==NULL);
899 /* Add enqueued object to parameter vector */
900 taskpointerarray[parameter->slot]=ptr;
902 /* Reset iterators */
903 for(j=0; j<numiterators; j++) {
904 toiReset(¶meter->iterators[j]);
907 /* Find initial state */
908 for(j=0; j<numiterators; j++) {
910 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
911 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
913 /* Need to backtrack */
914 toiReset(¶meter->iterators[j]);
918 /* Nothing to enqueue */
924 /* Enqueue current state */
926 struct taskparamdescriptor *tpd=
927 RUNMALLOC_I(sizeof(struct taskparamdescriptor));
929 tpd->numParameters=numiterators+1;
930 tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
932 for(j=0; j<=numiterators; j++) {
933 //store the actual parameters
934 tpd->parameterArray[j]=taskpointerarray[j];
937 if (!gencontains(activetasks,tpd)) {
938 genputtable_I(activetasks, tpd, tpd);
940 RUNFREE_I(tpd->parameterArray);
944 /* This loop iterates to the next parameter combination */
948 for(j=numiterators-1; j<numiterators; j++) {
950 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
951 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
953 /* Need to backtrack */
954 toiReset(¶meter->iterators[j]);
958 /* Nothing more to enqueue */
972 int containstag(struct ___Object___ *ptr,
973 struct ___TagDescriptor___ *tag);
976 void releasewritelock_r(void * lock, void * redirectlock) {
978 int reallock = (int)lock;
979 targetcore = (reallock >> 5) % NUMCORES;
981 BAMBOO_DEBUGPRINT(0xe671);
982 BAMBOO_DEBUGPRINT_REG((int)lock);
983 BAMBOO_DEBUGPRINT_REG(reallock);
984 BAMBOO_DEBUGPRINT_REG(targetcore);
986 if(targetcore == BAMBOO_NUM_OF_CORE) {
987 BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
988 BAMBOO_DEBUGPRINT(0xf001);
989 // reside on this core
990 if(!RuntimeHashcontainskey(locktbl, reallock)) {
991 // no locks for this object, something is wrong
995 struct LockValue * lockvalue = NULL;
996 BAMBOO_DEBUGPRINT(0xe672);
997 RuntimeHashget(locktbl, reallock, &rwlock_obj);
998 lockvalue = (struct LockValue *)rwlock_obj;
999 BAMBOO_DEBUGPRINT_REG(lockvalue->value);
1001 lockvalue->redirectlock = (int)redirectlock;
1002 BAMBOO_DEBUGPRINT_REG(lockvalue->value);
1004 BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1005 BAMBOO_DEBUGPRINT(0xf000);
1008 // send lock release with redirect info msg
1009 // for 32 bit machine, the size is always 4 words
1010 send_msg_4(targetcore, REDIRECTRELEASE, 1, (int)lock,
1011 (int)redirectlock, false);
1016 void executetasks() {
1017 void * taskpointerarray[MAXTASKPARAMS+OFFSET];
1020 struct ___Object___ * tmpparam = NULL;
1021 struct parameterdescriptor * pd=NULL;
1022 struct parameterwrapper *pw=NULL;
1032 while(hashsize(activetasks)>0) {
1034 BAMBOO_DEBUGPRINT(0xe990);
1036 /* See if there are any active tasks */
1038 #ifdef ACCURATEPROFILE
1039 PROFILE_TASK_START("tpd checking");
1043 currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
1044 genfreekey(activetasks, currtpd);
1046 numparams=currtpd->task->numParameters;
1047 numtotal=currtpd->task->numTotal;
1049 // (TODO, this table should be empty after all locks are released)
1051 // get all required locks
1052 runtime_locklen = 0;
1053 // check which locks are needed
1054 for(i = 0; i < numparams; i++) {
1055 void * param = currtpd->parameterArray[i];
1059 if(((struct ___Object___ *)param)->type == STARTUPTYPE) {
1061 taskpointerarray[i+OFFSET]=param;
1064 struct ___Object___ * obj = (struct ___Object___ *)param;
1065 while(obj->lock != NULL) {
1066 obj = (struct ___Object___ *)(obj->lock);
1068 tmplock = (int)(obj);
1069 // insert into the locks array
1070 for(j = 0; j < runtime_locklen; j++) {
1071 if(runtime_locks[j].value == tmplock) {
1074 } else if(runtime_locks[j].value > tmplock) {
1079 int h = runtime_locklen;
1081 runtime_locks[h].redirectlock = runtime_locks[h-1].redirectlock;
1082 runtime_locks[h].value = runtime_locks[h-1].value;
1084 runtime_locks[j].value = tmplock;
1085 runtime_locks[j].redirectlock = (int)param;
1088 } // for(i = 0; i < numparams; i++)
1089 // grab these required locks
1090 BAMBOO_DEBUGPRINT(0xe991);
1092 for(i = 0; i < runtime_locklen; i++) {
1093 int * lock = (int *)(runtime_locks[i].value);
1095 // require locks for this parameter if it is not a startup object
1096 BAMBOO_DEBUGPRINT_REG((int)lock);
1097 BAMBOO_DEBUGPRINT_REG((int)(runtime_locks[i].value));
1099 BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1100 BAMBOO_DEBUGPRINT(0xf001);
1102 BAMBOO_WAITING_FOR_LOCK(0);
1106 while(BAMBOO_WAITING_FOR_LOCK(0) != -1) {
1110 grount = lockresult;
1119 BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1120 BAMBOO_DEBUGPRINT(0xf000);
1123 BAMBOO_DEBUGPRINT(0xe992);
1124 BAMBOO_DEBUGPRINT_REG(lock);
1125 // check if has the lock already
1126 // can not get the lock, try later
1127 // release all grabbed locks for previous parameters
1128 for(j = 0; j < i; ++j) {
1129 lock = (int*)(runtime_locks[j].value/*redirectlock*/);
1130 releasewritelock(lock);
1132 genputtable(activetasks, currtpd, currtpd);
1133 if(hashsize(activetasks) == 1) {
1134 // only one task right now, wait a little while before next try
1139 #ifdef ACCURATEPROFILE
1140 // fail, set the end of the checkTaskInfo
1145 } // line 2752: for(i = 0; i < runtime_locklen; i++)
1147 BAMBOO_DEBUGPRINT(0xe993);
1148 /* Make sure that the parameters are still in the queues */
1149 for(i=0; i<numparams; i++) {
1150 void * parameter=currtpd->parameterArray[i];
1153 BAMBOO_CACHE_FLUSH_RANGE((int)parameter,
1154 classsize[((struct ___Object___ *)parameter)->type]);
1155 tmpparam = (struct ___Object___ *)parameter;
1156 pd=currtpd->task->descriptorarray[i];
1157 pw=(struct parameterwrapper *) pd->queue;
1158 /* Check that object is still in queue */
1160 if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
1161 BAMBOO_DEBUGPRINT(0xe994);
1162 BAMBOO_DEBUGPRINT_REG(parameter);
1163 // release grabbed locks
1164 for(j = 0; j < runtime_locklen; ++j) {
1165 int * lock = (int *)(runtime_locks[j].value);
1166 releasewritelock(lock);
1168 RUNFREE(currtpd->parameterArray);
1174 /* Check if the object's flags still meets requirements */
1178 for(tmpi = 0; tmpi < pw->numberofterms; ++tmpi) {
1179 andmask=pw->intarray[tmpi*2];
1180 checkmask=pw->intarray[tmpi*2+1];
1181 if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
1187 // flags are never suitable
1188 // remove this obj from the queue
1190 int UNUSED, UNUSED2;
1192 BAMBOO_DEBUGPRINT(0xe995);
1193 BAMBOO_DEBUGPRINT_REG(parameter);
1194 ObjectHashget(pw->objectset, (int) parameter, (int *) &next,
1195 (int *) &enterflags, &UNUSED, &UNUSED2);
1196 ObjectHashremove(pw->objectset, (int)parameter);
1197 if (enterflags!=NULL)
1198 RUNFREE(enterflags);
1199 // release grabbed locks
1200 for(j = 0; j < runtime_locklen; ++j) {
1201 int * lock = (int *)(runtime_locks[j].value/*redirectlock*/);
1202 releasewritelock(lock);
1204 RUNFREE(currtpd->parameterArray);
1207 #ifdef ACCURATEPROFILE
1208 // fail, set the end of the checkTaskInfo
1216 /* Check that object still has necessary tags */
1217 for(j=0; j<pd->numbertags; j++) {
1218 int slotid=pd->tagarray[2*j]+numparams;
1219 struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
1220 if (!containstag(parameter, tagd)) {
1221 BAMBOO_DEBUGPRINT(0xe996);
1223 // release grabbed locks
1225 for(tmpj = 0; tmpj < runtime_locklen; ++tmpj) {
1226 int * lock = (int *)(runtime_locks[tmpj].value/*redirectlock*/);
1227 releasewritelock(lock);
1230 RUNFREE(currtpd->parameterArray);
1237 taskpointerarray[i+OFFSET]=parameter;
1238 } // for(i=0; i<numparams; i++)
1240 for(; i<numtotal; i++) {
1241 taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
1246 /* Actually call task */
1248 ((int *)taskpointerarray)[0]=currtpd->numParameters;
1249 taskpointerarray[1]=NULL;
1251 #ifdef ACCURATEPROFILE
1252 // check finish, set the end of the checkTaskInfo
1255 PROFILE_TASK_START(currtpd->task->name);
1257 BAMBOO_DEBUGPRINT(0xe997);
1258 ((void (*)(void **))currtpd->task->taskptr)(taskpointerarray);
1260 #ifdef ACCURATEPROFILE
1261 // task finish, set the end of the checkTaskInfo
1263 // new a PostTaskInfo for the post-task execution
1264 PROFILE_TASK_START("post task execution");
1266 BAMBOO_DEBUGPRINT(0xe998);
1267 BAMBOO_DEBUGPRINT_REG(islock);
1270 BAMBOO_DEBUGPRINT(0xe999);
1271 for(i = runtime_locklen; i>0; i--) {
1272 void * ptr = (void *)(runtime_locks[i-1].redirectlock);
1273 int * lock = (int *)(runtime_locks[i-1].value);
1274 BAMBOO_DEBUGPRINT_REG((int)ptr);
1275 BAMBOO_DEBUGPRINT_REG((int)lock);
1276 BAMBOO_DEBUGPRINT_REG(*((int*)lock+5));
1277 #ifndef MULTICORE_GC
1279 if(RuntimeHashcontainskey(lockRedirectTbl, (int)lock)) {
1281 RuntimeHashget(lockRedirectTbl, (int)lock, &redirectlock);
1282 RuntimeHashremovekey(lockRedirectTbl, (int)lock);
1283 releasewritelock_r(lock, (int *)redirectlock);
1291 releasewritelock(lock); // ptr
1296 // post task execution finish, set the end of the postTaskInfo
1299 // Free up task parameter descriptor
1300 RUNFREE(currtpd->parameterArray);
1303 BAMBOO_DEBUGPRINT(0xe99a);
1305 } // while(hashsize(activetasks)>0)
1306 BAMBOO_DEBUGPRINT(0xe99b);
1309 /* This function processes an objects tags */
1310 void processtags(struct parameterdescriptor *pd,
1312 struct parameterwrapper *parameter,
1313 int * iteratorcount,
1318 for(i=0; i<pd->numbertags; i++) {
1319 int slotid=pd->tagarray[2*i];
1320 int tagid=pd->tagarray[2*i+1];
1322 if (statusarray[slotid+numparams]==0) {
1323 parameter->iterators[*iteratorcount].istag=1;
1324 parameter->iterators[*iteratorcount].tagid=tagid;
1325 parameter->iterators[*iteratorcount].slot=slotid+numparams;
1326 parameter->iterators[*iteratorcount].tagobjectslot=index;
1327 statusarray[slotid+numparams]=1;
1333 void processobject(struct parameterwrapper *parameter,
1335 struct parameterdescriptor *pd,
1341 struct ObjectHash * objectset=
1342 ((struct parameterwrapper *)pd->queue)->objectset;
1344 parameter->iterators[*iteratorcount].istag=0;
1345 parameter->iterators[*iteratorcount].slot=index;
1346 parameter->iterators[*iteratorcount].objectset=objectset;
1347 statusarray[index]=1;
1349 for(i=0; i<pd->numbertags; i++) {
1350 int slotid=pd->tagarray[2*i];
1351 if (statusarray[slotid+numparams]!=0) {
1352 /* This tag has already been enqueued, use it to narrow search */
1353 parameter->iterators[*iteratorcount].tagbindings[tagcount]=
1358 parameter->iterators[*iteratorcount].numtags=tagcount;
1363 /* This function builds the iterators for a task & parameter */
1365 void builditerators(struct taskdescriptor * task,
1367 struct parameterwrapper * parameter) {
1368 int statusarray[MAXTASKPARAMS];
1370 int numparams=task->numParameters;
1371 int iteratorcount=0;
1372 for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
1374 statusarray[index]=1; /* Initial parameter */
1375 /* Process tags for initial iterator */
1377 processtags(task->descriptorarray[index], index, parameter,
1378 &iteratorcount, statusarray, numparams);
1382 /* Check for objects with existing tags */
1383 for(i=0; i<numparams; i++) {
1384 if (statusarray[i]==0) {
1385 struct parameterdescriptor *pd=task->descriptorarray[i];
1387 for(j=0; j<pd->numbertags; j++) {
1388 int slotid=pd->tagarray[2*j];
1389 if(statusarray[slotid+numparams]!=0) {
1390 processobject(parameter,i,pd,&iteratorcount,
1391 statusarray,numparams);
1392 processtags(pd,i,parameter,&iteratorcount,statusarray,numparams);
1399 /* Next do objects w/ unbound tags*/
1401 for(i=0; i<numparams; i++) {
1402 if (statusarray[i]==0) {
1403 struct parameterdescriptor *pd=task->descriptorarray[i];
1404 if (pd->numbertags>0) {
1405 processobject(parameter,i,pd,&iteratorcount,statusarray,numparams);
1406 processtags(pd,i,parameter,&iteratorcount,statusarray,numparams);
1412 /* Nothing with a tag enqueued */
1414 for(i=0; i<numparams; i++) {
1415 if (statusarray[i]==0) {
1416 struct parameterdescriptor *pd=task->descriptorarray[i];
1417 processobject(parameter,i,pd,&iteratorcount,statusarray,numparams);
1418 processtags(pd,i,parameter,&iteratorcount,statusarray,numparams);
1431 if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
1434 for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
1435 struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
1437 printf("%s\n", task->name);
1439 for(j=0; j<task->numParameters; j++) {
1440 struct parameterdescriptor *param=task->descriptorarray[j];
1441 struct parameterwrapper *parameter=param->queue;
1442 struct ObjectHash * set=parameter->objectset;
1443 struct ObjectIterator objit;
1445 printf(" Parameter %d\n", j);
1447 ObjectHashiterator(set, &objit);
1448 while(ObjhasNext(&objit)) {
1449 struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
1450 struct ___Object___ * tagptr=obj->___tags___;
1451 int nonfailed=Objdata4(&objit);
1452 int numflags=Objdata3(&objit);
1453 int flags=Objdata2(&objit);
1456 printf(" Contains %lx\n", obj);
1457 printf(" flag=%d\n", obj->flag);
1460 } else if (tagptr->type==TAGTYPE) {
1462 printf(" tag=%lx\n",tagptr);
1468 struct ArrayObject *ao=(struct ArrayObject *)tagptr;
1469 for(; tagindex<ao->___cachedCode___; tagindex++) {
1471 printf(" tag=%lx\n",ARRAYGET(ao,struct ___TagDescriptor___*,
1483 /* This function processes the task information to create queues for
1484 each parameter type. */
1485 void processtasks() {
1487 if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
1490 for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
1491 struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
1494 /* Build objectsets */
1495 for(j=0; j<task->numParameters; j++) {
1496 struct parameterdescriptor *param=task->descriptorarray[j];
1497 struct parameterwrapper *parameter=param->queue;
1498 parameter->objectset=allocateObjectHash(10);
1499 parameter->task=task;
1502 /* Build iterators for parameters */
1503 for(j=0; j<task->numParameters; j++) {
1504 struct parameterdescriptor *param=task->descriptorarray[j];
1505 struct parameterwrapper *parameter=param->queue;
1506 builditerators(task, j, parameter);
1511 void toiReset(struct tagobjectiterator * it) {
1514 } else if (it->numtags>0) {
1517 ObjectHashiterator(it->objectset, &it->it);
1521 int toiHasNext(struct tagobjectiterator *it,
1522 void ** objectarray OPTARG(int * failed)) {
1525 /* Get object with tags */
1526 struct ___Object___ *obj=objectarray[it->tagobjectslot];
1527 struct ___Object___ *tagptr=obj->___tags___;
1528 if (tagptr->type==TAGTYPE) {
1529 if ((it->tagobjindex==0)&& /* First object */
1530 (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
1535 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
1536 int tagindex=it->tagobjindex;
1537 for(; tagindex<ao->___cachedCode___; tagindex++) {
1538 struct ___TagDescriptor___ *td=
1539 ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
1540 if (td->flag==it->tagid) {
1541 it->tagobjindex=tagindex; /* Found right type of tag */
1547 } else if (it->numtags>0) {
1548 /* Use tags to locate appropriate objects */
1549 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
1550 struct ___Object___ *objptr=tag->flagptr;
1552 if (objptr->type!=OBJECTARRAYTYPE) {
1553 if (it->tagobjindex>0)
1555 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
1557 for(i=1; i<it->numtags; i++) {
1558 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
1559 if (!containstag(objptr,tag2))
1564 struct ArrayObject *ao=(struct ArrayObject *) objptr;
1567 for(tagindex=it->tagobjindex;tagindex<ao->___cachedCode___;tagindex++){
1568 struct ___Object___ *objptr=
1569 ARRAYGET(ao,struct ___Object___*,tagindex);
1570 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
1572 for(i=1; i<it->numtags; i++) {
1573 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
1574 if (!containstag(objptr,tag2))
1577 it->tagobjindex=tagindex;
1582 it->tagobjindex=tagindex;
1586 return ObjhasNext(&it->it);
1590 int containstag(struct ___Object___ *ptr,
1591 struct ___TagDescriptor___ *tag) {
1593 struct ___Object___ * objptr=tag->flagptr;
1594 if (objptr->type==OBJECTARRAYTYPE) {
1595 struct ArrayObject *ao=(struct ArrayObject *)objptr;
1596 for(j=0; j<ao->___cachedCode___; j++) {
1597 if (ptr==ARRAYGET(ao, struct ___Object___*, j)) {
1607 void toiNext(struct tagobjectiterator *it,
1608 void ** objectarray OPTARG(int * failed)) {
1609 /* hasNext has all of the intelligence */
1612 /* Get object with tags */
1613 struct ___Object___ *obj=objectarray[it->tagobjectslot];
1614 struct ___Object___ *tagptr=obj->___tags___;
1615 if (tagptr->type==TAGTYPE) {
1617 objectarray[it->slot]=tagptr;
1619 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
1620 objectarray[it->slot]=
1621 ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
1623 } else if (it->numtags>0) {
1624 /* Use tags to locate appropriate objects */
1625 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
1626 struct ___Object___ *objptr=tag->flagptr;
1627 if (objptr->type!=OBJECTARRAYTYPE) {
1629 objectarray[it->slot]=objptr;
1631 struct ArrayObject *ao=(struct ArrayObject *) objptr;
1632 objectarray[it->slot]=
1633 ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
1636 /* Iterate object */
1637 objectarray[it->slot]=(void *)Objkey(&it->it);