2 #include "structdefs.h"
14 extern int classsize[];
15 jmp_buf error_handler;
20 float failurechance=0;
22 int injectinstructionfailures;
24 float instfailurechance=0;
31 #include "checkpoint.h"
33 #include "SimpleHash.h"
34 #include "GenericHashtable.h"
35 #include <sys/select.h>
38 #include "instrument.h"
41 struct Queue * activetasks;
42 struct parameterwrapper * objectqueues[NUMCLASSES];
43 struct genhashtable * failedtasks;
44 struct taskparamdescriptor * currtpd;
45 struct RuntimeHash * forward;
46 struct RuntimeHash * reverse;
49 int main(int argc, char **argv) {
51 GC_init(); // Initialize the garbage collector
58 /* Create table for failed tasks */
59 failedtasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd,
60 (int (*)(void *,void *)) &comparetpd);
61 /* Create queue of active tasks */
62 activetasks=createQueue();
64 /* Process task information */
67 /* Create startup object */
68 createstartupobject(argc, argv);
70 /* Start executing the tasks */
74 void createstartupobject(int argc, char ** argv) {
77 /* Allocate startup object */
79 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(NULL, STARTUPTYPE);
80 struct ArrayObject * stringarray=allocate_newarray(NULL, STRINGARRAYTYPE, argc-1);
82 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
83 struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1);
85 /* Build array of strings */
86 startupobject->___parameters___=stringarray;
88 int length=strlen(argv[i]);
90 struct ___String___ *newstring=NewString(NULL, argv[i],length);
92 struct ___String___ *newstring=NewString(argv[i],length);
94 ((void **)(((char *)& stringarray->___length___)+sizeof(int)))[i-1]=newstring;
97 /* Set initialized flag for startup object */
98 flagorand(startupobject,1,0xFFFFFFFF);
101 int hashCodetpd(struct taskparamdescriptor *ftd) {
102 int hash=(int)ftd->task;
104 for(i=0;i<ftd->numParameters;i++) {
105 hash^=(int)ftd->parameterArray[i];
110 int comparetpd(struct taskparamdescriptor *ftd1, struct taskparamdescriptor *ftd2) {
112 if (ftd1->task!=ftd2->task)
114 for(i=0;i<ftd1->numParameters;i++)
115 if (ftd1->parameterArray[i]!=ftd2->parameterArray[i])
120 /* This function updates the flag for object ptr. It or's the flag
121 with the or mask and and's it with the andmask. */
123 void flagorand(void * ptr, int ormask, int andmask) {
124 int oldflag=((int *)ptr)[1];
125 struct RuntimeHash *flagptr=(struct RuntimeHash *)(((int*)ptr)[2]);
126 int flag=ormask|oldflag;
128 if (flag==oldflag) /* Don't do anything */
132 /*Remove object from all queues */
133 while(flagptr!=NULL) {
134 struct RuntimeHash *next;
135 RuntimeHashget(flagptr, (int) ptr, (int *) &next);
136 RuntimeHashremove(flagptr, (int)ptr, (int) next);
141 struct QueueItem *tmpptr;
142 struct parameterwrapper * parameter=objectqueues[((int *)ptr)[0]];
144 struct RuntimeHash * prevptr=NULL;
145 while(parameter!=NULL) {
146 for(i=0;i<parameter->numberofterms;i++) {
147 int andmask=parameter->intarray[i*2];
148 int checkmask=parameter->intarray[i*2+1];
149 if ((flag&andmask)==checkmask) {
150 RuntimeHashadd(parameter->objectset, (int) ptr, (int) prevptr);
151 prevptr=parameter->objectset;
153 struct RuntimeIterator iteratorarray[MAXTASKPARAMS];
154 void * taskpointerarray[MAXTASKPARAMS];
156 int numparams=parameter->task->numParameters;
158 struct taskdescriptor * task=parameter->task;
160 for(j=0;j<numparams;j++) {
161 struct parameterwrapper *pw=(struct parameterwrapper *)task->descriptorarray[j]->queue;
163 taskpointerarray[j]=ptr;
166 RuntimeHashiterator(pw->objectset, &iteratorarray[j]);
167 if (RunhasNext(&iteratorarray[j])) {
168 taskpointerarray[j]=(void *) Runkey(&iteratorarray[j]);
169 Runnext(&iteratorarray[j]);
172 break; /* No tasks to dispatch */
176 /* Queue task items... */
179 struct taskparamdescriptor *tpd=RUNMALLOC(sizeof(struct taskparamdescriptor));
181 tpd->numParameters=numparams;
182 tpd->parameterArray=RUNMALLOC(sizeof(void *)*numparams);
183 for(j=0;j<numparams;j++)
184 tpd->parameterArray[j]=taskpointerarray[j];
186 if (!gencontains(failedtasks, tpd))
187 addNewItem(activetasks, tpd);
189 RUNFREE(tpd->parameterArray);
193 /* This loop iterates to the next parameter combination */
194 for(j=0;j<numparams;j++) {
196 if ((j+1)==numparams)
200 if (RunhasNext(&iteratorarray[j])) {
201 taskpointerarray[j]=(void *) Runkey(&iteratorarray[j]);
202 Runnext(&iteratorarray[j]);
204 } else if ((j+1)!=numparams) {
205 RuntimeHashiterator(task->descriptorarray[j]->queue, &iteratorarray[j]);
216 parameter=parameter->next;
218 ((struct RuntimeHash **)ptr)[2]=prevptr;
222 /* Handler for signals. The signals catch null pointer errors and
223 arithmatic errors. */
225 void myhandler(int sig, siginfo_t *info, void *uap) {
227 printf("sig=%d\n",sig);
230 longjmp(error_handler,1);
235 struct RuntimeHash *fdtoobject;
237 void addreadfd(int fd) {
240 FD_SET(fd, &readfds);
243 void removereadfd(int fd) {
244 FD_CLR(fd, &readfds);
245 if (maxreadfd==(fd+1)) {
247 while(maxreadfd>0&&!FD_ISSET(maxreadfd-1, &readfds))
258 void executetasks() {
259 void * taskpointerarray[MAXTASKPARAMS+OFFSET];
261 /* Set up signal handlers */
262 struct sigaction sig;
263 sig.sa_sigaction=&myhandler;
264 sig.sa_flags=SA_SIGINFO;
265 sigemptyset(&sig.sa_mask);
267 /* Catch bus errors, segmentation faults, and floating point exceptions*/
268 sigaction(SIGBUS,&sig,0);
269 sigaction(SIGSEGV,&sig,0);
270 sigaction(SIGFPE,&sig,0);
271 sigaction(SIGPIPE,&sig,0);
276 fdtoobject=allocateRuntimeHash(100);
278 /* Map first block of memory to protected, anonymous page */
279 mmap(0, 0x1000, 0, MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
282 while(!isEmpty(activetasks)||(maxreadfd>0)) {
284 /* Check if any filedescriptors have IO pending */
287 struct timeval timeout={0,0};
291 numselect=select(maxreadfd, &tmpreadfds, NULL, NULL, &timeout);
293 /* Process ready fd's */
295 for(fd=0;fd<maxreadfd;fd++) {
296 if (FD_ISSET(fd, &tmpreadfds)) {
297 /* Set ready flag on object */
299 if (RuntimeHashget(fdtoobject, fd,(int *) &objptr)) {
300 flagorand(objptr,1,0xFFFFFFFF); /* Set the first flag to 1 */
307 /* See if there are any active tasks */
308 if (!isEmpty(activetasks)) {
310 struct QueueItem * qi=(struct QueueItem *) getTail(activetasks);
311 currtpd=(struct taskparamdescriptor *) qi->objectptr;
312 removeItem(activetasks, qi);
314 /* Check if this task has failed */
315 if (gencontains(failedtasks, currtpd)) {
316 // Free up task parameter descriptor
317 RUNFREE(currtpd->parameterArray);
322 /* Make sure that the parameters are still in the queues */
323 for(i=0;i<currtpd->task->numParameters;i++) {
324 void * parameter=currtpd->parameterArray[i];
325 struct parameterdescriptor * pd=currtpd->task->descriptorarray[i];
326 struct parameterwrapper *pw=(struct parameterwrapper *) pd->queue;
327 if (!RuntimeHashcontainskey(pw->objectset, (int) parameter)) {
328 RUNFREE(currtpd->parameterArray);
332 taskpointerarray[i+OFFSET]=parameter;
335 /* Checkpoint the state */
336 forward=allocateRuntimeHash(100);
337 reverse=allocateRuntimeHash(100);
338 void ** checkpoint=makecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, forward, reverse);
340 if (x=setjmp(error_handler)) {
344 printf("Fatal Error=%d, Recovering!\n",x);
346 genputtable(failedtasks,currtpd,currtpd);
347 restorecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, checkpoint, forward, reverse);
348 freeRuntimeHash(forward);
349 freeRuntimeHash(reverse);
354 if (injectfailures) {
355 if ((((double)random())/RAND_MAX)<failurechance) {
356 printf("\nINJECTING TASK FAILURE to %s\n", currtpd->task->name);
357 longjmp(error_handler,10);
360 /* Actually call task */
362 ((int *)taskpointerarray)[0]=currtpd->task->numParameters;
363 taskpointerarray[1]=NULL;
367 printf("ENTER %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
368 ((void (*) (void **)) currtpd->task->taskptr)(taskpointerarray);
369 printf("EXIT %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
371 ((void (*) (void **)) currtpd->task->taskptr)(taskpointerarray);
372 freeRuntimeHash(forward);
373 freeRuntimeHash(reverse);
375 // Free up task parameter descriptor
376 RUNFREE(currtpd->parameterArray);
386 /* This function processes the task information to create queues for
387 each parameter type. */
389 void processtasks() {
391 for(i=0;i<numtasks;i++) {
392 struct taskdescriptor * task=taskarray[i];
395 for(j=0;j<task->numParameters;j++) {
396 struct parameterdescriptor *param=task->descriptorarray[j];
397 struct parameterwrapper * parameter=RUNMALLOC(sizeof(struct parameterwrapper));
398 struct parameterwrapper ** ptr=&objectqueues[param->type];
400 param->queue=parameter;
401 parameter->objectset=allocateRuntimeHash(10);
402 parameter->numberofterms=param->numberterms;
403 parameter->intarray=param->intarray;
404 parameter->task=task;
405 /* Link new queue in */
415 /* This function inject failures */
417 void injectinstructionfailure() {
419 if (injectinstructionfailures) {
422 instructioncount=failurecount;
423 instaccum+=failurecount;
424 if ((((double)random())/RAND_MAX)<instfailurechance) {
427 printf("FAILURE!!! %d\n",numfailures);
428 longjmp(error_handler,11);
433 if (injectinstructionfailures) {
436 instaccum+=failurecount;
437 if ((((double)random())/RAND_MAX)<instfailurechance) {
440 printf("FAILURE!!! %d\n",numfailures);
448 void CALL01(___System______printString____L___String___,struct ___String___ * ___s___) {
449 struct ArrayObject * chararray=VAR(___s___)->___value___;
451 int offset=VAR(___s___)->___offset___;
452 for(i=0;i<VAR(___s___)->___count___;i++) {
453 short sc=((short *)(((char *)& chararray->___length___)+sizeof(int)))[i+offset];
458 /* Object allocation function */
461 void * allocate_new(void * ptr, int type) {
462 struct ___Object___ * v=(struct ___Object___ *) mygcmalloc((struct garbagelist *) ptr, classsize[type]);
472 /* Array allocation function */
474 struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
475 struct ArrayObject * v=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+length*classsize[type]);
477 v->___length___=length;
487 void * allocate_new(int type) {
488 void * v=FREEMALLOC(classsize[type]);
493 /* Array allocation function */
495 struct ArrayObject * allocate_newarray(int type, int length) {
496 struct ArrayObject * v=FREEMALLOC(sizeof(struct ArrayObject)+length*classsize[type]);
498 v->___length___=length;
504 /* Converts C character arrays into Java strings */
506 struct ___String___ * NewString(void * ptr, const char *str,int length) {
508 struct ___String___ * NewString(const char *str,int length) {
511 struct ArrayObject * chararray=allocate_newarray((struct garbagelist *)ptr, CHARARRAYTYPE, length);
512 struct ___String___ * strobj=allocate_new((struct garbagelist *) ptr, STRINGTYPE);
514 struct ArrayObject * chararray=allocate_newarray(CHARARRAYTYPE, length);
515 struct ___String___ * strobj=allocate_new(STRINGTYPE);
518 strobj->___value___=chararray;
519 strobj->___count___=length;
520 strobj->___offset___=0;
522 for(i=0;i<length;i++) {
523 ((short *)(((char *)& chararray->___length___)+sizeof(int)))[i]=(short)str[i]; }
527 /* Generated code calls this if we fail a bounds check */
529 void failedboundschk() {
531 printf("Array out of bounds\n");
538 longjmp(error_handler,2);
542 /* Abort task call */
545 longjmp(error_handler,4);
547 printf("Aborting\n");