2 #include "structdefs.h"
14 extern int classsize[];
15 jmp_buf error_handler;
19 #include "checkpoint.h"
21 #include "SimpleHash.h"
22 #include "GenericHashtable.h"
23 #include <sys/select.h>
26 #include "instrument.h"
29 struct Queue * activetasks;
30 struct parameterwrapper * objectqueues[NUMCLASSES];
31 struct genhashtable * failedtasks;
34 float failurechance=0;
36 int injectinstructionfailures;
38 float instfailurechance=0;
42 int main(int argc, char **argv) {
44 GC_init(); // Initialize the garbage collector
53 /* Allocate startup object */
54 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
55 struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1);
56 failedtasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd,
57 (int (*)(void *,void *)) &comparetpd);
58 activetasks=createQueue();
62 flagorand(startupobject,1,0xFFFFFFFF);
64 /* Build array of strings */
66 startupobject->___parameters___=stringarray;
69 int length=strlen(argv[i]);
70 struct ___String___ *newstring=NewString(argv[i],length);
71 ((void **)(((char *)& stringarray->___length___)+sizeof(int)))[i-1]=newstring;
77 int hashCodetpd(struct taskparamdescriptor *ftd) {
78 int hash=(int)ftd->task;
80 for(i=0;i<ftd->numParameters;i++) {
81 hash^=(int)ftd->parameterArray[i];
86 int comparetpd(struct taskparamdescriptor *ftd1, struct taskparamdescriptor *ftd2) {
88 if (ftd1->task!=ftd2->task)
90 for(i=0;i<ftd1->numParameters;i++)
91 if (ftd1->parameterArray[i]!=ftd2->parameterArray[i])
96 /* This function updates the flag for object ptr. It or's the flag
97 with the or mask and and's it with the andmask. */
99 void flagorand(void * ptr, int ormask, int andmask) {
100 int flag=((int *)ptr)[1];
101 struct RuntimeHash *flagptr=(struct RuntimeHash *)(((int*)ptr)[2]);
106 /*Remove object from all queues */
107 while(flagptr!=NULL) {
108 struct RuntimeHash *next;
109 RuntimeHashget(flagptr, (int) ptr, (int *) &next);
110 RuntimeHashremove(flagptr, (int)ptr, (int) next);
115 struct QueueItem *tmpptr;
116 struct parameterwrapper * parameter=objectqueues[((int *)ptr)[0]];
118 struct RuntimeHash * prevptr=NULL;
119 while(parameter!=NULL) {
120 for(i=0;i<parameter->numberofterms;i++) {
121 int andmask=parameter->intarray[i*2];
122 int checkmask=parameter->intarray[i*2+1];
123 if ((flag&andmask)==checkmask) {
124 RuntimeHashadd(parameter->objectset, (int) ptr, (int) prevptr);
125 prevptr=parameter->objectset;
127 struct RuntimeIterator iteratorarray[MAXTASKPARAMS];
128 void * taskpointerarray[MAXTASKPARAMS];
130 int numparams=parameter->task->numParameters;
132 struct taskdescriptor * task=parameter->task;
134 for(j=0;j<numparams;j++) {
135 struct parameterwrapper *pw=(struct parameterwrapper *)task->descriptorarray[j]->queue;
137 taskpointerarray[j]=ptr;
140 RuntimeHashiterator(pw->objectset, &iteratorarray[j]);
141 if (RunhasNext(&iteratorarray[j])) {
142 taskpointerarray[j]=(void *) Runkey(&iteratorarray[j]);
143 Runnext(&iteratorarray[j]);
146 break; /* No tasks to dispatch */
150 /* Queue task items... */
153 struct taskparamdescriptor *tpd=RUNMALLOC(sizeof(struct taskparamdescriptor));
155 tpd->numParameters=numparams;
156 tpd->parameterArray=RUNMALLOC(sizeof(void *)*numparams);
157 for(j=0;j<numparams;j++)
158 tpd->parameterArray[j]=taskpointerarray[j];
160 if (!gencontains(failedtasks, tpd))
161 addNewItem(activetasks, tpd);
163 /* This loop iterates to the next parameter combination */
164 for(j=0;j<numparams;j++) {
166 if ((j+1)==numparams)
170 if (RunhasNext(&iteratorarray[j])) {
171 taskpointerarray[j]=(void *) Runkey(&iteratorarray[j]);
172 Runnext(&iteratorarray[j]);
174 } else if ((j+1)!=numparams) {
175 RuntimeHashiterator(task->descriptorarray[j]->queue, &iteratorarray[j]);
186 parameter=parameter->next;
188 ((struct RuntimeHash **)ptr)[2]=prevptr;
192 /* Handler for signals. The signals catch null pointer errors and
193 arithmatic errors. */
195 void myhandler(int sig, siginfo_t *info, void *uap) {
197 printf("sig=%d\n",sig);
200 longjmp(error_handler,1);
205 struct RuntimeHash *fdtoobject;
207 void addreadfd(int fd) {
210 FD_SET(fd, &readfds);
213 void removereadfd(int fd) {
214 FD_CLR(fd, &readfds);
215 if (maxreadfd==(fd+1)) {
217 while(maxreadfd>0&&!FD_ISSET(maxreadfd-1, &readfds))
228 void executetasks() {
229 void * taskpointerarray[MAXTASKPARAMS+OFFSET];
231 /* Set up signal handlers */
232 struct sigaction sig;
233 sig.sa_sigaction=&myhandler;
234 sig.sa_flags=SA_SIGINFO;
235 sigemptyset(&sig.sa_mask);
237 /* Catch bus errors, segmentation faults, and floating point exceptions*/
238 sigaction(SIGBUS,&sig,0);
239 sigaction(SIGSEGV,&sig,0);
240 sigaction(SIGFPE,&sig,0);
245 fdtoobject=allocateRuntimeHash(100);
247 /* Map first block of memory to protected, anonymous page */
248 mmap(0, 0x1000, 0, MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
251 while(!isEmpty(activetasks)||(maxreadfd>0)) {
253 /* Check if any filedescriptors have IO pending */
256 struct timeval timeout={0,0};
260 numselect=select(maxreadfd, &tmpreadfds, NULL, NULL, &timeout);
262 /* Process ready fd's */
264 for(fd=0;fd<maxreadfd;fd++) {
265 if (FD_ISSET(fd, &tmpreadfds)) {
266 /* Set ready flag on object */
268 if (RuntimeHashget(fdtoobject, fd,(int *) &objptr)) {
269 flagorand(objptr,1,0xFFFFFFFF); /* Set the first flag to 1 */
276 /* See if there are any active tasks */
277 if (!isEmpty(activetasks)) {
279 struct QueueItem * qi=(struct QueueItem *) getTail(activetasks);
280 struct taskparamdescriptor *tpd=(struct taskparamdescriptor *) qi->objectptr;
281 removeItem(activetasks, qi);
283 /* Check if this task has failed */
284 if (gencontains(failedtasks, tpd))
287 /* Make sure that the parameters are still in the queues */
288 for(i=0;i<tpd->task->numParameters;i++) {
289 void * parameter=tpd->parameterArray[i];
290 struct parameterdescriptor * pd=tpd->task->descriptorarray[i];
291 struct parameterwrapper *pw=(struct parameterwrapper *) pd->queue;
292 if (!RuntimeHashcontainskey(pw->objectset, (int) parameter))
294 taskpointerarray[i+OFFSET]=parameter;
297 /* Checkpoint the state */
298 struct RuntimeHash * forward=allocateRuntimeHash(100);
299 struct RuntimeHash * reverse=allocateRuntimeHash(100);
300 void ** checkpoint=makecheckpoint(tpd->task->numParameters, &taskpointerarray[OFFSET], forward, reverse);
302 if (x=setjmp(error_handler)) {
306 printf("Fatal Error=%d, Recovering!\n",x);
308 genputtable(failedtasks,tpd,tpd);
309 /* for(i=0;i<tpd->task->numParameters;i++) {
310 void *parameter=tpd->parameterArray[i];
312 // Create mapping from object -> failed tasks
313 struct tpdlist * tpnew=RUNMALLOC(sizeof(struct tpdlist));
315 if (gencontains(failedobjects, parameter)) {
316 struct tpdlist * tpdptr=gengettable(failedobjects, parameter);
317 tpnew->next=tpdptr->next;
321 genputtable(failedobjects, parameter, tpnew);
325 restorecheckpoint(tpd->task->numParameters, &taskpointerarray[OFFSET], checkpoint, forward, reverse);
327 if (injectfailures) {
328 if ((((double)random())/RAND_MAX)<failurechance) {
329 printf("\nINJECTING TASK FAILURE to %s\n", tpd->task->name);
330 longjmp(error_handler,10);
333 /* Actually call task */
335 ((int *)taskpointerarray)[0]=tpd->task->numParameters;
336 taskpointerarray[1]=NULL;
340 printf("ENTER %s count=%d\n",tpd->task->name, (instaccum-instructioncount));
341 ((void (*) (void **)) tpd->task->taskptr)(taskpointerarray);
342 printf("EXIT %s count=%d\n",tpd->task->name, (instaccum-instructioncount));
344 ((void (*) (void **)) tpd->task->taskptr)(taskpointerarray);
351 /* This function processes the task information to create queues for
352 each parameter type. */
354 void processtasks() {
356 for(i=0;i<numtasks;i++) {
357 struct taskdescriptor * task=taskarray[i];
360 for(j=0;j<task->numParameters;j++) {
361 struct parameterdescriptor *param=task->descriptorarray[j];
362 struct parameterwrapper * parameter=RUNMALLOC(sizeof(struct parameterwrapper));
363 struct parameterwrapper ** ptr=&objectqueues[param->type];
365 param->queue=parameter;
366 parameter->objectset=allocateRuntimeHash(10);
367 parameter->numberofterms=param->numberterms;
368 parameter->intarray=param->intarray;
369 parameter->task=task;
370 /* Link new queue in */
380 /* This function inject failures */
382 void injectinstructionfailure() {
384 if (injectinstructionfailures) {
387 instructioncount=failurecount;
388 instaccum+=failurecount;
389 if ((((double)random())/RAND_MAX)<instfailurechance) {
392 printf("FAILURE!!!\n");
393 longjmp(error_handler,11);
400 int CALL01(___Object______hashCode____, struct ___Object___ * ___this___) {
401 return (int) VAR(___this___);
404 int CALL01(___Object______getType____, struct ___Object___ * ___this___) {
405 return ((int *)VAR(___this___))[0];
408 void CALL01(___System______printString____L___String___,struct ___String___ * ___s___) {
409 struct ArrayObject * chararray=VAR(___s___)->___value___;
411 int offset=VAR(___s___)->___offset___;
412 for(i=0;i<VAR(___s___)->___count___;i++) {
413 short sc=((short *)(((char *)& chararray->___length___)+sizeof(int)))[i+offset];
418 /* Object allocation function */
420 void * allocate_new(int type) {
421 void * v=FREEMALLOC(classsize[type]);
426 /* Array allocation function */
428 struct ArrayObject * allocate_newarray(int type, int length) {
429 struct ArrayObject * v=FREEMALLOC(sizeof(struct ArrayObject)+length*classsize[type]);
431 v->___length___=length;
435 /* Converts C character arrays into Java strings */
437 struct ___String___ * NewString(const char *str,int length) {
438 struct ArrayObject * chararray=allocate_newarray(CHARARRAYTYPE, length);
439 struct ___String___ * strobj=allocate_new(STRINGTYPE);
441 strobj->___value___=chararray;
442 strobj->___count___=length;
443 strobj->___offset___=0;
445 for(i=0;i<length;i++) {
446 ((short *)(((char *)& chararray->___length___)+sizeof(int)))[i]=(short)str[i]; }
450 /* Generated code calls this if we fail a bounds check */
452 void failedboundschk() {
454 printf("Array out of bounds\n");
457 longjmp(error_handler,2);
461 /* Abort task call */
464 longjmp(error_handler,4);
466 printf("Aborting\n");