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;
43 void processOptions() {
46 for(i=0;environ[i]!=0;i++) {
47 if (strncmp(environ[i],"BRISTLECONE=",12)==0) {
48 options=environ[i]+12;
53 while(options!=NULL) {
54 if (strncmp(options,"-injectfailures",sizeof("-injectfailures")-1)==0) {
55 options=strchr(options,' ');
56 if (options!=NULL) options++;
59 sscanf(options, "%f", &failurechance);
61 printf("Injecting errors with chance=%f\n",failurechance);
62 options=strchr(options,' ');
63 if (options!=NULL) options++;
64 } else if (strncmp(options,"-injectinstructionfailures",sizeof("-injectinstructionfailures")-1)==0) {
65 options=strchr(options,' ');
66 if (options!=NULL) options++;
69 sscanf(options, "%d", &failurecount);
70 options=strchr(options,' ');
71 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 instaccum=failurecount;
86 instructioncount=failurecount;
87 injectinstructionfailures=1;
88 printf("Number of failures=%d\n",numfailures);
89 printf("Injecting errors with count=%d\n",failurecount);
90 printf("Injecting errors with chance=%f\n",instfailurechance);
91 } else if (strncmp(options, "-debugtask",sizeof("-debugtask")-1)==0) {
92 options=strchr(options,' ');
93 if (options!=NULL) options++;
95 printf("Debug task option on.\n");
96 } else if (strncmp(options, "-initializerandom", sizeof("-initializerandom")-1)==0) {
97 options=strchr(options,' ');
98 if (options!=NULL) options++;
99 printf("Initializing random number generator.\n");
106 int main(int argc, char **argv) {
107 GC_init(); // Initialize the garbage collector
115 /* Allocate startup object */
116 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
117 struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1);
118 failedtasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd,
119 (int (*)(void *,void *)) &comparetpd);
120 /* failedobjects=genallocatehashtable(NULL,NULL);*/
122 activetasks=createQueue();
126 flagorand(startupobject,1,0xFFFFFFFF);
128 /* Build array of strings */
130 startupobject->___parameters___=stringarray;
132 for(i=1;i<argc;i++) {
133 int length=strlen(argv[i]);
134 struct ___String___ *newstring=NewString(argv[i],length);
135 ((void **)(((char *)& stringarray->___length___)+sizeof(int)))[i-1]=newstring;
141 int hashCodetpd(struct taskparamdescriptor *ftd) {
142 int hash=(int)ftd->task;
144 for(i=0;i<ftd->numParameters;i++) {
145 hash^=(int)ftd->parameterArray[i];
150 int comparetpd(struct taskparamdescriptor *ftd1, struct taskparamdescriptor *ftd2) {
152 if (ftd1->task!=ftd2->task)
154 for(i=0;i<ftd1->numParameters;i++)
155 if (ftd1->parameterArray[i]!=ftd2->parameterArray[i])
160 void flagorand(void * ptr, int ormask, int andmask) {
161 int flag=((int *)ptr)[1];
162 struct RuntimeHash *flagptr=(struct RuntimeHash *)(((int*)ptr)[2]);
166 /*Remove from all queues */
167 while(flagptr!=NULL) {
168 struct RuntimeHash *next;
169 RuntimeHashget(flagptr, (int) ptr, (int *) &next);
170 RuntimeHashremove(flagptr, (int)ptr, (int) next);
175 struct QueueItem *tmpptr;
176 struct parameterwrapper * parameter=objectqueues[((int *)ptr)[0]];
178 struct RuntimeHash * prevptr=NULL;
179 while(parameter!=NULL) {
180 for(i=0;i<parameter->numberofterms;i++) {
181 int andmask=parameter->intarray[i*2];
182 int checkmask=parameter->intarray[i*2+1];
183 if ((flag&andmask)==checkmask) {
184 RuntimeHashadd(parameter->objectset, (int) ptr, (int) prevptr);
185 prevptr=parameter->objectset;
187 struct RuntimeIterator iteratorarray[MAXTASKPARAMS];
188 void * taskpointerarray[MAXTASKPARAMS];
190 int numparams=parameter->task->numParameters;
192 struct taskdescriptor * task=parameter->task;
194 for(j=0;j<numparams;j++) {
195 struct parameterwrapper *pw=(struct parameterwrapper *)task->descriptorarray[j]->queue;
197 taskpointerarray[j]=ptr;
200 RuntimeHashiterator(pw->objectset, &iteratorarray[j]);
201 if (RunhasNext(&iteratorarray[j])) {
202 taskpointerarray[j]=(void *) Runkey(&iteratorarray[j]);
203 Runnext(&iteratorarray[j]);
206 break; /* No tasks to dispatch */
210 /* Queue task items... */
213 struct taskparamdescriptor *tpd=RUNMALLOC(sizeof(struct taskparamdescriptor));
215 tpd->numParameters=numparams;
216 tpd->parameterArray=RUNMALLOC(sizeof(void *)*numparams);
217 for(j=0;j<numparams;j++)
218 tpd->parameterArray[j]=taskpointerarray[j];
220 if (!gencontains(failedtasks, tpd))
221 addNewItem(activetasks, tpd);
223 /* This loop iterates to the next parameter combination */
224 for(j=0;j<numparams;j++) {
226 if ((j+1)==numparams)
230 if (RunhasNext(&iteratorarray[j])) {
231 taskpointerarray[j]=(void *) Runkey(&iteratorarray[j]);
232 Runnext(&iteratorarray[j]);
234 } else if ((j+1)!=numparams) {
235 RuntimeHashiterator(task->descriptorarray[j]->queue, &iteratorarray[j]);
246 parameter=parameter->next;
248 ((struct RuntimeHash **)ptr)[2]=prevptr;
252 /* Handler for signals. The signals catch null pointer errors and
253 arithmatic errors. */
254 void myhandler(int sig, siginfo_t *info, void *uap) {
256 printf("sig=%d\n",sig);
259 longjmp(error_handler,1);
264 struct RuntimeHash *fdtoobject;
266 void addreadfd(int fd) {
269 FD_SET(fd, &readfds);
272 void removereadfd(int fd) {
273 FD_CLR(fd, &readfds);
274 if (maxreadfd==(fd+1)) {
276 while(maxreadfd>0&&!FD_ISSET(maxreadfd-1, &readfds))
282 void restoreObject(void * obj) {
283 if (gencontains(failedobjects, obj)) {
284 struct tpdlist *tpd=gengettable(failedobjects, obj);
285 genfreekey(failedobjects, obj);
288 struct taskparamdescriptor *task=tpd->task;
289 genfreekey(failedtasks, task);
290 for(i=0;i<task->numParameters;i++) {
291 void *objother=task->parameterArray[i];
292 struct tpdlist *tpdother=gengettable(failedobjects, objother);
293 struct tpdlist *tmpptr;
294 genfreekey(failedobjects, objother);
295 struct tpdlist **tpdptr=&tpdother;
296 while((*tpdptr)->task!=task)
297 tpdptr=&((*tpdptr)->next);
299 (*tpdptr)=(*tpdptr)->next;
302 genputtable(failedobjects, objother, tpdother);
306 struct tpdlist *old=tpd;
321 void executetasks() {
322 void * taskpointerarray[MAXTASKPARAMS+OFFSET];
324 /* Set up signal handlers */
325 struct sigaction sig;
326 sig.sa_sigaction=&myhandler;
327 sig.sa_flags=SA_SIGINFO;
328 sigemptyset(&sig.sa_mask);
330 /* Catch bus errors, segmentation faults, and floating point exceptions*/
331 sigaction(SIGBUS,&sig,0);
332 sigaction(SIGSEGV,&sig,0);
333 sigaction(SIGFPE,&sig,0);
338 fdtoobject=allocateRuntimeHash(100);
340 /* Map first block of memory to protected, anonymous page */
341 mmap(0, 0x1000, 0, MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
344 while(!isEmpty(activetasks)||(maxreadfd>0)) {
346 /* Check if any filedescriptors have IO pending */
349 struct timeval timeout={0,0};
353 numselect=select(maxreadfd, &tmpreadfds, NULL, NULL, &timeout);
355 /* Process ready fd's */
357 for(fd=0;fd<maxreadfd;fd++) {
358 if (FD_ISSET(fd, &tmpreadfds)) {
359 /* Set ready flag on object */
361 if (RuntimeHashget(fdtoobject, fd,(int *) &objptr)) {
362 flagorand(objptr,1,0xFFFFFFFF); /* Set the first flag to 1 */
369 /* See if there are any active tasks */
370 if (!isEmpty(activetasks)) {
372 struct QueueItem * qi=(struct QueueItem *) getTail(activetasks);
373 struct taskparamdescriptor *tpd=(struct taskparamdescriptor *) qi->objectptr;
374 removeItem(activetasks, qi);
376 /* Check if this task has failed */
377 if (gencontains(failedtasks, tpd))
380 /* Make sure that the parameters are still in the queues */
381 for(i=0;i<tpd->task->numParameters;i++) {
382 void * parameter=tpd->parameterArray[i];
383 struct parameterdescriptor * pd=tpd->task->descriptorarray[i];
384 struct parameterwrapper *pw=(struct parameterwrapper *) pd->queue;
385 if (!RuntimeHashcontainskey(pw->objectset, (int) parameter))
387 taskpointerarray[i+OFFSET]=parameter;
390 /* Checkpoint the state */
391 struct RuntimeHash * forward=allocateRuntimeHash(100);
392 struct RuntimeHash * reverse=allocateRuntimeHash(100);
393 void ** checkpoint=makecheckpoint(tpd->task->numParameters, &taskpointerarray[OFFSET], forward, reverse);
395 if (x=setjmp(error_handler)) {
399 printf("Fatal Error=%d, Recovering!\n",x);
401 genputtable(failedtasks,tpd,tpd);
402 /* for(i=0;i<tpd->task->numParameters;i++) {
403 void *parameter=tpd->parameterArray[i];
405 // Create mapping from object -> failed tasks
406 struct tpdlist * tpnew=RUNMALLOC(sizeof(struct tpdlist));
408 if (gencontains(failedobjects, parameter)) {
409 struct tpdlist * tpdptr=gengettable(failedobjects, parameter);
410 tpnew->next=tpdptr->next;
414 genputtable(failedobjects, parameter, tpnew);
418 restorecheckpoint(tpd->task->numParameters, &taskpointerarray[OFFSET], checkpoint, forward, reverse);
420 if (injectfailures) {
421 if ((((double)random())/RAND_MAX)<failurechance) {
422 printf("\nINJECTING TASK FAILURE to %s\n", tpd->task->name);
423 longjmp(error_handler,10);
426 /* Actually call task */
428 ((int *)taskpointerarray)[0]=tpd->task->numParameters;
429 taskpointerarray[1]=NULL;
433 printf("ENTER %s count=%d\n",tpd->task->name, (instaccum-instructioncount));
434 ((void (*) (void **)) tpd->task->taskptr)(taskpointerarray);
435 printf("EXIT %s count=%d\n",tpd->task->name, (instaccum-instructioncount));
437 ((void (*) (void **)) tpd->task->taskptr)(taskpointerarray);
444 /* This function processes the task information to create queues for
445 each parameter type. */
447 void processtasks() {
449 for(i=0;i<numtasks;i++) {
450 struct taskdescriptor * task=taskarray[i];
453 for(j=0;j<task->numParameters;j++) {
454 struct parameterdescriptor *param=task->descriptorarray[j];
455 struct parameterwrapper * parameter=RUNMALLOC(sizeof(struct parameterwrapper));
456 struct parameterwrapper ** ptr=&objectqueues[param->type];
458 param->queue=parameter;
459 parameter->objectset=allocateRuntimeHash(10);
460 parameter->numberofterms=param->numberterms;
461 parameter->intarray=param->intarray;
462 parameter->task=task;
463 /* Link new queue in */
473 /* This function inject failures */
475 void injectinstructionfailure() {
477 if (injectinstructionfailures) {
480 instructioncount=failurecount;
481 instaccum+=failurecount;
482 if ((((double)random())/RAND_MAX)<instfailurechance) {
485 printf("FAILURE!!!\n");
486 longjmp(error_handler,11);
493 int CALL01(___Object______hashCode____, struct ___Object___ * ___this___) {
494 return (int) VAR(___this___);
497 int CALL01(___Object______getType____, struct ___Object___ * ___this___) {
498 return ((int *)VAR(___this___))[0];
501 void CALL01(___System______printString____L___String___,struct ___String___ * ___s___) {
502 struct ArrayObject * chararray=VAR(___s___)->___value___;
504 int offset=VAR(___s___)->___offset___;
505 for(i=0;i<VAR(___s___)->___count___;i++) {
506 short sc=((short *)(((char *)& chararray->___length___)+sizeof(int)))[i+offset];
511 void * allocate_new(int type) {
512 void * v=FREEMALLOC(classsize[type]);
517 struct ArrayObject * allocate_newarray(int type, int length) {
518 struct ArrayObject * v=FREEMALLOC(sizeof(struct ArrayObject)+length*classsize[type]);
520 v->___length___=length;
524 struct ___String___ * NewString(const char *str,int length) {
525 struct ArrayObject * chararray=allocate_newarray(CHARARRAYTYPE, length);
526 struct ___String___ * strobj=allocate_new(STRINGTYPE);
528 strobj->___value___=chararray;
529 strobj->___count___=length;
530 strobj->___offset___=0;
532 for(i=0;i<length;i++) {
533 ((short *)(((char *)& chararray->___length___)+sizeof(int)))[i]=(short)str[i]; }
537 /* Generated code calls this if we fail a bounds check */
538 void failedboundschk() {
540 printf("Array out of bounds\n");
543 longjmp(error_handler,2);
549 longjmp(error_handler,4);
551 printf("Aborting\n");