2 #include "structdefs.h"
14 extern int classsize[];
15 jmp_buf error_handler;
20 float failurechance=0;
22 int injectinstructionfailures;
24 float instfailurechance=0;
33 #include "checkpoint.h"
35 #include "SimpleHash.h"
36 #include "GenericHashtable.h"
37 #include <sys/select.h>
40 #include "instrument.h"
43 struct Queue * activetasks;
44 struct parameterwrapper * objectqueues[NUMCLASSES];
45 struct genhashtable * failedtasks;
46 struct taskparamdescriptor * currtpd;
47 struct RuntimeHash * forward;
48 struct RuntimeHash * reverse;
51 int main(int argc, char **argv) {
53 GC_init(); // Initialize the garbage collector
59 initializeexithandler();
60 /* Create table for failed tasks */
61 failedtasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd,
62 (int (*)(void *,void *)) &comparetpd);
63 /* Create queue of active tasks */
64 activetasks=createQueue();
66 /* Process task information */
69 /* Create startup object */
70 createstartupobject(argc, argv);
72 /* Start executing the tasks */
76 void createstartupobject(int argc, char ** argv) {
79 /* Allocate startup object */
81 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(NULL, STARTUPTYPE);
82 struct ArrayObject * stringarray=allocate_newarray(NULL, STRINGARRAYTYPE, argc-1);
84 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
85 struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1);
87 /* Build array of strings */
88 startupobject->___parameters___=stringarray;
90 int length=strlen(argv[i]);
92 struct ___String___ *newstring=NewString(NULL, argv[i],length);
94 struct ___String___ *newstring=NewString(argv[i],length);
96 ((void **)(((char *)& stringarray->___length___)+sizeof(int)))[i-1]=newstring;
99 /* Set initialized flag for startup object */
100 flagorand(startupobject,1,0xFFFFFFFF);
103 int hashCodetpd(struct taskparamdescriptor *ftd) {
104 int hash=(int)ftd->task;
106 for(i=0;i<ftd->numParameters;i++) {
107 hash^=(int)ftd->parameterArray[i];
112 int comparetpd(struct taskparamdescriptor *ftd1, struct taskparamdescriptor *ftd2) {
114 if (ftd1->task!=ftd2->task)
116 for(i=0;i<ftd1->numParameters;i++)
117 if (ftd1->parameterArray[i]!=ftd2->parameterArray[i])
122 /* This function updates the flag for object ptr. It or's the flag
123 with the or mask and and's it with the andmask. */
125 void flagorand(void * ptr, int ormask, int andmask) {
126 int oldflag=((int *)ptr)[1];
127 int flag=ormask|oldflag;
129 if (flag==oldflag) /* Don't do anything */
131 else flagbody(ptr, flag);
134 void flagorandinit(void * ptr, int ormask, int andmask) {
135 int oldflag=((int *)ptr)[1];
136 int flag=ormask|oldflag;
141 void flagbody(void *ptr, int flag) {
142 struct RuntimeHash *flagptr=(struct RuntimeHash *)(((int*)ptr)[2]);
145 /*Remove object from all queues */
146 while(flagptr!=NULL) {
147 struct RuntimeHash *next;
148 RuntimeHashget(flagptr, (int) ptr, (int *) &next);
149 RuntimeHashremove(flagptr, (int)ptr, (int) next);
154 struct QueueItem *tmpptr;
155 struct parameterwrapper * parameter=objectqueues[((int *)ptr)[0]];
157 struct RuntimeHash * prevptr=NULL;
158 while(parameter!=NULL) {
159 for(i=0;i<parameter->numberofterms;i++) {
160 int andmask=parameter->intarray[i*2];
161 int checkmask=parameter->intarray[i*2+1];
162 if ((flag&andmask)==checkmask) {
163 RuntimeHashadd(parameter->objectset, (int) ptr, (int) prevptr);
164 prevptr=parameter->objectset;
166 struct RuntimeIterator iteratorarray[MAXTASKPARAMS];
167 void * taskpointerarray[MAXTASKPARAMS];
169 int numparams=parameter->task->numParameters;
171 struct taskdescriptor * task=parameter->task;
173 for(j=0;j<numparams;j++) {
174 struct parameterwrapper *pw=(struct parameterwrapper *)task->descriptorarray[j]->queue;
176 taskpointerarray[j]=ptr;
179 RuntimeHashiterator(pw->objectset, &iteratorarray[j]);
180 if (RunhasNext(&iteratorarray[j])) {
181 taskpointerarray[j]=(void *) Runkey(&iteratorarray[j]);
182 Runnext(&iteratorarray[j]);
185 break; /* No tasks to dispatch */
189 /* Queue task items... */
192 struct taskparamdescriptor *tpd=RUNMALLOC(sizeof(struct taskparamdescriptor));
194 tpd->numParameters=numparams;
195 tpd->parameterArray=RUNMALLOC(sizeof(void *)*numparams);
196 for(j=0;j<numparams;j++)
197 tpd->parameterArray[j]=taskpointerarray[j];
199 if (!gencontains(failedtasks, tpd))
200 addNewItem(activetasks, tpd);
202 RUNFREE(tpd->parameterArray);
206 /* This loop iterates to the next parameter combination */
207 for(j=0;j<numparams;j++) {
209 if ((j+1)==numparams)
213 if (RunhasNext(&iteratorarray[j])) {
214 taskpointerarray[j]=(void *) Runkey(&iteratorarray[j]);
215 Runnext(&iteratorarray[j]);
217 } else if ((j+1)!=numparams) {
218 RuntimeHashiterator(task->descriptorarray[j]->queue, &iteratorarray[j]);
229 parameter=parameter->next;
231 ((struct RuntimeHash **)ptr)[2]=prevptr;
235 /* Handler for signals. The signals catch null pointer errors and
236 arithmatic errors. */
238 void myhandler(int sig, siginfo_t *info, void *uap) {
240 printf("sig=%d\n",sig);
243 longjmp(error_handler,1);
248 struct RuntimeHash *fdtoobject;
250 void addreadfd(int fd) {
253 FD_SET(fd, &readfds);
256 void removereadfd(int fd) {
257 FD_CLR(fd, &readfds);
258 if (maxreadfd==(fd+1)) {
260 while(maxreadfd>0&&!FD_ISSET(maxreadfd-1, &readfds))
271 void executetasks() {
272 void * taskpointerarray[MAXTASKPARAMS+OFFSET];
274 /* Set up signal handlers */
275 struct sigaction sig;
276 sig.sa_sigaction=&myhandler;
277 sig.sa_flags=SA_SIGINFO;
278 sigemptyset(&sig.sa_mask);
280 /* Catch bus errors, segmentation faults, and floating point exceptions*/
281 sigaction(SIGBUS,&sig,0);
282 sigaction(SIGSEGV,&sig,0);
283 sigaction(SIGFPE,&sig,0);
284 sigaction(SIGPIPE,&sig,0);
289 fdtoobject=allocateRuntimeHash(100);
291 /* Map first block of memory to protected, anonymous page */
292 mmap(0, 0x1000, 0, MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
295 while(!isEmpty(activetasks)||(maxreadfd>0)) {
297 /* Check if any filedescriptors have IO pending */
300 struct timeval timeout={0,0};
304 numselect=select(maxreadfd, &tmpreadfds, NULL, NULL, &timeout);
306 /* Process ready fd's */
308 for(fd=0;fd<maxreadfd;fd++) {
309 if (FD_ISSET(fd, &tmpreadfds)) {
310 /* Set ready flag on object */
312 // printf("Setting fd %d\n",fd);
313 if (RuntimeHashget(fdtoobject, fd,(int *) &objptr)) {
314 flagorand(objptr,1,0xFFFFFFFF); /* Set the first flag to 1 */
321 /* See if there are any active tasks */
322 if (!isEmpty(activetasks)) {
324 struct QueueItem * qi=(struct QueueItem *) getTail(activetasks);
325 currtpd=(struct taskparamdescriptor *) qi->objectptr;
326 removeItem(activetasks, qi);
328 /* Check if this task has failed */
329 if (gencontains(failedtasks, currtpd)) {
330 // Free up task parameter descriptor
331 RUNFREE(currtpd->parameterArray);
336 /* Make sure that the parameters are still in the queues */
337 for(i=0;i<currtpd->task->numParameters;i++) {
338 void * parameter=currtpd->parameterArray[i];
339 struct parameterdescriptor * pd=currtpd->task->descriptorarray[i];
340 struct parameterwrapper *pw=(struct parameterwrapper *) pd->queue;
341 if (!RuntimeHashcontainskey(pw->objectset, (int) parameter)) {
342 RUNFREE(currtpd->parameterArray);
346 taskpointerarray[i+OFFSET]=parameter;
349 /* Checkpoint the state */
350 forward=allocateRuntimeHash(100);
351 reverse=allocateRuntimeHash(100);
352 void ** checkpoint=makecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, forward, reverse);
354 if (x=setjmp(error_handler)) {
358 printf("Fatal Error=%d, Recovering!\n",x);
360 genputtable(failedtasks,currtpd,currtpd);
361 restorecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, checkpoint, forward, reverse);
362 freeRuntimeHash(forward);
363 freeRuntimeHash(reverse);
368 if (injectfailures) {
369 if ((((double)random())/RAND_MAX)<failurechance) {
370 printf("\nINJECTING TASK FAILURE to %s\n", currtpd->task->name);
371 longjmp(error_handler,10);
374 /* Actually call task */
376 ((int *)taskpointerarray)[0]=currtpd->task->numParameters;
377 taskpointerarray[1]=NULL;
381 printf("ENTER %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
382 ((void (*) (void **)) currtpd->task->taskptr)(taskpointerarray);
383 printf("EXIT %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
385 ((void (*) (void **)) currtpd->task->taskptr)(taskpointerarray);
386 freeRuntimeHash(forward);
387 freeRuntimeHash(reverse);
389 // Free up task parameter descriptor
390 RUNFREE(currtpd->parameterArray);
400 /* This function processes the task information to create queues for
401 each parameter type. */
403 void processtasks() {
405 for(i=0;i<numtasks;i++) {
406 struct taskdescriptor * task=taskarray[i];
409 for(j=0;j<task->numParameters;j++) {
410 struct parameterdescriptor *param=task->descriptorarray[j];
411 struct parameterwrapper * parameter=RUNMALLOC(sizeof(struct parameterwrapper));
412 struct parameterwrapper ** ptr=&objectqueues[param->type];
414 param->queue=parameter;
415 parameter->objectset=allocateRuntimeHash(10);
416 parameter->numberofterms=param->numberterms;
417 parameter->intarray=param->intarray;
418 parameter->task=task;
419 /* Link new queue in */
429 void exithandler(int sig, siginfo_t *info, void * uap) {
433 void initializeexithandler() {
434 struct sigaction sig;
435 sig.sa_sigaction=&exithandler;
436 sig.sa_flags=SA_SIGINFO;
437 sigemptyset(&sig.sa_mask);
438 sigaction(SIGUSR2, &sig, 0);
442 /* This function inject failures */
444 void injectinstructionfailure() {
446 if (injectinstructionfailures) {
449 instructioncount=failurecount;
450 instaccum+=failurecount;
451 if ((((double)random())/RAND_MAX)<instfailurechance) {
454 printf("FAILURE!!! %d\n",numfailures);
455 longjmp(error_handler,11);
460 if (injectinstructionfailures) {
463 instaccum+=failurecount;
464 if ((((double)random())/RAND_MAX)<instfailurechance) {
467 printf("FAILURE!!! %d\n",numfailures);
475 void CALL01(___System______printString____L___String___,struct ___String___ * ___s___) {
476 struct ArrayObject * chararray=VAR(___s___)->___value___;
478 int offset=VAR(___s___)->___offset___;
479 for(i=0;i<VAR(___s___)->___count___;i++) {
480 short sc=((short *)(((char *)& chararray->___length___)+sizeof(int)))[i+offset];
485 /* Object allocation function */
488 void * allocate_new(void * ptr, int type) {
489 struct ___Object___ * v=(struct ___Object___ *) mygcmalloc((struct garbagelist *) ptr, classsize[type]);
499 /* Array allocation function */
501 struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
502 struct ArrayObject * v=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+length*classsize[type]);
505 printf("ERROR: negative array\n");
508 v->___length___=length;
518 void * allocate_new(int type) {
519 void * v=FREEMALLOC(classsize[type]);
524 /* Array allocation function */
526 struct ArrayObject * allocate_newarray(int type, int length) {
527 struct ArrayObject * v=FREEMALLOC(sizeof(struct ArrayObject)+length*classsize[type]);
529 v->___length___=length;
535 /* Converts C character arrays into Java strings */
537 struct ___String___ * NewString(void * ptr, const char *str,int length) {
539 struct ___String___ * NewString(const char *str,int length) {
543 struct ArrayObject * chararray=allocate_newarray((struct garbagelist *)ptr, CHARARRAYTYPE, length);
544 int ptrarray[]={1, (int) ptr, (int) chararray};
545 struct ___String___ * strobj=allocate_new((struct garbagelist *) &ptrarray, STRINGTYPE);
546 chararray=(struct ArrayObject *) ptrarray[2];
548 struct ArrayObject * chararray=allocate_newarray(CHARARRAYTYPE, length);
549 struct ___String___ * strobj=allocate_new(STRINGTYPE);
551 strobj->___value___=chararray;
552 strobj->___count___=length;
553 strobj->___offset___=0;
555 for(i=0;i<length;i++) {
556 ((short *)(((char *)& chararray->___length___)+sizeof(int)))[i]=(short)str[i]; }
560 /* Generated code calls this if we fail a bounds check */
562 void failedboundschk() {
564 printf("Array out of bounds\n");
571 longjmp(error_handler,2);
575 /* Abort task call */
578 longjmp(error_handler,4);
580 printf("Aborting\n");