2 #include "structdefs.h"
13 extern int classsize[];
14 jmp_buf error_handler;
18 #include "checkpoint.h"
20 #include "SimpleHash.h"
21 #include "GenericHashtable.h"
22 #include <sys/select.h>
25 #include "instrument.h"
28 struct Queue * activetasks;
29 struct parameterwrapper * objectqueues[NUMCLASSES];
30 struct genhashtable * failedtasks;
31 /*struct genhashtable * failedobjects;*/
32 extern char ** environ;
35 float failurechance=0;
37 int injectinstructionfailures;
39 float instfailurechance=0;
42 void processOptions() {
45 for(i=0;environ[i]!=0;i++) {
46 if (strncmp(environ[i],"BRISTLECONE=",12)==0) {
47 options=environ[i]+12;
52 while(options!=NULL) {
53 if (strncmp(options,"-injectfailures",sizeof("-injectfailures")-1)==0) {
54 options=strchr(options,' ');
55 if (options!=NULL) options++;
58 sscanf(options, "%f", &failurechance);
60 printf("Injecting errors with chance=%f\n",failurechance);
61 options=strchr(options,' ');
62 if (options!=NULL) options++;
63 } else if (strncmp(options,"-injectinstructionfailures",sizeof("-injectinstructionfailures")-1)==0) {
64 options=strchr(options,' ');
65 if (options!=NULL) options++;
68 sscanf(options, "%d", &failurecount);
69 options=strchr(options,' ');
70 if (options!=NULL) options++;
75 sscanf(options, "%f", &instfailurechance);
76 options=strchr(options,' ');
77 if (options!=NULL) options++;
81 sscanf(options, "%d", &numfailures);
82 options=strchr(options,' ');
83 if (options!=NULL) options++;
85 instructioncount=failurecount;
86 injectinstructionfailures=1;
87 printf("Number of failures=%d\n",numfailures);
88 printf("Injecting errors with count=%d\n",failurecount);
89 printf("Injecting errors with chance=%f\n",instfailurechance);
90 } else if (strncmp(options, "-debugtask",sizeof("-debugtask")-1)==0) {
91 options=strchr(options,' ');
92 if (options!=NULL) options++;
94 printf("Debug task option on.\n");
100 int main(int argc, char **argv) {
101 GC_init(); // Initialize the garbage collector
109 /* Allocate startup object */
110 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
111 struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1);
112 failedtasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd,
113 (int (*)(void *,void *)) &comparetpd);
114 /* failedobjects=genallocatehashtable(NULL,NULL);*/
116 activetasks=createQueue();
120 flagorand(startupobject,1,0xFFFFFFFF);
122 /* Build array of strings */
124 startupobject->___parameters___=stringarray;
126 for(i=1;i<argc;i++) {
127 int length=strlen(argv[i]);
128 struct ___String___ *newstring=NewString(argv[i],length);
129 ((void **)(((char *)& stringarray->___length___)+sizeof(int)))[i-1]=newstring;
135 int hashCodetpd(struct taskparamdescriptor *ftd) {
136 int hash=(int)ftd->task;
138 for(i=0;i<ftd->numParameters;i++) {
139 hash^=(int)ftd->parameterArray[i];
144 int comparetpd(struct taskparamdescriptor *ftd1, struct taskparamdescriptor *ftd2) {
146 if (ftd1->task!=ftd2->task)
148 for(i=0;i<ftd1->numParameters;i++)
149 if (ftd1->parameterArray[i]!=ftd2->parameterArray[i])
154 void flagorand(void * ptr, int ormask, int andmask) {
155 int flag=((int *)ptr)[1];
156 struct RuntimeHash *flagptr=(struct RuntimeHash *)(((int*)ptr)[2]);
160 /*Remove from all queues */
161 while(flagptr!=NULL) {
162 struct RuntimeHash *next;
163 RuntimeHashget(flagptr, (int) ptr, (int *) &next);
164 RuntimeHashremove(flagptr, (int)ptr, (int) next);
169 struct QueueItem *tmpptr;
170 struct parameterwrapper * parameter=objectqueues[((int *)ptr)[0]];
172 struct RuntimeHash * prevptr=NULL;
173 while(parameter!=NULL) {
174 for(i=0;i<parameter->numberofterms;i++) {
175 int andmask=parameter->intarray[i*2];
176 int checkmask=parameter->intarray[i*2+1];
177 if ((flag&andmask)==checkmask) {
178 RuntimeHashadd(parameter->objectset, (int) ptr, (int) prevptr);
179 prevptr=parameter->objectset;
181 struct RuntimeIterator iteratorarray[MAXTASKPARAMS];
182 void * taskpointerarray[MAXTASKPARAMS];
184 int numparams=parameter->task->numParameters;
186 struct taskdescriptor * task=parameter->task;
188 for(j=0;j<numparams;j++) {
189 struct parameterwrapper *pw=(struct parameterwrapper *)task->descriptorarray[j]->queue;
191 taskpointerarray[j]=ptr;
194 RuntimeHashiterator(pw->objectset, &iteratorarray[j]);
195 if (RunhasNext(&iteratorarray[j])) {
196 taskpointerarray[j]=(void *) Runkey(&iteratorarray[j]);
197 Runnext(&iteratorarray[j]);
200 break; /* No tasks to dispatch */
204 /* Queue task items... */
207 struct taskparamdescriptor *tpd=RUNMALLOC(sizeof(struct taskparamdescriptor));
209 tpd->numParameters=numparams;
210 tpd->parameterArray=RUNMALLOC(sizeof(void *)*numparams);
211 for(j=0;j<numparams;j++)
212 tpd->parameterArray[j]=taskpointerarray[j];
214 if (!gencontains(failedtasks, tpd))
215 addNewItem(activetasks, tpd);
217 /* This loop iterates to the next parameter combination */
218 for(j=0;j<numparams;j++) {
220 if ((j+1)==numparams)
224 if (RunhasNext(&iteratorarray[j])) {
225 taskpointerarray[j]=(void *) Runkey(&iteratorarray[j]);
226 Runnext(&iteratorarray[j]);
228 } else if ((j+1)!=numparams) {
229 RuntimeHashiterator(task->descriptorarray[j]->queue, &iteratorarray[j]);
240 parameter=parameter->next;
242 ((struct RuntimeHash **)ptr)[2]=prevptr;
246 /* Handler for signals. The signals catch null pointer errors and
247 arithmatic errors. */
248 void myhandler(int sig, siginfo_t *info, void *uap) {
250 printf("sig=%d\n",sig);
253 longjmp(error_handler,1);
258 struct RuntimeHash *fdtoobject;
260 void addreadfd(int fd) {
263 FD_SET(fd, &readfds);
266 void removereadfd(int fd) {
267 FD_CLR(fd, &readfds);
268 if (maxreadfd==(fd+1)) {
270 while(maxreadfd>0&&!FD_ISSET(maxreadfd-1, &readfds))
276 void restoreObject(void * obj) {
277 if (gencontains(failedobjects, obj)) {
278 struct tpdlist *tpd=gengettable(failedobjects, obj);
279 genfreekey(failedobjects, obj);
282 struct taskparamdescriptor *task=tpd->task;
283 genfreekey(failedtasks, task);
284 for(i=0;i<task->numParameters;i++) {
285 void *objother=task->parameterArray[i];
286 struct tpdlist *tpdother=gengettable(failedobjects, objother);
287 struct tpdlist *tmpptr;
288 genfreekey(failedobjects, objother);
289 struct tpdlist **tpdptr=&tpdother;
290 while((*tpdptr)->task!=task)
291 tpdptr=&((*tpdptr)->next);
293 (*tpdptr)=(*tpdptr)->next;
296 genputtable(failedobjects, objother, tpdother);
300 struct tpdlist *old=tpd;
309 void executetasks() {
310 void * taskpointerarray[MAXTASKPARAMS];
312 /* Set up signal handlers */
313 struct sigaction sig;
314 sig.sa_sigaction=&myhandler;
315 sig.sa_flags=SA_SIGINFO;
316 sigemptyset(&sig.sa_mask);
318 /* Catch bus errors, segmentation faults, and floating point exceptions*/
319 sigaction(SIGBUS,&sig,0);
320 sigaction(SIGSEGV,&sig,0);
321 sigaction(SIGFPE,&sig,0);
326 fdtoobject=allocateRuntimeHash(100);
328 /* Map first block of memory to protected, anonymous page */
329 mmap(0, 0x1000, 0, MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
332 while(!isEmpty(activetasks)||(maxreadfd>0)) {
334 /* Check if any filedescriptors have IO pending */
337 struct timeval timeout={0,0};
341 numselect=select(maxreadfd, &tmpreadfds, NULL, NULL, &timeout);
343 /* Process ready fd's */
345 for(fd=0;fd<maxreadfd;fd++) {
346 if (FD_ISSET(fd, &tmpreadfds)) {
347 /* Set ready flag on object */
349 if (RuntimeHashget(fdtoobject, fd,(int *) &objptr)) {
350 flagorand(objptr,1,0xFFFFFFFF); /* Set the first flag to 1 */
357 /* See if there are any active tasks */
358 if (!isEmpty(activetasks)) {
360 struct QueueItem * qi=(struct QueueItem *) getTail(activetasks);
361 struct taskparamdescriptor *tpd=(struct taskparamdescriptor *) qi->objectptr;
362 removeItem(activetasks, qi);
364 /* Check if this task has failed */
365 if (gencontains(failedtasks, tpd))
368 /* Make sure that the parameters are still in the queues */
369 for(i=0;i<tpd->task->numParameters;i++) {
370 void * parameter=tpd->parameterArray[i];
371 struct parameterdescriptor * pd=tpd->task->descriptorarray[i];
372 struct parameterwrapper *pw=(struct parameterwrapper *) pd->queue;
373 if (!RuntimeHashcontainskey(pw->objectset, (int) parameter))
375 taskpointerarray[i]=parameter;
378 /* Checkpoint the state */
379 struct RuntimeHash * forward=allocateRuntimeHash(100);
380 struct RuntimeHash * reverse=allocateRuntimeHash(100);
381 void ** checkpoint=makecheckpoint(tpd->task->numParameters, taskpointerarray, forward, reverse);
383 if (x=setjmp(error_handler)) {
387 printf("Fatal Error=%d, Recovering!\n",x);
389 genputtable(failedtasks,tpd,tpd);
390 /* for(i=0;i<tpd->task->numParameters;i++) {
391 void *parameter=tpd->parameterArray[i];
393 // Create mapping from object -> failed tasks
394 struct tpdlist * tpnew=RUNMALLOC(sizeof(struct tpdlist));
396 if (gencontains(failedobjects, parameter)) {
397 struct tpdlist * tpdptr=gengettable(failedobjects, parameter);
398 tpnew->next=tpdptr->next;
402 genputtable(failedobjects, parameter, tpnew);
406 restorecheckpoint(tpd->task->numParameters, taskpointerarray, checkpoint, forward, reverse);
408 if (injectfailures) {
409 if ((((double)random())/RAND_MAX)<failurechance) {
410 printf("\nINJECTING TASK FAILURE to %s\n", tpd->task->name);
411 longjmp(error_handler,10);
414 /* Actually call task */
416 printf("ENTER %s\n",tpd->task->name);
417 ((void (*) (void **)) tpd->task->taskptr)(taskpointerarray);
418 printf("EXIT %s\n",tpd->task->name);
420 ((void (*) (void **)) tpd->task->taskptr)(taskpointerarray);
427 /* This function processes the task information to create queues for
428 each parameter type. */
430 void processtasks() {
432 for(i=0;i<numtasks;i++) {
433 struct taskdescriptor * task=taskarray[i];
436 for(j=0;j<task->numParameters;j++) {
437 struct parameterdescriptor *param=task->descriptorarray[j];
438 struct parameterwrapper * parameter=RUNMALLOC(sizeof(struct parameterwrapper));
439 struct parameterwrapper ** ptr=&objectqueues[param->type];
441 param->queue=parameter;
442 parameter->objectset=allocateRuntimeHash(10);
443 parameter->numberofterms=param->numberterms;
444 parameter->intarray=param->intarray;
445 parameter->task=task;
446 /* Link new queue in */
456 /* This function inject failures */
458 void injectinstructionfailure() {
460 if (injectinstructionfailures) {
465 instructioncount=failurecount;
466 if ((((double)random())/RAND_MAX)<instfailurechance) {
467 printf("FAILURE!!!\n");
468 longjmp(error_handler,11);
475 int ___Object______hashCode____(struct ___Object___ * ___this___) {
476 return (int) ___this___;
479 int ___Object______getType____(struct ___Object___ * ptr) {
480 return ((int *)ptr)[0];
483 void ___System______printString____L___String___(struct ___String___ * s) {
484 struct ArrayObject * chararray=s->___value___;
486 int offset=s->___offset___;
487 for(i=0;i<s->___count___;i++) {
488 short s= ((short *)(((char *)& chararray->___length___)+sizeof(int)))[i+offset];
493 void * allocate_new(int type) {
494 void * v=FREEMALLOC(classsize[type]);
499 struct ArrayObject * allocate_newarray(int type, int length) {
500 struct ArrayObject * v=FREEMALLOC(sizeof(struct ArrayObject)+length*classsize[type]);
502 v->___length___=length;
506 struct ___String___ * NewString(const char *str,int length) {
507 struct ArrayObject * chararray=allocate_newarray(CHARARRAYTYPE, length);
508 struct ___String___ * strobj=allocate_new(STRINGTYPE);
510 strobj->___value___=chararray;
511 strobj->___count___=length;
512 strobj->___offset___=0;
514 for(i=0;i<length;i++) {
515 ((short *)(((char *)& chararray->___length___)+sizeof(int)))[i]=(short)str[i]; }
519 /* Generated code calls this if we fail a bounds check */
520 void failedboundschk() {
522 printf("Array out of bounds\n");
525 longjmp(error_handler,2);
531 longjmp(error_handler,4);
533 printf("Aborting\n");