switch to spaces only..
[IRC.git] / Robust / src / Runtime / task.c
1 #ifdef TASK
2 #include "runtime.h"
3 #include "structdefs.h"
4 #include "mem.h"
5 #include "checkpoint.h"
6 #include "Queue.h"
7 #include "SimpleHash.h"
8 #include "GenericHashtable.h"
9 #include <sys/select.h>
10 #include <sys/types.h>
11 #include <sys/mman.h>
12 #include <string.h>
13 #include <signal.h>
14
15 extern int injectfailures;
16 extern float failurechance;
17 extern int debugtask;
18 extern int instaccum;
19 extern int errors;
20
21 #ifdef CONSCHECK
22 #include "instrument.h"
23 #endif
24
25 #ifdef FASTCHECK
26 struct ___Object___ * ___fcrevert___;
27 #include "localobjects.h"
28 #endif
29
30 struct genhashtable * activetasks;
31 struct parameterwrapper * objectqueues[NUMCLASSES];
32 struct genhashtable * failedtasks;
33 struct taskparamdescriptor * currtpd;
34 struct ctable * forward;
35 struct ctable * reverse;
36
37 int main(int argc, char **argv) {
38 #ifdef BOEHM_GC
39   GC_init(); // Initialize the garbage collector
40 #endif
41 #ifdef CONSCHECK
42   initializemmap();
43 #endif
44   processOptions();
45   initializeexithandler();
46   /* Create table for failed tasks */
47   failedtasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd,
48                                    (int (*)(void *,void *)) &comparetpd);
49   /* Create queue of active tasks */
50   activetasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd,
51                                    (int (*)(void *,void *)) &comparetpd);
52
53   /* Process task information */
54   processtasks();
55
56   /* Create startup object */
57   createstartupobject(argc, argv);
58
59   /* Start executing the tasks */
60   executetasks();
61 }
62
63 void createstartupobject(int argc, char ** argv) {
64   int i;
65
66   /* Allocate startup object     */
67 #ifdef PRECISE_GC
68   struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(NULL, STARTUPTYPE);
69   struct ArrayObject * stringarray=allocate_newarray(NULL, STRINGARRAYTYPE, argc-1);
70 #else
71   struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
72   struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1);
73 #endif
74   /* Build array of strings */
75   startupobject->___parameters___=stringarray;
76   for(i=1; i<argc; i++) {
77     int length=strlen(argv[i]);
78 #ifdef PRECISE_GC
79     struct ___String___ *newstring=NewString(NULL, argv[i],length);
80 #else
81     struct ___String___ *newstring=NewString(argv[i],length);
82 #endif
83     ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=newstring;
84   }
85
86   /* Set initialized flag for startup object */
87   flagorand(startupobject,1,0xFFFFFFFF);
88   enqueueObject(startupobject);
89 }
90
91 int hashCodetpd(struct taskparamdescriptor *ftd) {
92   int hash=(int)ftd->task;
93   int i;
94   for(i=0; i<ftd->numParameters; i++) {
95     hash^=(int)ftd->parameterArray[i];
96   }
97   return hash;
98 }
99
100 int comparetpd(struct taskparamdescriptor *ftd1, struct taskparamdescriptor *ftd2) {
101   int i;
102   if (ftd1->task!=ftd2->task)
103     return 0;
104   for(i=0; i<ftd1->numParameters; i++)
105     if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
106       return 0;
107 #ifdef OPTIONAL
108   for(i=0; i<ftd1->numParameters; i++) {
109     if(ftd1->failed[i]!=ftd2->failed[i])
110       return 0;
111   }
112 #endif
113   return 1;
114 }
115
116 /* This function sets a tag. */
117 #ifdef PRECISE_GC
118 void tagset(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
119 #else
120 void tagset(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
121 #endif
122   struct ___Object___ * tagptr=obj->___tags___;
123   if (tagptr==NULL) {
124     obj->___tags___=(struct ___Object___ *)tagd;
125   } else {
126     /* Have to check if it is already set */
127     if (tagptr->type==TAGTYPE) {
128       struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
129       if (td==tagd)
130         return;
131 #ifdef PRECISE_GC
132       int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
133       struct ArrayObject * ao=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
134       obj=(struct ___Object___ *)ptrarray[2];
135       tagd=(struct ___TagDescriptor___ *)ptrarray[3];
136       td=(struct ___TagDescriptor___ *) obj->___tags___;
137 #else
138       struct ArrayObject * ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
139 #endif
140       ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
141       ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
142       obj->___tags___=(struct ___Object___ *) ao;
143       ao->___cachedCode___=2;
144     } else {
145       /* Array Case */
146       int i;
147       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
148       for(i=0; i<ao->___cachedCode___; i++) {
149         struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___*, i);
150         if (td==tagd)
151           return;
152       }
153       if (ao->___cachedCode___<ao->___length___) {
154         ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
155         ao->___cachedCode___++;
156       } else {
157 #ifdef PRECISE_GC
158         int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
159         struct ArrayObject * aonew=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
160         obj=(struct ___Object___ *)ptrarray[2];
161         tagd=(struct ___TagDescriptor___ *) ptrarray[3];
162         ao=(struct ArrayObject *)obj->___tags___;
163 #else
164         struct ArrayObject * aonew=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
165 #endif
166         aonew->___cachedCode___=ao->___length___+1;
167         for(i=0; i<ao->___length___; i++) {
168           ARRAYSET(aonew, struct ___TagDescriptor___*, i, ARRAYGET(ao, struct ___TagDescriptor___*, i));
169         }
170         ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
171       }
172     }
173   }
174
175   {
176     struct ___Object___ * tagset=tagd->flagptr;
177     if(tagset==NULL) {
178       tagd->flagptr=obj;
179     } else if (tagset->type!=OBJECTARRAYTYPE) {
180 #ifdef PRECISE_GC
181       int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
182       struct ArrayObject * ao=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
183       obj=(struct ___Object___ *)ptrarray[2];
184       tagd=(struct ___TagDescriptor___ *)ptrarray[3];
185 #else
186       struct ArrayObject * ao=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
187 #endif
188       ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
189       ARRAYSET(ao, struct ___Object___ *, 1, obj);
190       ao->___cachedCode___=2;
191       tagd->flagptr=(struct ___Object___ *)ao;
192     } else {
193       struct ArrayObject *ao=(struct ArrayObject *) tagset;
194       if (ao->___cachedCode___<ao->___length___) {
195         ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
196       } else {
197         int i;
198 #ifdef PRECISE_GC
199         int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
200         struct ArrayObject * aonew=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL+ao->___length___);
201         obj=(struct ___Object___ *)ptrarray[2];
202         tagd=(struct ___TagDescriptor___ *)ptrarray[3];
203         ao=(struct ArrayObject *)tagd->flagptr;
204 #else
205         struct ArrayObject * aonew=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
206 #endif
207         aonew->___cachedCode___=ao->___cachedCode___+1;
208         for(i=0; i<ao->___length___; i++) {
209           ARRAYSET(aonew, struct ___Object___*, i, ARRAYGET(ao, struct ___Object___*, i));
210         }
211         ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
212         tagd->flagptr=(struct ___Object___ *) aonew;
213       }
214     }
215   }
216 }
217
218 /* This function clears a tag. */
219 #ifdef PRECISE_GC
220 void tagclear(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
221 #else
222 void tagclear(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
223 #endif
224   /* We'll assume that tag is alway there.
225      Need to statically check for this of course. */
226   struct ___Object___ * tagptr=obj->___tags___;
227
228   if (tagptr->type==TAGTYPE) {
229     if ((struct ___TagDescriptor___ *)tagptr==tagd)
230       obj->___tags___=NULL;
231     else
232       printf("ERROR 1 in tagclear\n");
233   } else {
234     struct ArrayObject *ao=(struct ArrayObject *) tagptr;
235     int i;
236     for(i=0; i<ao->___cachedCode___; i++) {
237       struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___ *, i);
238       if (td==tagd) {
239         ao->___cachedCode___--;
240         if (i<ao->___cachedCode___)
241           ARRAYSET(ao, struct ___TagDescriptor___ *, i, ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
242         ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
243         if (ao->___cachedCode___==0)
244           obj->___tags___=NULL;
245         goto PROCESSCLEAR;
246       }
247     }
248     printf("ERROR 2 in tagclear\n");
249   }
250 PROCESSCLEAR:
251   {
252     struct ___Object___ *tagset=tagd->flagptr;
253     if (tagset->type!=OBJECTARRAYTYPE) {
254       if (tagset==obj)
255         tagd->flagptr=NULL;
256       else
257         printf("ERROR 3 in tagclear\n");
258     } else {
259       struct ArrayObject *ao=(struct ArrayObject *) tagset;
260       int i;
261       for(i=0; i<ao->___cachedCode___; i++) {
262         struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
263         if (tobj==obj) {
264           ao->___cachedCode___--;
265           if (i<ao->___cachedCode___)
266             ARRAYSET(ao, struct ___Object___ *, i, ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
267           ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
268           if (ao->___cachedCode___==0)
269             tagd->flagptr=NULL;
270           goto ENDCLEAR;
271         }
272       }
273       printf("ERROR 4 in tagclear\n");
274     }
275   }
276 ENDCLEAR:
277   return;
278 }
279
280 /* This function allocates a new tag. */
281 #ifdef PRECISE_GC
282 struct ___TagDescriptor___ * allocate_tag(void *ptr, int index) {
283   struct ___TagDescriptor___ * v=(struct ___TagDescriptor___ *) mygcmalloc((struct garbagelist *) ptr, classsize[TAGTYPE]);
284 #else
285 struct ___TagDescriptor___ * allocate_tag(int index) {
286   struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
287 #endif
288   v->type=TAGTYPE;
289   v->flag=index;
290   return v;
291 }
292
293
294
295 /* This function updates the flag for object ptr.  It or's the flag
296    with the or mask and and's it with the andmask. */
297
298 void flagbody(struct ___Object___ *ptr, int flag);
299 #ifdef OPTIONAL
300 void enqueueoptional(struct ___Object___ * currobj, int numfailedfses, int * failedfses, struct taskdescriptor * task, int index);
301 #endif
302
303 int flagcomp(const int *val1, const int *val2) {
304   return (*val1)-(*val2);
305 }
306
307 void flagorand(void * ptr, int ormask, int andmask) {
308 #ifdef OPTIONAL
309   struct ___Object___ * obj = (struct ___Object___ *)ptr;
310   if(obj->numfses) { /*store the information about fses*/
311     int flag, i, j,counter, offset=0;
312     for(i=0; i<obj->numfses; i++) {
313       int oldoffset;
314       counter=obj->fses[offset++];
315       oldoffset=offset;
316       for(j=0; j<counter; j++) {
317         flag=obj->fses[offset];
318         obj->fses[offset++]=(flag|ormask)&andmask;
319       }
320       qsort(&obj->fses[oldoffset], sizeof(int), counter, (int (*)(const void *, const void *)) &flagcomp);
321     }
322     enqueueoptional(obj, 0, NULL, NULL, 0);
323   } else
324 #endif
325   {
326     int oldflag=((int *)ptr)[1];
327     int flag=ormask|oldflag;
328     flag&=andmask;
329     flagbody(ptr, flag);
330   }
331 }
332
333 bool intflagorand(void * ptr, int ormask, int andmask) {
334 #ifdef OPTIONAL
335   struct ___Object___ * obj = (struct ___Object___ *)ptr;
336   if(obj->numfses) { /*store the information about fses*/
337     int flag, i, j,counter, offset=0;
338     for(i=0; i<obj->numfses; i++) {
339       int oldoffset;
340       counter=obj->fses[offset++];
341       oldoffset=offset;
342       for(j=0; j<counter; j++) {
343         flag=obj->fses[offset];
344         obj->fses[offset++]=(flag|ormask)&andmask;
345       }
346       qsort(&obj->fses[oldoffset], sizeof(int), counter, (int (*)(const void *, const void *)) &flagcomp);
347     }
348     enqueueoptional(obj, 0, NULL, NULL, 0);
349   } else
350 #endif
351   {
352     int oldflag=((int *)ptr)[1];
353     int flag=ormask|oldflag;
354     flag&=andmask;
355     if (flag==oldflag)   /* Don't do anything */
356       return false;
357     else {
358       flagbody(ptr, flag);
359       return true;
360     }
361   }
362 }
363
364 void flagorandinit(void * ptr, int ormask, int andmask) {
365   int oldflag=((int *)ptr)[1];
366   int flag=ormask|oldflag;
367   flag&=andmask;
368   flagbody(ptr,flag);
369 }
370
371 void flagbody(struct ___Object___ *ptr, int flag) {
372   struct parameterwrapper *flagptr=(struct parameterwrapper *)ptr->flagptr;
373   ptr->flag=flag;
374
375   /*Remove object from all queues */
376   while(flagptr!=NULL) {
377     struct parameterwrapper *next;
378     int UNUSED, UNUSED2;
379     int * enterflags;
380     ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
381     ObjectHashremove(flagptr->objectset, (int)ptr);
382     if (enterflags!=NULL)
383       free(enterflags);
384     flagptr=next;
385   }
386 }
387
388 void enqueueObject(void *vptr) {
389   struct ___Object___ *ptr = (struct ___Object___ *)vptr;
390
391   {
392     struct QueueItem *tmpptr;
393     struct parameterwrapper * parameter=objectqueues[ptr->type];
394     int i;
395     struct parameterwrapper * prevptr=NULL;
396     struct ___Object___ *tagptr=ptr->___tags___;
397
398     /* Outer loop iterates through all parameter queues an object of
399        this type could be in.  */
400
401     while(parameter!=NULL) {
402       /* Check tags */
403       if (parameter->numbertags>0) {
404         if (tagptr==NULL)
405           goto nextloop;  //that means the object has no tag but that param needs tag
406         else if(tagptr->type==TAGTYPE) { //one tag
407           struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
408           for(i=0; i<parameter->numbertags; i++) {
409             //slotid is parameter->tagarray[2*i];
410             int tagid=parameter->tagarray[2*i+1];
411             if (tagid!=tagptr->flag)
412               goto nextloop;  /*We don't have this tag */
413           }
414         } else { //multiple tags
415           struct ArrayObject * ao=(struct ArrayObject *) tagptr;
416           for(i=0; i<parameter->numbertags; i++) {
417             //slotid is parameter->tagarray[2*i];
418             int tagid=parameter->tagarray[2*i+1];
419             int j;
420             for(j=0; j<ao->___cachedCode___; j++) {
421               if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
422                 goto foundtag;
423             }
424             goto nextloop;
425 foundtag:
426             ;
427           }
428         }
429       }
430
431       /* Check flags */
432       for(i=0; i<parameter->numberofterms; i++) {
433         int andmask=parameter->intarray[i*2];
434         int checkmask=parameter->intarray[i*2+1];
435         if ((ptr->flag&andmask)==checkmask) {
436           enqueuetasks(parameter, prevptr, ptr, NULL, 0);
437           prevptr=parameter;
438           break;
439         }
440       }
441 nextloop:
442       parameter=parameter->next;
443     }
444     ptr->flagptr=prevptr;
445   }
446 }
447
448 #ifdef OPTIONAL
449
450 int checktags(struct ___Object___ * currobj, struct fsanalysiswrapper * fswrapper) {
451   /* Check Tags */
452   struct ___Object___ * tagptr = currobj->___tags___;
453   if(fswrapper->numtags>0) {
454     if (tagptr==NULL)
455       return 0;  //that means the object has no tag but that param
456     //needs tag
457     else if(tagptr->type==TAGTYPE) { //one tag
458       if(fswrapper->numtags!=1)
459         return 0;  //we don't have the right number of tags
460       struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
461       if (fswrapper->tags[0]!=tagptr->flag)
462         return 0;
463     } else {  //multiple tags
464       struct ArrayObject * ao=(struct ArrayObject *) tagptr;
465       int tag_counter=0;
466       int foundtag=0;
467
468       if(ao->___length___!=fswrapper->numtags)
469         return 0;  //we don't have the right number of tags
470       for(tag_counter=0; tag_counter<fswrapper->numtags; tag_counter++) {
471         int tagid=fswrapper->tags[tag_counter];
472         int j;
473         for(j=0; j<ao->___cachedCode___; j++) {
474           if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, tag_counter)->flag)
475             return 1;
476         }
477         return 0;
478       }
479     }
480   }
481   return 1;
482 }
483
484 int getlength(int *flist, int len) {
485   int count=0;
486   int i;
487   for(i=0; i<len; i++) {
488     int size=flist[count];
489     count+=1+size;
490   }
491   return count;
492 }
493
494 int * domergeor(int *flist1, int len1, int *flist2, int len2) {
495   int size1=getlength(flist1, len1);
496   int size2=getlength(flist2, len2);
497   int *merge=RUNMALLOC((size1+size2)*sizeof(int));
498   memcpy(merge, flist1, size1*sizeof(int));
499   memcpy(&merge[size1], flist2, size2*sizeof(int));
500   return merge;
501 }
502
503 int domerge(int * flist1, int len1, int *flist2, int len2, int *merge) {
504   int count=0;
505   int i=0;
506   int j=0;
507   while(i<len1||j<len2) {
508     if (i<len1&&(j==len2||flist1[i]<flist2[j])) {
509       if(merge!=NULL) {
510         merge[count]=flist1[i];
511       }
512       i++;
513       count++;
514     } else if (j<len2&&(i==len1||flist2[j]<flist1[i])) {
515       if(merge!=NULL) {
516         merge[count]=flist2[j];
517       }
518       j++;
519       count++;
520     } else if (i<len1&&j<len2&&flist1[i]==flist2[j]) {
521       if(merge!=NULL) {
522         merge[count]=flist1[i];
523       }
524       i++;
525       j++;
526       count++;
527     }
528   }
529   return count;
530 }
531
532 /* Merge flags from ftlmerge into ftl. */
533 void mergeitems(struct failedtasklist *ftl, struct failedtasklist *ftlmerge) {
534   int length=0;
535   int i,j;
536   int *mergedlist;
537   int offset=0;
538   for(i=0; i<ftl->numflags; i++) {
539     int len=ftl->flags[offset++];
540     int offsetmerge=0;
541     for(j=0; j<ftlmerge->numflags; j++) {
542       int lenmerge=ftlmerge->flags[offsetmerge++];
543       length+=1+domerge(&ftl->flags[offset],len,&ftlmerge->flags[offsetmerge],lenmerge, NULL);
544       offsetmerge+=lenmerge;
545     }
546     offset+=len;
547   }
548   mergedlist=RUNMALLOC(sizeof(int)*length);
549
550   offset=0;
551   length=0;
552   for(i=0; i<ftl->numflags; i++) {
553     int len=ftl->flags[offset++];
554     int offsetmerge=0;
555     for(j=0; j<ftlmerge->numflags; j++) {
556       int lenmerge=ftlmerge->flags[offsetmerge++];
557       int size=domerge(&ftl->flags[offset],len,&ftlmerge->flags[offsetmerge],lenmerge,&mergedlist[length+1]);
558       mergedlist[length]=size;
559       length+=size+1;
560     }
561   }
562   RUNFREE(ftl->flags);
563   ftl->flags=mergedlist;
564   ftl->numflags*=ftlmerge->numflags;
565 }
566
567 void mergefailedlists(struct failedtasklist **andlist, struct failedtasklist *list) {
568   struct failedtasklist *tmpptr;
569   while((*andlist)!=NULL) {
570     struct failedtasklist *searchftl=list;
571     while(searchftl!=NULL) {
572       if ((*andlist)->task==searchftl->task&&
573           (*andlist)->index==searchftl->index) {
574         mergeitems(*andlist, searchftl);
575         break;
576       }
577       searchftl=searchftl->next;
578     }
579     if (searchftl==NULL) {
580       //didn't find andlist
581       tmpptr=*andlist;
582       *andlist=(*andlist)->next; //splice item out of list
583       RUNFREE(tmpptr->flags); //free the item
584       RUNFREE(tmpptr);
585     } else {
586       andlist=&((*andlist)->next); //iterate to next item
587     }
588   }
589   //free the list we're searching
590   while(list!=NULL) {
591     tmpptr=list->next;
592     RUNFREE(list->flags);
593     RUNFREE(list);
594     list=tmpptr;
595   }
596 }
597
598 struct failedtasklist * processfailstate(struct classanalysiswrapper * classwrapper, struct taskdescriptor *task, int index, struct ___Object___ * currobj, int flagstate) {
599   struct failedtasklist *list=NULL;
600   int i,h;
601   struct fsanalysiswrapper *fswrapper=NULL;
602   for(h=0; h<classwrapper->numfsanalysiswrappers; h++) {
603     struct fsanalysiswrapper * tmp=classwrapper->fsanalysiswrapperarray[h];
604     if (tmp->flags==flagstate&&checktags(currobj, tmp)) {
605       //we only match exactly here
606       fswrapper=tmp;
607       break;
608     }
609   }
610   if (fswrapper==NULL)
611     return list;
612   for(i=0; i<fswrapper->numtaskfailures; i++) {
613     int j;
614     struct taskfailure * taskfail=fswrapper->taskfailurearray[i];
615     if (taskfail->task==task&&taskfail->index==index) {
616       int start=0;
617       while(start<taskfail->numoptionaltaskdescriptors) {
618         struct taskdescriptor *currtask=NULL;
619         struct failedtasklist *tmpftl;
620         int currindex;
621         int totallength=0;
622         int *enterflags;
623         int numenterflags, offset;
624         struct parameterwrapper *pw;
625         for(j=start; j<taskfail->numoptionaltaskdescriptors; j++) {
626           struct optionaltaskdescriptor *otd=taskfail->optionaltaskdescriptorarray[j];
627           if(currtask==NULL) {
628             currtask=otd->task;
629             currindex=otd->index;
630           } else if (currtask!=otd->task||currindex!=otd->index)
631             break;
632           totallength+=otd->numenterflags;
633         }
634         pw=currtask->descriptorarray[currindex]->queue;
635         enterflags=RUNMALLOC(totallength*sizeof(int));
636         numenterflags=j-start;
637         offset=0;
638         for(start; start<j; start++) {
639           struct optionaltaskdescriptor *otd=taskfail->optionaltaskdescriptorarray[start];
640           enterflags[offset++]=otd->numenterflags;
641           memcpy(&enterflags[offset], otd->enterflags, otd->numenterflags*sizeof(int));
642           offset+=otd->numenterflags;
643         }
644         tmpftl=RUNMALLOC(sizeof(struct failedtasklist));
645         tmpftl->next=list;
646         tmpftl->task=currtask;
647         tmpftl->numflags=numenterflags;
648         tmpftl->flags=enterflags;
649         list=tmpftl;
650       }
651     }
652   }
653   return list;
654 }
655
656 struct failedtasklist * processnormfailstate(struct classanalysiswrapper * classwrapper, struct ___Object___ * currobj, int flagstate) {
657   struct failedtasklist *list=NULL;
658   int i,h;
659   int start=0;
660   struct fsanalysiswrapper *fswrapper=NULL;
661   for(h=0; h<classwrapper->numfsanalysiswrappers; h++) {
662     struct fsanalysiswrapper * tmp=classwrapper->fsanalysiswrapperarray[h];
663     if (tmp->flags==flagstate&&checktags(currobj, tmp)) {
664       //we only match exactly here
665       fswrapper=tmp;
666       break;
667     }
668   }
669   if(fswrapper==NULL)
670     return NULL;
671
672   while(start<fswrapper->numoptionaltaskdescriptors) {
673     struct taskdescriptor *currtask=NULL;
674     struct failedtasklist *tmpftl;
675     int j;
676     int currindex;
677     int totallength=0;
678     int *enterflags;
679     int numenterflags, offset;
680     struct parameterwrapper *pw;
681     for(j=start; j<fswrapper->numoptionaltaskdescriptors; j++) {
682       struct optionaltaskdescriptor *otd=fswrapper->optionaltaskdescriptorarray[j];
683       if(currtask==NULL) {
684         currtask=otd->task;
685         currindex=otd->index;
686       } else if (currtask!=otd->task||currindex!=otd->index)
687         break;
688       totallength+=otd->numenterflags;
689     }
690     pw=currtask->descriptorarray[currindex]->queue;
691     enterflags=RUNMALLOC(totallength*sizeof(int));
692     numenterflags=j-start;
693     offset=0;
694     for(start; start<j; start++) {
695       struct optionaltaskdescriptor *otd=fswrapper->optionaltaskdescriptorarray[start];
696       enterflags[offset++]=otd->numenterflags;
697       memcpy(&enterflags[offset], otd->enterflags, otd->numenterflags*sizeof(int));
698       offset+=otd->numenterflags;
699     }
700     tmpftl=RUNMALLOC(sizeof(struct failedtasklist));
701     tmpftl->next=list;
702     tmpftl->task=currtask;
703     tmpftl->numflags=numenterflags;
704     tmpftl->flags=enterflags;
705     list=tmpftl;
706   }
707   return list;
708 }
709
710
711
712 void enqueuelist(struct ___Object___ * currobj, struct failedtasklist * andlist) {
713   while(andlist!=NULL) {
714     struct failedtasklist *tmp=andlist;
715     struct parameterwrapper *pw=andlist->task->descriptorarray[andlist->index]->queue;
716     struct parmaeterwrapper *next;
717     int * flags;
718     int numflags;
719     int isnonfailed;
720
721     if (enqueuetasks(pw, currobj->flagptr, currobj, tmp->flags, tmp->numflags))
722       currobj->flagptr=pw;
723
724     andlist=andlist->next;
725     RUNFREE(tmp);
726   }
727 }
728
729 void enqueueoptional(struct ___Object___ * currobj, int numfailedfses, int * failedfses, struct taskdescriptor * task, int index) {
730   struct classanalysiswrapper * classwrapper=NULL;
731
732   /*test what optionaltaskdescriptors are available, find the class
733      corresponding*/
734   if (classanalysiswrapperarray[currobj->type]!=NULL) {
735     classwrapper = classanalysiswrapperarray[currobj->type];
736   } else
737     return;
738
739   if(task!=NULL) {
740     /* We have a failure */
741     if (failedfses==NULL) {
742       /* Failed in normal state */
743       /*first time the method is invoked*/
744       int i,h;
745       struct fsanalysiswrapper *fswrapper=NULL;
746
747       for(h=0; h<classwrapper->numfsanalysiswrappers; h++) {
748         struct fsanalysiswrapper * tmp=classwrapper->fsanalysiswrapperarray[h];
749         if (tmp->flags==currobj->flag&&checktags(currobj, tmp)) {
750           //we only match exactly here
751           fswrapper=tmp;
752           break;
753         }
754       }
755       if(fswrapper==NULL) //nothing to do in this state
756         return;
757       for(i=0; i<fswrapper->numtaskfailures; i++) {
758         int j;
759         struct taskfailure * taskfail=fswrapper->taskfailurearray[i];
760         if (taskfail->task==task&&taskfail->index==index) {
761           int start=0;
762           while(start<taskfail->numoptionaltaskdescriptors) {
763             struct taskdescriptor *currtask=NULL;
764             int currindex;
765             int totallength=0;
766             int *enterflags;
767             int numenterflags, offset;
768             struct parameterwrapper *pw;
769             for(j=start; j<taskfail->numoptionaltaskdescriptors; j++) {
770               struct optionaltaskdescriptor *otd=taskfail->optionaltaskdescriptorarray[j];
771               if(currtask==NULL) {
772                 currtask=otd->task;
773                 currindex=otd->index;
774               } else if (currtask!=otd->task||currindex!=otd->index)
775                 break;
776               totallength+=otd->numenterflags; //1 is to store the lengths
777             }
778             pw=currtask->descriptorarray[currindex]->queue;
779             numenterflags=j-start;
780             enterflags=RUNMALLOC((totallength+numenterflags)*sizeof(int));
781
782             offset=0;
783             for(start; start<j; start++) {
784               struct optionaltaskdescriptor *otd=taskfail->optionaltaskdescriptorarray[start];
785               enterflags[offset++]=otd->numenterflags;
786               memcpy(&enterflags[offset], otd->enterflags, otd->numenterflags*sizeof(int));
787               offset+=otd->numenterflags;
788             }
789             //Enqueue this one
790             if (enqueuetasks(pw, currobj->flagptr, currobj, enterflags, numenterflags))
791               currobj->flagptr=pw;
792           }
793         }
794       }
795     } else {
796       /* Failed in failed state */
797       int i;
798       int offset=0;
799       for(i=0; i<numfailedfses; i++) {
800         int numfses=failedfses[offset++];
801         int j;
802         struct failedtasklist *andlist=NULL;
803         for(j=0; j<numfses; j++) {
804           int flagstate=failedfses[offset++];
805           struct failedtasklist *currlist=processfailstate(classwrapper, task, index, currobj, flagstate);
806           if (andlist==NULL)
807             andlist=currlist;
808           else
809             mergefailedlists(&andlist, currlist);
810         }
811         enqueuelist(currobj, andlist);
812       }
813     }
814   } else {
815     /* No failure, but we are in a failed state */
816     struct parameterwrapper *flagptr=(struct parameterwrapper *)currobj->flagptr;
817
818     /*Remove object from all queues */
819     while(flagptr!=NULL) {
820       struct parameterwrapper *next;
821       int UNUSED, UNUSED2;
822       int * enterflags;
823       ObjectHashget(flagptr->objectset, (int) currobj, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
824       ObjectHashremove(flagptr->objectset, (int)currobj);
825       if (enterflags!=NULL)
826         free(enterflags);
827       flagptr=next;
828     }
829
830     /* Failed in failed state */
831     int i;
832     int offset=0;
833     for(i=0; i<currobj->numfses; i++) {
834       int numfses=currobj->fses[offset++];
835       int j;
836       struct failedtasklist *andlist=NULL;
837       for(j=0; j<numfses; j++) {
838         int flagstate=currobj->fses[offset++];
839         struct failedtasklist *currlist=processnormfailstate(classwrapper, currobj, flagstate);
840         if (andlist==NULL)
841           andlist=currlist;
842         else
843           mergefailedlists(&andlist, currlist);
844       }
845       enqueuelist(currobj, andlist);
846     }
847   }
848 }
849
850
851 #endif
852
853 int enqueuetasks(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr, int * enterflags, int numenterflags) {
854   void * taskpointerarray[MAXTASKPARAMS];
855 #ifdef OPTIONAL
856   int failed[MAXTASKPARAMS];
857 #endif
858   int j;
859   int numparams=parameter->task->numParameters;
860   int numiterators=parameter->task->numTotal-1;
861   int retval=1;
862   int addnormal=1;
863   int adderror=1;
864
865   struct taskdescriptor * task=parameter->task;
866
867 #ifdef OPTIONAL
868   if (ObjectHashcontainskey(parameter->objectset, (int) ptr)) {
869     /* The object is already here...or it with the existing item */
870     int * oldflags;
871     int oldnumflags;
872     int oldptr;
873     int oldstatus;
874     int *mergedflags;
875     ObjectHashget(parameter->objectset, (int) ptr, &oldptr, (int *) &oldflags, &oldnumflags, &oldstatus);
876     mergedflags=domergeor(oldflags, oldnumflags, enterflags, numenterflags);
877     ObjectHashupdate(parameter->objectset, (int) ptr, oldptr, mergedflags, oldnumflags+numenterflags, oldstatus||(enterflags==NULL));
878
879     RUNFREE(oldflags);
880     RUNFREE(enterflags);
881
882     //only add if truly needed
883     if (oldstatus)
884       addnormal=0;
885     if (oldnumflags>0)
886       adderror=0;
887
888     retval=0;
889   } else {
890 #endif
891   ObjectHashadd(parameter->objectset, (int) ptr, (int) prevptr, (int) enterflags, numenterflags, enterflags==NULL);  //this add the object to parameterwrapper
892 #ifdef OPTIONAL
893 }
894 #endif
895
896   /* Add enqueued object to parameter vector */
897   taskpointerarray[parameter->slot]=ptr;
898 #ifdef OPTIONAL
899   failed[parameter->slot]=(enterflags!=NULL);
900 #endif
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
924   while(1) {
925     /* Enqueue current state */
926     int launch = 0;
927     struct taskparamdescriptor *tpd=RUNMALLOC(sizeof(struct taskparamdescriptor));
928     tpd->task=task;
929     tpd->numParameters=numiterators+1;
930     tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
931 #ifdef OPTIONAL
932     tpd->failed=RUNMALLOC(sizeof(int)*(numiterators+1));
933 #endif
934     for(j=0; j<=numiterators; j++) {
935       tpd->parameterArray[j]=taskpointerarray[j]; //store the actual parameters
936 #ifdef OPTIONAL
937       tpd->failed[j]=failed[j];
938       if (failed[j]!=0&&failed[j]!=1) {
939         printf("BAD\n");
940       }
941 #endif
942     }
943     /* Enqueue task */
944     if ((!gencontains(failedtasks, tpd)&&!gencontains(activetasks,tpd))) {
945       genputtable(activetasks, tpd, tpd);
946     } else {
947       RUNFREE(tpd->parameterArray);
948 #ifdef OPTIONAL
949       RUNFREE(tpd->failed);
950 #endif
951       RUNFREE(tpd);
952     }
953
954     /* This loop iterates to the next parameter combination */
955     if (numiterators==0)
956       return retval;
957
958     for(j=numiterators-1; j<numiterators; j++) {
959 backtrackinc:
960       if(toiHasNext(&parameter->iterators[j], taskpointerarray OPTARG(failed))) {
961         toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
962       } else if (j>0) {
963         /* Need to backtrack */
964         toiReset(&parameter->iterators[j]);
965         j--;
966         goto backtrackinc;
967       } else {
968         /* Nothing more to enqueue */
969         return retval;
970       }
971     }
972   }
973   return retval;
974 }
975
976 /* Handler for signals. The signals catch null pointer errors and
977    arithmatic errors. */
978
979 void myhandler(int sig, siginfo_t *info, void *uap) {
980   sigset_t toclear;
981 #ifdef DEBUG
982   printf("sig=%d\n",sig);
983   printf("signal\n");
984 #endif
985   sigemptyset(&toclear);
986   sigaddset(&toclear, sig);
987   sigprocmask(SIG_UNBLOCK, &toclear,NULL);
988   longjmp(error_handler,1);
989 }
990
991 fd_set readfds;
992 int maxreadfd;
993 struct RuntimeHash *fdtoobject;
994
995 void addreadfd(int fd) {
996   if (fd>=maxreadfd)
997     maxreadfd=fd+1;
998   FD_SET(fd, &readfds);
999 }
1000
1001 void removereadfd(int fd) {
1002   FD_CLR(fd, &readfds);
1003   if (maxreadfd==(fd+1)) {
1004     maxreadfd--;
1005     while(maxreadfd>0&&!FD_ISSET(maxreadfd-1, &readfds))
1006       maxreadfd--;
1007   }
1008 }
1009
1010 #ifdef PRECISE_GC
1011 #define OFFSET 2
1012 #else
1013 #define OFFSET 0
1014 #endif
1015
1016 #ifdef OPTIONAL
1017 int * fsescopy(int *src, int len) {
1018   int *dst;
1019   if (src==NULL)
1020     return NULL;
1021   dst=RUNMALLOC(len*sizeof(int));
1022   memcpy(dst, src, len*sizeof(int));
1023   return dst;
1024 }
1025 #endif
1026
1027 void executetasks() {
1028   void * taskpointerarray[MAXTASKPARAMS+OFFSET];
1029 #ifdef OPTIONAL
1030   int * fsesarray[MAXTASKPARAMS];
1031   int * oldfsesarray[MAXTASKPARAMS];
1032   int numfsesarray[MAXTASKPARAMS];
1033 #endif
1034
1035   /* Set up signal handlers */
1036   struct sigaction sig;
1037   sig.sa_sigaction=&myhandler;
1038   sig.sa_flags=SA_SIGINFO;
1039   sigemptyset(&sig.sa_mask);
1040
1041   /* Catch bus errors, segmentation faults, and floating point exceptions*/
1042   if (!errors) {
1043     sigaction(SIGBUS,&sig,0);
1044     sigaction(SIGSEGV,&sig,0);
1045     sigaction(SIGFPE,&sig,0);
1046     sigaction(SIGPIPE,&sig,0);
1047   }
1048
1049   /* Zero fd set */
1050   FD_ZERO(&readfds);
1051   maxreadfd=0;
1052   fdtoobject=allocateRuntimeHash(100);
1053
1054   /* Map first block of memory to protected, anonymous page */
1055   mmap(0, 0x1000, 0, MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
1056
1057 newtask:
1058   while((hashsize(activetasks)>0)||(maxreadfd>0)) {
1059
1060     /* Check if any filedescriptors have IO pending */
1061     if (maxreadfd>0) {
1062       int i;
1063       struct timeval timeout={0,0};
1064       fd_set tmpreadfds;
1065       int numselect;
1066       tmpreadfds=readfds;
1067       numselect=select(maxreadfd, &tmpreadfds, NULL, NULL, &timeout);
1068       if (numselect>0) {
1069         /* Process ready fd's */
1070         int fd;
1071         for(fd=0; fd<maxreadfd; fd++) {
1072           if (FD_ISSET(fd, &tmpreadfds)) {
1073             /* Set ready flag on object */
1074             void * objptr;
1075             //      printf("Setting fd %d\n",fd);
1076             if (RuntimeHashget(fdtoobject, fd,(int *) &objptr)) {
1077               if(intflagorand(objptr,1,0xFFFFFFFF)) { /* Set the first flag to 1 */
1078                 enqueueObject(objptr);
1079               }
1080             }
1081           }
1082         }
1083       }
1084     }
1085
1086     /* See if there are any active tasks */
1087     if (hashsize(activetasks)>0) {
1088       int i;
1089       currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
1090       genfreekey(activetasks, currtpd);
1091
1092       /* Check if this task has failed, allow a task that contains optional objects to fire */
1093       if (gencontains(failedtasks, currtpd)) {
1094         // Free up task parameter descriptor
1095         RUNFREE(currtpd->parameterArray);
1096 #ifdef OPTIONAL
1097         RUNFREE(currtpd->failed);
1098 #endif
1099         RUNFREE(currtpd);
1100         goto newtask;
1101       }
1102       int numparams=currtpd->task->numParameters;
1103       int numtotal=currtpd->task->numTotal;
1104
1105       /* Make sure that the parameters are still in the queues */
1106       for(i=0; i<numparams; i++) {
1107         void * parameter=currtpd->parameterArray[i];
1108         struct parameterdescriptor * pd=currtpd->task->descriptorarray[i];
1109         struct parameterwrapper *pw=(struct parameterwrapper *) pd->queue;
1110         int j;
1111         /* Check that object is still in queue */
1112 #ifdef OPTIONAL
1113         {
1114           int UNUSED, UNUSED2;
1115           int *flags;
1116           int numflags, isnonfailed;
1117           int failed=currtpd->failed[i];
1118           if (!ObjectHashget(pw->objectset, (int) parameter, &UNUSED, (int *) &flags, &numflags, &isnonfailed)) {
1119             RUNFREE(currtpd->parameterArray);
1120             RUNFREE(currtpd->failed);
1121             RUNFREE(currtpd);
1122             goto newtask;
1123           } else {
1124             if (failed&&(flags!=NULL)) {
1125               //Failed parameter
1126               fsesarray[i]=flags;
1127               numfsesarray[i]=numflags;
1128             } else if (!failed && isnonfailed) {
1129               //Non-failed parameter
1130               fsesarray[i]=NULL;
1131               numfsesarray[i]=0;
1132             } else {
1133               RUNFREE(currtpd->parameterArray);
1134               RUNFREE(currtpd->failed);
1135               RUNFREE(currtpd);
1136               goto newtask;
1137             }
1138           }
1139         }
1140 #else
1141         {
1142           if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
1143             RUNFREE(currtpd->parameterArray);
1144             RUNFREE(currtpd);
1145             goto newtask;
1146           }
1147         }
1148 #endif
1149 parameterpresent:
1150         ;
1151         /* Check that object still has necessary tags */
1152         for(j=0; j<pd->numbertags; j++) {
1153           int slotid=pd->tagarray[2*j]+numparams;
1154           struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
1155           if (!containstag(parameter, tagd)) {
1156             RUNFREE(currtpd->parameterArray);
1157 #ifdef OPTIONAL
1158             RUNFREE(currtpd->failed);
1159 #endif
1160             RUNFREE(currtpd);
1161             goto newtask;
1162           }
1163         }
1164
1165         taskpointerarray[i+OFFSET]=parameter;
1166       }
1167       /* Copy the tags */
1168       for(; i<numtotal; i++) {
1169         taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
1170       }
1171
1172       {
1173         /* Checkpoint the state */
1174 #ifdef FASTCHECK
1175         ___fcrevert___=NULL;
1176 #else
1177         forward=cCreate(256, 0.4);
1178         reverse=cCreate(256, 0.4);
1179         void ** checkpoint=makecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, forward, reverse);
1180 #endif
1181         int x;
1182         if (x=setjmp(error_handler)) {
1183           int counter;
1184           /* Recover */
1185 #ifdef DEBUG
1186           printf("Fatal Error=%d, Recovering!\n",x);
1187 #endif
1188           genputtable(failedtasks,currtpd,currtpd);
1189 #ifdef FASTCHECK
1190           REVERT_OBJ(___fcrevert___);
1191 #else
1192           restorecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, checkpoint, forward, reverse);
1193 #endif
1194
1195 #ifdef OPTIONAL
1196           for(counter=0; counter<currtpd->task->numParameters; counter++) {
1197             //enqueue as failed
1198             enqueueoptional(currtpd->parameterArray[counter], numfsesarray[counter], fsesarray[counter], currtpd->task, counter);
1199
1200             //free fses copies
1201             if (fsesarray[counter]!=NULL)
1202               RUNFREE(fsesarray[counter]);
1203           }
1204 #endif
1205 #ifndef FASTCHECK
1206           cDelete(forward);
1207           cDelete(reverse);
1208           freemalloc();
1209           forward=NULL;
1210           reverse=NULL;
1211 #endif
1212
1213         } else {
1214           if (injectfailures) {
1215             if ((((double)random())/RAND_MAX)<failurechance) {
1216               printf("\nINJECTING TASK FAILURE to %s\n", currtpd->task->name);
1217               longjmp(error_handler,10);
1218             }
1219           }
1220           /* Actually call task */
1221 #ifdef PRECISE_GC
1222           ((int *)taskpointerarray)[0]=currtpd->numParameters;
1223           taskpointerarray[1]=NULL;
1224 #endif
1225 #ifdef OPTIONAL
1226           //get the task flags set
1227           for(i=0; i<numparams; i++) {
1228             oldfsesarray[i]=((struct ___Object___ *)taskpointerarray[i+OFFSET])->fses;
1229             fsesarray[i]=fsescopy(fsesarray[i], numfsesarray[i]);
1230             ((struct ___Object___ *)taskpointerarray[i+OFFSET])->fses=fsesarray[i];
1231           }
1232 #endif
1233           if(debugtask) {
1234             printf("ENTER %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
1235             ((void (*)(void **))currtpd->task->taskptr)(taskpointerarray);
1236             printf("EXIT %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
1237           } else
1238             ((void (*)(void **))currtpd->task->taskptr)(taskpointerarray);
1239
1240 #ifdef OPTIONAL
1241           for(i=0; i<numparams; i++) {
1242             //free old fses
1243             if(oldfsesarray[i]!=NULL)
1244               RUNFREE(oldfsesarray[i]);
1245           }
1246 #endif
1247
1248 #ifdef FASTCHECK
1249           while(___fcrevert___) {
1250             struct ___Object___ *tmpptr=___fcrevert___->___nextobject___;
1251             COMMIT_OBJ(___fcrevert___);
1252             ___fcrevert___=tmpptr;
1253           }
1254 #else
1255           cDelete(forward);
1256           cDelete(reverse);
1257           freemalloc();
1258 #endif
1259           // Free up task parameter descriptor
1260           RUNFREE(currtpd->parameterArray);
1261 #ifdef OPTIONAL
1262           RUNFREE(currtpd->failed);
1263 #endif
1264           RUNFREE(currtpd);
1265           forward=NULL;
1266           reverse=NULL;
1267         }
1268       }
1269     }
1270   }
1271 }
1272
1273 /* This function processes an objects tags */
1274 void processtags(struct parameterdescriptor *pd, int index, struct parameterwrapper *parameter, int * iteratorcount, int *statusarray, int numparams) {
1275   int i;
1276
1277   for(i=0; i<pd->numbertags; i++) {
1278     int slotid=pd->tagarray[2*i];
1279     int tagid=pd->tagarray[2*i+1];
1280
1281     if (statusarray[slotid+numparams]==0) {
1282       parameter->iterators[*iteratorcount].istag=1;
1283       parameter->iterators[*iteratorcount].tagid=tagid;
1284       parameter->iterators[*iteratorcount].slot=slotid+numparams;
1285       parameter->iterators[*iteratorcount].tagobjectslot=index;
1286       statusarray[slotid+numparams]=1;
1287       (*iteratorcount)++;
1288     }
1289   }
1290 }
1291
1292
1293 void processobject(struct parameterwrapper *parameter, int index, struct parameterdescriptor *pd, int *iteratorcount, int * statusarray, int numparams) {
1294   int i;
1295   int tagcount=0;
1296   struct ObjectHash * objectset=((struct parameterwrapper *)pd->queue)->objectset;
1297
1298   parameter->iterators[*iteratorcount].istag=0;
1299   parameter->iterators[*iteratorcount].slot=index;
1300   parameter->iterators[*iteratorcount].objectset=objectset;
1301   statusarray[index]=1;
1302
1303   for(i=0; i<pd->numbertags; i++) {
1304     int slotid=pd->tagarray[2*i];
1305     int tagid=pd->tagarray[2*i+1];
1306     if (statusarray[slotid+numparams]!=0) {
1307       /* This tag has already been enqueued, use it to narrow search */
1308       parameter->iterators[*iteratorcount].tagbindings[tagcount]=slotid+numparams;
1309       tagcount++;
1310     }
1311   }
1312   parameter->iterators[*iteratorcount].numtags=tagcount;
1313
1314   (*iteratorcount)++;
1315 }
1316
1317 /* This function builds the iterators for a task & parameter */
1318
1319 void builditerators(struct taskdescriptor * task, int index, struct parameterwrapper * parameter) {
1320   int statusarray[MAXTASKPARAMS];
1321   int i;
1322   int numparams=task->numParameters;
1323   int iteratorcount=0;
1324   for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
1325
1326   statusarray[index]=1; /* Initial parameter */
1327   /* Process tags for initial iterator */
1328
1329   processtags(task->descriptorarray[index], index, parameter, &iteratorcount, statusarray, numparams);
1330
1331   while(1) {
1332 loopstart:
1333     /* Check for objects with existing tags */
1334     for(i=0; i<numparams; i++) {
1335       if (statusarray[i]==0) {
1336         struct parameterdescriptor *pd=task->descriptorarray[i];
1337         int j;
1338         for(j=0; j<pd->numbertags; j++) {
1339           int slotid=pd->tagarray[2*j];
1340           if(statusarray[slotid+numparams]!=0) {
1341             processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
1342             processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
1343             goto loopstart;
1344           }
1345         }
1346       }
1347     }
1348
1349     /* Next do objects w/ unbound tags*/
1350
1351     for(i=0; i<numparams; i++) {
1352       if (statusarray[i]==0) {
1353         struct parameterdescriptor *pd=task->descriptorarray[i];
1354         if (pd->numbertags>0) {
1355           processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
1356           processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
1357           goto loopstart;
1358         }
1359       }
1360     }
1361
1362     /* Nothing with a tag enqueued */
1363
1364     for(i=0; i<numparams; i++) {
1365       if (statusarray[i]==0) {
1366         struct parameterdescriptor *pd=task->descriptorarray[i];
1367         processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
1368         processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
1369         goto loopstart;
1370       }
1371     }
1372
1373     /* Nothing left */
1374     return;
1375   }
1376 }
1377
1378 void printdebug() {
1379   int i;
1380   int j;
1381   for(i=0; i<numtasks; i++) {
1382     struct taskdescriptor * task=taskarray[i];
1383     printf("%s\n", task->name);
1384     for(j=0; j<task->numParameters; j++) {
1385       struct parameterdescriptor *param=task->descriptorarray[j];
1386       struct parameterwrapper *parameter=param->queue;
1387       struct ObjectHash * set=parameter->objectset;
1388       struct ObjectIterator objit;
1389       printf("  Parameter %d\n", j);
1390       ObjectHashiterator(set, &objit);
1391       while(ObjhasNext(&objit)) {
1392         struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
1393         struct ___Object___ * tagptr=obj->___tags___;
1394         int nonfailed=Objdata4(&objit);
1395         int numflags=Objdata3(&objit);
1396         int flags=Objdata2(&objit);
1397         Objnext(&objit);
1398         printf("    Contains %lx\n", obj);
1399         printf("      flag=%d\n", obj->flag);
1400 #ifdef OPTIONAL
1401         printf("      flagsstored=%x\n",flags);
1402         printf("      numflags=%d\n", numflags);
1403         printf("      nonfailed=%d\n",nonfailed);
1404 #endif
1405         if (tagptr==NULL) {
1406         } else if (tagptr->type==TAGTYPE) {
1407           printf("      tag=%lx\n",tagptr);
1408         } else {
1409           int tagindex=0;
1410           struct ArrayObject *ao=(struct ArrayObject *)tagptr;
1411           for(; tagindex<ao->___cachedCode___; tagindex++) {
1412             printf("      tag=%lx\n",ARRAYGET(ao, struct ___TagDescriptor___*, tagindex));
1413           }
1414         }
1415       }
1416     }
1417   }
1418 }
1419
1420
1421 /* This function processes the task information to create queues for
1422    each parameter type. */
1423
1424 void processtasks() {
1425   int i;
1426   for(i=0; i<numtasks; i++) {
1427     struct taskdescriptor * task=taskarray[i];
1428     int j;
1429
1430     for(j=0; j<task->numParameters; j++) {
1431       struct parameterdescriptor *param=task->descriptorarray[j];
1432       struct parameterwrapper * parameter=RUNMALLOC(sizeof(struct parameterwrapper));
1433       struct parameterwrapper ** ptr=&objectqueues[param->type];
1434
1435       param->queue=parameter;
1436       parameter->objectset=allocateObjectHash(10);
1437       parameter->numberofterms=param->numberterms;
1438       parameter->intarray=param->intarray;
1439       parameter->numbertags=param->numbertags;
1440       parameter->tagarray=param->tagarray;
1441       parameter->task=task;
1442       parameter->slot=j;
1443       /* Link new queue in */
1444       while((*ptr)!=NULL)
1445         ptr=&((*ptr)->next);
1446       (*ptr)=parameter;
1447     }
1448
1449     /* Build iterators for parameters */
1450     for(j=0; j<task->numParameters; j++) {
1451       struct parameterdescriptor *param=task->descriptorarray[j];
1452       struct parameterwrapper *parameter=param->queue;
1453       builditerators(task, j, parameter);
1454     }
1455   }
1456 }
1457
1458 void toiReset(struct tagobjectiterator * it) {
1459   if (it->istag) {
1460     it->tagobjindex=0;
1461   } else if (it->numtags>0) {
1462     it->tagobjindex=0;
1463 #ifdef OPTIONAL
1464     it->failedstate=0;
1465 #endif
1466   } else {
1467     ObjectHashiterator(it->objectset, &it->it);
1468 #ifdef OPTIONAL
1469     it->failedstate=0;
1470 #endif
1471   }
1472 }
1473
1474 int toiHasNext(struct tagobjectiterator *it, void ** objectarray OPTARG(int * failed)) {
1475   if (it->istag) {
1476     /* Iterate tag */
1477     /* Get object with tags */
1478     struct ___Object___ *obj=objectarray[it->tagobjectslot];
1479     struct ___Object___ *tagptr=obj->___tags___;
1480     if (tagptr->type==TAGTYPE) {
1481       if ((it->tagobjindex==0)&& /* First object */
1482           (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
1483         return 1;
1484       else
1485         return 0;
1486     } else {
1487       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
1488       int tagindex=it->tagobjindex;
1489       for(; tagindex<ao->___cachedCode___; tagindex++) {
1490         struct ___TagDescriptor___ *td=ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
1491         if (td->flag==it->tagid) {
1492           it->tagobjindex=tagindex; /* Found right type of tag */
1493           return 1;
1494         }
1495       }
1496       return 0;
1497     }
1498   } else if (it->numtags>0) {
1499     /* Use tags to locate appropriate objects */
1500     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
1501     struct ___Object___ *objptr=tag->flagptr;
1502     int i;
1503     if (objptr->type!=OBJECTARRAYTYPE) {
1504       if (it->tagobjindex>0)
1505         return 0;
1506       if (!ObjectHashcontainskey(it->objectset, (int) objptr))
1507         return 0;
1508       for(i=1; i<it->numtags; i++) {
1509         struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
1510         if (!containstag(objptr,tag2))
1511           return 0;
1512       }
1513 #ifdef OPTIONAL
1514       if (it->failedstate==1) {
1515         int UNUSED, UNUSED2;
1516         int * flags;
1517         int isnonfailed;
1518         ObjectHashget(it->objectset, (int) objptr, &UNUSED, (int *) &flags, &UNUSED2, &isnonfailed);
1519         if (flags!=NULL) {
1520           return 1;
1521         } else {
1522           it->tagobjindex++;
1523           it->failedstate=0;
1524           return 0;
1525         }
1526       } else {
1527         int UNUSED, UNUSED2;
1528         int * flags;
1529         int isnonfailed;
1530         ObjectHashget(it->objectset, (int) objptr, &UNUSED, (int *) &flags, &UNUSED2, &isnonfailed);
1531         if (!isnonfailed) {
1532           it->failedstate=1;
1533         }
1534         return 1;
1535       }
1536 #endif
1537       return 1;
1538     } else {
1539       struct ArrayObject *ao=(struct ArrayObject *) objptr;
1540       int tagindex;
1541       int i;
1542 #ifdef OPTIONAL
1543       if (it->failedstate==1) {
1544         int UNUSED, UNUSED2;
1545         int * flags;
1546         int isnonfailed;
1547         struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, it->tagobjindex);
1548         ObjectHashget(it->objectset, (int) objptr, &UNUSED, (int *) &flags, &UNUSED2, &isnonfailed);
1549         if (flags!=NULL) {
1550           return 1;
1551         } else {
1552           it->failedstate=0;
1553           it->tagobjindex++;
1554         }
1555       }
1556 #endif
1557       for(tagindex=it->tagobjindex; tagindex<ao->___cachedCode___; tagindex++) {
1558         struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
1559         if (!ObjectHashcontainskey(it->objectset, (int) objptr))
1560           continue;
1561         for(i=1; i<it->numtags; i++) {
1562           struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
1563           if (!containstag(objptr,tag2))
1564             goto nexttag;
1565         }
1566 #ifdef OPTIONAL
1567         {
1568           int UNUSED, UNUSED2;
1569           int flags, isnonfailed;
1570           struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
1571           ObjectHashget(it->objectset, (int) objptr, &UNUSED, &flags, &UNUSED2, &isnonfailed);
1572           if (!isnonfailed) {
1573             it->failedstate=1;
1574           }
1575         }
1576 #endif
1577         it->tagobjindex=tagindex;
1578         return 1;
1579 nexttag:
1580         ;
1581       }
1582       it->tagobjindex=tagindex;
1583       return 0;
1584     }
1585   } else {
1586 #ifdef OPTIONAL
1587     if (it->failedstate==1) {
1588       if (Objdata2(&it->it))
1589         return 1;
1590       else {
1591         it->failedstate=0;
1592         Objnext(&it->it);
1593       }
1594     }
1595     if (ObjhasNext(&it->it)) {
1596       if (!Objdata4(&it->it)) {
1597         //failed state only
1598         it->failedstate=1;
1599       }
1600       return 1;
1601     } else
1602       return 0;
1603 #else
1604     return ObjhasNext(&it->it);
1605 #endif
1606   }
1607 }
1608
1609 int containstag(struct ___Object___ *ptr, struct ___TagDescriptor___ *tag) {
1610   int j;
1611   struct ___Object___ * objptr=tag->flagptr;
1612   if (objptr->type==OBJECTARRAYTYPE) {
1613     struct ArrayObject *ao=(struct ArrayObject *)objptr;
1614     for(j=0; j<ao->___cachedCode___; j++) {
1615       if (ptr==ARRAYGET(ao, struct ___Object___*, j))
1616         return 1;
1617     }
1618     return 0;
1619   } else
1620     return objptr==ptr;
1621 }
1622
1623 void toiNext(struct tagobjectiterator *it, void ** objectarray OPTARG(int * failed)) {
1624   /* hasNext has all of the intelligence */
1625   if(it->istag) {
1626     /* Iterate tag */
1627     /* Get object with tags */
1628     struct ___Object___ *obj=objectarray[it->tagobjectslot];
1629     struct ___Object___ *tagptr=obj->___tags___;
1630 #ifdef OPTIONAL
1631     failed[it->slot]=0; //have to set it to something
1632 #endif
1633     if (tagptr->type==TAGTYPE) {
1634       it->tagobjindex++;
1635       objectarray[it->slot]=tagptr;
1636     } else {
1637       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
1638       objectarray[it->slot]=ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
1639     }
1640   } else if (it->numtags>0) {
1641     /* Use tags to locate appropriate objects */
1642     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
1643     struct ___Object___ *objptr=tag->flagptr;
1644     if (objptr->type!=OBJECTARRAYTYPE) {
1645 #ifdef OPTIONAL
1646       failed[it->slot]=it->failedstate;
1647       objectarray[it->slot]=objptr;
1648       if (it->failedstate==0) {
1649         it->failedstate=1;
1650       } else {
1651         it->failedstate=0;
1652         it->tagobjindex++;
1653       }
1654 #else
1655       it->tagobjindex++;
1656       objectarray[it->slot]=objptr;
1657 #endif
1658     } else {
1659       struct ArrayObject *ao=(struct ArrayObject *) objptr;
1660 #ifdef OPTIONAL
1661       failed[it->slot]=it->failedstate;
1662       objectarray[it->slot]=ARRAYGET(ao, struct ___Object___ *, it->tagobjindex);
1663       if (it->failedstate==0) {
1664         it->failedstate=1;
1665       } else {
1666         it->failedstate=0;
1667         it->tagobjindex++;
1668       }
1669 #else
1670       objectarray[it->slot]=ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
1671 #endif
1672     }
1673   } else {
1674     /* Iterate object */
1675     void * tmpp = (void *) Objkey(&it->it);
1676     objectarray[it->slot]=tmpp;
1677 #ifdef OPTIONAL
1678     failed[it->slot]=it->failedstate;
1679     if (it->failedstate==0) {
1680       it->failedstate=1;
1681     } else {
1682       it->failedstate=0;
1683       Objnext(&it->it);
1684     }
1685 #else
1686     Objnext(&it->it);
1687 #endif
1688   }
1689 }
1690 #endif