Polish multicore code
[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,
380               struct ___Object___ * obj,
381               struct ___TagDescriptor___ * tagd) {
382 #else
383 void tagclear(struct ___Object___ * obj,
384               struct ___TagDescriptor___ * tagd) {
385 #endif
386   /* We'll assume that tag is alway there.
387      Need to statically check for this of course. */
388   struct ___Object___ * tagptr=obj->___tags___;
389
390   if (tagptr->type==TAGTYPE) {
391     if ((struct ___TagDescriptor___ *)tagptr==tagd)
392       obj->___tags___=NULL;
393   } else {
394     struct ArrayObject *ao=(struct ArrayObject *) tagptr;
395     int i;
396     for(i=0; i<ao->___cachedCode___; i++) {
397       struct ___TagDescriptor___ * td=
398         ARRAYGET(ao, struct ___TagDescriptor___ *, i);
399       if (td==tagd) {
400                 ao->___cachedCode___--;
401                 if (i<ao->___cachedCode___)
402                   ARRAYSET(ao, struct ___TagDescriptor___ *, i,
403                           ARRAYGET(ao,struct ___TagDescriptor___*,ao->___cachedCode___));
404                 ARRAYSET(ao,struct ___TagDescriptor___ *,ao->___cachedCode___, NULL);
405                 if (ao->___cachedCode___==0)
406                   obj->___tags___=NULL;
407                 goto PROCESSCLEAR;
408       }
409     }
410   }
411 PROCESSCLEAR:
412   {
413     struct ___Object___ *tagset=tagd->flagptr;
414     if (tagset->type!=OBJECTARRAYTYPE) {
415       if (tagset==obj)
416                 tagd->flagptr=NULL;
417     } else {
418       struct ArrayObject *ao=(struct ArrayObject *) tagset;
419       int i;
420       for(i=0; i<ao->___cachedCode___; i++) {
421                 struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
422                 if (tobj==obj) {
423                   ao->___cachedCode___--;
424                   if (i<ao->___cachedCode___)
425                         ARRAYSET(ao, struct ___Object___ *, i,
426                                 ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
427                   ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
428                   if (ao->___cachedCode___==0)
429                         tagd->flagptr=NULL;
430                   goto ENDCLEAR;
431                 }
432       }
433     }
434   }
435 ENDCLEAR:
436   return;
437 }
438
439 /* This function allocates a new tag. */
440 #ifdef MULTICORE_GC
441 struct ___TagDescriptor___ * allocate_tag(void *ptr,
442                                           int index) {
443   struct ___TagDescriptor___ * v=
444     (struct ___TagDescriptor___ *) FREEMALLOC((struct garbagelist *) ptr,
445                                               classsize[TAGTYPE]);
446 #else
447 struct ___TagDescriptor___ * allocate_tag(int index) {
448   struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
449 #endif
450   v->type=TAGTYPE;
451   v->flag=index;
452   return v;
453 }
454
455 /* This function updates the flag for object ptr.  It or's the flag
456    with the or mask and and's it with the andmask. */
457
458 void flagbody(struct ___Object___ *ptr,
459               int flag,
460               struct parameterwrapper ** queues,
461               int length,
462               bool isnew);
463
464 int flagcomp(const int *val1, const int *val2) {
465   return (*val1)-(*val2);
466 }
467
468 void flagorand(void * ptr,
469                int ormask,
470                int andmask,
471                struct parameterwrapper ** queues,
472                int length) {
473   int oldflag=((int *)ptr)[2]; // the flag field is now the third one
474   int flag=ormask|oldflag;
475   flag&=andmask;
476   flagbody(ptr, flag, queues, length, false);
477 }
478
479 bool intflagorand(void * ptr,
480                   int ormask,
481                   int andmask) {
482   int oldflag=((int *)ptr)[2]; // the flag field is the third one
483   int flag=ormask|oldflag;
484   flag&=andmask;
485   if (flag==oldflag)   /* Don't do anything */
486     return false;
487   else {
488     flagbody(ptr, flag, NULL, 0, false);
489     return true;
490   }
491 }
492
493 void flagorandinit(void * ptr,
494                    int ormask,
495                    int andmask) {
496   int oldflag=((int *)ptr)[2]; // the flag field is the third one
497   int flag=ormask|oldflag;
498   flag&=andmask;
499   flagbody(ptr,flag,NULL,0,true);
500 }
501
502 void flagbody(struct ___Object___ *ptr,
503               int flag,
504               struct parameterwrapper ** vqueues,
505               int vlength,
506               bool isnew) {
507   struct parameterwrapper * flagptr = NULL;
508   int i = 0;
509   struct parameterwrapper ** queues = vqueues;
510   int length = vlength;
511   int next;
512   int UNUSED, UNUSED2;
513   int * enterflags = NULL;
514   if((!isnew) && (queues == NULL)) {
515     if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
516       queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
517       length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
518     } else {
519       return;
520     }
521   }
522   ptr->flag=flag;
523
524   /*Remove object from all queues */
525   for(i = 0; i < length; ++i) {
526     flagptr = queues[i];
527     ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next,
528                   (int *) &enterflags, &UNUSED, &UNUSED2);
529     ObjectHashremove(flagptr->objectset, (int)ptr);
530     if (enterflags!=NULL)
531       RUNFREE(enterflags);
532   }
533 }
534
535 void enqueueObject(void * vptr,
536                    struct parameterwrapper ** vqueues,
537                    int vlength) {
538   struct ___Object___ *ptr = (struct ___Object___ *)vptr;
539
540   {
541     struct parameterwrapper * parameter=NULL;
542     int j;
543     int i;
544     struct parameterwrapper * prevptr=NULL;
545     struct ___Object___ *tagptr=NULL;
546     struct parameterwrapper ** queues = vqueues;
547     int length = vlength;
548     if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
549       return;
550     }
551     if(queues == NULL) {
552       queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
553       length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
554     }
555     tagptr=ptr->___tags___;
556
557     /* Outer loop iterates through all parameter queues an object of
558        this type could be in.  */
559     for(j = 0; j < length; ++j) {
560       parameter = queues[j];
561       /* Check tags */
562       if (parameter->numbertags>0) {
563                 if (tagptr==NULL)
564                   goto nextloop;  //that means the object has no tag
565                 //but that param needs tag
566                 else if(tagptr->type==TAGTYPE) {     //one tag
567                   for(i=0; i<parameter->numbertags; i++) {
568                         //slotid is parameter->tagarray[2*i];
569                         int tagid=parameter->tagarray[2*i+1];
570                         if (tagid!=tagptr->flag)
571                           goto nextloop;   /*We don't have this tag */
572                   }
573                 } else {   //multiple tags
574                   struct ArrayObject * ao=(struct ArrayObject *) tagptr;
575                   for(i=0; i<parameter->numbertags; i++) {
576                         //slotid is parameter->tagarray[2*i];
577                         int tagid=parameter->tagarray[2*i+1];
578                         int j;
579                         for(j=0; j<ao->___cachedCode___; j++) {
580                           if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
581                                 goto foundtag;
582                         }
583                         goto nextloop;
584 foundtag:
585                         ;
586                   }
587                 }
588       }
589
590       /* Check flags */
591       for(i=0; i<parameter->numberofterms; i++) {
592                 int andmask=parameter->intarray[i*2];
593                 int checkmask=parameter->intarray[i*2+1];
594                 if ((ptr->flag&andmask)==checkmask) {
595                   enqueuetasks(parameter, prevptr, ptr, NULL, 0);
596                   prevptr=parameter;
597                   break;
598                 }
599       }
600 nextloop:
601       ;
602     }
603   }
604 }
605
606 void enqueueObject_I(void * vptr,
607                      struct parameterwrapper ** vqueues,
608                      int vlength) {
609   struct ___Object___ *ptr = (struct ___Object___ *)vptr;
610
611   {
612     struct parameterwrapper * parameter=NULL;
613     int j;
614     int i;
615     struct parameterwrapper * prevptr=NULL;
616     struct ___Object___ *tagptr=NULL;
617     struct parameterwrapper ** queues = vqueues;
618     int length = vlength;
619     if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
620       return;
621     }
622     if(queues == NULL) {
623       queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
624       length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
625     }
626     tagptr=ptr->___tags___;
627
628     /* Outer loop iterates through all parameter queues an object of
629        this type could be in.  */
630     for(j = 0; j < length; ++j) {
631       parameter = queues[j];
632       /* Check tags */
633       if (parameter->numbertags>0) {
634                 if (tagptr==NULL)
635                   goto nextloop;      //that means the object has no tag
636                 //but that param needs tag
637                 else if(tagptr->type==TAGTYPE) {   //one tag
638                   for(i=0; i<parameter->numbertags; i++) {
639                         //slotid is parameter->tagarray[2*i];
640                         int tagid=parameter->tagarray[2*i+1];
641                         if (tagid!=tagptr->flag)
642                           goto nextloop;            /*We don't have this tag */
643                   }
644                 } else {    //multiple tags
645                   struct ArrayObject * ao=(struct ArrayObject *) tagptr;
646                   for(i=0; i<parameter->numbertags; i++) {
647                         //slotid is parameter->tagarray[2*i];
648                         int tagid=parameter->tagarray[2*i+1];
649                         int j;
650                         for(j=0; j<ao->___cachedCode___; j++) {
651                           if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
652                                 goto foundtag;
653                         }
654                         goto nextloop;
655 foundtag:
656                         ;
657                   }
658                 }
659       }
660
661       /* Check flags */
662       for(i=0; i<parameter->numberofterms; i++) {
663                 int andmask=parameter->intarray[i*2];
664                 int checkmask=parameter->intarray[i*2+1];
665                 if ((ptr->flag&andmask)==checkmask) {
666                   enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
667                   prevptr=parameter;
668                   break;
669                 }
670       }
671 nextloop:
672       ;
673     }
674   }
675 }
676
677
678 int * getAliasLock(void ** ptrs,
679                    int length,
680                    struct RuntimeHash * tbl) {
681 #ifdef TILERA_BME
682   int i = 0;
683   int locks[length];
684   int locklen = 0;
685   // sort all the locks required by the objs in the aliased set
686   for(; i < length; i++) {
687         struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
688         int lock = 0;
689         int j = 0;
690         if(ptr->lock == NULL) {
691           lock = (int)(ptr);
692         } else {
693           lock = (int)(ptr->lock);
694         }
695         bool insert = true;
696         for(j = 0; j < locklen; j++) {
697           if(locks[j] == lock) {
698                 insert = false;
699                 break;
700           } else if(locks[j] > lock) {
701                 break;
702           }
703         }
704         if(insert) {
705           int h = locklen;
706           for(; h > j; h--) {
707                 locks[h] = locks[h-1];
708           }
709           locks[j] = lock;
710           locklen++;
711         }
712   }
713   // use the smallest lock as the shared lock for the whole set
714   return (int *)(locks[0]);
715 #else // TILERA_BME
716   // TODO possible bug here!!!
717   if(length == 0) {
718     return (int*)(RUNMALLOC(sizeof(int)));
719   } else {
720     int i = 0;
721     int locks[length];
722     int locklen = 0;
723     bool redirect = false;
724     int redirectlock = 0;
725     for(; i < length; i++) {
726       struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
727       int lock = 0;
728       int j = 0;
729       if(ptr->lock == NULL) {
730                 lock = (int)(ptr);
731       } else {
732                 lock = (int)(ptr->lock);
733       }
734       if(redirect) {
735                 if(lock != redirectlock) {
736                   RuntimeHashadd(tbl, lock, redirectlock);
737                 }
738       } else {
739                 if(RuntimeHashcontainskey(tbl, lock)) {
740                   // already redirected
741                   redirect = true;
742                   RuntimeHashget(tbl, lock, &redirectlock);
743                   for(; j < locklen; j++) {
744                         if(locks[j] != redirectlock) {
745                           RuntimeHashadd(tbl, locks[j], redirectlock);
746                         }
747                   }
748                 } else {
749                   bool insert = true;
750                   for(j = 0; j < locklen; j++) {
751                         if(locks[j] == lock) {
752                           insert = false;
753                           break;
754                         } else if(locks[j] > lock) {
755                           break;
756                         }
757                   }
758                   if(insert) {
759                         int h = locklen;
760                         for(; h > j; h--) {
761                           locks[h] = locks[h-1];
762                         }
763                         locks[j] = lock;
764                         locklen++;
765                   }
766                 }
767       }
768     }
769     if(redirect) {
770       return (int *)redirectlock;
771     } else {
772           // use the first lock as the shared lock
773           for(j = 1; j < locklen; j++) {
774                 if(locks[j] != locks[0]) {
775                   RuntimeHashadd(tbl, locks[j], locks[0]);
776                 }
777           }
778       return (int *)(locks[0]);
779     }
780   }
781 #endif // TILERA_BME
782 }
783
784 void addAliasLock(void * ptr,
785                   int lock) {
786   struct ___Object___ * obj = (struct ___Object___ *)ptr;
787   if(((int)ptr != lock) && (obj->lock != (int*)lock)) {
788     // originally no alias lock associated or have a different alias lock
789     // flush it as the new one
790 #ifdef TILERA_BME
791     while(obj->lock != NULL) {
792       // previously have alias lock, trace the 'root' obj and redirect it
793       obj = (struct ___Object___ *)(obj->lock);
794     } 
795 #endif // TILERA_BME
796     obj->lock = (int *)lock;
797   }
798 }
799
800 int enqueuetasks(struct parameterwrapper *parameter,
801                  struct parameterwrapper *prevptr,
802                  struct ___Object___ *ptr,
803                  int * enterflags,
804                  int numenterflags) {
805   void * taskpointerarray[MAXTASKPARAMS];
806   int j;
807   int numiterators=parameter->task->numTotal-1;
808   int retval=1;
809
810   struct taskdescriptor * task=parameter->task;
811
812   //this add the object to parameterwrapper
813   ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags,
814       numenterflags, enterflags==NULL);
815
816   /* Add enqueued object to parameter vector */
817   taskpointerarray[parameter->slot]=ptr;
818
819   /* Reset iterators */
820   for(j=0; j<numiterators; j++) {
821     toiReset(&parameter->iterators[j]);
822   }
823
824   /* Find initial state */
825   for(j=0; j<numiterators; j++) {
826 backtrackinit:
827     if(toiHasNext(&parameter->iterators[j],taskpointerarray OPTARG(failed)))
828       toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
829     else if (j>0) {
830       /* Need to backtrack */
831       toiReset(&parameter->iterators[j]);
832       j--;
833       goto backtrackinit;
834     } else {
835       /* Nothing to enqueue */
836       return retval;
837     }
838   }
839
840   while(1) {
841     /* Enqueue current state */
842     //int launch = 0;
843     struct taskparamdescriptor *tpd=
844       RUNMALLOC(sizeof(struct taskparamdescriptor));
845     tpd->task=task;
846     tpd->numParameters=numiterators+1;
847     tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
848
849     for(j=0; j<=numiterators; j++) {
850       //store the actual parameters
851       tpd->parameterArray[j]=taskpointerarray[j];
852     }
853     /* Enqueue task */
854     if (!gencontains(activetasks,tpd)) {
855       genputtable(activetasks, tpd, tpd);
856     } else {
857       RUNFREE(tpd->parameterArray);
858       RUNFREE(tpd);
859     }
860
861     /* This loop iterates to the next parameter combination */
862     if (numiterators==0)
863       return retval;
864
865     for(j=numiterators-1; j<numiterators; j++) {
866 backtrackinc:
867       if(toiHasNext(&parameter->iterators[j],taskpointerarray OPTARG(failed)))
868         toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
869       else if (j>0) {
870         /* Need to backtrack */
871         toiReset(&parameter->iterators[j]);
872         j--;
873         goto backtrackinc;
874       } else {
875         /* Nothing more to enqueue */
876         return retval;
877       }
878     }
879   }
880   return retval;
881 }
882
883 int enqueuetasks_I(struct parameterwrapper *parameter,
884                    struct parameterwrapper *prevptr,
885                    struct ___Object___ *ptr,
886                    int * enterflags,
887                    int numenterflags) {
888   void * taskpointerarray[MAXTASKPARAMS];
889   int j;
890   int numiterators=parameter->task->numTotal-1;
891   int retval=1;
892
893   struct taskdescriptor * task=parameter->task;
894
895   //this add the object to parameterwrapper
896   ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags,
897                   numenterflags, enterflags==NULL);
898
899   /* Add enqueued object to parameter vector */
900   taskpointerarray[parameter->slot]=ptr;
901
902   /* Reset iterators */
903   for(j=0; j<numiterators; j++) {
904     toiReset(&parameter->iterators[j]);
905   }
906
907   /* Find initial state */
908   for(j=0; j<numiterators; j++) {
909 backtrackinit:
910     if(toiHasNext(&parameter->iterators[j],taskpointerarray OPTARG(failed)))
911       toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
912     else if (j>0) {
913       /* Need to backtrack */
914       toiReset(&parameter->iterators[j]);
915       j--;
916       goto backtrackinit;
917     } else {
918       /* Nothing to enqueue */
919       return retval;
920     }
921   }
922
923   while(1) {
924     /* Enqueue current state */
925     //int launch = 0;
926     struct taskparamdescriptor *tpd=
927       RUNMALLOC_I(sizeof(struct taskparamdescriptor));
928     tpd->task=task;
929     tpd->numParameters=numiterators+1;
930     tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
931
932     for(j=0; j<=numiterators; j++) {
933       //store the actual parameters
934       tpd->parameterArray[j]=taskpointerarray[j];
935     }
936     /* Enqueue task */
937     if (!gencontains(activetasks,tpd)) {
938       genputtable_I(activetasks, tpd, tpd);
939     } else {
940       RUNFREE_I(tpd->parameterArray);
941       RUNFREE_I(tpd);
942     }
943
944     /* This loop iterates to the next parameter combination */
945     if (numiterators==0)
946       return retval;
947
948     for(j=numiterators-1; j<numiterators; j++) {
949 backtrackinc:
950       if(toiHasNext(&parameter->iterators[j], taskpointerarray OPTARG(failed)))
951         toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
952       else if (j>0) {
953         /* Need to backtrack */
954         toiReset(&parameter->iterators[j]);
955         j--;
956         goto backtrackinc;
957       } else {
958         /* Nothing more to enqueue */
959         return retval;
960       }
961     }
962   }
963   return retval;
964 }
965
966 #ifdef MULTICORE_GC
967 #define OFFSET 2
968 #else
969 #define OFFSET 0
970 #endif
971
972 int containstag(struct ___Object___ *ptr,
973                 struct ___TagDescriptor___ *tag);
974
975 #ifndef MULTICORE_GC
976 void releasewritelock_r(void * lock, void * redirectlock) {
977   int targetcore = 0;
978   int reallock = (int)lock;
979   targetcore = (reallock >> 5) % NUMCORES;
980
981   BAMBOO_DEBUGPRINT(0xe671);
982   BAMBOO_DEBUGPRINT_REG((int)lock);
983   BAMBOO_DEBUGPRINT_REG(reallock);
984   BAMBOO_DEBUGPRINT_REG(targetcore);
985
986   if(targetcore == BAMBOO_NUM_OF_CORE) {
987     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
988     BAMBOO_DEBUGPRINT(0xf001);
989     // reside on this core
990     if(!RuntimeHashcontainskey(locktbl, reallock)) {
991       // no locks for this object, something is wrong
992       BAMBOO_EXIT(0xe20c);
993     } else {
994       int rwlock_obj = 0;
995       struct LockValue * lockvalue = NULL;
996       BAMBOO_DEBUGPRINT(0xe672);
997       RuntimeHashget(locktbl, reallock, &rwlock_obj);
998       lockvalue = (struct LockValue *)rwlock_obj;
999       BAMBOO_DEBUGPRINT_REG(lockvalue->value);
1000       lockvalue->value++;
1001       lockvalue->redirectlock = (int)redirectlock;
1002       BAMBOO_DEBUGPRINT_REG(lockvalue->value);
1003     }
1004     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1005     BAMBOO_DEBUGPRINT(0xf000);
1006     return;
1007   } else {
1008     // send lock release with redirect info msg
1009     // for 32 bit machine, the size is always 4 words
1010     send_msg_4(targetcore, REDIRECTRELEASE, 1, (int)lock,
1011                (int)redirectlock, false);
1012   }
1013 }
1014 #endif
1015
1016 void executetasks() {
1017   void * taskpointerarray[MAXTASKPARAMS+OFFSET];
1018   int numparams=0;
1019   int numtotal=0;
1020   struct ___Object___ * tmpparam = NULL;
1021   struct parameterdescriptor * pd=NULL;
1022   struct parameterwrapper *pw=NULL;
1023   int j = 0;
1024   int x = 0;
1025   bool islock = true;
1026
1027   int grount = 0;
1028   int andmask=0;
1029   int checkmask=0;
1030
1031 newtask:
1032   while(hashsize(activetasks)>0) {
1033     GCCHECK(NULL);
1034     BAMBOO_DEBUGPRINT(0xe990);
1035
1036     /* See if there are any active tasks */
1037     int i;
1038 #ifdef ACCURATEPROFILE
1039     PROFILE_TASK_START("tpd checking");
1040 #endif
1041
1042     busystatus = true;
1043     currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
1044     genfreekey(activetasks, currtpd);
1045
1046     numparams=currtpd->task->numParameters;
1047     numtotal=currtpd->task->numTotal;
1048
1049     // (TODO, this table should be empty after all locks are released)
1050     // reset all locks
1051     // get all required locks
1052     runtime_locklen = 0;
1053     // check which locks are needed
1054     for(i = 0; i < numparams; i++) {
1055       void * param = currtpd->parameterArray[i];
1056       int tmplock = 0;
1057       int j = 0;
1058       bool insert = true;
1059       if(((struct ___Object___ *)param)->type == STARTUPTYPE) {
1060         islock = false;
1061         taskpointerarray[i+OFFSET]=param;
1062         goto execute;
1063       }
1064       struct ___Object___ * obj = (struct ___Object___ *)param;
1065       while(obj->lock != NULL) {
1066         obj = (struct ___Object___ *)(obj->lock);
1067       }
1068       tmplock = (int)(obj);
1069       // insert into the locks array
1070       for(j = 0; j < runtime_locklen; j++) {
1071         if(runtime_locks[j].value == tmplock) {
1072           insert = false;
1073           break;
1074         } else if(runtime_locks[j].value > tmplock) {
1075           break;
1076         }
1077       }
1078       if(insert) {
1079         int h = runtime_locklen;
1080         for(; h > j; h--) {
1081           runtime_locks[h].redirectlock = runtime_locks[h-1].redirectlock;
1082           runtime_locks[h].value = runtime_locks[h-1].value;
1083         }
1084         runtime_locks[j].value = tmplock;
1085         runtime_locks[j].redirectlock = (int)param;
1086         runtime_locklen++;
1087       }
1088     }  // for(i = 0; i < numparams; i++)
1089     // grab these required locks
1090     BAMBOO_DEBUGPRINT(0xe991);
1091
1092     for(i = 0; i < runtime_locklen; i++) {
1093       int * lock = (int *)(runtime_locks[i].value);
1094       islock = true;
1095       // require locks for this parameter if it is not a startup object
1096       BAMBOO_DEBUGPRINT_REG((int)lock);
1097       BAMBOO_DEBUGPRINT_REG((int)(runtime_locks[i].value));
1098       getwritelock(lock);
1099       BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1100       BAMBOO_DEBUGPRINT(0xf001);
1101       while(!lockflag) {
1102         BAMBOO_WAITING_FOR_LOCK(0);
1103       }
1104 #ifndef INTERRUPT
1105       if(reside) {
1106         while(BAMBOO_WAITING_FOR_LOCK(0) != -1) {
1107         }
1108       }
1109 #endif
1110       grount = lockresult;
1111
1112       lockresult = 0;
1113       lockobj = 0;
1114       lock2require = 0;
1115       lockflag = false;
1116 #ifndef INTERRUPT
1117       reside = false;
1118 #endif
1119       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1120       BAMBOO_DEBUGPRINT(0xf000);
1121
1122       if(grount == 0) {
1123         BAMBOO_DEBUGPRINT(0xe992);
1124         BAMBOO_DEBUGPRINT_REG(lock);
1125         // check if has the lock already
1126         // can not get the lock, try later
1127         // release all grabbed locks for previous parameters            
1128         for(j = 0; j < i; ++j) {
1129           lock = (int*)(runtime_locks[j].value/*redirectlock*/);
1130           releasewritelock(lock);
1131         }
1132         genputtable(activetasks, currtpd, currtpd);
1133         if(hashsize(activetasks) == 1) {
1134           // only one task right now, wait a little while before next try
1135           int halt = 10000;
1136           while(halt--) {
1137           }
1138         }
1139 #ifdef ACCURATEPROFILE
1140         // fail, set the end of the checkTaskInfo
1141         PROFILE_TASK_END();
1142 #endif
1143         goto newtask;
1144       }
1145     }   // line 2752:  for(i = 0; i < runtime_locklen; i++)
1146
1147     BAMBOO_DEBUGPRINT(0xe993);
1148     /* Make sure that the parameters are still in the queues */
1149     for(i=0; i<numparams; i++) {
1150       void * parameter=currtpd->parameterArray[i];
1151
1152       // flush the object
1153       BAMBOO_CACHE_FLUSH_RANGE((int)parameter,
1154           classsize[((struct ___Object___ *)parameter)->type]);
1155       tmpparam = (struct ___Object___ *)parameter;
1156       pd=currtpd->task->descriptorarray[i];
1157       pw=(struct parameterwrapper *) pd->queue;
1158       /* Check that object is still in queue */
1159       {
1160         if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
1161           BAMBOO_DEBUGPRINT(0xe994);
1162           BAMBOO_DEBUGPRINT_REG(parameter);
1163           // release grabbed locks
1164           for(j = 0; j < runtime_locklen; ++j) {
1165             int * lock = (int *)(runtime_locks[j].value);
1166             releasewritelock(lock);
1167           }
1168           RUNFREE(currtpd->parameterArray);
1169           RUNFREE(currtpd);
1170           currtpd = NULL;
1171           goto newtask;
1172         }
1173       } 
1174       /* Check if the object's flags still meets requirements */
1175       {
1176         int tmpi = 0;
1177         bool ismet = false;
1178         for(tmpi = 0; tmpi < pw->numberofterms; ++tmpi) {
1179           andmask=pw->intarray[tmpi*2];
1180           checkmask=pw->intarray[tmpi*2+1];
1181           if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
1182             ismet = true;
1183             break;
1184           }
1185         }
1186         if (!ismet) {
1187           // flags are never suitable
1188           // remove this obj from the queue
1189           int next;
1190           int UNUSED, UNUSED2;
1191           int * enterflags;
1192           BAMBOO_DEBUGPRINT(0xe995);
1193           BAMBOO_DEBUGPRINT_REG(parameter);
1194           ObjectHashget(pw->objectset, (int) parameter, (int *) &next,
1195               (int *) &enterflags, &UNUSED, &UNUSED2);
1196           ObjectHashremove(pw->objectset, (int)parameter);
1197           if (enterflags!=NULL)
1198             RUNFREE(enterflags);
1199           // release grabbed locks
1200           for(j = 0; j < runtime_locklen; ++j) {
1201             int * lock = (int *)(runtime_locks[j].value/*redirectlock*/);
1202             releasewritelock(lock);
1203           }
1204           RUNFREE(currtpd->parameterArray);
1205           RUNFREE(currtpd);
1206           currtpd = NULL;
1207 #ifdef ACCURATEPROFILE
1208           // fail, set the end of the checkTaskInfo
1209           PROFILE_TASK_END();
1210 #endif
1211           goto newtask;
1212         }   //if (!ismet)
1213       } 
1214 parameterpresent:
1215       ;
1216       /* Check that object still has necessary tags */
1217       for(j=0; j<pd->numbertags; j++) {
1218         int slotid=pd->tagarray[2*j]+numparams;
1219         struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
1220         if (!containstag(parameter, tagd)) {
1221           BAMBOO_DEBUGPRINT(0xe996);
1222           {
1223             // release grabbed locks
1224             int tmpj = 0;
1225             for(tmpj = 0; tmpj < runtime_locklen; ++tmpj) {
1226               int * lock = (int *)(runtime_locks[tmpj].value/*redirectlock*/);
1227               releasewritelock(lock);
1228             }
1229           }
1230           RUNFREE(currtpd->parameterArray);
1231           RUNFREE(currtpd);
1232           currtpd = NULL;
1233           goto newtask;         
1234         }   
1235       }   
1236
1237       taskpointerarray[i+OFFSET]=parameter;
1238     }   // for(i=0; i<numparams; i++)
1239     /* Copy the tags */
1240     for(; i<numtotal; i++) {
1241       taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
1242     }
1243
1244     {
1245 execute:
1246       /* Actually call task */
1247 #ifdef MULTICORE_GC
1248       ((int *)taskpointerarray)[0]=currtpd->numParameters;
1249       taskpointerarray[1]=NULL;
1250 #endif
1251 #ifdef ACCURATEPROFILE
1252       // check finish, set the end of the checkTaskInfo
1253       PROFILE_TASK_END();
1254 #endif
1255       PROFILE_TASK_START(currtpd->task->name);
1256
1257       BAMBOO_DEBUGPRINT(0xe997);
1258       ((void (*)(void **))currtpd->task->taskptr)(taskpointerarray);
1259
1260 #ifdef ACCURATEPROFILE
1261       // task finish, set the end of the checkTaskInfo
1262       PROFILE_TASK_END();
1263       // new a PostTaskInfo for the post-task execution
1264       PROFILE_TASK_START("post task execution");
1265 #endif
1266       BAMBOO_DEBUGPRINT(0xe998);
1267       BAMBOO_DEBUGPRINT_REG(islock);
1268
1269       if(islock) {
1270         BAMBOO_DEBUGPRINT(0xe999);
1271         for(i = runtime_locklen; i>0; i--) {
1272           void * ptr = (void *)(runtime_locks[i-1].redirectlock);
1273           int * lock = (int *)(runtime_locks[i-1].value);
1274           BAMBOO_DEBUGPRINT_REG((int)ptr);
1275           BAMBOO_DEBUGPRINT_REG((int)lock);
1276           BAMBOO_DEBUGPRINT_REG(*((int*)lock+5));
1277 #ifndef MULTICORE_GC
1278 #ifndef TILERA_BME
1279           if(RuntimeHashcontainskey(lockRedirectTbl, (int)lock)) {
1280             int redirectlock;
1281             RuntimeHashget(lockRedirectTbl, (int)lock, &redirectlock);
1282             RuntimeHashremovekey(lockRedirectTbl, (int)lock);
1283             releasewritelock_r(lock, (int *)redirectlock);
1284           } else {
1285 #else
1286           {
1287 #endif
1288 #else
1289           {
1290 #endif
1291             releasewritelock(lock); // ptr
1292           }
1293         }
1294       }     // if(islock)
1295
1296       // post task execution finish, set the end of the postTaskInfo
1297       PROFILE_TASK_END();
1298
1299       // Free up task parameter descriptor
1300       RUNFREE(currtpd->parameterArray);
1301       RUNFREE(currtpd);
1302       currtpd = NULL;
1303       BAMBOO_DEBUGPRINT(0xe99a);
1304     }   
1305   } //  while(hashsize(activetasks)>0)
1306   BAMBOO_DEBUGPRINT(0xe99b);
1307 }
1308
1309 /* This function processes an objects tags */
1310 void processtags(struct parameterdescriptor *pd,
1311                  int index,
1312                  struct parameterwrapper *parameter,
1313                  int * iteratorcount,
1314                  int *statusarray,
1315                  int numparams) {
1316   int i;
1317
1318   for(i=0; i<pd->numbertags; i++) {
1319     int slotid=pd->tagarray[2*i];
1320     int tagid=pd->tagarray[2*i+1];
1321
1322     if (statusarray[slotid+numparams]==0) {
1323       parameter->iterators[*iteratorcount].istag=1;
1324       parameter->iterators[*iteratorcount].tagid=tagid;
1325       parameter->iterators[*iteratorcount].slot=slotid+numparams;
1326       parameter->iterators[*iteratorcount].tagobjectslot=index;
1327       statusarray[slotid+numparams]=1;
1328       (*iteratorcount)++;
1329     }
1330   }
1331 }
1332
1333 void processobject(struct parameterwrapper *parameter,
1334                    int index,
1335                    struct parameterdescriptor *pd,
1336                    int *iteratorcount,
1337                    int * statusarray,
1338                    int numparams) {
1339   int i;
1340   int tagcount=0;
1341   struct ObjectHash * objectset=
1342     ((struct parameterwrapper *)pd->queue)->objectset;
1343
1344   parameter->iterators[*iteratorcount].istag=0;
1345   parameter->iterators[*iteratorcount].slot=index;
1346   parameter->iterators[*iteratorcount].objectset=objectset;
1347   statusarray[index]=1;
1348
1349   for(i=0; i<pd->numbertags; i++) {
1350     int slotid=pd->tagarray[2*i];
1351     if (statusarray[slotid+numparams]!=0) {
1352       /* This tag has already been enqueued, use it to narrow search */
1353       parameter->iterators[*iteratorcount].tagbindings[tagcount]=
1354         slotid+numparams;
1355       tagcount++;
1356     }
1357   }
1358   parameter->iterators[*iteratorcount].numtags=tagcount;
1359
1360   (*iteratorcount)++;
1361 }
1362
1363 /* This function builds the iterators for a task & parameter */
1364
1365 void builditerators(struct taskdescriptor * task,
1366                     int index,
1367                     struct parameterwrapper * parameter) {
1368   int statusarray[MAXTASKPARAMS];
1369   int i;
1370   int numparams=task->numParameters;
1371   int iteratorcount=0;
1372   for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
1373
1374   statusarray[index]=1; /* Initial parameter */
1375   /* Process tags for initial iterator */
1376
1377   processtags(task->descriptorarray[index], index, parameter,
1378               &iteratorcount, statusarray, numparams);
1379
1380   while(1) {
1381 loopstart:
1382     /* Check for objects with existing tags */
1383     for(i=0; i<numparams; i++) {
1384       if (statusarray[i]==0) {
1385                 struct parameterdescriptor *pd=task->descriptorarray[i];
1386                 int j;
1387                 for(j=0; j<pd->numbertags; j++) {
1388                   int slotid=pd->tagarray[2*j];
1389                   if(statusarray[slotid+numparams]!=0) {
1390                         processobject(parameter,i,pd,&iteratorcount,
1391                                 statusarray,numparams);
1392                         processtags(pd,i,parameter,&iteratorcount,statusarray,numparams);
1393                         goto loopstart;
1394                   }
1395                 }
1396       }
1397     }
1398
1399     /* Next do objects w/ unbound tags*/
1400
1401     for(i=0; i<numparams; i++) {
1402       if (statusarray[i]==0) {
1403                 struct parameterdescriptor *pd=task->descriptorarray[i];
1404                 if (pd->numbertags>0) {
1405                   processobject(parameter,i,pd,&iteratorcount,statusarray,numparams);
1406                   processtags(pd,i,parameter,&iteratorcount,statusarray,numparams);
1407                   goto loopstart;
1408                 }
1409       }
1410     }
1411
1412     /* Nothing with a tag enqueued */
1413
1414     for(i=0; i<numparams; i++) {
1415       if (statusarray[i]==0) {
1416                 struct parameterdescriptor *pd=task->descriptorarray[i];
1417                 processobject(parameter,i,pd,&iteratorcount,statusarray,numparams);
1418                 processtags(pd,i,parameter,&iteratorcount,statusarray,numparams);
1419                 goto loopstart;
1420       }
1421     }
1422
1423     /* Nothing left */
1424     return;
1425   }
1426 }
1427
1428 void printdebug() {
1429   int i;
1430   int j;
1431   if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
1432     return;
1433   }
1434   for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
1435     struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
1436 #ifndef RAW
1437     printf("%s\n", task->name);
1438 #endif
1439     for(j=0; j<task->numParameters; j++) {
1440       struct parameterdescriptor *param=task->descriptorarray[j];
1441       struct parameterwrapper *parameter=param->queue;
1442       struct ObjectHash * set=parameter->objectset;
1443       struct ObjectIterator objit;
1444 #ifndef RAW
1445       printf("  Parameter %d\n", j);
1446 #endif
1447       ObjectHashiterator(set, &objit);
1448       while(ObjhasNext(&objit)) {
1449                 struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
1450                 struct ___Object___ * tagptr=obj->___tags___;
1451                 int nonfailed=Objdata4(&objit);
1452                 int numflags=Objdata3(&objit);
1453                 int flags=Objdata2(&objit);
1454                 Objnext(&objit);
1455 #ifndef RAW
1456                 printf("    Contains %lx\n", obj);
1457                 printf("      flag=%d\n", obj->flag);
1458 #endif
1459                 if (tagptr==NULL) {
1460                 } else if (tagptr->type==TAGTYPE) {
1461 #ifndef RAW
1462                   printf("      tag=%lx\n",tagptr);
1463 #else
1464                   ;
1465 #endif
1466                 } else {
1467                   int tagindex=0;
1468                   struct ArrayObject *ao=(struct ArrayObject *)tagptr;
1469                   for(; tagindex<ao->___cachedCode___; tagindex++) {
1470 #ifndef RAW
1471                         printf("      tag=%lx\n",ARRAYGET(ao,struct ___TagDescriptor___*,
1472                                                                                           tagindex));
1473 #else
1474                         ;
1475 #endif
1476                   }
1477                 }
1478       }
1479     }
1480   }
1481 }
1482
1483 /* This function processes the task information to create queues for
1484    each parameter type. */
1485 void processtasks() {
1486   int i;
1487   if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
1488     return;
1489   }
1490   for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
1491     struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
1492     int j;
1493
1494     /* Build objectsets */
1495     for(j=0; j<task->numParameters; j++) {
1496       struct parameterdescriptor *param=task->descriptorarray[j];
1497       struct parameterwrapper *parameter=param->queue;
1498       parameter->objectset=allocateObjectHash(10);
1499       parameter->task=task;
1500     }
1501
1502     /* Build iterators for parameters */
1503     for(j=0; j<task->numParameters; j++) {
1504       struct parameterdescriptor *param=task->descriptorarray[j];
1505       struct parameterwrapper *parameter=param->queue;
1506       builditerators(task, j, parameter);
1507     }
1508   }
1509 }
1510
1511 void toiReset(struct tagobjectiterator * it) {
1512   if (it->istag) {
1513     it->tagobjindex=0;
1514   } else if (it->numtags>0) {
1515     it->tagobjindex=0;
1516   } else {
1517     ObjectHashiterator(it->objectset, &it->it);
1518   }
1519 }
1520
1521 int toiHasNext(struct tagobjectiterator *it,
1522                void ** objectarray OPTARG(int * failed)) {
1523   if (it->istag) {
1524     /* Iterate tag */
1525     /* Get object with tags */
1526     struct ___Object___ *obj=objectarray[it->tagobjectslot];
1527     struct ___Object___ *tagptr=obj->___tags___;
1528     if (tagptr->type==TAGTYPE) {
1529       if ((it->tagobjindex==0)&& /* First object */
1530                   (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
1531                 return 1;
1532           else
1533                 return 0;
1534     } else {
1535       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
1536       int tagindex=it->tagobjindex;
1537       for(; tagindex<ao->___cachedCode___; tagindex++) {
1538                 struct ___TagDescriptor___ *td=
1539                   ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
1540                 if (td->flag==it->tagid) {
1541                   it->tagobjindex=tagindex; /* Found right type of tag */
1542                   return 1;
1543                 }
1544       }
1545       return 0;
1546     }
1547   } else if (it->numtags>0) {
1548     /* Use tags to locate appropriate objects */
1549     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
1550     struct ___Object___ *objptr=tag->flagptr;
1551     int i;
1552     if (objptr->type!=OBJECTARRAYTYPE) {
1553       if (it->tagobjindex>0)
1554                 return 0;
1555       if (!ObjectHashcontainskey(it->objectset, (int) objptr))
1556                 return 0;
1557       for(i=1; i<it->numtags; i++) {
1558                 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
1559                 if (!containstag(objptr,tag2))
1560                   return 0;
1561       }
1562       return 1;
1563     } else {
1564       struct ArrayObject *ao=(struct ArrayObject *) objptr;
1565       int tagindex;
1566       int i;
1567       for(tagindex=it->tagobjindex;tagindex<ao->___cachedCode___;tagindex++){
1568                 struct ___Object___ *objptr=
1569                   ARRAYGET(ao,struct ___Object___*,tagindex);
1570                 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
1571                   continue;
1572                 for(i=1; i<it->numtags; i++) {
1573                   struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
1574                   if (!containstag(objptr,tag2))
1575                         goto nexttag;
1576                 }
1577                 it->tagobjindex=tagindex;
1578                 return 1;
1579 nexttag:
1580                 ;
1581           }
1582       it->tagobjindex=tagindex;
1583       return 0;
1584     }
1585   } else {
1586     return ObjhasNext(&it->it);
1587   }
1588 }
1589
1590 int containstag(struct ___Object___ *ptr,
1591                 struct ___TagDescriptor___ *tag) {
1592   int j;
1593   struct ___Object___ * objptr=tag->flagptr;
1594   if (objptr->type==OBJECTARRAYTYPE) {
1595     struct ArrayObject *ao=(struct ArrayObject *)objptr;
1596     for(j=0; j<ao->___cachedCode___; j++) {
1597       if (ptr==ARRAYGET(ao, struct ___Object___*, j)) {
1598                 return 1;
1599       }
1600     }
1601     return 0;
1602   } else {
1603     return objptr==ptr;
1604   }
1605 }
1606
1607 void toiNext(struct tagobjectiterator *it,
1608              void ** objectarray OPTARG(int * failed)) {
1609   /* hasNext has all of the intelligence */
1610   if(it->istag) {
1611     /* Iterate tag */
1612     /* Get object with tags */
1613     struct ___Object___ *obj=objectarray[it->tagobjectslot];
1614     struct ___Object___ *tagptr=obj->___tags___;
1615     if (tagptr->type==TAGTYPE) {
1616       it->tagobjindex++;
1617       objectarray[it->slot]=tagptr;
1618     } else {
1619       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
1620       objectarray[it->slot]=
1621         ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
1622     }
1623   } else if (it->numtags>0) {
1624     /* Use tags to locate appropriate objects */
1625     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
1626     struct ___Object___ *objptr=tag->flagptr;
1627     if (objptr->type!=OBJECTARRAYTYPE) {
1628       it->tagobjindex++;
1629       objectarray[it->slot]=objptr;
1630     } else {
1631       struct ArrayObject *ao=(struct ArrayObject *) objptr;
1632       objectarray[it->slot]=
1633         ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
1634     }
1635   } else {
1636     /* Iterate object */
1637     objectarray[it->slot]=(void *)Objkey(&it->it);
1638     Objnext(&it->it);
1639   }
1640 }
1641 #endif