changes committed
[IRC.git] / Robust / src / Runtime / bamboo / multicoretask.c
1 #ifdef TASK
2 #include "runtime.h"
3 #include "multicoreruntime.h"
4 #include "multicoretaskprofile.h"
5 #include "multicoretask.h"
6
7 #ifndef INLINE
8 #define INLINE    inline __attribute__((always_inline))
9 #endif 
10
11 //  data structures for task invocation
12 struct genhashtable * activetasks;
13 struct taskparamdescriptor * currtpd;
14 struct LockValue runtime_locks[MAXTASKPARAMS];
15 int runtime_locklen;
16
17 // specific functions used inside critical sections
18 void enqueueObject_I(void * ptr,
19                      struct parameterwrapper ** queues,
20                      int length);
21 int enqueuetasks_I(struct parameterwrapper *parameter,
22                    struct parameterwrapper *prevptr,
23                    struct ___Object___ *ptr,
24                    int * enterflags,
25                    int numenterflags);
26
27 INLINE void initlocktable() {
28 #ifdef MULTICORE_GC
29   // do nothing
30 #else
31   // create the lock table, lockresult table and obj queue
32   locktable.size = 20;
33   locktable.bucket =
34     (struct RuntimeNode **) RUNMALLOC_I(sizeof(struct RuntimeNode *)*20);
35   /* Set allocation blocks*/
36   locktable.listhead=NULL;
37   locktable.listtail=NULL;
38   /*Set data counts*/
39   locktable.numelements = 0;
40   lockobj = 0;
41   lock2require = 0;
42   lockresult = 0;
43   lockflag = false;
44   lockRedirectTbl = allocateRuntimeHash_I(20);
45   objRedirectLockTbl = allocateRuntimeHash_I(20);
46 #endif
47 }
48
49 INLINE void dislocktable() {
50 #ifdef MULTICORE_GC
51   // do nothing
52 #else
53   freeRuntimeHash(lockRedirectTbl);
54   freeRuntimeHash(objRedirectLockTbl);
55   RUNFREE(locktable.bucket);
56 #endif
57 }
58
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
63   }
64   totransobjqueue = createQueue_I();
65   objqueue.head = NULL;
66   objqueue.tail = NULL;
67   currtpd = NULL;
68   for(int i = 0; i < MAXTASKPARAMS; i++) {
69     runtime_locks[i].redirectlock = 0;
70     runtime_locks[i].value = 0;
71   }
72   runtime_locklen = 0;
73   initlocktable();
74   INIT_TASKPROFILE_DATA();
75 }
76
77 INLINE void distaskdata() {
78   if(activetasks != NULL) {
79     genfreehashtable(activetasks);
80   }
81   if(currtpd != NULL) {
82     RUNFREE(currtpd->parameterArray);
83     RUNFREE(currtpd);
84     currtpd = NULL;
85   }
86   dislocktable();
87 }
88
89 INLINE bool checkObjQueue() {
90   bool rflag = false;
91   struct transObjInfo * objInfo = NULL;
92   int grount = 0;
93
94 #ifdef ACCURATEPROFILE
95   PROFILE_TASK_START("objqueue checking");
96 #endif
97
98   while(!isEmpty(&objqueue)) {
99     void * obj = NULL;
100     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
101     BAMBOO_DEBUGPRINT(0xf001);
102     BAMBOO_DEBUGPRINT(0xeee1);
103     rflag = true;
104     objInfo = (struct transObjInfo *)getItem(&objqueue);
105     obj = objInfo->objptr;
106     BAMBOO_DEBUGPRINT_REG((int)obj);
107     // grab lock and flush the obj
108     grount = 0;
109     struct ___Object___ * tmpobj = (struct ___Object___ *)obj;
110     while(tmpobj->lock != NULL) {
111       tmpobj = (struct ___Object___ *)(tmpobj->lock);
112     }
113     getwritelock_I(tmpobj);
114     while(!lockflag) {
115       BAMBOO_WAITING_FOR_LOCK(0);
116     } 
117     grount = lockresult;
118     BAMBOO_DEBUGPRINT_REG(grount);
119
120     lockresult = 0;
121     lockobj = 0;
122     lock2require = 0;
123     lockflag = false;
124 #ifndef INTERRUPT
125     reside = false;
126 #endif
127
128     if(grount == 1) {
129       int k = 0;
130       // flush the object
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));
144       } 
145       releasewritelock_I(tmpobj);
146       RUNFREE_I(objInfo->queues);
147       RUNFREE_I(objInfo);
148     } else {
149       // can not get lock
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);
160                   RUNFREE_I(objInfo);
161                   goto objqueuebreak;
162                 } else {
163                   prev = qitem;
164                 } 
165                 qitem = getNextQueueItem(prev);
166           } 
167       // try to execute active tasks already enqueued first
168       addNewItem_I(&objqueue, objInfo);
169 objqueuebreak:
170       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
171       BAMBOO_DEBUGPRINT(0xf000);
172       break;
173     } 
174     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
175     BAMBOO_DEBUGPRINT(0xf000);
176   }
177
178 #ifdef ACCURATEPROFILE
179   PROFILE_TASK_END();
180 #endif
181
182   BAMBOO_DEBUGPRINT(0xee02);
183   return rflag;
184 }
185
186 struct ___createstartupobject____I_locals {
187   INTPTR size;
188   void * next;
189   struct  ___StartupObject___ * ___startupobject___;
190   struct ArrayObject * ___stringarray___;
191 };
192
193 void createstartupobject(int argc,
194                          char ** argv) {
195   int i;
196
197   /* Allocate startup object     */
198 #ifdef MULTICORE_GC
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;
207 #else
208   struct ___StartupObject___ *startupobject=
209     (struct ___StartupObject___*) allocate_new(STARTUPTYPE);
210   struct ArrayObject * stringarray=
211     allocate_newarray(STRINGARRAYTYPE, argc-1);
212 #endif
213   /* Build array of strings */
214   startupobject->___parameters___=stringarray;
215   for(i=1; i<argc; i++) {
216     int length=strlen(argv[i]);
217 #ifdef MULTICORE_GC
218     struct ___String___ *newstring=NewString(&___locals___, argv[i],length);
219 #else
220     struct ___String___ *newstring=NewString(argv[i],length);
221 #endif
222     ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=
223       newstring;
224   }
225
226   startupobject->version = 0;
227   startupobject->lock = NULL;
228
229   /* Set initialized flag for startup object */
230   flagorandinit(startupobject,1,0xFFFFFFFF);
231   enqueueObject(startupobject, NULL, 0);
232   BAMBOO_CACHE_FLUSH_ALL();
233 }
234
235 int hashCodetpd(struct taskparamdescriptor *ftd) {
236   int hash=(int)ftd->task;
237   int i;
238   for(i=0; i<ftd->numParameters; i++) {
239     hash^=(int)ftd->parameterArray[i];
240   }
241   return hash;
242 }
243
244 int comparetpd(struct taskparamdescriptor *ftd1,
245                struct taskparamdescriptor *ftd2) {
246   int i;
247   if (ftd1->task!=ftd2->task)
248     return 0;
249   for(i=0; i<ftd1->numParameters; i++)
250     if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
251       return 0;
252   return 1;
253 }
254
255 /* This function sets a tag. */
256 #ifdef MULTICORE_GC
257 void tagset(void *ptr,
258             struct ___Object___ * obj,
259             struct ___TagDescriptor___ * tagd) {
260 #else
261 void tagset(struct ___Object___ * obj,
262             struct ___TagDescriptor___ * tagd) {
263 #endif
264   struct ArrayObject * ao=NULL;
265   struct ___Object___ * tagptr=obj->___tags___;
266   if (tagptr==NULL) {
267     obj->___tags___=(struct ___Object___ *)tagd;
268   } else {
269     /* Have to check if it is already set */
270     if (tagptr->type==TAGTYPE) {
271       struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
272       if (td==tagd) {
273                 return;
274       }
275 #ifdef MULTICORE_GC
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___;
282 #else
283       ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
284 #endif
285
286       ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
287       ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
288       obj->___tags___=(struct ___Object___ *) ao;
289       ao->___cachedCode___=2;
290     } else {
291       /* Array Case */
292       int i;
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);
297                 if (td==tagd) {
298                   return;
299                 }
300       }
301       if (ao->___cachedCode___<ao->___length___) {
302                 ARRAYSET(ao, struct ___TagDescriptor___ *,ao->___cachedCode___,tagd);
303                 ao->___cachedCode___++;
304       } else {
305 #ifdef MULTICORE_GC
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___;
313 #else
314                 struct ArrayObject * aonew=
315                   allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
316 #endif
317
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));
322                 }
323                 ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___,tagd);
324       }
325     }
326   }
327
328   {
329     struct ___Object___ * tagset=tagd->flagptr;
330     if(tagset==NULL) {
331       tagd->flagptr=obj;
332     } else if (tagset->type!=OBJECTARRAYTYPE) {
333 #ifdef MULTICORE_GC
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];
339 #else
340       struct ArrayObject * ao=
341         allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
342 #endif
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;
347     } else {
348       struct ArrayObject *ao=(struct ArrayObject *) tagset;
349       if (ao->___cachedCode___<ao->___length___) {
350         ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
351       } else {
352         int i;
353 #ifdef MULTICORE_GC
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;
361 #else
362         struct ArrayObject * aonew=allocate_newarray(OBJECTARRAYTYPE,
363                                                      OBJECTARRAYINTERVAL+ao->___length___);
364 #endif
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));
369         }
370         ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
371         tagd->flagptr=(struct ___Object___ *) aonew;
372       }
373     }
374   }
375 }
376  
377 /* This function clears a tag. */
378 #ifdef MULTICORE_GC
379 void tagclear(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
380 #else
381 void tagclear(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
382 #endif
383   /* We'll assume that tag is alway there.
384      Need to statically check for this of course. */
385   struct ___Object___ * tagptr=obj->___tags___;
386   
387   if (tagptr->type==TAGTYPE) {
388     if ((struct ___TagDescriptor___ *)tagptr==tagd)
389       obj->___tags___=NULL;
390   } else {
391     struct ArrayObject *ao=(struct ArrayObject *) tagptr;
392     int i;
393     for(i=0; i<ao->___cachedCode___; i++) {
394       struct ___TagDescriptor___ * td=
395         ARRAYGET(ao, struct ___TagDescriptor___ *, i);
396       if (td==tagd) {
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;
404         goto PROCESSCLEAR;
405       }
406     }
407   }
408  PROCESSCLEAR:
409   {
410     struct ___Object___ *tagset=tagd->flagptr;
411     if (tagset->type!=OBJECTARRAYTYPE) {
412       if (tagset==obj)
413         tagd->flagptr=NULL;
414     } else {
415       struct ArrayObject *ao=(struct ArrayObject *) tagset;
416       int i;
417       for(i=0; i<ao->___cachedCode___; i++) {
418         struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
419         if (tobj==obj) {
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)
426             tagd->flagptr=NULL;
427           goto ENDCLEAR;
428         }
429       }
430     }
431   }
432  ENDCLEAR:
433   return;
434 }
435
436 /* This function allocates a new tag. */
437 #ifdef MULTICORE_GC
438 struct ___TagDescriptor___ * allocate_tag(void *ptr, int index) {
439   struct ___TagDescriptor___ * v=
440     (struct ___TagDescriptor___ *) FREEMALLOC((struct garbagelist *) ptr,
441                                               classsize[TAGTYPE]);
442 #else
443 struct ___TagDescriptor___ * allocate_tag(int index) {
444   struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
445 #endif
446   v->type=TAGTYPE;
447   v->flag=index;
448   return v;
449 }
450
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. */
453
454 void flagbody(struct ___Object___ *ptr, int flag, struct parameterwrapper ** queues, int length, bool isnew);
455
456 int flagcomp(const int *val1, const int *val2) {
457   return (*val1)-(*val2);
458 }
459  
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;
463   flag&=andmask;
464   flagbody(ptr, flag, queues, length, false);
465 }
466
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;
470   flag&=andmask;
471   if (flag==oldflag)   /* Don't do anything */
472     return false;
473   else {
474     flagbody(ptr, flag, NULL, 0, false);
475     return true;
476   }
477 }
478  
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;
482   flag&=andmask;
483   flagbody(ptr,flag,NULL,0,true);
484 }
485  
486 void flagbody(struct ___Object___ *ptr,
487               int flag,
488               struct parameterwrapper ** vqueues,
489               int vlength,
490               bool isnew) {
491   struct parameterwrapper * flagptr = NULL;
492   int i = 0;
493   struct parameterwrapper ** queues = vqueues;
494   int length = vlength;
495   int next;
496   int UNUSED, UNUSED2;
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];
502     } else {
503       return;
504     }
505   }
506   ptr->flag=flag;
507
508   /*Remove object from all queues */
509   for(i = 0; i < length; i++) {
510     flagptr = queues[i];
511     ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next,
512                   (int *) &enterflags, &UNUSED, &UNUSED2);
513     ObjectHashremove(flagptr->objectset, (int)ptr);
514     if (enterflags!=NULL)
515       RUNFREE(enterflags);
516   }
517 }
518
519 void enqueueObject(void * vptr,
520                    struct parameterwrapper ** vqueues,
521                    int vlength) {
522   struct ___Object___ *ptr = (struct ___Object___ *)vptr;
523   
524   {
525     struct parameterwrapper * parameter=NULL;
526     int j;
527     int i;
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) {
533       return;
534     }
535     if(queues == NULL) {
536       queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
537       length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
538     }
539     tagptr=ptr->___tags___;
540
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];
545       /* Check tags */
546       if (parameter->numbertags>0) {
547         if (tagptr==NULL)
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 */
556           }
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];
562             int j;
563             for(j=0; j<ao->___cachedCode___; j++) {
564               if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
565                 goto foundtag;
566             }
567             goto nextloop;
568           foundtag:
569             ;
570           }
571         }
572       }
573       
574       /* Check flags */
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);
580           prevptr=parameter;
581           break;
582         }
583       }
584     nextloop:
585       ;
586     }
587   }
588 }
589
590 void enqueueObject_I(void * vptr,
591                      struct parameterwrapper ** vqueues,
592                      int vlength) {
593   struct ___Object___ *ptr = (struct ___Object___ *)vptr;
594
595   {
596     struct parameterwrapper * parameter=NULL;
597     int j;
598     int i;
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) {
604       return;
605     }
606     if(queues == NULL) {
607       queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
608       length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
609     }
610     tagptr=ptr->___tags___;
611
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];
616       /* Check tags */
617       if (parameter->numbertags>0) {
618         if (tagptr==NULL)
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 */
627           }
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];
633             int j;
634             for(j=0; j<ao->___cachedCode___; j++) {
635               if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
636                 goto foundtag;
637             }
638             goto nextloop;
639           foundtag:
640             ;
641           }
642         }
643       }
644       
645       /* Check flags */
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);
651           prevptr=parameter;
652           break;
653         }
654       }
655     nextloop:
656       ;
657     }
658   }
659 }
660
661
662 int * getAliasLock(void ** ptrs, int length, struct RuntimeHash * tbl) {
663 #ifdef TILERA_BME
664   int i = 0;
665   int locks[length];
666   int locklen = 0;
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]);
670     int lock = 0;
671     int j = 0;
672     if(ptr->lock == NULL) {
673       lock = (int)(ptr);
674     } else {
675       lock = (int)(ptr->lock);
676     }
677     bool insert = true;
678     for(j = 0; j < locklen; j++) {
679       if(locks[j] == lock) {
680         insert = false;
681         break;
682       } else if(locks[j] > lock) {
683         break;
684       }
685     }
686     if(insert) {
687       int h = locklen;
688       for(; h > j; h--) {
689         locks[h] = locks[h-1];
690       }
691       locks[j] = lock;
692       locklen++;
693     }
694   }
695   // use the smallest lock as the shared lock for the whole set
696   return (int *)(locks[0]);
697 #else // TILERA_BME
698   // TODO possible bug here!!!
699   if(length == 0) {
700     return (int*)(RUNMALLOC(sizeof(int)));
701   } else {
702     int i = 0;
703     int locks[length];
704     int locklen = 0;
705     bool redirect = false;
706     int redirectlock = 0;
707     for(; i < length; i++) {
708       struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
709       int lock = 0;
710       int j = 0;
711       if(ptr->lock == NULL) {
712         lock = (int)(ptr);
713       } else {
714         lock = (int)(ptr->lock);
715       }
716       if(redirect) {
717         if(lock != redirectlock) {
718           RuntimeHashadd(tbl, lock, redirectlock);
719         }
720       } else {
721         if(RuntimeHashcontainskey(tbl, lock)) {
722           // already redirected
723           redirect = true;
724           RuntimeHashget(tbl, lock, &redirectlock);
725           for(; j < locklen; j++) {
726             if(locks[j] != redirectlock) {
727               RuntimeHashadd(tbl, locks[j], redirectlock);
728             }
729           }
730         } else {
731           bool insert = true;
732           for(j = 0; j < locklen; j++) {
733             if(locks[j] == lock) {
734               insert = false;
735               break;
736             } else if(locks[j] > lock) {
737               break;
738             }
739           }
740           if(insert) {
741             int h = locklen;
742             for(; h > j; h--) {
743               locks[h] = locks[h-1];
744             }
745             locks[j] = lock;
746             locklen++;
747           }
748         }
749       }
750     }
751     if(redirect) {
752       return (int *)redirectlock;
753     } else {
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]);
758         }
759       }
760       return (int *)(locks[0]);
761     }
762   }
763 #endif // TILERA_BME
764 }
765
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
771 #ifdef TILERA_BME
772     while(obj->lock != NULL) {
773       // previously have alias lock, trace the 'root' obj and redirect it
774       obj = (struct ___Object___ *)(obj->lock);
775     } 
776 #endif // TILERA_BME
777     obj->lock = (int *)lock;
778   }
779 }
780
781 int enqueuetasks(struct parameterwrapper *parameter,
782                  struct parameterwrapper *prevptr,
783                  struct ___Object___ *ptr,
784                  int * enterflags,
785                  int numenterflags) {
786   void * taskpointerarray[MAXTASKPARAMS];
787   int j;
788   int numiterators=parameter->task->numTotal-1;
789   int retval=1;
790
791   struct taskdescriptor * task=parameter->task;
792
793   //this add the object to parameterwrapper
794   ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags,
795       numenterflags, enterflags==NULL);
796
797   /* Add enqueued object to parameter vector */
798   taskpointerarray[parameter->slot]=ptr;
799
800   /* Reset iterators */
801   for(j=0; j<numiterators; j++) {
802     toiReset(&parameter->iterators[j]);
803   }
804
805   /* Find initial state */
806   for(j=0; j<numiterators; j++) {
807 backtrackinit:
808     if(toiHasNext(&parameter->iterators[j],taskpointerarray OPTARG(failed)))
809       toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
810     else if (j>0) {
811       /* Need to backtrack */
812       toiReset(&parameter->iterators[j]);
813       j--;
814       goto backtrackinit;
815     } else {
816       /* Nothing to enqueue */
817       return retval;
818     }
819   }
820
821   while(1) {
822     /* Enqueue current state */
823     //int launch = 0;
824     struct taskparamdescriptor *tpd=
825       RUNMALLOC(sizeof(struct taskparamdescriptor));
826     tpd->task=task;
827     tpd->numParameters=numiterators+1;
828     tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
829
830     for(j=0; j<=numiterators; j++) {
831       //store the actual parameters
832       tpd->parameterArray[j]=taskpointerarray[j];
833     }
834     /* Enqueue task */
835     if (!gencontains(activetasks,tpd)) {
836       genputtable(activetasks, tpd, tpd);
837     } else {
838       RUNFREE(tpd->parameterArray);
839       RUNFREE(tpd);
840     }
841
842     /* This loop iterates to the next parameter combination */
843     if (numiterators==0)
844       return retval;
845
846     for(j=numiterators-1; j<numiterators; j++) {
847 backtrackinc:
848       if(toiHasNext(&parameter->iterators[j],taskpointerarray OPTARG(failed)))
849         toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
850       else if (j>0) {
851         /* Need to backtrack */
852         toiReset(&parameter->iterators[j]);
853         j--;
854         goto backtrackinc;
855       } else {
856         /* Nothing more to enqueue */
857         return retval;
858       }
859     }
860   }
861   return retval;
862 }
863
864 int enqueuetasks_I(struct parameterwrapper *parameter,
865                    struct parameterwrapper *prevptr,
866                    struct ___Object___ *ptr,
867                    int * enterflags,
868                    int numenterflags) {
869   void * taskpointerarray[MAXTASKPARAMS];
870   int j;
871   int numiterators=parameter->task->numTotal-1;
872   int retval=1;
873
874   struct taskdescriptor * task=parameter->task;
875
876   //this add the object to parameterwrapper
877   ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags,
878                   numenterflags, enterflags==NULL);
879
880   /* Add enqueued object to parameter vector */
881   taskpointerarray[parameter->slot]=ptr;
882
883   /* Reset iterators */
884   for(j=0; j<numiterators; j++) {
885     toiReset(&parameter->iterators[j]);
886   }
887
888   /* Find initial state */
889   for(j=0; j<numiterators; j++) {
890 backtrackinit:
891     if(toiHasNext(&parameter->iterators[j],taskpointerarray OPTARG(failed)))
892       toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
893     else if (j>0) {
894       /* Need to backtrack */
895       toiReset(&parameter->iterators[j]);
896       j--;
897       goto backtrackinit;
898     } else {
899       /* Nothing to enqueue */
900       return retval;
901     }
902   }
903
904   while(1) {
905     /* Enqueue current state */
906     //int launch = 0;
907     struct taskparamdescriptor *tpd=
908       RUNMALLOC_I(sizeof(struct taskparamdescriptor));
909     tpd->task=task;
910     tpd->numParameters=numiterators+1;
911     tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
912
913     for(j=0; j<=numiterators; j++) {
914       //store the actual parameters
915       tpd->parameterArray[j]=taskpointerarray[j];
916     }
917     /* Enqueue task */
918     if (!gencontains(activetasks,tpd)) {
919       genputtable_I(activetasks, tpd, tpd);
920     } else {
921       RUNFREE_I(tpd->parameterArray);
922       RUNFREE_I(tpd);
923     }
924
925     /* This loop iterates to the next parameter combination */
926     if (numiterators==0)
927       return retval;
928
929     for(j=numiterators-1; j<numiterators; j++) {
930 backtrackinc:
931       if(toiHasNext(&parameter->iterators[j], taskpointerarray OPTARG(failed)))
932         toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
933       else if (j>0) {
934         /* Need to backtrack */
935         toiReset(&parameter->iterators[j]);
936         j--;
937         goto backtrackinc;
938       } else {
939         /* Nothing more to enqueue */
940         return retval;
941       }
942     }
943   }
944   return retval;
945 }
946
947 #ifdef MULTICORE_GC
948 #define OFFSET 2
949 #else
950 #define OFFSET 0
951 #endif
952
953 int containstag(struct ___Object___ *ptr,
954                 struct ___TagDescriptor___ *tag);
955
956 #ifndef MULTICORE_GC
957 void releasewritelock_r(void * lock, void * redirectlock) {
958   int targetcore = 0;
959   int reallock = (int)lock;
960   targetcore = (reallock >> 5) % NUMCORES;
961
962   BAMBOO_DEBUGPRINT(0xe671);
963   BAMBOO_DEBUGPRINT_REG((int)lock);
964   BAMBOO_DEBUGPRINT_REG(reallock);
965   BAMBOO_DEBUGPRINT_REG(targetcore);
966
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
973       BAMBOO_EXIT(0xe20c);
974     } else {
975       int rwlock_obj = 0;
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);
981       lockvalue->value++;
982       lockvalue->redirectlock = (int)redirectlock;
983       BAMBOO_DEBUGPRINT_REG(lockvalue->value);
984     }
985     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
986     BAMBOO_DEBUGPRINT(0xf000);
987     return;
988   } else {
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);
993   }
994 }
995 #endif
996
997 void executetasks() {
998   void * taskpointerarray[MAXTASKPARAMS+OFFSET];
999   int numparams=0;
1000   int numtotal=0;
1001   struct ___Object___ * tmpparam = NULL;
1002   struct parameterdescriptor * pd=NULL;
1003   struct parameterwrapper *pw=NULL;
1004   int j = 0;
1005   int x = 0;
1006   bool islock = true;
1007
1008   int grount = 0;
1009   int andmask=0;
1010   int checkmask=0;
1011
1012 newtask:
1013   while(hashsize(activetasks)>0) {
1014     GCCHECK(NULL);
1015     BAMBOO_DEBUGPRINT(0xe990);
1016
1017     /* See if there are any active tasks */
1018     int i;
1019 #ifdef ACCURATEPROFILE
1020     PROFILE_TASK_START("tpd checking");
1021 #endif
1022
1023     busystatus = true;
1024     currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
1025     genfreekey(activetasks, currtpd);
1026
1027     numparams=currtpd->task->numParameters;
1028     numtotal=currtpd->task->numTotal;
1029
1030     // (TODO, this table should be empty after all locks are released)
1031     // reset all locks
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];
1037       int tmplock = 0;
1038       int j = 0;
1039       bool insert = true;
1040       if(((struct ___Object___ *)param)->type == STARTUPTYPE) {
1041         islock = false;
1042         taskpointerarray[i+OFFSET]=param;
1043         goto execute;
1044       }
1045       struct ___Object___ * obj = (struct ___Object___ *)param;
1046       while(obj->lock != NULL) {
1047         obj = (struct ___Object___ *)(obj->lock);
1048       }
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) {
1053           insert = false;
1054           break;
1055         } else if(runtime_locks[j].value > tmplock) {
1056           break;
1057         }
1058       }
1059       if(insert) {
1060         int h = runtime_locklen;
1061         for(; h > j; h--) {
1062           runtime_locks[h].redirectlock = runtime_locks[h-1].redirectlock;
1063           runtime_locks[h].value = runtime_locks[h-1].value;
1064         }
1065         runtime_locks[j].value = tmplock;
1066         runtime_locks[j].redirectlock = (int)param;
1067         runtime_locklen++;
1068       }
1069     }  // for(i = 0; i < numparams; i++)
1070     // grab these required locks
1071     BAMBOO_DEBUGPRINT(0xe991);
1072
1073     for(i = 0; i < runtime_locklen; i++) {
1074       int * lock = (int *)(runtime_locks[i].value);
1075       islock = true;
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));
1079       getwritelock(lock);
1080       BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1081       BAMBOO_DEBUGPRINT(0xf001);
1082       while(!lockflag) {
1083         BAMBOO_WAITING_FOR_LOCK(0);
1084       }
1085 #ifndef INTERRUPT
1086       if(reside) {
1087         while(BAMBOO_WAITING_FOR_LOCK(0) != -1) {
1088         }
1089       }
1090 #endif
1091       grount = lockresult;
1092
1093       lockresult = 0;
1094       lockobj = 0;
1095       lock2require = 0;
1096       lockflag = false;
1097 #ifndef INTERRUPT
1098       reside = false;
1099 #endif
1100       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1101       BAMBOO_DEBUGPRINT(0xf000);
1102
1103       if(grount == 0) {
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);
1112         }
1113         genputtable(activetasks, currtpd, currtpd);
1114         if(hashsize(activetasks) == 1) {
1115           // only one task right now, wait a little while before next try
1116           int halt = 10000;
1117           while(halt--) {
1118           }
1119         }
1120 #ifdef ACCURATEPROFILE
1121         // fail, set the end of the checkTaskInfo
1122         PROFILE_TASK_END();
1123 #endif
1124         goto newtask;
1125       }
1126     }   // line 2752:  for(i = 0; i < runtime_locklen; i++)
1127
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];
1132
1133       // flush the object
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 */
1140       {
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);
1148           }
1149           RUNFREE(currtpd->parameterArray);
1150           RUNFREE(currtpd);
1151           currtpd = NULL;
1152           goto newtask;
1153         }
1154       } 
1155       /* Check if the object's flags still meets requirements */
1156       {
1157         int tmpi = 0;
1158         bool ismet = false;
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) {
1163             ismet = true;
1164             break;
1165           }
1166         }
1167         if (!ismet) {
1168           // flags are never suitable
1169           // remove this obj from the queue
1170           int next;
1171           int UNUSED, UNUSED2;
1172           int * enterflags;
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);
1184           }
1185           RUNFREE(currtpd->parameterArray);
1186           RUNFREE(currtpd);
1187           currtpd = NULL;
1188 #ifdef ACCURATEPROFILE
1189           // fail, set the end of the checkTaskInfo
1190           PROFILE_TASK_END();
1191 #endif
1192           goto newtask;
1193         }   //if (!ismet)
1194       } 
1195 parameterpresent:
1196       ;
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
1204           int tmpj = 0;
1205           for(tmpj = 0; tmpj < runtime_locklen; tmpj++) {
1206             int * lock = (int *)(runtime_locks[tmpj].value/*redirectlock*/);
1207             releasewritelock(lock);
1208           }
1209           RUNFREE(currtpd->parameterArray);
1210           RUNFREE(currtpd);
1211           currtpd = NULL;
1212           goto newtask;         
1213         }   
1214       }   
1215
1216       taskpointerarray[i+OFFSET]=parameter;
1217     }   // for(i=0; i<numparams; i++)
1218     /* Copy the tags */
1219     for(; i<numtotal; i++) {
1220       taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
1221     }
1222
1223     {
1224 execute:
1225       /* Actually call task */
1226 #ifdef MULTICORE_GC
1227       ((int *)taskpointerarray)[0]=currtpd->numParameters;
1228       taskpointerarray[1]=NULL;
1229 #endif
1230 #ifdef ACCURATEPROFILE
1231       // check finish, set the end of the checkTaskInfo
1232       PROFILE_TASK_END();
1233 #endif
1234       PROFILE_TASK_START(currtpd->task->name);
1235
1236       BAMBOO_DEBUGPRINT(0xe997);
1237       ((void (*)(void **))currtpd->task->taskptr)(taskpointerarray);
1238
1239 #ifdef ACCURATEPROFILE
1240       // task finish, set the end of the checkTaskInfo
1241       PROFILE_TASK_END();
1242       // new a PostTaskInfo for the post-task execution
1243       PROFILE_TASK_START("post task execution");
1244 #endif
1245       BAMBOO_DEBUGPRINT(0xe998);
1246       BAMBOO_DEBUGPRINT_REG(islock);
1247
1248       if(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
1257 #ifndef TILERA_BME
1258           if(RuntimeHashcontainskey(lockRedirectTbl, (int)lock)) {
1259             int redirectlock;
1260             RuntimeHashget(lockRedirectTbl, (int)lock, &redirectlock);
1261             RuntimeHashremovekey(lockRedirectTbl, (int)lock);
1262             releasewritelock_r(lock, (int *)redirectlock);
1263           } else {
1264 #else
1265           {
1266 #endif
1267 #else
1268           {
1269 #endif
1270             releasewritelock(lock); // ptr
1271           }
1272         }
1273       }     // if(islock)
1274
1275       // post task execution finish, set the end of the postTaskInfo
1276       PROFILE_TASK_END();
1277
1278       // Free up task parameter descriptor
1279       RUNFREE(currtpd->parameterArray);
1280       RUNFREE(currtpd);
1281       currtpd = NULL;
1282       BAMBOO_DEBUGPRINT(0xe99a);
1283     }   
1284   } //  while(hashsize(activetasks)>0)
1285   BAMBOO_DEBUGPRINT(0xe99b);
1286 }
1287
1288 /* This function processes an objects tags */
1289 void processtags(struct parameterdescriptor *pd,
1290                  int index,
1291                  struct parameterwrapper *parameter,
1292                  int * iteratorcount,
1293                  int *statusarray,
1294                  int numparams) {
1295   int i;
1296
1297   for(i=0; i<pd->numbertags; i++) {
1298     int slotid=pd->tagarray[2*i];
1299     int tagid=pd->tagarray[2*i+1];
1300
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;
1307       (*iteratorcount)++;
1308     }
1309   }
1310 }
1311
1312 void processobject(struct parameterwrapper *parameter,
1313                    int index,
1314                    struct parameterdescriptor *pd,
1315                    int *iteratorcount,
1316                    int * statusarray,
1317                    int numparams) {
1318   int i;
1319   int tagcount=0;
1320   struct ObjectHash * objectset=
1321     ((struct parameterwrapper *)pd->queue)->objectset;
1322
1323   parameter->iterators[*iteratorcount].istag=0;
1324   parameter->iterators[*iteratorcount].slot=index;
1325   parameter->iterators[*iteratorcount].objectset=objectset;
1326   statusarray[index]=1;
1327
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]=
1333         slotid+numparams;
1334       tagcount++;
1335     }
1336   }
1337   parameter->iterators[*iteratorcount].numtags=tagcount;
1338
1339   (*iteratorcount)++;
1340 }
1341
1342 /* This function builds the iterators for a task & parameter */
1343
1344 void builditerators(struct taskdescriptor * task,
1345                     int index,
1346                     struct parameterwrapper * parameter) {
1347   int statusarray[MAXTASKPARAMS];
1348   int i;
1349   int numparams=task->numParameters;
1350   int iteratorcount=0;
1351   for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
1352
1353   statusarray[index]=1; /* Initial parameter */
1354   /* Process tags for initial iterator */
1355
1356   processtags(task->descriptorarray[index], index, parameter,
1357               &iteratorcount, statusarray, numparams);
1358
1359   while(1) {
1360 loopstart:
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];
1365         int j;
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);
1372             goto loopstart;
1373           }
1374         }
1375       }
1376     }
1377     
1378     /* Next do objects w/ unbound tags*/
1379     
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);
1386           goto loopstart;
1387         }
1388       }
1389     }
1390     
1391     /* Nothing with a tag enqueued */
1392     
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);
1398         goto loopstart;
1399       }
1400     }
1401     
1402     /* Nothing left */
1403     return;
1404   }
1405 }
1406
1407 void printdebug() {
1408   int i;
1409   int j;
1410   if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
1411     return;
1412   }
1413   for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
1414     struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
1415 #ifndef RAW
1416     printf("%s\n", task->name);
1417 #endif
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;
1423 #ifndef RAW
1424       printf("  Parameter %d\n", j);
1425 #endif
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);
1433         Objnext(&objit);
1434 #ifndef RAW
1435         printf("    Contains %lx\n", obj);
1436         printf("      flag=%d\n", obj->flag);
1437 #endif
1438         if (tagptr==NULL) {
1439         } else if (tagptr->type==TAGTYPE) {
1440 #ifndef RAW
1441           printf("      tag=%lx\n",tagptr);
1442 #endif
1443         } else {
1444           int tagindex=0;
1445           struct ArrayObject *ao=(struct ArrayObject *)tagptr;
1446           for(; tagindex<ao->___cachedCode___; tagindex++) {
1447 #ifndef RAW
1448             printf("      tag=%lx\n",ARRAYGET(ao,struct ___TagDescriptor___*, tagindex));
1449 #else
1450             ;
1451 #endif
1452           }
1453         }
1454       }
1455     }
1456   }
1457 }
1458
1459 /* This function processes the task information to create queues for
1460    each parameter type. */
1461 void processtasks() {
1462   int i;
1463   if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
1464     return;
1465   }
1466   for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
1467     struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
1468     int j;
1469
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;
1476     }
1477
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);
1483     }
1484   }
1485 }
1486
1487 void toiReset(struct tagobjectiterator * it) {
1488   if (it->istag) {
1489     it->tagobjindex=0;
1490   } else if (it->numtags>0) {
1491     it->tagobjindex=0;
1492   } else {
1493     ObjectHashiterator(it->objectset, &it->it);
1494   }
1495 }
1496
1497 int toiHasNext(struct tagobjectiterator *it,
1498                void ** objectarray OPTARG(int * failed)) {
1499   if (it->istag) {
1500     /* Iterate tag */
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 */
1507                 return 1;
1508           else
1509                 return 0;
1510     } else {
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 */
1518                   return 1;
1519                 }
1520       }
1521       return 0;
1522     }
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;
1527     int i;
1528     if (objptr->type!=OBJECTARRAYTYPE) {
1529       if (it->tagobjindex>0)
1530         return 0;
1531       if (!ObjectHashcontainskey(it->objectset, (int) objptr))
1532         return 0;
1533       for(i=1; i<it->numtags; i++) {
1534         struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
1535         if (!containstag(objptr,tag2))
1536           return 0;
1537       }
1538       return 1;
1539     } else {
1540       struct ArrayObject *ao=(struct ArrayObject *) objptr;
1541       int tagindex;
1542       int i;
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))
1547           continue;
1548         for(i=1; i<it->numtags; i++) {
1549           struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
1550           if (!containstag(objptr,tag2))
1551             goto nexttag;
1552         }
1553         it->tagobjindex=tagindex;
1554         return 1;
1555       nexttag:
1556         ;
1557       }
1558       it->tagobjindex=tagindex;
1559       return 0;
1560     }
1561   } else {
1562     return ObjhasNext(&it->it);
1563   }
1564 }
1565
1566 int containstag(struct ___Object___ *ptr,
1567                 struct ___TagDescriptor___ *tag) {
1568   int j;
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)) {
1574         return 1;
1575       }
1576     }
1577     return 0;
1578   } else {
1579     return objptr==ptr;
1580   }
1581 }
1582
1583 void toiNext(struct tagobjectiterator *it,
1584              void ** objectarray OPTARG(int * failed)) {
1585   /* hasNext has all of the intelligence */
1586   if(it->istag) {
1587     /* Iterate tag */
1588     /* Get object with tags */
1589     struct ___Object___ *obj=objectarray[it->tagobjectslot];
1590     struct ___Object___ *tagptr=obj->___tags___;
1591     if (tagptr->type==TAGTYPE) {
1592       it->tagobjindex++;
1593       objectarray[it->slot]=tagptr;
1594     } else {
1595       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
1596       objectarray[it->slot]=
1597         ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
1598     }
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) {
1604       it->tagobjindex++;
1605       objectarray[it->slot]=objptr;
1606     } else {
1607       struct ArrayObject *ao=(struct ArrayObject *) objptr;
1608       objectarray[it->slot]=
1609         ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
1610     }
1611   } else {
1612     /* Iterate object */
1613     objectarray[it->slot]=(void *)Objkey(&it->it);
1614     Objnext(&it->it);
1615   }
1616 }
1617 #endif