Changes to accommodate the runtime for multicore gc w/o tasks
[IRC.git] / Robust / src / Runtime / bamboo / multicoretask.c
1 #ifdef TASK
2 #include "runtime.h"
3 #include "multicoreruntime.h"
4 #include "runtime_arch.h"
5 #include "GenericHashtable.h"
6
7 #ifndef INLINE
8 #define INLINE    inline __attribute__((always_inline))
9 #endif // #ifndef INLINE
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 inittaskdata() {
28   int i = 0;
29   
30   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
31     // startup core to initialize corestatus[]
32     for(i = 0; i < NUMCORESACTIVE; ++i) {
33 #ifdef PROFILE
34       // initialize the profile data arrays
35       profilestatus[i] = 1;
36 #endif // PROFILE
37     } // for(i = 0; i < NUMCORESACTIVE; ++i)
38     total_num_t6 = 0; // TODO for test
39   }
40   totransobjqueue = createQueue_I();
41   objqueue.head = NULL;
42   objqueue.tail = NULL;
43
44   currtpd = NULL;
45
46 #ifdef PROFILE
47   stall = false;
48   totalexetime = -1;
49   taskInfoIndex = 0;
50   taskInfoOverflow = false;
51 #ifdef PROFILE_INTERRUPT
52   interruptInfoIndex = 0;
53   interruptInfoOverflow = false;
54 #endif // PROFILE_INTERRUPT
55 #endif // PROFILE
56
57   for(i = 0; i < MAXTASKPARAMS; i++) {
58     runtime_locks[i].redirectlock = 0;
59     runtime_locks[i].value = 0;
60   }
61   runtime_locklen = 0;
62
63 #ifndef MULTICORE_GC
64   // create the lock table, lockresult table and obj queue
65   locktable.size = 20;
66   locktable.bucket =
67     (struct RuntimeNode **) RUNMALLOC_I(sizeof(struct RuntimeNode *)*20);
68   /* Set allocation blocks*/
69   locktable.listhead=NULL;
70   locktable.listtail=NULL;
71   /*Set data counts*/
72   locktable.numelements = 0;
73   lockobj = 0;
74   lock2require = 0;
75   lockresult = 0;
76   lockflag = false;
77   lockRedirectTbl = allocateRuntimeHash_I(20);
78   objRedirectLockTbl = allocateRuntimeHash_I(20);
79 #endif
80 }
81
82 INLINE void distaskdata() {
83   if(activetasks != NULL) {
84     genfreehashtable(activetasks);
85   }
86   if(currtpd != NULL) {
87     RUNFREE(currtpd->parameterArray);
88     RUNFREE(currtpd);
89     currtpd = NULL;
90   }
91 #ifndef MULTICORE_GC
92   freeRuntimeHash(lockRedirectTbl);
93   freeRuntimeHash(objRedirectLockTbl);
94   RUNFREE(locktable.bucket);
95 #endif
96 }
97
98 INLINE bool checkObjQueue() {
99   bool rflag = false;
100   struct transObjInfo * objInfo = NULL;
101   int grount = 0;
102
103 #ifdef PROFILE
104 #ifdef ACCURATEPROFILE
105   bool isChecking = false;
106   if(!isEmpty(&objqueue)) {
107     profileTaskStart("objqueue checking");
108     isChecking = true;
109   }  // if(!isEmpty(&objqueue))
110 #endif
111 #endif
112
113   while(!isEmpty(&objqueue)) {
114     void * obj = NULL;
115     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
116     BAMBOO_DEBUGPRINT(0xf001);
117     BAMBOO_DEBUGPRINT(0xeee1);
118     rflag = true;
119     objInfo = (struct transObjInfo *)getItem(&objqueue);
120     obj = objInfo->objptr;
121     BAMBOO_DEBUGPRINT_REG((int)obj);
122     // grab lock and flush the obj
123     grount = 0;
124         struct ___Object___ * tmpobj = (struct ___Object___ *)obj;
125         while(tmpobj->lock != NULL) {
126           tmpobj = (struct ___Object___ *)(tmpobj->lock);
127         }
128     getwritelock_I(tmpobj);
129     while(!lockflag) {
130       BAMBOO_WAITING_FOR_LOCK(0);
131     }   // while(!lockflag)
132     grount = lockresult;
133     BAMBOO_DEBUGPRINT_REG(grount);
134
135     lockresult = 0;
136     lockobj = 0;
137     lock2require = 0;
138     lockflag = false;
139 #ifndef INTERRUPT
140     reside = false;
141 #endif
142
143     if(grount == 1) {
144       int k = 0;
145       // flush the object
146 #ifdef CACHEFLUSH
147       BAMBOO_CACHE_FLUSH_RANGE((int)obj,sizeof(int));
148       BAMBOO_CACHE_FLUSH_RANGE((int)obj,
149                   classsize[((struct ___Object___ *)obj)->type]);
150 #endif
151       // enqueue the object
152       for(k = 0; k < objInfo->length; ++k) {
153                 int taskindex = objInfo->queues[2 * k];
154                 int paramindex = objInfo->queues[2 * k + 1];
155                 struct parameterwrapper ** queues =
156                   &(paramqueues[BAMBOO_NUM_OF_CORE][taskindex][paramindex]);
157                 BAMBOO_DEBUGPRINT_REG(taskindex);
158                 BAMBOO_DEBUGPRINT_REG(paramindex);
159                 enqueueObject_I(obj, queues, 1);
160                 BAMBOO_DEBUGPRINT_REG(hashsize(activetasks));
161       }  // for(k = 0; k < objInfo->length; ++k)
162       releasewritelock_I(tmpobj);
163       RUNFREE(objInfo->queues);
164       RUNFREE(objInfo);
165     } else {
166       // can not get lock
167       // put it at the end of the queue if no update version in the queue
168       struct QueueItem * qitem = getHead(&objqueue);
169       struct QueueItem * prev = NULL;
170       while(qitem != NULL) {
171                 struct transObjInfo * tmpinfo =
172                         (struct transObjInfo *)(qitem->objectptr);
173                 if(tmpinfo->objptr == obj) {
174                   // the same object in the queue, which should be enqueued
175                   // recently. Current one is outdate, do not re-enqueue it
176                   RUNFREE(objInfo->queues);
177                   RUNFREE(objInfo);
178                   goto objqueuebreak;
179                 } else {
180                   prev = qitem;
181                 }  // if(tmpinfo->objptr == obj)
182                 qitem = getNextQueueItem(prev);
183           }  // while(qitem != NULL)
184       // try to execute active tasks already enqueued first
185       addNewItem_I(&objqueue, objInfo);
186 objqueuebreak:
187       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
188       BAMBOO_DEBUGPRINT(0xf000);
189       break;
190     }  // if(grount == 1)
191     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
192     BAMBOO_DEBUGPRINT(0xf000);
193   }  // while(!isEmpty(&objqueue))
194
195 #ifdef PROFILE
196 #ifdef ACCURATEPROFILE
197   if(isChecking) {
198     profileTaskEnd();
199   }  // if(isChecking)
200 #endif
201 #endif
202
203   BAMBOO_DEBUGPRINT(0xee02);
204   return rflag;
205 }
206
207 struct ___createstartupobject____I_locals {
208   INTPTR size;
209   void * next;
210   struct  ___StartupObject___ * ___startupobject___;
211   struct ArrayObject * ___stringarray___;
212 }; // struct ___createstartupobject____I_locals
213
214 void createstartupobject(int argc,
215                          char ** argv) {
216   int i;
217
218   /* Allocate startup object     */
219 #ifdef MULTICORE_GC
220   struct ___createstartupobject____I_locals ___locals___ = 
221   {2, NULL, NULL, NULL};
222   struct ___StartupObject___ *startupobject=
223     (struct ___StartupObject___*) allocate_new(&___locals___, STARTUPTYPE);
224   ___locals___.___startupobject___ = startupobject;
225   struct ArrayObject * stringarray=
226     allocate_newarray(&___locals___, STRINGARRAYTYPE, argc-1);
227   ___locals___.___stringarray___ = stringarray;
228 #else
229   struct ___StartupObject___ *startupobject=
230     (struct ___StartupObject___*) allocate_new(STARTUPTYPE);
231   struct ArrayObject * stringarray=
232     allocate_newarray(STRINGARRAYTYPE, argc-1);
233 #endif
234   /* Build array of strings */
235   startupobject->___parameters___=stringarray;
236   for(i=1; i<argc; i++) {
237     int length=strlen(argv[i]);
238 #ifdef MULTICORE_GC
239     struct ___String___ *newstring=NewString(&___locals___, argv[i],length);
240 #else
241     struct ___String___ *newstring=NewString(argv[i],length);
242 #endif
243     ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=
244       newstring;
245   }
246
247   startupobject->version = 0;
248   startupobject->lock = NULL;
249
250   /* Set initialized flag for startup object */
251   flagorandinit(startupobject,1,0xFFFFFFFF);
252   enqueueObject(startupobject, NULL, 0);
253 #ifdef CACHEFLUSH
254   BAMBOO_CACHE_FLUSH_ALL();
255 #endif
256 }
257
258 int hashCodetpd(struct taskparamdescriptor *ftd) {
259   int hash=(int)ftd->task;
260   int i;
261   for(i=0; i<ftd->numParameters; i++) {
262     hash^=(int)ftd->parameterArray[i];
263   }
264   return hash;
265 }
266
267 int comparetpd(struct taskparamdescriptor *ftd1,
268                struct taskparamdescriptor *ftd2) {
269   int i;
270   if (ftd1->task!=ftd2->task)
271     return 0;
272   for(i=0; i<ftd1->numParameters; i++)
273     if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
274       return 0;
275   return 1;
276 }
277
278 /* This function sets a tag. */
279 #ifdef MULTICORE_GC
280 void tagset(void *ptr,
281             struct ___Object___ * obj,
282             struct ___TagDescriptor___ * tagd) {
283 #else
284 void tagset(struct ___Object___ * obj,
285             struct ___TagDescriptor___ * tagd) {
286 #endif
287   struct ArrayObject * ao=NULL;
288   struct ___Object___ * tagptr=obj->___tags___;
289   if (tagptr==NULL) {
290     obj->___tags___=(struct ___Object___ *)tagd;
291   } else {
292     /* Have to check if it is already set */
293     if (tagptr->type==TAGTYPE) {
294       struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
295       if (td==tagd) {
296                 return;
297       }
298 #ifdef MULTICORE_GC
299       int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
300       struct ArrayObject * ao=
301         allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
302       obj=(struct ___Object___ *)ptrarray[2];
303       tagd=(struct ___TagDescriptor___ *)ptrarray[3];
304       td=(struct ___TagDescriptor___ *) obj->___tags___;
305 #else
306       ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
307 #endif
308
309       ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
310       ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
311       obj->___tags___=(struct ___Object___ *) ao;
312       ao->___cachedCode___=2;
313     } else {
314       /* Array Case */
315       int i;
316       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
317       for(i=0; i<ao->___cachedCode___; i++) {
318                 struct ___TagDescriptor___ * td=
319                   ARRAYGET(ao, struct ___TagDescriptor___*, i);
320                 if (td==tagd) {
321                   return;
322                 }
323       }
324       if (ao->___cachedCode___<ao->___length___) {
325                 ARRAYSET(ao, struct ___TagDescriptor___ *,ao->___cachedCode___,tagd);
326                 ao->___cachedCode___++;
327       } else {
328 #ifdef MULTICORE_GC
329                 int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
330                 struct ArrayObject * aonew=
331                   allocate_newarray(&ptrarray,TAGARRAYTYPE,
332                                                         TAGARRAYINTERVAL+ao->___length___);
333                 obj=(struct ___Object___ *)ptrarray[2];
334                 tagd=(struct ___TagDescriptor___ *) ptrarray[3];
335                 ao=(struct ArrayObject *)obj->___tags___;
336 #else
337                 struct ArrayObject * aonew=
338                   allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
339 #endif
340
341                 aonew->___cachedCode___=ao->___length___+1;
342                 for(i=0; i<ao->___length___; i++) {
343                   ARRAYSET(aonew, struct ___TagDescriptor___*, i,
344                                    ARRAYGET(ao, struct ___TagDescriptor___*, i));
345                 }
346                 ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___,tagd);
347       }
348     }
349   }
350
351   {
352     struct ___Object___ * tagset=tagd->flagptr;
353     if(tagset==NULL) {
354       tagd->flagptr=obj;
355     } else if (tagset->type!=OBJECTARRAYTYPE) {
356 #ifdef MULTICORE_GC
357       int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
358       struct ArrayObject * ao=
359         allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
360       obj=(struct ___Object___ *)ptrarray[2];
361       tagd=(struct ___TagDescriptor___ *)ptrarray[3];
362 #else
363       struct ArrayObject * ao=
364         allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
365 #endif
366       ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
367       ARRAYSET(ao, struct ___Object___ *, 1, obj);
368       ao->___cachedCode___=2;
369       tagd->flagptr=(struct ___Object___ *)ao;
370     } else {
371       struct ArrayObject *ao=(struct ArrayObject *) tagset;
372       if (ao->___cachedCode___<ao->___length___) {
373                 ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
374       } else {
375                 int i;
376 #ifdef MULTICORE_GC
377                 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
378                 struct ArrayObject * aonew=
379                   allocate_newarray(&ptrarray,OBJECTARRAYTYPE,
380                                                         OBJECTARRAYINTERVAL+ao->___length___);
381                 obj=(struct ___Object___ *)ptrarray[2];
382                 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
383                 ao=(struct ArrayObject *)tagd->flagptr;
384 #else
385                 struct ArrayObject * aonew=allocate_newarray(OBJECTARRAYTYPE,
386                         OBJECTARRAYINTERVAL+ao->___length___);
387 #endif
388                 aonew->___cachedCode___=ao->___cachedCode___+1;
389                 for(i=0; i<ao->___length___; i++) {
390                   ARRAYSET(aonew, struct ___Object___*, i,
391                                    ARRAYGET(ao, struct ___Object___*, i));
392                 }
393                 ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
394                 tagd->flagptr=(struct ___Object___ *) aonew;
395       }
396     }
397   }
398 }
399
400 /* This function clears a tag. */
401 #ifdef MULTICORE_GC
402 void tagclear(void *ptr,
403               struct ___Object___ * obj,
404               struct ___TagDescriptor___ * tagd) {
405 #else
406 void tagclear(struct ___Object___ * obj,
407               struct ___TagDescriptor___ * tagd) {
408 #endif
409   /* We'll assume that tag is alway there.
410      Need to statically check for this of course. */
411   struct ___Object___ * tagptr=obj->___tags___;
412
413   if (tagptr->type==TAGTYPE) {
414     if ((struct ___TagDescriptor___ *)tagptr==tagd)
415       obj->___tags___=NULL;
416   } else {
417     struct ArrayObject *ao=(struct ArrayObject *) tagptr;
418     int i;
419     for(i=0; i<ao->___cachedCode___; i++) {
420       struct ___TagDescriptor___ * td=
421         ARRAYGET(ao, struct ___TagDescriptor___ *, i);
422       if (td==tagd) {
423                 ao->___cachedCode___--;
424                 if (i<ao->___cachedCode___)
425                   ARRAYSET(ao, struct ___TagDescriptor___ *, i,
426                           ARRAYGET(ao,struct ___TagDescriptor___*,ao->___cachedCode___));
427                 ARRAYSET(ao,struct ___TagDescriptor___ *,ao->___cachedCode___, NULL);
428                 if (ao->___cachedCode___==0)
429                   obj->___tags___=NULL;
430                 goto PROCESSCLEAR;
431       }
432     }
433   }
434 PROCESSCLEAR:
435   {
436     struct ___Object___ *tagset=tagd->flagptr;
437     if (tagset->type!=OBJECTARRAYTYPE) {
438       if (tagset==obj)
439                 tagd->flagptr=NULL;
440     } else {
441       struct ArrayObject *ao=(struct ArrayObject *) tagset;
442       int i;
443       for(i=0; i<ao->___cachedCode___; i++) {
444                 struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
445                 if (tobj==obj) {
446                   ao->___cachedCode___--;
447                   if (i<ao->___cachedCode___)
448                         ARRAYSET(ao, struct ___Object___ *, i,
449                                 ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
450                   ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
451                   if (ao->___cachedCode___==0)
452                         tagd->flagptr=NULL;
453                   goto ENDCLEAR;
454                 }
455       }
456     }
457   }
458 ENDCLEAR:
459   return;
460 }
461
462 /* This function allocates a new tag. */
463 #ifdef MULTICORE_GC
464 struct ___TagDescriptor___ * allocate_tag(void *ptr,
465                                           int index) {
466   struct ___TagDescriptor___ * v=
467     (struct ___TagDescriptor___ *) FREEMALLOC((struct garbagelist *) ptr,
468                                               classsize[TAGTYPE]);
469 #else
470 struct ___TagDescriptor___ * allocate_tag(int index) {
471   struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
472 #endif
473   v->type=TAGTYPE;
474   v->flag=index;
475   return v;
476 }
477
478 /* This function updates the flag for object ptr.  It or's the flag
479    with the or mask and and's it with the andmask. */
480
481 void flagbody(struct ___Object___ *ptr,
482               int flag,
483               struct parameterwrapper ** queues,
484               int length,
485               bool isnew);
486
487 int flagcomp(const int *val1, const int *val2) {
488   return (*val1)-(*val2);
489 }
490
491 void flagorand(void * ptr,
492                int ormask,
493                int andmask,
494                struct parameterwrapper ** queues,
495                int length) {
496   {
497     int oldflag=((int *)ptr)[1];
498     int flag=ormask|oldflag;
499     flag&=andmask;
500     flagbody(ptr, flag, queues, length, false);
501   }
502 }
503
504 bool intflagorand(void * ptr,
505                   int ormask,
506                   int andmask) {
507   {
508     int oldflag=((int *)ptr)[1];
509     int flag=ormask|oldflag;
510     flag&=andmask;
511     if (flag==oldflag)   /* Don't do anything */
512       return false;
513     else {
514       flagbody(ptr, flag, NULL, 0, false);
515       return true;
516     }
517   }
518 }
519
520 void flagorandinit(void * ptr,
521                    int ormask,
522                    int andmask) {
523   int oldflag=((int *)ptr)[1];
524   int flag=ormask|oldflag;
525   flag&=andmask;
526   flagbody(ptr,flag,NULL,0,true);
527 }
528
529 void flagbody(struct ___Object___ *ptr,
530               int flag,
531               struct parameterwrapper ** vqueues,
532               int vlength,
533               bool isnew) {
534   struct parameterwrapper * flagptr = NULL;
535   int i = 0;
536   struct parameterwrapper ** queues = vqueues;
537   int length = vlength;
538   int next;
539   int UNUSED, UNUSED2;
540   int * enterflags = NULL;
541   if((!isnew) && (queues == NULL)) {
542     if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
543       queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
544       length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
545     } else {
546       return;
547     }
548   }
549   ptr->flag=flag;
550
551   /*Remove object from all queues */
552   for(i = 0; i < length; ++i) {
553     flagptr = queues[i];
554     ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next,
555                   (int *) &enterflags, &UNUSED, &UNUSED2);
556     ObjectHashremove(flagptr->objectset, (int)ptr);
557     if (enterflags!=NULL)
558       RUNFREE(enterflags);
559   }
560 }
561
562 void enqueueObject(void * vptr,
563                    struct parameterwrapper ** vqueues,
564                    int vlength) {
565   struct ___Object___ *ptr = (struct ___Object___ *)vptr;
566
567   {
568     struct parameterwrapper * parameter=NULL;
569     int j;
570     int i;
571     struct parameterwrapper * prevptr=NULL;
572     struct ___Object___ *tagptr=NULL;
573     struct parameterwrapper ** queues = vqueues;
574     int length = vlength;
575     if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
576       return;
577     }
578     if(queues == NULL) {
579       queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
580       length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
581     }
582     tagptr=ptr->___tags___;
583
584     /* Outer loop iterates through all parameter queues an object of
585        this type could be in.  */
586     for(j = 0; j < length; ++j) {
587       parameter = queues[j];
588       /* Check tags */
589       if (parameter->numbertags>0) {
590                 if (tagptr==NULL)
591                   goto nextloop;  //that means the object has no tag
592                 //but that param needs tag
593                 else if(tagptr->type==TAGTYPE) {     //one tag
594                   for(i=0; i<parameter->numbertags; i++) {
595                         //slotid is parameter->tagarray[2*i];
596                         int tagid=parameter->tagarray[2*i+1];
597                         if (tagid!=tagptr->flag)
598                           goto nextloop;   /*We don't have this tag */
599                   }
600                 } else {   //multiple tags
601                   struct ArrayObject * ao=(struct ArrayObject *) tagptr;
602                   for(i=0; i<parameter->numbertags; i++) {
603                         //slotid is parameter->tagarray[2*i];
604                         int tagid=parameter->tagarray[2*i+1];
605                         int j;
606                         for(j=0; j<ao->___cachedCode___; j++) {
607                           if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
608                                 goto foundtag;
609                         }
610                         goto nextloop;
611 foundtag:
612                         ;
613                   }
614                 }
615       }
616
617       /* Check flags */
618       for(i=0; i<parameter->numberofterms; i++) {
619                 int andmask=parameter->intarray[i*2];
620                 int checkmask=parameter->intarray[i*2+1];
621                 if ((ptr->flag&andmask)==checkmask) {
622                   enqueuetasks(parameter, prevptr, ptr, NULL, 0);
623                   prevptr=parameter;
624                   break;
625                 }
626       }
627 nextloop:
628       ;
629     }
630   }
631 }
632
633 void enqueueObject_I(void * vptr,
634                      struct parameterwrapper ** vqueues,
635                      int vlength) {
636   struct ___Object___ *ptr = (struct ___Object___ *)vptr;
637
638   {
639     struct parameterwrapper * parameter=NULL;
640     int j;
641     int i;
642     struct parameterwrapper * prevptr=NULL;
643     struct ___Object___ *tagptr=NULL;
644     struct parameterwrapper ** queues = vqueues;
645     int length = vlength;
646     if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
647       return;
648     }
649     if(queues == NULL) {
650       queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
651       length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
652     }
653     tagptr=ptr->___tags___;
654
655     /* Outer loop iterates through all parameter queues an object of
656        this type could be in.  */
657     for(j = 0; j < length; ++j) {
658       parameter = queues[j];
659       /* Check tags */
660       if (parameter->numbertags>0) {
661                 if (tagptr==NULL)
662                   goto nextloop;      //that means the object has no tag
663                 //but that param needs tag
664                 else if(tagptr->type==TAGTYPE) {   //one tag
665                   for(i=0; i<parameter->numbertags; i++) {
666                         //slotid is parameter->tagarray[2*i];
667                         int tagid=parameter->tagarray[2*i+1];
668                         if (tagid!=tagptr->flag)
669                           goto nextloop;            /*We don't have this tag */
670                   }
671                 } else {    //multiple tags
672                   struct ArrayObject * ao=(struct ArrayObject *) tagptr;
673                   for(i=0; i<parameter->numbertags; i++) {
674                         //slotid is parameter->tagarray[2*i];
675                         int tagid=parameter->tagarray[2*i+1];
676                         int j;
677                         for(j=0; j<ao->___cachedCode___; j++) {
678                           if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
679                                 goto foundtag;
680                         }
681                         goto nextloop;
682 foundtag:
683                         ;
684                   }
685                 }
686       }
687
688       /* Check flags */
689       for(i=0; i<parameter->numberofterms; i++) {
690                 int andmask=parameter->intarray[i*2];
691                 int checkmask=parameter->intarray[i*2+1];
692                 if ((ptr->flag&andmask)==checkmask) {
693                   enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
694                   prevptr=parameter;
695                   break;
696                 }
697       }
698 nextloop:
699       ;
700     }
701   }
702 }
703
704
705 int * getAliasLock(void ** ptrs,
706                    int length,
707                    struct RuntimeHash * tbl) {
708 #ifdef TILERA_BME
709   int i = 0;
710   int locks[length];
711   int locklen = 0;
712   // sort all the locks required by the objs in the aliased set
713   for(; i < length; i++) {
714         struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
715         int lock = 0;
716         int j = 0;
717         if(ptr->lock == NULL) {
718           lock = (int)(ptr);
719         } else {
720           lock = (int)(ptr->lock);
721         }
722         bool insert = true;
723         for(j = 0; j < locklen; j++) {
724           if(locks[j] == lock) {
725                 insert = false;
726                 break;
727           } else if(locks[j] > lock) {
728                 break;
729           }
730         }
731         if(insert) {
732           int h = locklen;
733           for(; h > j; h--) {
734                 locks[h] = locks[h-1];
735           }
736           locks[j] = lock;
737           locklen++;
738         }
739   }
740   // use the smallest lock as the shared lock for the whole set
741   return (int *)(locks[0]);
742 #else // TILERA_BME
743   // TODO possible bug here!!!
744   if(length == 0) {
745     return (int*)(RUNMALLOC(sizeof(int)));
746   } else {
747     int i = 0;
748     int locks[length];
749     int locklen = 0;
750     bool redirect = false;
751     int redirectlock = 0;
752     for(; i < length; i++) {
753       struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
754       int lock = 0;
755       int j = 0;
756       if(ptr->lock == NULL) {
757                 lock = (int)(ptr);
758       } else {
759                 lock = (int)(ptr->lock);
760       }
761       if(redirect) {
762                 if(lock != redirectlock) {
763                   RuntimeHashadd(tbl, lock, redirectlock);
764                 }
765       } else {
766                 if(RuntimeHashcontainskey(tbl, lock)) {
767                   // already redirected
768                   redirect = true;
769                   RuntimeHashget(tbl, lock, &redirectlock);
770                   for(; j < locklen; j++) {
771                         if(locks[j] != redirectlock) {
772                           RuntimeHashadd(tbl, locks[j], redirectlock);
773                         }
774                   }
775                 } else {
776                   bool insert = true;
777                   for(j = 0; j < locklen; j++) {
778                         if(locks[j] == lock) {
779                           insert = false;
780                           break;
781                         } else if(locks[j] > lock) {
782                           break;
783                         }
784                   }
785                   if(insert) {
786                         int h = locklen;
787                         for(; h > j; h--) {
788                           locks[h] = locks[h-1];
789                         }
790                         locks[j] = lock;
791                         locklen++;
792                   }
793                 }
794       }
795     }
796     if(redirect) {
797       return (int *)redirectlock;
798     } else {
799           // use the first lock as the shared lock
800           for(j = 1; j < locklen; j++) {
801                 if(locks[j] != locks[0]) {
802                   RuntimeHashadd(tbl, locks[j], locks[0]);
803                 }
804           }
805       return (int *)(locks[0]);
806     }
807   }
808 #endif // TILERA_BME
809 }
810
811 void addAliasLock(void * ptr,
812                   int lock) {
813   struct ___Object___ * obj = (struct ___Object___ *)ptr;
814   if(((int)ptr != lock) && (obj->lock != (int*)lock)) {
815     // originally no alias lock associated or have a different alias lock
816     // flush it as the new one
817 #ifdef TILERA_BME
818         while(obj->lock != NULL) {
819           // previously have alias lock, trace the 'root' obj and redirect it
820           obj = (struct ___Object___ *)(obj->lock);
821         } 
822 #endif // TILERA_BME
823     obj->lock = (int *)lock;
824   }
825 }
826
827 #ifdef PROFILE
828 inline void setTaskExitIndex(int index) {
829   taskInfoArray[taskInfoIndex]->exitIndex = index;
830 }
831
832 inline void addNewObjInfo(void * nobj) {
833   if(taskInfoArray[taskInfoIndex]->newObjs == NULL) {
834     taskInfoArray[taskInfoIndex]->newObjs = createQueue();
835   }
836   addNewItem(taskInfoArray[taskInfoIndex]->newObjs, nobj);
837 }
838 #endif
839
840 INLINE void processmsg_transobj_I() {
841   MSG_INDEXINC_I();
842   struct transObjInfo * transObj=RUNMALLOC_I(sizeof(struct transObjInfo));
843   int k = 0;
844 #ifndef CLOSE_PRINT
845   BAMBOO_DEBUGPRINT(0xe880);
846 #endif
847   if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
848 #ifndef CLOSE_PRINT
849     BAMBOO_DEBUGPRINT_REG(msgdata[msgdataindex] /*[2]*/);
850 #endif
851     BAMBOO_EXIT(0xe005);
852   }
853   // store the object and its corresponding queue info, enqueue it later
854   transObj->objptr = (void *)msgdata[msgdataindex];  //[2]
855   MSG_INDEXINC_I();
856   transObj->length = (msglength - 3) / 2;
857   transObj->queues = RUNMALLOC_I(sizeof(int)*(msglength - 3));
858   for(k = 0; k < transObj->length; ++k) {
859     transObj->queues[2*k] = msgdata[msgdataindex];   //[3+2*k];
860     MSG_INDEXINC_I();
861     transObj->queues[2*k+1] = msgdata[msgdataindex]; //[3+2*k+1];
862     MSG_INDEXINC_I();
863   }
864   // check if there is an existing duplicate item
865   {
866     struct QueueItem * qitem = getHead(&objqueue);
867     struct QueueItem * prev = NULL;
868     while(qitem != NULL) {
869       struct transObjInfo * tmpinfo =
870         (struct transObjInfo *)(qitem->objectptr);
871       if(tmpinfo->objptr == transObj->objptr) {
872                 // the same object, remove outdate one
873                 RUNFREE(tmpinfo->queues);
874                 RUNFREE(tmpinfo);
875                 removeItem(&objqueue, qitem);
876                 //break;
877       } else {
878                 prev = qitem;
879       }
880       if(prev == NULL) {
881                 qitem = getHead(&objqueue);
882       } else {
883                 qitem = getNextQueueItem(prev);
884       }
885     }
886     addNewItem_I(&objqueue, (void *)transObj);
887   }
888   ++(self_numreceiveobjs);
889 #ifdef MULTICORE_GC
890   if(gcprocessing) {
891         if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
892           // set the gcprecheck to enable checking again
893           gcprecheck = true;
894         } else {
895           // send a update pregc information msg to the master core
896           if(BAMBOO_CHECK_SEND_MODE()) {
897                 cache_msg_4(STARTUPCORE, GCFINISHPRE, BAMBOO_NUM_OF_CORE, 
898                         self_numsendobjs, self_numreceiveobjs);
899           } else {
900                 send_msg_4(STARTUPCORE, GCFINISHPRE, BAMBOO_NUM_OF_CORE, 
901                         self_numsendobjs, self_numreceiveobjs, true);
902           }
903         }
904   }
905 #endif 
906 }
907
908 #ifndef MULTICORE_GC
909 INLINE void processmsg_lockrequest_I() {
910   // check to see if there is a lock exist for the required obj
911   // msgdata[1] -> lock type
912   int locktype = msgdata[msgdataindex]; //[1];
913   MSG_INDEXINC_I();
914   int data2 = msgdata[msgdataindex];  // obj pointer
915   MSG_INDEXINC_I();
916   int data3 = msgdata[msgdataindex];  // lock
917   MSG_INDEXINC_I();
918   int data4 = msgdata[msgdataindex];  // request core
919   MSG_INDEXINC_I();
920   // -1: redirected, 0: approved, 1: denied
921   int deny=processlockrequest(locktype, data3, data2, data4, data4, true);
922   if(deny == -1) {
923     // this lock request is redirected
924     return;
925   } else {
926     // send response msg
927     // for 32 bit machine, the size is always 4 words, cache the msg first
928     int tmp = deny==1 ? LOCKDENY : LOCKGROUNT;
929     if(BAMBOO_CHECK_SEND_MODE()) {
930           cache_msg_4(data4, tmp, locktype, data2, data3);
931     } else {
932           send_msg_4(data4, tmp, locktype, data2, data3, true);
933     }
934   }
935 }
936
937 INLINE void processmsg_lockgrount_I() {
938   MSG_INDEXINC_I();
939   if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
940 #ifndef CLOSE_PRINT
941     BAMBOO_DEBUGPRINT_REG(msgdata[msgdataindex] /*[2]*/);
942 #endif
943     BAMBOO_EXIT(0xe007);
944   }
945   int data2 = msgdata[msgdataindex];
946   MSG_INDEXINC_I();
947   int data3 = msgdata[msgdataindex];
948   MSG_INDEXINC_I();
949   if((lockobj == data2) && (lock2require == data3)) {
950 #ifndef CLOSE_PRINT
951     BAMBOO_DEBUGPRINT(0xe882);
952 #endif
953     lockresult = 1;
954     lockflag = true;
955 #ifndef INTERRUPT
956     reside = false;
957 #endif
958   } else {
959     // conflicts on lockresults
960 #ifndef CLOSE_PRINT
961     BAMBOO_DEBUGPRINT_REG(data2);
962 #endif
963     BAMBOO_EXIT(0xe008);
964   }
965 }
966
967 INLINE void processmsg_lockdeny_I() {
968   MSG_INDEXINC_I();
969   int data2 = msgdata[msgdataindex];
970   MSG_INDEXINC_I();
971   int data3 = msgdata[msgdataindex];
972   MSG_INDEXINC_I();
973   if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
974 #ifndef CLOSE_PRINT
975     BAMBOO_DEBUGPRINT_REG(data2);
976 #endif
977     BAMBOO_EXIT(0xe009);
978   }
979   if((lockobj == data2) && (lock2require == data3)) {
980 #ifndef CLOSE_PRINT
981     BAMBOO_DEBUGPRINT(0xe883);
982 #endif
983     lockresult = 0;
984     lockflag = true;
985 #ifndef INTERRUPT
986     reside = false;
987 #endif
988   } else {
989     // conflicts on lockresults
990 #ifndef CLOSE_PRINT
991     BAMBOO_DEBUGPRINT_REG(data2);
992 #endif
993     BAMBOO_EXIT(0xe00a);
994   }
995 }
996
997 INLINE void processmsg_lockrelease_I() {
998   int data1 = msgdata[msgdataindex];
999   MSG_INDEXINC_I();
1000   int data2 = msgdata[msgdataindex];
1001   MSG_INDEXINC_I();
1002   int data3 = msgdata[msgdataindex];
1003   MSG_INDEXINC_I();
1004   // receive lock release msg
1005   processlockrelease(data1, data2, 0, false);
1006 }
1007
1008 INLINE void processmsg_redirectlock_I() {
1009   // check to see if there is a lock exist for the required obj
1010   int data1 = msgdata[msgdataindex];
1011   MSG_INDEXINC_I();    //msgdata[1]; // lock type
1012   int data2 = msgdata[msgdataindex];
1013   MSG_INDEXINC_I();    //msgdata[2]; // obj pointer
1014   int data3 = msgdata[msgdataindex];
1015   MSG_INDEXINC_I();    //msgdata[3]; // redirect lock
1016   int data4 = msgdata[msgdataindex];
1017   MSG_INDEXINC_I();    //msgdata[4]; // root request core
1018   int data5 = msgdata[msgdataindex];
1019   MSG_INDEXINC_I();    //msgdata[5]; // request core
1020   int deny = processlockrequest(data1, data3, data2, data5, data4, true);
1021   if(deny == -1) {
1022     // this lock request is redirected
1023     return;
1024   } else {
1025     // send response msg
1026     // for 32 bit machine, the size is always 4 words, cache the msg first
1027     if(BAMBOO_CHECK_SEND_MODE()) {
1028           cache_msg_4(data4, deny==1 ? REDIRECTDENY : REDIRECTGROUNT,
1029                                   data1, data2, data3);
1030     } else {
1031           send_msg_4(data4, deny==1?REDIRECTDENY:REDIRECTGROUNT,
1032                                  data1, data2, data3, true);
1033     }
1034   }
1035 }
1036
1037 INLINE void processmsg_redirectgrount_I() {
1038   MSG_INDEXINC_I();
1039   int data2 = msgdata[msgdataindex];
1040   MSG_INDEXINC_I();
1041   if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
1042 #ifndef CLOSE_PRINT
1043     BAMBOO_DEBUGPRINT_REG(data2);
1044 #endif
1045     BAMBOO_EXIT(0xe00b);
1046   }
1047   if(lockobj == data2) {
1048 #ifndef CLOSE_PRINT
1049     BAMBOO_DEBUGPRINT(0xe891);
1050 #endif
1051     int data3 = msgdata[msgdataindex];
1052     MSG_INDEXINC_I();
1053     lockresult = 1;
1054     lockflag = true;
1055     RuntimeHashadd_I(objRedirectLockTbl, lockobj, data3);
1056 #ifndef INTERRUPT
1057     reside = false;
1058 #endif
1059   } else {
1060     // conflicts on lockresults
1061 #ifndef CLOSE_PRINT
1062     BAMBOO_DEBUGPRINT_REG(data2);
1063 #endif
1064     BAMBOO_EXIT(0xe00c);
1065   }
1066 }
1067
1068 INLINE void processmsg_redirectdeny_I() {
1069   MSG_INDEXINC_I();
1070   int data2 = msgdata[msgdataindex];
1071   MSG_INDEXINC_I();
1072   int data3 = msgdata[msgdataindex];
1073   MSG_INDEXINC_I();
1074   if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
1075 #ifndef CLOSE_PRINT
1076     BAMBOO_DEBUGPRINT_REG(data2);
1077 #endif
1078     BAMBOO_EXIT(0xe00d);
1079   }
1080   if(lockobj == data2) {
1081 #ifndef CLOSE_PRINT
1082     BAMBOO_DEBUGPRINT(0xe892);
1083 #endif
1084     lockresult = 0;
1085     lockflag = true;
1086 #ifndef INTERRUPT
1087     reside = false;
1088 #endif
1089   } else {
1090     // conflicts on lockresults
1091 #ifndef CLOSE_PRINT
1092     BAMBOO_DEBUGPRINT_REG(data2);
1093 #endif
1094     BAMBOO_EXIT(0xe00e);
1095   }
1096 }
1097
1098 INLINE void processmsg_redirectrelease_I() {
1099   int data1 = msgdata[msgdataindex];
1100   MSG_INDEXINC_I();
1101   int data2 = msgdata[msgdataindex];
1102   MSG_INDEXINC_I();
1103   int data3 = msgdata[msgdataindex];
1104   MSG_INDEXINC_I();
1105   processlockrelease(data1, data2, data3, true);
1106 }
1107 #endif // #ifndef MULTICORE_GC
1108
1109 #ifdef PROFILE
1110 INLINE void processmsg_profileoutput_I() {
1111   if(BAMBOO_NUM_OF_CORE == STARTUPCORE) {
1112     // startup core can not receive profile output finish msg
1113     BAMBOO_EXIT(0xe00f);
1114   }
1115 #ifndef CLOSE_PRINT
1116   BAMBOO_DEBUGPRINT(0xe885);
1117 #endif
1118   stall = true;
1119   totalexetime = msgdata[msgdataindex];  //[1]
1120   MSG_INDEXINC_I();
1121 #ifdef RT_TEST
1122   BAMBOO_DEBUGPRINT_REG(dot_num);
1123 #else
1124   outputProfileData();
1125 #endif
1126   // cache the msg first
1127   if(BAMBOO_CHECK_SEND_MODE()) {
1128         cache_msg_2(STARTUPCORE, PROFILEFINISH, BAMBOO_NUM_OF_CORE);
1129   } else {
1130         send_msg_2(STARTUPCORE, PROFILEFINISH, BAMBOO_NUM_OF_CORE, true);
1131   }
1132 }
1133
1134 INLINE void processmsg_profilefinish_I() {
1135   if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1136     // non startup core can not receive profile output finish msg
1137 #ifndef CLOSE_PRINT
1138     BAMBOO_DEBUGPRINT_REG(msgdata[msgdataindex /*1*/]);
1139 #endif
1140     BAMBOO_EXIT(0xe010);
1141   }
1142 #ifndef CLOSE_PRINT
1143   BAMBOO_DEBUGPRINT(0xe886);
1144 #endif
1145   int data1 = msgdata[msgdataindex];
1146   MSG_INDEXINC_I();
1147   profilestatus[data1] = 0;
1148 }
1149 #endif // #ifdef PROFILE
1150
1151 int enqueuetasks(struct parameterwrapper *parameter,
1152                  struct parameterwrapper *prevptr,
1153                  struct ___Object___ *ptr,
1154                  int * enterflags,
1155                  int numenterflags) {
1156   void * taskpointerarray[MAXTASKPARAMS];
1157   int j;
1158   int numiterators=parameter->task->numTotal-1;
1159   int retval=1;
1160
1161   struct taskdescriptor * task=parameter->task;
1162
1163   //this add the object to parameterwrapper
1164   ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags,
1165                 numenterflags, enterflags==NULL);
1166
1167   /* Add enqueued object to parameter vector */
1168   taskpointerarray[parameter->slot]=ptr;
1169
1170   /* Reset iterators */
1171   for(j=0; j<numiterators; j++) {
1172     toiReset(&parameter->iterators[j]);
1173   }
1174
1175   /* Find initial state */
1176   for(j=0; j<numiterators; j++) {
1177 backtrackinit:
1178     if(toiHasNext(&parameter->iterators[j],taskpointerarray OPTARG(failed)))
1179       toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
1180     else if (j>0) {
1181       /* Need to backtrack */
1182       toiReset(&parameter->iterators[j]);
1183       j--;
1184       goto backtrackinit;
1185     } else {
1186       /* Nothing to enqueue */
1187       return retval;
1188     }
1189   }
1190
1191   while(1) {
1192     /* Enqueue current state */
1193     //int launch = 0;
1194     struct taskparamdescriptor *tpd=
1195       RUNMALLOC(sizeof(struct taskparamdescriptor));
1196     tpd->task=task;
1197     tpd->numParameters=numiterators+1;
1198     tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
1199
1200     for(j=0; j<=numiterators; j++) {
1201       //store the actual parameters
1202       tpd->parameterArray[j]=taskpointerarray[j];
1203     }
1204     /* Enqueue task */
1205     if (!gencontains(activetasks,tpd)) {
1206       genputtable(activetasks, tpd, tpd);
1207     } else {
1208       RUNFREE(tpd->parameterArray);
1209       RUNFREE(tpd);
1210     }
1211
1212     /* This loop iterates to the next parameter combination */
1213     if (numiterators==0)
1214       return retval;
1215
1216     for(j=numiterators-1; j<numiterators; j++) {
1217 backtrackinc:
1218       if(toiHasNext(
1219                         &parameter->iterators[j],taskpointerarray OPTARG(failed)))
1220                 toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
1221       else if (j>0) {
1222                 /* Need to backtrack */
1223                 toiReset(&parameter->iterators[j]);
1224                 j--;
1225                 goto backtrackinc;
1226       } else {
1227                 /* Nothing more to enqueue */
1228                 return retval;
1229       }
1230     }
1231   }
1232   return retval;
1233 }
1234
1235 int enqueuetasks_I(struct parameterwrapper *parameter,
1236                    struct parameterwrapper *prevptr,
1237                    struct ___Object___ *ptr,
1238                    int * enterflags,
1239                    int numenterflags) {
1240   void * taskpointerarray[MAXTASKPARAMS];
1241   int j;
1242   int numiterators=parameter->task->numTotal-1;
1243   int retval=1;
1244
1245   struct taskdescriptor * task=parameter->task;
1246
1247   //this add the object to parameterwrapper
1248   ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags,
1249                   numenterflags, enterflags==NULL);
1250
1251   /* Add enqueued object to parameter vector */
1252   taskpointerarray[parameter->slot]=ptr;
1253
1254   /* Reset iterators */
1255   for(j=0; j<numiterators; j++) {
1256     toiReset(&parameter->iterators[j]);
1257   }
1258
1259   /* Find initial state */
1260   for(j=0; j<numiterators; j++) {
1261 backtrackinit:
1262     if(toiHasNext(&parameter->iterators[j],taskpointerarray OPTARG(failed)))
1263       toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
1264     else if (j>0) {
1265       /* Need to backtrack */
1266       toiReset(&parameter->iterators[j]);
1267       j--;
1268       goto backtrackinit;
1269     } else {
1270       /* Nothing to enqueue */
1271       return retval;
1272     }
1273   }
1274
1275   while(1) {
1276     /* Enqueue current state */
1277     //int launch = 0;
1278     struct taskparamdescriptor *tpd=
1279       RUNMALLOC_I(sizeof(struct taskparamdescriptor));
1280     tpd->task=task;
1281     tpd->numParameters=numiterators+1;
1282     tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
1283
1284     for(j=0; j<=numiterators; j++) {
1285       //store the actual parameters
1286       tpd->parameterArray[j]=taskpointerarray[j];
1287     }
1288     /* Enqueue task */
1289     if (!gencontains(activetasks,tpd)) {
1290       genputtable_I(activetasks, tpd, tpd);
1291     } else {
1292       RUNFREE(tpd->parameterArray);
1293       RUNFREE(tpd);
1294     }
1295
1296     /* This loop iterates to the next parameter combination */
1297     if (numiterators==0)
1298       return retval;
1299
1300     for(j=numiterators-1; j<numiterators; j++) {
1301 backtrackinc:
1302       if(toiHasNext(
1303                         &parameter->iterators[j], taskpointerarray OPTARG(failed)))
1304                 toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
1305       else if (j>0) {
1306                 /* Need to backtrack */
1307                 toiReset(&parameter->iterators[j]);
1308                 j--;
1309                 goto backtrackinc;
1310       } else {
1311                 /* Nothing more to enqueue */
1312                 return retval;
1313       }
1314     }
1315   }
1316   return retval;
1317 }
1318
1319 #ifdef MULTICORE_GC
1320 #define OFFSET 2
1321 #else
1322 #define OFFSET 0
1323 #endif
1324
1325 int containstag(struct ___Object___ *ptr,
1326                 struct ___TagDescriptor___ *tag);
1327
1328 #ifndef MULTICORE_GC
1329 void releasewritelock_r(void * lock, void * redirectlock) {
1330   int targetcore = 0;
1331   int reallock = (int)lock;
1332   targetcore = (reallock >> 5) % NUMCORES;
1333
1334   BAMBOO_DEBUGPRINT(0xe671);
1335   BAMBOO_DEBUGPRINT_REG((int)lock);
1336   BAMBOO_DEBUGPRINT_REG(reallock);
1337   BAMBOO_DEBUGPRINT_REG(targetcore);
1338
1339   if(targetcore == BAMBOO_NUM_OF_CORE) {
1340     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1341     BAMBOO_DEBUGPRINT(0xf001);
1342     // reside on this core
1343     if(!RuntimeHashcontainskey(locktbl, reallock)) {
1344       // no locks for this object, something is wrong
1345       BAMBOO_EXIT(0xe01f);
1346     } else {
1347       int rwlock_obj = 0;
1348       struct LockValue * lockvalue = NULL;
1349       BAMBOO_DEBUGPRINT(0xe672);
1350       RuntimeHashget(locktbl, reallock, &rwlock_obj);
1351       lockvalue = (struct LockValue *)rwlock_obj;
1352       BAMBOO_DEBUGPRINT_REG(lockvalue->value);
1353       lockvalue->value++;
1354       lockvalue->redirectlock = (int)redirectlock;
1355       BAMBOO_DEBUGPRINT_REG(lockvalue->value);
1356     }
1357     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1358     BAMBOO_DEBUGPRINT(0xf000);
1359     return;
1360   } else {
1361     // send lock release with redirect info msg
1362     // for 32 bit machine, the size is always 4 words
1363     send_msg_4(targetcore, REDIRECTRELEASE, 1, (int)lock,
1364                (int)redirectlock, false);
1365   }
1366 }
1367 #endif
1368
1369 void executetasks() {
1370   void * taskpointerarray[MAXTASKPARAMS+OFFSET];
1371   int numparams=0;
1372   int numtotal=0;
1373   struct ___Object___ * tmpparam = NULL;
1374   struct parameterdescriptor * pd=NULL;
1375   struct parameterwrapper *pw=NULL;
1376   int j = 0;
1377   int x = 0;
1378   bool islock = true;
1379
1380   int grount = 0;
1381   int andmask=0;
1382   int checkmask=0;
1383
1384 newtask:
1385   while(hashsize(activetasks)>0) {
1386 #ifdef MULTICORE_GC
1387     if(gcflag) gc(NULL);
1388 #endif
1389     BAMBOO_DEBUGPRINT(0xe990);
1390
1391     /* See if there are any active tasks */
1392     int i;
1393 #ifdef PROFILE
1394 #ifdef ACCURATEPROFILE
1395     profileTaskStart("tpd checking");
1396 #endif
1397 #endif
1398
1399     busystatus = true;
1400     currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
1401     genfreekey(activetasks, currtpd);
1402
1403     numparams=currtpd->task->numParameters;
1404     numtotal=currtpd->task->numTotal;
1405
1406     // (TODO, this table should be empty after all locks are released)
1407     // reset all locks
1408     // get all required locks
1409     runtime_locklen = 0;
1410     // check which locks are needed
1411     for(i = 0; i < numparams; i++) {
1412       void * param = currtpd->parameterArray[i];
1413       int tmplock = 0;
1414       int j = 0;
1415       bool insert = true;
1416       if(((struct ___Object___ *)param)->type == STARTUPTYPE) {
1417                 islock = false;
1418                 taskpointerarray[i+OFFSET]=param;
1419                 goto execute;
1420       }
1421       /*if(((struct ___Object___ *)param)->lock == NULL) {
1422                 tmplock = (int)param;
1423       } else {
1424                 struct ___Object___ * obj = (struct ___Object___ *)param;
1425                 while(obj->lock != NULL) {
1426                   obj = (struct ___Object___ *)(obj->lock);
1427                 }
1428                 tmplock = (int)(obj);
1429       }*/
1430           struct ___Object___ * obj = (struct ___Object___ *)param;
1431           while(obj->lock != NULL) {
1432                 obj = (struct ___Object___ *)(obj->lock);
1433           }
1434           tmplock = (int)(obj);
1435       // insert into the locks array
1436       for(j = 0; j < runtime_locklen; j++) {
1437                 if(runtime_locks[j].value == tmplock) {
1438                   insert = false;
1439                   break;
1440                 } else if(runtime_locks[j].value > tmplock) {
1441                   break;
1442                 }
1443       }
1444       if(insert) {
1445                 int h = runtime_locklen;
1446                 for(; h > j; h--) {
1447                   runtime_locks[h].redirectlock = runtime_locks[h-1].redirectlock;
1448                   runtime_locks[h].value = runtime_locks[h-1].value;
1449                 }
1450                 runtime_locks[j].value = tmplock;
1451                 runtime_locks[j].redirectlock = (int)param;
1452                 runtime_locklen++;
1453       }
1454     }  // line 2713: for(i = 0; i < numparams; i++)
1455     // grab these required locks
1456     BAMBOO_DEBUGPRINT(0xe991);
1457
1458     for(i = 0; i < runtime_locklen; i++) {
1459       int * lock = (int *)(runtime_locks[i].value);//(runtime_locks[i].redirectlock);
1460       islock = true;
1461       // require locks for this parameter if it is not a startup object
1462       BAMBOO_DEBUGPRINT_REG((int)lock);
1463       BAMBOO_DEBUGPRINT_REG((int)(runtime_locks[i].value));
1464       getwritelock(lock);
1465       BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1466       BAMBOO_DEBUGPRINT(0xf001);
1467       while(!lockflag) {
1468                 BAMBOO_WAITING_FOR_LOCK(0);
1469           }
1470 #ifndef INTERRUPT
1471       if(reside) {
1472                 while(BAMBOO_WAITING_FOR_LOCK(0) != -1) {
1473                 }
1474       }
1475 #endif
1476       grount = lockresult;
1477
1478       lockresult = 0;
1479       lockobj = 0;
1480       lock2require = 0;
1481       lockflag = false;
1482 #ifndef INTERRUPT
1483       reside = false;
1484 #endif
1485       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1486       BAMBOO_DEBUGPRINT(0xf000);
1487
1488       if(grount == 0) {
1489                 BAMBOO_DEBUGPRINT(0xe992);
1490                 BAMBOO_DEBUGPRINT_REG(lock);
1491                 // check if has the lock already
1492                 // can not get the lock, try later
1493                 // release all grabbed locks for previous parameters
1494                 for(j = 0; j < i; ++j) {
1495                   lock = (int*)(runtime_locks[j].value/*redirectlock*/);
1496                   releasewritelock(lock);
1497                 }
1498                 genputtable(activetasks, currtpd, currtpd);
1499                 if(hashsize(activetasks) == 1) {
1500                   // only one task right now, wait a little while before next try
1501                   int halt = 10000;
1502                   while(halt--) {
1503                   }
1504                 }
1505 #ifdef PROFILE
1506 #ifdef ACCURATEPROFILE
1507                 // fail, set the end of the checkTaskInfo
1508                 profileTaskEnd();
1509 #endif
1510 #endif
1511                 goto newtask;
1512       }
1513     }   // line 2752:  for(i = 0; i < runtime_locklen; i++)
1514
1515     BAMBOO_DEBUGPRINT(0xe993);
1516     /* Make sure that the parameters are still in the queues */
1517     for(i=0; i<numparams; i++) {
1518       void * parameter=currtpd->parameterArray[i];
1519
1520       // flush the object
1521 #ifdef CACHEFLUSH
1522       BAMBOO_CACHE_FLUSH_RANGE((int)parameter,
1523                   classsize[((struct ___Object___ *)parameter)->type]);
1524 #endif
1525       tmpparam = (struct ___Object___ *)parameter;
1526       pd=currtpd->task->descriptorarray[i];
1527       pw=(struct parameterwrapper *) pd->queue;
1528       /* Check that object is still in queue */
1529       {
1530                 if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
1531                   BAMBOO_DEBUGPRINT(0xe994);
1532                   BAMBOO_DEBUGPRINT_REG(parameter);
1533                   // release grabbed locks
1534                   for(j = 0; j < runtime_locklen; ++j) {
1535                         int * lock = (int *)(runtime_locks[j].value/*redirectlock*/);
1536                         releasewritelock(lock);
1537                   }
1538                   RUNFREE(currtpd->parameterArray);
1539                   RUNFREE(currtpd);
1540                   currtpd = NULL;
1541                   goto newtask;
1542                 }
1543       }   // line2865
1544       /* Check if the object's flags still meets requirements */
1545       {
1546                 int tmpi = 0;
1547                 bool ismet = false;
1548                 for(tmpi = 0; tmpi < pw->numberofterms; ++tmpi) {
1549                   andmask=pw->intarray[tmpi*2];
1550                   checkmask=pw->intarray[tmpi*2+1];
1551                   if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
1552                         ismet = true;
1553                         break;
1554                   }
1555                 }
1556                 if (!ismet) {
1557                   // flags are never suitable
1558                   // remove this obj from the queue
1559                   int next;
1560                   int UNUSED, UNUSED2;
1561                   int * enterflags;
1562                   BAMBOO_DEBUGPRINT(0xe995);
1563                   BAMBOO_DEBUGPRINT_REG(parameter);
1564                   ObjectHashget(pw->objectset, (int) parameter, (int *) &next,
1565                                                 (int *) &enterflags, &UNUSED, &UNUSED2);
1566                   ObjectHashremove(pw->objectset, (int)parameter);
1567                   if (enterflags!=NULL)
1568                         RUNFREE(enterflags);
1569                   // release grabbed locks
1570                   for(j = 0; j < runtime_locklen; ++j) {
1571                         int * lock = (int *)(runtime_locks[j].value/*redirectlock*/);
1572                         releasewritelock(lock);
1573                   }
1574                   RUNFREE(currtpd->parameterArray);
1575                   RUNFREE(currtpd);
1576                   currtpd = NULL;
1577 #ifdef PROFILE
1578 #ifdef ACCURATEPROFILE
1579                   // fail, set the end of the checkTaskInfo
1580                   profileTaskEnd();
1581 #endif
1582 #endif
1583                   goto newtask;
1584                 }   // line 2878: if (!ismet)
1585       }   // line 2867
1586 parameterpresent:
1587       ;
1588       /* Check that object still has necessary tags */
1589       for(j=0; j<pd->numbertags; j++) {
1590                 int slotid=pd->tagarray[2*j]+numparams;
1591                 struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
1592                 if (!containstag(parameter, tagd)) {
1593                   BAMBOO_DEBUGPRINT(0xe996);
1594                   {
1595                         // release grabbed locks
1596                         int tmpj = 0;
1597                         for(tmpj = 0; tmpj < runtime_locklen; ++tmpj) {
1598                           int * lock = (int *)(runtime_locks[tmpj].value/*redirectlock*/);
1599                           releasewritelock(lock);
1600                         }
1601                   }
1602                   RUNFREE(currtpd->parameterArray);
1603                   RUNFREE(currtpd);
1604                   currtpd = NULL;
1605                   goto newtask;
1606                 }   // line2911: if (!containstag(parameter, tagd))
1607       }   // line 2808: for(j=0; j<pd->numbertags; j++)
1608
1609       taskpointerarray[i+OFFSET]=parameter;
1610     }   // line 2824: for(i=0; i<numparams; i++)
1611     /* Copy the tags */
1612     for(; i<numtotal; i++) {
1613       taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
1614     }
1615
1616     {
1617 execute:
1618       /* Actually call task */
1619 #ifdef MULTICORE_GC
1620       ((int *)taskpointerarray)[0]=currtpd->numParameters;
1621       taskpointerarray[1]=NULL;
1622 #endif
1623 #ifdef PROFILE
1624 #ifdef ACCURATEPROFILE
1625       // check finish, set the end of the checkTaskInfo
1626       profileTaskEnd();
1627 #endif
1628       profileTaskStart(currtpd->task->name);
1629 #endif
1630
1631       BAMBOO_DEBUGPRINT(0xe997);
1632       ((void (*)(void **))currtpd->task->taskptr)(taskpointerarray);
1633
1634 #ifdef PROFILE
1635 #ifdef ACCURATEPROFILE
1636       // task finish, set the end of the checkTaskInfo
1637       profileTaskEnd();
1638       // new a PostTaskInfo for the post-task execution
1639       profileTaskStart("post task execution");
1640 #endif
1641 #endif
1642       BAMBOO_DEBUGPRINT(0xe998);
1643       BAMBOO_DEBUGPRINT_REG(islock);
1644
1645       if(islock) {
1646                 BAMBOO_DEBUGPRINT(0xe999);
1647                 for(i = runtime_locklen; i>0; i--) {
1648                   void * ptr = (void *)(runtime_locks[i-1].redirectlock);
1649                   int * lock = (int *)(runtime_locks[i-1].value);
1650                   BAMBOO_DEBUGPRINT_REG((int)ptr);
1651                   BAMBOO_DEBUGPRINT_REG((int)lock);
1652                   BAMBOO_DEBUGPRINT_REG(*((int*)lock+5));
1653 #ifndef MULTICORE_GC
1654 #ifndef TILERA_BME
1655                   if(RuntimeHashcontainskey(lockRedirectTbl, (int)lock)) {
1656                         int redirectlock;
1657                         RuntimeHashget(lockRedirectTbl, (int)lock, &redirectlock);
1658                         RuntimeHashremovekey(lockRedirectTbl, (int)lock);
1659                         releasewritelock_r(lock, (int *)redirectlock);
1660                   } else -1{
1661 #else
1662                   {
1663 #endif
1664 #else
1665                   {
1666 #endif
1667                         releasewritelock(lock); // ptr
1668                   }
1669                 }
1670       }     // line 3015: if(islock)
1671
1672 #ifdef PROFILE
1673       // post task execution finish, set the end of the postTaskInfo
1674       profileTaskEnd();
1675 #endif
1676
1677       // Free up task parameter descriptor
1678       RUNFREE(currtpd->parameterArray);
1679       RUNFREE(currtpd);
1680       currtpd = NULL;
1681       BAMBOO_DEBUGPRINT(0xe99a);
1682     }   //
1683     //} //  if (hashsize(activetasks)>0)
1684   } //  while(hashsize(activetasks)>0)
1685   BAMBOO_DEBUGPRINT(0xe99b);
1686 }
1687
1688 /* This function processes an objects tags */
1689 void processtags(struct parameterdescriptor *pd,
1690                  int index,
1691                  struct parameterwrapper *parameter,
1692                  int * iteratorcount,
1693                  int *statusarray,
1694                  int numparams) {
1695   int i;
1696
1697   for(i=0; i<pd->numbertags; i++) {
1698     int slotid=pd->tagarray[2*i];
1699     int tagid=pd->tagarray[2*i+1];
1700
1701     if (statusarray[slotid+numparams]==0) {
1702       parameter->iterators[*iteratorcount].istag=1;
1703       parameter->iterators[*iteratorcount].tagid=tagid;
1704       parameter->iterators[*iteratorcount].slot=slotid+numparams;
1705       parameter->iterators[*iteratorcount].tagobjectslot=index;
1706       statusarray[slotid+numparams]=1;
1707       (*iteratorcount)++;
1708     }
1709   }
1710 }
1711
1712
1713 void processobject(struct parameterwrapper *parameter,
1714                    int index,
1715                    struct parameterdescriptor *pd,
1716                    int *iteratorcount,
1717                    int * statusarray,
1718                    int numparams) {
1719   int i;
1720   int tagcount=0;
1721   struct ObjectHash * objectset=
1722     ((struct parameterwrapper *)pd->queue)->objectset;
1723
1724   parameter->iterators[*iteratorcount].istag=0;
1725   parameter->iterators[*iteratorcount].slot=index;
1726   parameter->iterators[*iteratorcount].objectset=objectset;
1727   statusarray[index]=1;
1728
1729   for(i=0; i<pd->numbertags; i++) {
1730     int slotid=pd->tagarray[2*i];
1731     if (statusarray[slotid+numparams]!=0) {
1732       /* This tag has already been enqueued, use it to narrow search */
1733       parameter->iterators[*iteratorcount].tagbindings[tagcount]=
1734         slotid+numparams;
1735       tagcount++;
1736     }
1737   }
1738   parameter->iterators[*iteratorcount].numtags=tagcount;
1739
1740   (*iteratorcount)++;
1741 }
1742
1743 /* This function builds the iterators for a task & parameter */
1744
1745 void builditerators(struct taskdescriptor * task,
1746                     int index,
1747                     struct parameterwrapper * parameter) {
1748   int statusarray[MAXTASKPARAMS];
1749   int i;
1750   int numparams=task->numParameters;
1751   int iteratorcount=0;
1752   for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
1753
1754   statusarray[index]=1; /* Initial parameter */
1755   /* Process tags for initial iterator */
1756
1757   processtags(task->descriptorarray[index], index, parameter,
1758               &iteratorcount, statusarray, numparams);
1759
1760   while(1) {
1761 loopstart:
1762     /* Check for objects with existing tags */
1763     for(i=0; i<numparams; i++) {
1764       if (statusarray[i]==0) {
1765                 struct parameterdescriptor *pd=task->descriptorarray[i];
1766                 int j;
1767                 for(j=0; j<pd->numbertags; j++) {
1768                   int slotid=pd->tagarray[2*j];
1769                   if(statusarray[slotid+numparams]!=0) {
1770                         processobject(parameter,i,pd,&iteratorcount,
1771                                 statusarray,numparams);
1772                         processtags(pd,i,parameter,&iteratorcount,statusarray,numparams);
1773                         goto loopstart;
1774                   }
1775                 }
1776       }
1777     }
1778
1779     /* Next do objects w/ unbound tags*/
1780
1781     for(i=0; i<numparams; i++) {
1782       if (statusarray[i]==0) {
1783                 struct parameterdescriptor *pd=task->descriptorarray[i];
1784                 if (pd->numbertags>0) {
1785                   processobject(parameter,i,pd,&iteratorcount,statusarray,numparams);
1786                   processtags(pd,i,parameter,&iteratorcount,statusarray,numparams);
1787                   goto loopstart;
1788                 }
1789       }
1790     }
1791
1792     /* Nothing with a tag enqueued */
1793
1794     for(i=0; i<numparams; i++) {
1795       if (statusarray[i]==0) {
1796                 struct parameterdescriptor *pd=task->descriptorarray[i];
1797                 processobject(parameter,i,pd,&iteratorcount,statusarray,numparams);
1798                 processtags(pd,i,parameter,&iteratorcount,statusarray,numparams);
1799                 goto loopstart;
1800       }
1801     }
1802
1803     /* Nothing left */
1804     return;
1805   }
1806 }
1807
1808 void printdebug() {
1809   int i;
1810   int j;
1811   if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
1812     return;
1813   }
1814   for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
1815     struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
1816 #ifndef RAW
1817     printf("%s\n", task->name);
1818 #endif
1819     for(j=0; j<task->numParameters; j++) {
1820       struct parameterdescriptor *param=task->descriptorarray[j];
1821       struct parameterwrapper *parameter=param->queue;
1822       struct ObjectHash * set=parameter->objectset;
1823       struct ObjectIterator objit;
1824 #ifndef RAW
1825       printf("  Parameter %d\n", j);
1826 #endif
1827       ObjectHashiterator(set, &objit);
1828       while(ObjhasNext(&objit)) {
1829                 struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
1830                 struct ___Object___ * tagptr=obj->___tags___;
1831                 int nonfailed=Objdata4(&objit);
1832                 int numflags=Objdata3(&objit);
1833                 int flags=Objdata2(&objit);
1834                 Objnext(&objit);
1835 #ifndef RAW
1836                 printf("    Contains %lx\n", obj);
1837                 printf("      flag=%d\n", obj->flag);
1838 #endif
1839                 if (tagptr==NULL) {
1840                 } else if (tagptr->type==TAGTYPE) {
1841 #ifndef RAW
1842                   printf("      tag=%lx\n",tagptr);
1843 #else
1844                   ;
1845 #endif
1846                 } else {
1847                   int tagindex=0;
1848                   struct ArrayObject *ao=(struct ArrayObject *)tagptr;
1849                   for(; tagindex<ao->___cachedCode___; tagindex++) {
1850 #ifndef RAW
1851                         printf("      tag=%lx\n",ARRAYGET(ao,struct ___TagDescriptor___*,
1852                                                                                           tagindex));
1853 #else
1854                         ;
1855 #endif
1856                   }
1857                 }
1858       }
1859     }
1860   }
1861 }
1862
1863
1864 /* This function processes the task information to create queues for
1865    each parameter type. */
1866
1867 void processtasks() {
1868   int i;
1869   if(BAMBOO_NUM_OF_CORE > NUMCORESACTIVE - 1) {
1870     return;
1871   }
1872   for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
1873     struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
1874     int j;
1875
1876     /* Build objectsets */
1877     for(j=0; j<task->numParameters; j++) {
1878       struct parameterdescriptor *param=task->descriptorarray[j];
1879       struct parameterwrapper *parameter=param->queue;
1880       parameter->objectset=allocateObjectHash(10);
1881       parameter->task=task;
1882     }
1883
1884     /* Build iterators for parameters */
1885     for(j=0; j<task->numParameters; j++) {
1886       struct parameterdescriptor *param=task->descriptorarray[j];
1887       struct parameterwrapper *parameter=param->queue;
1888       builditerators(task, j, parameter);
1889     }
1890   }
1891 }
1892
1893 void toiReset(struct tagobjectiterator * it) {
1894   if (it->istag) {
1895     it->tagobjindex=0;
1896   } else if (it->numtags>0) {
1897     it->tagobjindex=0;
1898   } else {
1899     ObjectHashiterator(it->objectset, &it->it);
1900   }
1901 }
1902
1903 int toiHasNext(struct tagobjectiterator *it,
1904                void ** objectarray OPTARG(int * failed)) {
1905   if (it->istag) {
1906     /* Iterate tag */
1907     /* Get object with tags */
1908     struct ___Object___ *obj=objectarray[it->tagobjectslot];
1909     struct ___Object___ *tagptr=obj->___tags___;
1910     if (tagptr->type==TAGTYPE) {
1911       if ((it->tagobjindex==0)&& /* First object */
1912                   (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
1913                 return 1;
1914           else
1915                 return 0;
1916     } else {
1917       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
1918       int tagindex=it->tagobjindex;
1919       for(; tagindex<ao->___cachedCode___; tagindex++) {
1920                 struct ___TagDescriptor___ *td=
1921                   ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
1922                 if (td->flag==it->tagid) {
1923                   it->tagobjindex=tagindex; /* Found right type of tag */
1924                   return 1;
1925                 }
1926       }
1927       return 0;
1928     }
1929   } else if (it->numtags>0) {
1930     /* Use tags to locate appropriate objects */
1931     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
1932     struct ___Object___ *objptr=tag->flagptr;
1933     int i;
1934     if (objptr->type!=OBJECTARRAYTYPE) {
1935       if (it->tagobjindex>0)
1936                 return 0;
1937       if (!ObjectHashcontainskey(it->objectset, (int) objptr))
1938                 return 0;
1939       for(i=1; i<it->numtags; i++) {
1940                 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
1941                 if (!containstag(objptr,tag2))
1942                   return 0;
1943       }
1944       return 1;
1945     } else {
1946       struct ArrayObject *ao=(struct ArrayObject *) objptr;
1947       int tagindex;
1948       int i;
1949       for(tagindex=it->tagobjindex;tagindex<ao->___cachedCode___;tagindex++){
1950                 struct ___Object___ *objptr=
1951                   ARRAYGET(ao,struct ___Object___*,tagindex);
1952                 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
1953                   continue;
1954                 for(i=1; i<it->numtags; i++) {
1955                   struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
1956                   if (!containstag(objptr,tag2))
1957                         goto nexttag;
1958                 }
1959                 it->tagobjindex=tagindex;
1960                 return 1;
1961 nexttag:
1962                 ;
1963           }
1964       it->tagobjindex=tagindex;
1965       return 0;
1966     }
1967   } else {
1968     return ObjhasNext(&it->it);
1969   }
1970 }
1971
1972 int containstag(struct ___Object___ *ptr,
1973                 struct ___TagDescriptor___ *tag) {
1974   int j;
1975   struct ___Object___ * objptr=tag->flagptr;
1976   if (objptr->type==OBJECTARRAYTYPE) {
1977     struct ArrayObject *ao=(struct ArrayObject *)objptr;
1978     for(j=0; j<ao->___cachedCode___; j++) {
1979       if (ptr==ARRAYGET(ao, struct ___Object___*, j)) {
1980                 return 1;
1981       }
1982     }
1983     return 0;
1984   } else {
1985     return objptr==ptr;
1986   }
1987 }
1988
1989 void toiNext(struct tagobjectiterator *it,
1990              void ** objectarray OPTARG(int * failed)) {
1991   /* hasNext has all of the intelligence */
1992   if(it->istag) {
1993     /* Iterate tag */
1994     /* Get object with tags */
1995     struct ___Object___ *obj=objectarray[it->tagobjectslot];
1996     struct ___Object___ *tagptr=obj->___tags___;
1997     if (tagptr->type==TAGTYPE) {
1998       it->tagobjindex++;
1999       objectarray[it->slot]=tagptr;
2000     } else {
2001       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
2002       objectarray[it->slot]=
2003         ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
2004     }
2005   } else if (it->numtags>0) {
2006     /* Use tags to locate appropriate objects */
2007     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
2008     struct ___Object___ *objptr=tag->flagptr;
2009     if (objptr->type!=OBJECTARRAYTYPE) {
2010       it->tagobjindex++;
2011       objectarray[it->slot]=objptr;
2012     } else {
2013       struct ArrayObject *ao=(struct ArrayObject *) objptr;
2014       objectarray[it->slot]=
2015         ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
2016     }
2017   } else {
2018     /* Iterate object */
2019     objectarray[it->slot]=(void *)Objkey(&it->it);
2020     Objnext(&it->it);
2021   }
2022 }
2023
2024 #ifdef PROFILE
2025 inline void profileTaskStart(char * taskname) {
2026   if(!taskInfoOverflow) {
2027     TaskInfo* taskInfo = RUNMALLOC(sizeof(struct task_info));
2028     taskInfoArray[taskInfoIndex] = taskInfo;
2029     taskInfo->taskName = taskname;
2030     taskInfo->startTime = BAMBOO_GET_EXE_TIME();
2031     taskInfo->endTime = -1;
2032     taskInfo->exitIndex = -1;
2033     taskInfo->newObjs = NULL;
2034   }
2035 }
2036
2037 inline void profileTaskEnd() {
2038   if(!taskInfoOverflow) {
2039     taskInfoArray[taskInfoIndex]->endTime = BAMBOO_GET_EXE_TIME();
2040     taskInfoIndex++;
2041     if(taskInfoIndex == TASKINFOLENGTH) {
2042       taskInfoOverflow = true;
2043     }
2044   }
2045 }
2046
2047 // output the profiling data
2048 void outputProfileData() {
2049 #ifdef USEIO
2050   int i;
2051   unsigned long long totaltasktime = 0;
2052   unsigned long long preprocessingtime = 0;
2053   unsigned long long objqueuecheckingtime = 0;
2054   unsigned long long postprocessingtime = 0;
2055   unsigned long long other = 0;
2056   unsigned long long averagetasktime = 0;
2057   int tasknum = 0;
2058
2059   printf("Task Name, Start Time, End Time, Duration, Exit Index(, NewObj Name, Num)+\n");
2060   // output task related info
2061   for(i = 0; i < taskInfoIndex; i++) {
2062     TaskInfo* tmpTInfo = taskInfoArray[i];
2063     unsigned long long duration = tmpTInfo->endTime - tmpTInfo->startTime;
2064     printf("%s, %lld, %lld, %lld, %lld",
2065            tmpTInfo->taskName, tmpTInfo->startTime, tmpTInfo->endTime,
2066            duration, tmpTInfo->exitIndex);
2067     // summarize new obj info
2068     if(tmpTInfo->newObjs != NULL) {
2069       struct RuntimeHash * nobjtbl = allocateRuntimeHash(5);
2070       struct RuntimeIterator * iter = NULL;
2071       while(0 == isEmpty(tmpTInfo->newObjs)) {
2072                 char * objtype = (char *)(getItem(tmpTInfo->newObjs));
2073                 if(RuntimeHashcontainskey(nobjtbl, (int)(objtype))) {
2074                   int num = 0;
2075                   RuntimeHashget(nobjtbl, (int)objtype, &num);
2076                   RuntimeHashremovekey(nobjtbl, (int)objtype);
2077                   num++;
2078                   RuntimeHashadd(nobjtbl, (int)objtype, num);
2079                 } else {
2080                   RuntimeHashadd(nobjtbl, (int)objtype, 1);
2081                 }
2082                 //printf(stderr, "new obj!\n");
2083       }
2084
2085       // output all new obj info
2086       iter = RuntimeHashcreateiterator(nobjtbl);
2087       while(RunhasNext(iter)) {
2088                 char * objtype = (char *)Runkey(iter);
2089                 int num = Runnext(iter);
2090                 printf(", %s, %d", objtype, num);
2091       }
2092     }
2093     printf("\n");
2094     if(strcmp(tmpTInfo->taskName, "tpd checking") == 0) {
2095       preprocessingtime += duration;
2096     } else if(strcmp(tmpTInfo->taskName, "post task execution") == 0) {
2097       postprocessingtime += duration;
2098     } else if(strcmp(tmpTInfo->taskName, "objqueue checking") == 0) {
2099       objqueuecheckingtime += duration;
2100     } else {
2101       totaltasktime += duration;
2102       averagetasktime += duration;
2103       tasknum++;
2104     }
2105   }
2106
2107   if(taskInfoOverflow) {
2108     printf("Caution: task info overflow!\n");
2109   }
2110
2111   other = totalexetime-totaltasktime-preprocessingtime-postprocessingtime;
2112   averagetasktime /= tasknum;
2113
2114   printf("\nTotal time: %lld\n", totalexetime);
2115   printf("Total task execution time: %lld (%d%%)\n", totaltasktime,
2116          (int)(((double)totaltasktime/(double)totalexetime)*100));
2117   printf("Total objqueue checking time: %lld (%d%%)\n",
2118          objqueuecheckingtime,
2119          (int)(((double)objqueuecheckingtime/(double)totalexetime)*100));
2120   printf("Total pre-processing time: %lld (%d%%)\n", preprocessingtime,
2121          (int)(((double)preprocessingtime/(double)totalexetime)*100));
2122   printf("Total post-processing time: %lld (%d%%)\n", postprocessingtime,
2123          (int)(((double)postprocessingtime/(double)totalexetime)*100));
2124   printf("Other time: %lld (%d%%)\n", other,
2125          (int)(((double)other/(double)totalexetime)*100));
2126
2127
2128   printf("\nAverage task execution time: %lld\n", averagetasktime);
2129
2130 #else
2131   int i = 0;
2132   int j = 0;
2133
2134   BAMBOO_PRINT(0xdddd);
2135   // output task related info
2136   for(i= 0; i < taskInfoIndex; i++) {
2137     TaskInfo* tmpTInfo = taskInfoArray[i];
2138     char* tmpName = tmpTInfo->taskName;
2139     int nameLen = strlen(tmpName);
2140     BAMBOO_PRINT(0xddda);
2141     for(j = 0; j < nameLen; j++) {
2142       BAMBOO_PRINT_REG(tmpName[j]);
2143     }
2144     BAMBOO_PRINT(0xdddb);
2145     BAMBOO_PRINT_REG(tmpTInfo->startTime);
2146     BAMBOO_PRINT_REG(tmpTInfo->endTime);
2147     BAMBOO_PRINT_REG(tmpTInfo->exitIndex);
2148     if(tmpTInfo->newObjs != NULL) {
2149       struct RuntimeHash * nobjtbl = allocateRuntimeHash(5);
2150       struct RuntimeIterator * iter = NULL;
2151       while(0 == isEmpty(tmpTInfo->newObjs)) {
2152                 char * objtype = (char *)(getItem(tmpTInfo->newObjs));
2153                 if(RuntimeHashcontainskey(nobjtbl, (int)(objtype))) {
2154                   int num = 0;
2155                   RuntimeHashget(nobjtbl, (int)objtype, &num);
2156                   RuntimeHashremovekey(nobjtbl, (int)objtype);
2157                   num++;
2158                   RuntimeHashadd(nobjtbl, (int)objtype, num);
2159                 } else {
2160                   RuntimeHashadd(nobjtbl, (int)objtype, 1);
2161                 }
2162       }
2163
2164       // ouput all new obj info
2165       iter = RuntimeHashcreateiterator(nobjtbl);
2166       while(RunhasNext(iter)) {
2167                 char * objtype = (char *)Runkey(iter);
2168                 int num = Runnext(iter);
2169                 int nameLen = strlen(objtype);
2170                 BAMBOO_PRINT(0xddda);
2171                 for(j = 0; j < nameLen; j++) {
2172                   BAMBOO_PRINT_REG(objtype[j]);
2173                 }
2174                 BAMBOO_PRINT(0xdddb);
2175                 BAMBOO_PRINT_REG(num);
2176           }
2177         }
2178         BAMBOO_PRINT(0xdddc);
2179   }
2180
2181   if(taskInfoOverflow) {
2182         BAMBOO_PRINT(0xefee);
2183   }
2184
2185 #ifdef PROFILE_INTERRUPT
2186   // output interrupt related info
2187   for(i = 0; i < interruptInfoIndex; i++) {
2188         InterruptInfo* tmpIInfo = interruptInfoArray[i];
2189         BAMBOO_PRINT(0xddde);
2190         BAMBOO_PRINT_REG(tmpIInfo->startTime);
2191         BAMBOO_PRINT_REG(tmpIInfo->endTime);
2192         BAMBOO_PRINT(0xdddf);
2193   }
2194
2195   if(interruptInfoOverflow) {
2196         BAMBOO_PRINT(0xefef);
2197   }
2198 #endif // PROFILE_INTERRUPT
2199
2200   BAMBOO_PRINT(0xeeee);
2201 #endif
2202 }
2203 #endif  // #ifdef PROFILE
2204
2205 #endif