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, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
381 void tagclear(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
383 /* We'll assume that tag is alway there.
384 Need to statically check for this of course. */
385 struct ___Object___ * tagptr=obj->___tags___;
387 if (tagptr->type==TAGTYPE) {
388 if ((struct ___TagDescriptor___ *)tagptr==tagd)
389 obj->___tags___=NULL;
391 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
393 for(i=0; i<ao->___cachedCode___; i++) {
394 struct ___TagDescriptor___ * td=
395 ARRAYGET(ao, struct ___TagDescriptor___ *, i);
397 ao->___cachedCode___--;
398 if (i<ao->___cachedCode___)
399 ARRAYSET(ao, struct ___TagDescriptor___ *, i,
400 ARRAYGET(ao,struct ___TagDescriptor___*,ao->___cachedCode___));
401 ARRAYSET(ao,struct ___TagDescriptor___ *,ao->___cachedCode___, NULL);
402 if (ao->___cachedCode___==0)
403 obj->___tags___=NULL;
410 struct ___Object___ *tagset=tagd->flagptr;
411 if (tagset->type!=OBJECTARRAYTYPE) {
415 struct ArrayObject *ao=(struct ArrayObject *) tagset;
417 for(i=0; i<ao->___cachedCode___; i++) {
418 struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
420 ao->___cachedCode___--;
421 if (i<ao->___cachedCode___)
422 ARRAYSET(ao, struct ___Object___ *, i,
423 ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
424 ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
425 if (ao->___cachedCode___==0)
436 /* This function allocates a new tag. */
438 struct ___TagDescriptor___ * allocate_tag(void *ptr, int index) {
439 struct ___TagDescriptor___ * v=
440 (struct ___TagDescriptor___ *) FREEMALLOC((struct garbagelist *) ptr,
443 struct ___TagDescriptor___ * allocate_tag(int index) {
444 struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
451 /* This function updates the flag for object ptr. It or's the flag
452 with the or mask and and's it with the andmask. */
454 void flagbody(struct ___Object___ *ptr, int flag, struct parameterwrapper ** queues, int length, bool isnew);
456 int flagcomp(const int *val1, const int *val2) {
457 return (*val1)-(*val2);
460 void flagorand(void * ptr, int ormask, int andmask, struct parameterwrapper ** queues, int length) {
461 int oldflag=((int *)ptr)[2]; // the flag field is now the third one
462 int flag=ormask|oldflag;
464 flagbody(ptr, flag, queues, length, false);
467 bool intflagorand(void * ptr, int ormask, int andmask) {
468 int oldflag=((int *)ptr)[2]; // the flag field is the third one
469 int flag=ormask|oldflag;
471 if (flag==oldflag) /* Don't do anything */
474 flagbody(ptr, flag, NULL, 0, false);
479 void flagorandinit(void * ptr, int ormask, int andmask) {
480 int oldflag=((int *)ptr)[2]; // the flag field is the third one
481 int flag=ormask|oldflag;
483 flagbody(ptr,flag,NULL,0,true);
486 void flagbody(struct ___Object___ *ptr,
488 struct parameterwrapper ** vqueues,
491 struct parameterwrapper * flagptr = NULL;
493 struct parameterwrapper ** queues = vqueues;
494 int length = vlength;
497 int * enterflags = NULL;
498 if((!isnew) && (queues == NULL)) {
499 if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
500 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
501 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
508 /*Remove object from all queues */
509 for(i = 0; i < length; i++) {
511 ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next,
512 (int *) &enterflags, &UNUSED, &UNUSED2);
513 ObjectHashremove(flagptr->objectset, (int)ptr);
514 if (enterflags!=NULL)
519 void enqueueObject(void * vptr,
520 struct parameterwrapper ** vqueues,
522 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
525 struct parameterwrapper * parameter=NULL;
528 struct parameterwrapper * prevptr=NULL;
529 struct ___Object___ *tagptr=NULL;
530 struct parameterwrapper ** queues = vqueues;
531 int length = vlength;
532 if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
536 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
537 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
539 tagptr=ptr->___tags___;
541 /* Outer loop iterates through all parameter queues an object of
542 this type could be in. */
543 for(j = 0; j < length; j++) {
544 parameter = queues[j];
546 if (parameter->numbertags>0) {
548 goto nextloop; //that means the object has no tag
549 //but that param needs tag
550 else if(tagptr->type==TAGTYPE) { //one tag
551 for(i=0; i<parameter->numbertags; i++) {
552 //slotid is parameter->tagarray[2*i];
553 int tagid=parameter->tagarray[2*i+1];
554 if (tagid!=tagptr->flag)
555 goto nextloop; /*We don't have this tag */
557 } else { //multiple tags
558 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
559 for(i=0; i<parameter->numbertags; i++) {
560 //slotid is parameter->tagarray[2*i];
561 int tagid=parameter->tagarray[2*i+1];
563 for(j=0; j<ao->___cachedCode___; j++) {
564 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
575 for(i=0; i<parameter->numberofterms; i++) {
576 int andmask=parameter->intarray[i*2];
577 int checkmask=parameter->intarray[i*2+1];
578 if ((ptr->flag&andmask)==checkmask) {
579 enqueuetasks(parameter, prevptr, ptr, NULL, 0);
590 void enqueueObject_I(void * vptr,
591 struct parameterwrapper ** vqueues,
593 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
596 struct parameterwrapper * parameter=NULL;
599 struct parameterwrapper * prevptr=NULL;
600 struct ___Object___ *tagptr=NULL;
601 struct parameterwrapper ** queues = vqueues;
602 int length = vlength;
603 if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
607 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
608 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
610 tagptr=ptr->___tags___;
612 /* Outer loop iterates through all parameter queues an object of
613 this type could be in. */
614 for(j = 0; j < length; j++) {
615 parameter = queues[j];
617 if (parameter->numbertags>0) {
619 goto nextloop; //that means the object has no tag
620 //but that param needs tag
621 else if(tagptr->type==TAGTYPE) { //one tag
622 for(i=0; i<parameter->numbertags; i++) {
623 //slotid is parameter->tagarray[2*i];
624 int tagid=parameter->tagarray[2*i+1];
625 if (tagid!=tagptr->flag)
626 goto nextloop; /*We don't have this tag */
628 } else { //multiple tags
629 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
630 for(i=0; i<parameter->numbertags; i++) {
631 //slotid is parameter->tagarray[2*i];
632 int tagid=parameter->tagarray[2*i+1];
634 for(j=0; j<ao->___cachedCode___; j++) {
635 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
646 for(i=0; i<parameter->numberofterms; i++) {
647 int andmask=parameter->intarray[i*2];
648 int checkmask=parameter->intarray[i*2+1];
649 if ((ptr->flag&andmask)==checkmask) {
650 enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
662 int * getAliasLock(void ** ptrs, int length, struct RuntimeHash * tbl) {
667 // sort all the locks required by the objs in the aliased set
668 for(; i < length; i++) {
669 struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
672 if(ptr->lock == NULL) {
675 lock = (int)(ptr->lock);
678 for(j = 0; j < locklen; j++) {
679 if(locks[j] == lock) {
682 } else if(locks[j] > lock) {
689 locks[h] = locks[h-1];
695 // use the smallest lock as the shared lock for the whole set
696 return (int *)(locks[0]);
698 // TODO possible bug here!!!
700 return (int*)(RUNMALLOC(sizeof(int)));
705 bool redirect = false;
706 int redirectlock = 0;
707 for(; i < length; i++) {
708 struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
711 if(ptr->lock == NULL) {
714 lock = (int)(ptr->lock);
717 if(lock != redirectlock) {
718 RuntimeHashadd(tbl, lock, redirectlock);
721 if(RuntimeHashcontainskey(tbl, lock)) {
722 // already redirected
724 RuntimeHashget(tbl, lock, &redirectlock);
725 for(; j < locklen; j++) {
726 if(locks[j] != redirectlock) {
727 RuntimeHashadd(tbl, locks[j], redirectlock);
732 for(j = 0; j < locklen; j++) {
733 if(locks[j] == lock) {
736 } else if(locks[j] > lock) {
743 locks[h] = locks[h-1];
752 return (int *)redirectlock;
754 // use the first lock as the shared lock
755 for(j = 1; j < locklen; j++) {
756 if(locks[j] != locks[0]) {
757 RuntimeHashadd(tbl, locks[j], locks[0]);
760 return (int *)(locks[0]);
766 void addAliasLock(void * ptr, int lock) {
767 struct ___Object___ * obj = (struct ___Object___ *)ptr;
768 if(((int)ptr != lock) && (obj->lock != (int*)lock)) {
769 // originally no alias lock associated or have a different alias lock
770 // flush it as the new one
772 while(obj->lock != NULL) {
773 // previously have alias lock, trace the 'root' obj and redirect it
774 obj = (struct ___Object___ *)(obj->lock);
777 obj->lock = (int *)lock;
781 int enqueuetasks(struct parameterwrapper *parameter,
782 struct parameterwrapper *prevptr,
783 struct ___Object___ *ptr,
786 void * taskpointerarray[MAXTASKPARAMS];
788 int numiterators=parameter->task->numTotal-1;
791 struct taskdescriptor * task=parameter->task;
793 //this add the object to parameterwrapper
794 ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags,
795 numenterflags, enterflags==NULL);
797 /* Add enqueued object to parameter vector */
798 taskpointerarray[parameter->slot]=ptr;
800 /* Reset iterators */
801 for(j=0; j<numiterators; j++) {
802 toiReset(¶meter->iterators[j]);
805 /* Find initial state */
806 for(j=0; j<numiterators; j++) {
808 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
809 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
811 /* Need to backtrack */
812 toiReset(¶meter->iterators[j]);
816 /* Nothing to enqueue */
822 /* Enqueue current state */
824 struct taskparamdescriptor *tpd=
825 RUNMALLOC(sizeof(struct taskparamdescriptor));
827 tpd->numParameters=numiterators+1;
828 tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
830 for(j=0; j<=numiterators; j++) {
831 //store the actual parameters
832 tpd->parameterArray[j]=taskpointerarray[j];
835 if (!gencontains(activetasks,tpd)) {
836 genputtable(activetasks, tpd, tpd);
838 RUNFREE(tpd->parameterArray);
842 /* This loop iterates to the next parameter combination */
846 for(j=numiterators-1; j<numiterators; j++) {
848 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
849 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
851 /* Need to backtrack */
852 toiReset(¶meter->iterators[j]);
856 /* Nothing more to enqueue */
864 int enqueuetasks_I(struct parameterwrapper *parameter,
865 struct parameterwrapper *prevptr,
866 struct ___Object___ *ptr,
869 void * taskpointerarray[MAXTASKPARAMS];
871 int numiterators=parameter->task->numTotal-1;
874 struct taskdescriptor * task=parameter->task;
876 //this add the object to parameterwrapper
877 ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags,
878 numenterflags, enterflags==NULL);
880 /* Add enqueued object to parameter vector */
881 taskpointerarray[parameter->slot]=ptr;
883 /* Reset iterators */
884 for(j=0; j<numiterators; j++) {
885 toiReset(¶meter->iterators[j]);
888 /* Find initial state */
889 for(j=0; j<numiterators; j++) {
891 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
892 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
894 /* Need to backtrack */
895 toiReset(¶meter->iterators[j]);
899 /* Nothing to enqueue */
905 /* Enqueue current state */
907 struct taskparamdescriptor *tpd=
908 RUNMALLOC_I(sizeof(struct taskparamdescriptor));
910 tpd->numParameters=numiterators+1;
911 tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
913 for(j=0; j<=numiterators; j++) {
914 //store the actual parameters
915 tpd->parameterArray[j]=taskpointerarray[j];
918 if (!gencontains(activetasks,tpd)) {
919 genputtable_I(activetasks, tpd, tpd);
921 RUNFREE_I(tpd->parameterArray);
925 /* This loop iterates to the next parameter combination */
929 for(j=numiterators-1; j<numiterators; j++) {
931 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
932 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
934 /* Need to backtrack */
935 toiReset(¶meter->iterators[j]);
939 /* Nothing more to enqueue */
953 int containstag(struct ___Object___ *ptr,
954 struct ___TagDescriptor___ *tag);
957 void releasewritelock_r(void * lock, void * redirectlock) {
959 int reallock = (int)lock;
960 targetcore = (reallock >> 5) % NUMCORES;
962 BAMBOO_DEBUGPRINT(0xe671);
963 BAMBOO_DEBUGPRINT_REG((int)lock);
964 BAMBOO_DEBUGPRINT_REG(reallock);
965 BAMBOO_DEBUGPRINT_REG(targetcore);
967 if(targetcore == BAMBOO_NUM_OF_CORE) {
968 BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
969 BAMBOO_DEBUGPRINT(0xf001);
970 // reside on this core
971 if(!RuntimeHashcontainskey(locktbl, reallock)) {
972 // no locks for this object, something is wrong
976 struct LockValue * lockvalue = NULL;
977 BAMBOO_DEBUGPRINT(0xe672);
978 RuntimeHashget(locktbl, reallock, &rwlock_obj);
979 lockvalue = (struct LockValue *)rwlock_obj;
980 BAMBOO_DEBUGPRINT_REG(lockvalue->value);
982 lockvalue->redirectlock = (int)redirectlock;
983 BAMBOO_DEBUGPRINT_REG(lockvalue->value);
985 BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
986 BAMBOO_DEBUGPRINT(0xf000);
989 // send lock release with redirect info msg
990 // for 32 bit machine, the size is always 4 words
991 send_msg_4(targetcore, REDIRECTRELEASE, 1, (int)lock,
992 (int)redirectlock, false);
997 void executetasks() {
998 void * taskpointerarray[MAXTASKPARAMS+OFFSET];
1001 struct ___Object___ * tmpparam = NULL;
1002 struct parameterdescriptor * pd=NULL;
1003 struct parameterwrapper *pw=NULL;
1013 while(hashsize(activetasks)>0) {
1015 BAMBOO_DEBUGPRINT(0xe990);
1017 /* See if there are any active tasks */
1019 #ifdef ACCURATEPROFILE
1020 PROFILE_TASK_START("tpd checking");
1024 currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
1025 genfreekey(activetasks, currtpd);
1027 numparams=currtpd->task->numParameters;
1028 numtotal=currtpd->task->numTotal;
1030 // (TODO, this table should be empty after all locks are released)
1032 // get all required locks
1033 runtime_locklen = 0;
1034 // check which locks are needed
1035 for(i = 0; i < numparams; i++) {
1036 void * param = currtpd->parameterArray[i];
1040 if(((struct ___Object___ *)param)->type == STARTUPTYPE) {
1042 taskpointerarray[i+OFFSET]=param;
1045 struct ___Object___ * obj = (struct ___Object___ *)param;
1046 while(obj->lock != NULL) {
1047 obj = (struct ___Object___ *)(obj->lock);
1049 tmplock = (int)(obj);
1050 // insert into the locks array
1051 for(j = 0; j < runtime_locklen; j++) {
1052 if(runtime_locks[j].value == tmplock) {
1055 } else if(runtime_locks[j].value > tmplock) {
1060 int h = runtime_locklen;
1062 runtime_locks[h].redirectlock = runtime_locks[h-1].redirectlock;
1063 runtime_locks[h].value = runtime_locks[h-1].value;
1065 runtime_locks[j].value = tmplock;
1066 runtime_locks[j].redirectlock = (int)param;
1069 } // for(i = 0; i < numparams; i++)
1070 // grab these required locks
1071 BAMBOO_DEBUGPRINT(0xe991);
1073 for(i = 0; i < runtime_locklen; i++) {
1074 int * lock = (int *)(runtime_locks[i].value);
1076 // require locks for this parameter if it is not a startup object
1077 BAMBOO_DEBUGPRINT_REG((int)lock);
1078 BAMBOO_DEBUGPRINT_REG((int)(runtime_locks[i].value));
1080 BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1081 BAMBOO_DEBUGPRINT(0xf001);
1083 BAMBOO_WAITING_FOR_LOCK(0);
1087 while(BAMBOO_WAITING_FOR_LOCK(0) != -1) {
1091 grount = lockresult;
1100 BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1101 BAMBOO_DEBUGPRINT(0xf000);
1104 BAMBOO_DEBUGPRINT(0xe992);
1105 BAMBOO_DEBUGPRINT_REG(lock);
1106 // check if has the lock already
1107 // can not get the lock, try later
1108 // release all grabbed locks for previous parameters
1109 for(j = 0; j < i; j++) {
1110 lock = (int*)(runtime_locks[j].value/*redirectlock*/);
1111 releasewritelock(lock);
1113 genputtable(activetasks, currtpd, currtpd);
1114 if(hashsize(activetasks) == 1) {
1115 // only one task right now, wait a little while before next try
1120 #ifdef ACCURATEPROFILE
1121 // fail, set the end of the checkTaskInfo
1126 } // line 2752: for(i = 0; i < runtime_locklen; i++)
1128 BAMBOO_DEBUGPRINT(0xe993);
1129 /* Make sure that the parameters are still in the queues */
1130 for(i=0; i<numparams; i++) {
1131 void * parameter=currtpd->parameterArray[i];
1134 BAMBOO_CACHE_FLUSH_RANGE((int)parameter,
1135 classsize[((struct ___Object___ *)parameter)->type]);
1136 tmpparam = (struct ___Object___ *)parameter;
1137 pd=currtpd->task->descriptorarray[i];
1138 pw=(struct parameterwrapper *) pd->queue;
1139 /* Check that object is still in queue */
1141 if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
1142 BAMBOO_DEBUGPRINT(0xe994);
1143 BAMBOO_DEBUGPRINT_REG(parameter);
1144 // release grabbed locks
1145 for(j = 0; j < runtime_locklen; j++) {
1146 int * lock = (int *)(runtime_locks[j].value);
1147 releasewritelock(lock);
1149 RUNFREE(currtpd->parameterArray);
1155 /* Check if the object's flags still meets requirements */
1159 for(tmpi = 0; tmpi < pw->numberofterms; tmpi++) {
1160 andmask=pw->intarray[tmpi*2];
1161 checkmask=pw->intarray[tmpi*2+1];
1162 if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
1168 // flags are never suitable
1169 // remove this obj from the queue
1171 int UNUSED, UNUSED2;
1173 BAMBOO_DEBUGPRINT(0xe995);
1174 BAMBOO_DEBUGPRINT_REG(parameter);
1175 ObjectHashget(pw->objectset, (int) parameter, (int *) &next,
1176 (int *) &enterflags, &UNUSED, &UNUSED2);
1177 ObjectHashremove(pw->objectset, (int)parameter);
1178 if (enterflags!=NULL)
1179 RUNFREE(enterflags);
1180 // release grabbed locks
1181 for(j = 0; j < runtime_locklen; j++) {
1182 int * lock = (int *)(runtime_locks[j].value/*redirectlock*/);
1183 releasewritelock(lock);
1185 RUNFREE(currtpd->parameterArray);
1188 #ifdef ACCURATEPROFILE
1189 // fail, set the end of the checkTaskInfo
1197 /* Check that object still has necessary tags */
1198 for(j=0; j<pd->numbertags; j++) {
1199 int slotid=pd->tagarray[2*j]+numparams;
1200 struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
1201 if (!containstag(parameter, tagd)) {
1202 BAMBOO_DEBUGPRINT(0xe996);
1203 // release grabbed locks
1205 for(tmpj = 0; tmpj < runtime_locklen; tmpj++) {
1206 int * lock = (int *)(runtime_locks[tmpj].value/*redirectlock*/);
1207 releasewritelock(lock);
1209 RUNFREE(currtpd->parameterArray);
1216 taskpointerarray[i+OFFSET]=parameter;
1217 } // for(i=0; i<numparams; i++)
1219 for(; i<numtotal; i++) {
1220 taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
1225 /* Actually call task */
1227 ((int *)taskpointerarray)[0]=currtpd->numParameters;
1228 taskpointerarray[1]=NULL;
1230 #ifdef ACCURATEPROFILE
1231 // check finish, set the end of the checkTaskInfo
1234 PROFILE_TASK_START(currtpd->task->name);
1236 BAMBOO_DEBUGPRINT(0xe997);
1237 ((void (*)(void **))currtpd->task->taskptr)(taskpointerarray);
1239 #ifdef ACCURATEPROFILE
1240 // task finish, set the end of the checkTaskInfo
1242 // new a PostTaskInfo for the post-task execution
1243 PROFILE_TASK_START("post task execution");
1245 BAMBOO_DEBUGPRINT(0xe998);
1246 BAMBOO_DEBUGPRINT_REG(islock);
1249 BAMBOO_DEBUGPRINT(0xe999);
1250 for(i = runtime_locklen; i>0; i--) {
1251 void * ptr = (void *)(runtime_locks[i-1].redirectlock);
1252 int * lock = (int *)(runtime_locks[i-1].value);
1253 BAMBOO_DEBUGPRINT_REG((int)ptr);
1254 BAMBOO_DEBUGPRINT_REG((int)lock);
1255 BAMBOO_DEBUGPRINT_REG(*((int*)lock+5));
1256 #ifndef MULTICORE_GC
1258 if(RuntimeHashcontainskey(lockRedirectTbl, (int)lock)) {
1260 RuntimeHashget(lockRedirectTbl, (int)lock, &redirectlock);
1261 RuntimeHashremovekey(lockRedirectTbl, (int)lock);
1262 releasewritelock_r(lock, (int *)redirectlock);
1270 releasewritelock(lock); // ptr
1275 // post task execution finish, set the end of the postTaskInfo
1278 // Free up task parameter descriptor
1279 RUNFREE(currtpd->parameterArray);
1282 BAMBOO_DEBUGPRINT(0xe99a);
1284 } // while(hashsize(activetasks)>0)
1285 BAMBOO_DEBUGPRINT(0xe99b);
1288 /* This function processes an objects tags */
1289 void processtags(struct parameterdescriptor *pd,
1291 struct parameterwrapper *parameter,
1292 int * iteratorcount,
1297 for(i=0; i<pd->numbertags; i++) {
1298 int slotid=pd->tagarray[2*i];
1299 int tagid=pd->tagarray[2*i+1];
1301 if (statusarray[slotid+numparams]==0) {
1302 parameter->iterators[*iteratorcount].istag=1;
1303 parameter->iterators[*iteratorcount].tagid=tagid;
1304 parameter->iterators[*iteratorcount].slot=slotid+numparams;
1305 parameter->iterators[*iteratorcount].tagobjectslot=index;
1306 statusarray[slotid+numparams]=1;
1312 void processobject(struct parameterwrapper *parameter,
1314 struct parameterdescriptor *pd,
1320 struct ObjectHash * objectset=
1321 ((struct parameterwrapper *)pd->queue)->objectset;
1323 parameter->iterators[*iteratorcount].istag=0;
1324 parameter->iterators[*iteratorcount].slot=index;
1325 parameter->iterators[*iteratorcount].objectset=objectset;
1326 statusarray[index]=1;
1328 for(i=0; i<pd->numbertags; i++) {
1329 int slotid=pd->tagarray[2*i];
1330 if (statusarray[slotid+numparams]!=0) {
1331 /* This tag has already been enqueued, use it to narrow search */
1332 parameter->iterators[*iteratorcount].tagbindings[tagcount]=
1337 parameter->iterators[*iteratorcount].numtags=tagcount;
1342 /* This function builds the iterators for a task & parameter */
1344 void builditerators(struct taskdescriptor * task,
1346 struct parameterwrapper * parameter) {
1347 int statusarray[MAXTASKPARAMS];
1349 int numparams=task->numParameters;
1350 int iteratorcount=0;
1351 for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
1353 statusarray[index]=1; /* Initial parameter */
1354 /* Process tags for initial iterator */
1356 processtags(task->descriptorarray[index], index, parameter,
1357 &iteratorcount, statusarray, numparams);
1361 /* Check for objects with existing tags */
1362 for(i=0; i<numparams; i++) {
1363 if (statusarray[i]==0) {
1364 struct parameterdescriptor *pd=task->descriptorarray[i];
1366 for(j=0; j<pd->numbertags; j++) {
1367 int slotid=pd->tagarray[2*j];
1368 if(statusarray[slotid+numparams]!=0) {
1369 processobject(parameter,i,pd,&iteratorcount,
1370 statusarray,numparams);
1371 processtags(pd,i,parameter,&iteratorcount,statusarray,numparams);
1378 /* Next do objects w/ unbound tags*/
1380 for(i=0; i<numparams; i++) {
1381 if (statusarray[i]==0) {
1382 struct parameterdescriptor *pd=task->descriptorarray[i];
1383 if (pd->numbertags>0) {
1384 processobject(parameter,i,pd,&iteratorcount,statusarray,numparams);
1385 processtags(pd,i,parameter,&iteratorcount,statusarray,numparams);
1391 /* Nothing with a tag enqueued */
1393 for(i=0; i<numparams; i++) {
1394 if (statusarray[i]==0) {
1395 struct parameterdescriptor *pd=task->descriptorarray[i];
1396 processobject(parameter,i,pd,&iteratorcount,statusarray,numparams);
1397 processtags(pd,i,parameter,&iteratorcount,statusarray,numparams);
1410 if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
1413 for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
1414 struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
1416 printf("%s\n", task->name);
1418 for(j=0; j<task->numParameters; j++) {
1419 struct parameterdescriptor *param=task->descriptorarray[j];
1420 struct parameterwrapper *parameter=param->queue;
1421 struct ObjectHash * set=parameter->objectset;
1422 struct ObjectIterator objit;
1424 printf(" Parameter %d\n", j);
1426 ObjectHashiterator(set, &objit);
1427 while(ObjhasNext(&objit)) {
1428 struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
1429 struct ___Object___ * tagptr=obj->___tags___;
1430 int nonfailed=Objdata4(&objit);
1431 int numflags=Objdata3(&objit);
1432 int flags=Objdata2(&objit);
1435 printf(" Contains %lx\n", obj);
1436 printf(" flag=%d\n", obj->flag);
1439 } else if (tagptr->type==TAGTYPE) {
1441 printf(" tag=%lx\n",tagptr);
1445 struct ArrayObject *ao=(struct ArrayObject *)tagptr;
1446 for(; tagindex<ao->___cachedCode___; tagindex++) {
1448 printf(" tag=%lx\n",ARRAYGET(ao,struct ___TagDescriptor___*, tagindex));
1459 /* This function processes the task information to create queues for
1460 each parameter type. */
1461 void processtasks() {
1463 if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
1466 for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
1467 struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
1470 /* Build objectsets */
1471 for(j=0; j<task->numParameters; j++) {
1472 struct parameterdescriptor *param=task->descriptorarray[j];
1473 struct parameterwrapper *parameter=param->queue;
1474 parameter->objectset=allocateObjectHash(10);
1475 parameter->task=task;
1478 /* Build iterators for parameters */
1479 for(j=0; j<task->numParameters; j++) {
1480 struct parameterdescriptor *param=task->descriptorarray[j];
1481 struct parameterwrapper *parameter=param->queue;
1482 builditerators(task, j, parameter);
1487 void toiReset(struct tagobjectiterator * it) {
1490 } else if (it->numtags>0) {
1493 ObjectHashiterator(it->objectset, &it->it);
1497 int toiHasNext(struct tagobjectiterator *it,
1498 void ** objectarray OPTARG(int * failed)) {
1501 /* Get object with tags */
1502 struct ___Object___ *obj=objectarray[it->tagobjectslot];
1503 struct ___Object___ *tagptr=obj->___tags___;
1504 if (tagptr->type==TAGTYPE) {
1505 if ((it->tagobjindex==0)&& /* First object */
1506 (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
1511 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
1512 int tagindex=it->tagobjindex;
1513 for(; tagindex<ao->___cachedCode___; tagindex++) {
1514 struct ___TagDescriptor___ *td=
1515 ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
1516 if (td->flag==it->tagid) {
1517 it->tagobjindex=tagindex; /* Found right type of tag */
1523 } else if (it->numtags>0) {
1524 /* Use tags to locate appropriate objects */
1525 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
1526 struct ___Object___ *objptr=tag->flagptr;
1528 if (objptr->type!=OBJECTARRAYTYPE) {
1529 if (it->tagobjindex>0)
1531 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
1533 for(i=1; i<it->numtags; i++) {
1534 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
1535 if (!containstag(objptr,tag2))
1540 struct ArrayObject *ao=(struct ArrayObject *) objptr;
1543 for(tagindex=it->tagobjindex;tagindex<ao->___cachedCode___;tagindex++){
1544 struct ___Object___ *objptr=
1545 ARRAYGET(ao,struct ___Object___*,tagindex);
1546 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
1548 for(i=1; i<it->numtags; i++) {
1549 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
1550 if (!containstag(objptr,tag2))
1553 it->tagobjindex=tagindex;
1558 it->tagobjindex=tagindex;
1562 return ObjhasNext(&it->it);
1566 int containstag(struct ___Object___ *ptr,
1567 struct ___TagDescriptor___ *tag) {
1569 struct ___Object___ * objptr=tag->flagptr;
1570 if (objptr->type==OBJECTARRAYTYPE) {
1571 struct ArrayObject *ao=(struct ArrayObject *)objptr;
1572 for(j=0; j<ao->___cachedCode___; j++) {
1573 if (ptr==ARRAYGET(ao, struct ___Object___*, j)) {
1583 void toiNext(struct tagobjectiterator *it,
1584 void ** objectarray OPTARG(int * failed)) {
1585 /* hasNext has all of the intelligence */
1588 /* Get object with tags */
1589 struct ___Object___ *obj=objectarray[it->tagobjectslot];
1590 struct ___Object___ *tagptr=obj->___tags___;
1591 if (tagptr->type==TAGTYPE) {
1593 objectarray[it->slot]=tagptr;
1595 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
1596 objectarray[it->slot]=
1597 ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
1599 } else if (it->numtags>0) {
1600 /* Use tags to locate appropriate objects */
1601 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
1602 struct ___Object___ *objptr=tag->flagptr;
1603 if (objptr->type!=OBJECTARRAYTYPE) {
1605 objectarray[it->slot]=objptr;
1607 struct ArrayObject *ao=(struct ArrayObject *) objptr;
1608 objectarray[it->slot]=
1609 ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
1612 /* Iterate object */
1613 objectarray[it->slot]=(void *)Objkey(&it->it);