changes to runtime/etc to build in repair checking code
[IRC.git] / Robust / src / Runtime / runtime.c
1 #include "runtime.h"
2 #include "structdefs.h"
3 #include <string.h>
4 #include <signal.h>
5 #include "mem.h"
6 #include<fcntl.h>
7 #include<sys/types.h>
8 #include<sys/mman.h>
9 #include<errno.h>
10 #include<signal.h>
11 #include<stdio.h>
12
13 extern int classsize[];
14 jmp_buf error_handler;
15
16 #ifdef TASK
17 #include "checkpoint.h"
18 #include "Queue.h"
19 #include "SimpleHash.h"
20 #include "GenericHashtable.h"
21
22 struct Queue * activetasks;
23 struct parameterwrapper * objectqueues[NUMCLASSES];
24 struct genhashtable * failedtasks;
25
26 int main(int argc, char **argv) {
27   GC_init();
28   {
29   int i;
30   /* Allocate startup object */
31   struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
32   struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc); 
33   failedtasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd, 
34                                    (int (*)(void *,void *)) &comparetpd);
35   
36   activetasks=createQueue();
37
38   /* Set flags */
39   processtasks();
40   flagorand(startupobject,1,0xFFFFFFFF);
41
42   /* Build array of strings */
43
44   startupobject->___parameters___=stringarray;
45
46   for(i=0;i<argc;i++) {
47     int length=strlen(argv[i]);
48     struct ___String___ *newstring=NewString(argv[i],length);
49     ((void **)(((char *)& stringarray->___length___)+sizeof(int)))[i]=newstring;
50   }
51   executetasks();
52   }
53 }
54
55 int hashCodetpd(struct taskparamdescriptor *ftd) {
56   int hash=(int)ftd->task;
57   int i;
58   for(i=0;i<ftd->numParameters;i++) {
59     hash^=(int)ftd->parameterArray[i];
60   }
61   return hash;
62 }
63
64 int comparetpd(struct taskparamdescriptor *ftd1, struct taskparamdescriptor *ftd2) {
65   int i;
66   if (ftd1->task!=ftd2->task)
67     return 0;
68   for(i=0;i<ftd1->numParameters;i++)
69     if (ftd1->parameterArray[i]!=ftd2->parameterArray[i])
70       return 0;
71   return 1;
72 }
73
74 void flagorand(void * ptr, int ormask, int andmask) {
75   int flag=((int *)ptr)[1];
76   struct RuntimeHash *flagptr=(struct RuntimeHash *)(((int*)ptr)[2]);
77   flag|=ormask;
78   flag&=andmask;
79   ((int*)ptr)[1]=flag;
80   /*Remove from all queues */
81   while(flagptr!=NULL) {
82     struct RuntimeHash *next;
83     RuntimeHashget(flagptr, (int) ptr, (int *) &next);
84     RuntimeHashremove(flagptr, (int)ptr, (int) next);
85     flagptr=next;
86   }
87   
88   {
89     struct QueueItem *tmpptr;
90     struct parameterwrapper * parameter=objectqueues[((int *)ptr)[0]];
91     int i;
92     struct RuntimeHash * prevptr=NULL;
93     while(parameter!=NULL) {
94       for(i=0;i<parameter->numberofterms;i++) {
95         int andmask=parameter->intarray[i*2];
96         int checkmask=parameter->intarray[i*2+1];
97         if ((flag&andmask)==checkmask) {
98           RuntimeHashadd(parameter->objectset, (int) ptr, (int) prevptr);
99           prevptr=parameter->objectset;
100           {
101             struct RuntimeIterator iteratorarray[MAXTASKPARAMS];
102             void * taskpointerarray[MAXTASKPARAMS];
103             int j;
104             int numparams=parameter->task->numParameters;
105             int done=1;
106             struct taskdescriptor * task=parameter->task;
107             int newindex=-1;
108             for(j=0;j<numparams;j++) {
109               struct parameterwrapper *pw=(struct parameterwrapper *)task->descriptorarray[j]->queue;
110               if (parameter==pw) {
111                 taskpointerarray[j]=ptr;
112                 newindex=j;
113               } else {
114                 RuntimeHashiterator(pw->objectset, &iteratorarray[j]);
115                 if (RunhasNext(&iteratorarray[j]))
116                   taskpointerarray[j]=(void *) Runnext(&iteratorarray[j]);
117                 else
118                   break; /* No tasks to dispatch */
119               }
120             }
121             /* Queue task items... */
122
123             while(done) {
124               struct taskparamdescriptor *tpd=RUNMALLOC(sizeof(struct taskparamdescriptor));
125               tpd->task=task;
126               tpd->numParameters=numparams;
127               tpd->parameterArray=RUNMALLOC(sizeof(void *)*numparams);
128               for(j=0;j<numparams;j++)
129                 tpd->parameterArray[j]=taskpointerarray[j];
130               /* Queue task */
131               if (!gencontains(failedtasks, tpd))
132                 addNewItem(activetasks, tpd);
133               
134               /* This loop iterates to the next paramter combination */
135               for(j=0;j<numparams;j++) {
136                 if (j==newindex) {
137                   if ((j+1)==numparams)
138                     done=0;
139                   continue;
140                 }
141                 if (RunhasNext(&iteratorarray[j])) {
142                   taskpointerarray[j]=(void *) Runnext(&iteratorarray[j]);
143                   break;
144                 } else if ((j+1)!=numparams) {
145                   RuntimeHashiterator(task->descriptorarray[j]->queue, &iteratorarray[j]);
146                 } else {
147                   done=0;
148                   break;
149                 }
150               }
151             }
152           }
153           break;
154         }
155       }
156       parameter=parameter->next;
157     }
158     ((struct RuntimeHash **)ptr)[2]=prevptr;
159   }
160 }
161
162 /* Handler for signals */
163 void myhandler(int sig, struct __siginfo *info, void *uap) {
164 #ifdef DEBUG
165   printf("sig=%d\n",sig);
166   printf("signal\n");
167 #endif
168   longjmp(error_handler,1);
169 }
170
171 void executetasks() {
172   void * taskpointerarray[MAXTASKPARAMS];
173
174   /* Set up signal handlers */
175   struct sigaction sig;
176   sig.sa_sigaction=&myhandler;
177   sig.sa_flags=SA_SIGINFO;
178   sigemptyset(&sig.sa_mask);
179
180   /* Catch bus errors, segmentation faults, and floating point exceptions*/
181   sigaction(SIGBUS,&sig,0);
182   sigaction(SIGSEGV,&sig,0);
183   sigaction(SIGFPE,&sig,0);
184
185   /* Map first block of memory to protected, anonymous page */
186   mmap(0, 0x1000, 0, MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
187
188   newtask:
189   while(!isEmpty(activetasks)) {
190     struct QueueItem * qi=(struct QueueItem *) getTail(activetasks);
191     struct taskparamdescriptor *tpd=(struct taskparamdescriptor *) qi->objectptr;
192     int i;
193     removeItem(activetasks, qi);
194     
195     for(i=0;i<tpd->task->numParameters;i++) {
196       void * parameter=tpd->parameterArray[i];
197       struct parameterdescriptor * pd=tpd->task->descriptorarray[i];
198       struct parameterwrapper *pw=(struct parameterwrapper *) pd->queue;
199       if (!RuntimeHashcontainskey(pw->objectset, (int) parameter))
200         goto newtask;
201       taskpointerarray[i]=parameter;
202     }
203     {
204       struct RuntimeHash * forward=allocateRuntimeHash(100);
205       struct RuntimeHash * reverse=allocateRuntimeHash(100);
206       void ** checkpoint=makecheckpoint(tpd->task->numParameters, taskpointerarray, forward, reverse);
207       if (setjmp(error_handler)) {
208         /* Recover */
209         int h;
210 #ifdef DEBUG
211         printf("Recovering\n");
212 #endif
213         genputtable(failedtasks,tpd,tpd);
214         restorecheckpoint(tpd->task->numParameters, taskpointerarray, checkpoint, forward, reverse);
215       } else {
216         /* Actually call task */
217         ((void (*) (void **)) tpd->task->taskptr)(taskpointerarray);
218       }
219     }
220   }
221 }
222
223 void processtasks() {
224   int i;
225   for(i=0;i<numtasks;i++) {
226     struct taskdescriptor * task=taskarray[i];
227     int j;
228
229     for(j=0;j<task->numParameters;j++) {
230       struct parameterdescriptor *param=task->descriptorarray[j];
231       struct parameterwrapper * parameter=RUNMALLOC(sizeof(struct parameterwrapper));
232       struct parameterwrapper ** ptr=&objectqueues[param->type];
233
234       param->queue=parameter;
235       parameter->objectset=allocateRuntimeHash(10);
236       parameter->numberofterms=param->numberterms;
237       parameter->intarray=param->intarray;
238       parameter->task=task;
239       /* Link new queue in */
240       while((*ptr)!=NULL)
241         ptr=&((*ptr)->next);
242       (*ptr)=parameter;
243     }
244   }
245 }
246 #endif
247
248 int ___Object______hashcode____(struct ___Object___ * ___this___) {
249   return (int) ___this___;
250 }
251
252 void ___System______printString____L___String___(struct ___String___ * s) {
253     struct ArrayObject * chararray=s->___string___;
254     int i;
255     for(i=0;i<chararray->___length___;i++) {
256         short s= ((short *)(((char *)& chararray->___length___)+sizeof(int)))[i];
257         putchar(s);
258     }
259 }
260
261 void * allocate_new(int type) {
262   void * v=FREEMALLOC(classsize[type]);
263   *((int *)v)=type;
264   return v;
265 }
266
267 struct ArrayObject * allocate_newarray(int type, int length) {
268   struct ArrayObject * v=FREEMALLOC(sizeof(struct ArrayObject)+length*classsize[type]);
269   v->type=type;
270   v->___length___=length;
271   return v;
272 }
273
274 struct ___String___ * NewString(char *str,int length) {
275   struct ArrayObject * chararray=allocate_newarray(CHARARRAYTYPE, length);
276   struct ___String___ * strobj=allocate_new(STRINGTYPE);
277   int i;
278   strobj->___string___=chararray;
279   for(i=0;i<length;i++) {
280     ((short *)(((char *)& chararray->___length___)+sizeof(int)))[i]=(short)str[i];  }
281   return strobj;
282 }
283
284 void failedboundschk() {
285 #ifndef TASK
286   printf("Array out of bounds\n");
287   exit(-1);
288 #else
289   longjmp(error_handler,2);
290 #endif
291 }
292
293 void failednullptr() {
294 #ifndef TASK
295   printf("Dereferenced a null pointer\n");
296   exit(-1);
297 #else
298   longjmp(error_handler,3);
299 #endif
300 }