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