fixed broken method signatures
[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 #include <sys/select.h>
22 #include <sys/socket.h>
23 #include <fcntl.h>
24 #include <arpa/inet.h>
25
26 #ifdef CONSCHECK
27 #include "instrument.h"
28 #endif
29
30 struct Queue * activetasks;
31 struct parameterwrapper * objectqueues[NUMCLASSES];
32 struct genhashtable * failedtasks;
33
34 int main(int argc, char **argv) {
35   GC_init();
36 #ifdef CONSCHECK
37   initializemmap();
38 #endif
39   {
40   int i;
41   /* Allocate startup object */
42   struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
43   struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1); 
44   failedtasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd, 
45                                    (int (*)(void *,void *)) &comparetpd);
46   
47   activetasks=createQueue();
48
49   /* Set flags */
50   processtasks();
51   flagorand(startupobject,1,0xFFFFFFFF);
52
53   /* Build array of strings */
54
55   startupobject->___parameters___=stringarray;
56
57   for(i=1;i<argc;i++) {
58     int length=strlen(argv[i]);
59     struct ___String___ *newstring=NewString(argv[i],length);
60     ((void **)(((char *)& stringarray->___length___)+sizeof(int)))[i-1]=newstring;
61   }
62   executetasks();
63   }
64 }
65
66 int hashCodetpd(struct taskparamdescriptor *ftd) {
67   int hash=(int)ftd->task;
68   int i;
69   for(i=0;i<ftd->numParameters;i++) {
70     hash^=(int)ftd->parameterArray[i];
71   }
72   return hash;
73 }
74
75 int comparetpd(struct taskparamdescriptor *ftd1, struct taskparamdescriptor *ftd2) {
76   int i;
77   if (ftd1->task!=ftd2->task)
78     return 0;
79   for(i=0;i<ftd1->numParameters;i++)
80     if (ftd1->parameterArray[i]!=ftd2->parameterArray[i])
81       return 0;
82   return 1;
83 }
84
85 void flagorand(void * ptr, int ormask, int andmask) {
86   int flag=((int *)ptr)[1];
87   struct RuntimeHash *flagptr=(struct RuntimeHash *)(((int*)ptr)[2]);
88   flag|=ormask;
89   flag&=andmask;
90   ((int*)ptr)[1]=flag;
91   /*Remove from all queues */
92   while(flagptr!=NULL) {
93     struct RuntimeHash *next;
94     RuntimeHashget(flagptr, (int) ptr, (int *) &next);
95     RuntimeHashremove(flagptr, (int)ptr, (int) next);
96     flagptr=next;
97   }
98   
99   {
100     struct QueueItem *tmpptr;
101     struct parameterwrapper * parameter=objectqueues[((int *)ptr)[0]];
102     int i;
103     struct RuntimeHash * prevptr=NULL;
104     while(parameter!=NULL) {
105       for(i=0;i<parameter->numberofterms;i++) {
106         int andmask=parameter->intarray[i*2];
107         int checkmask=parameter->intarray[i*2+1];
108         if ((flag&andmask)==checkmask) {
109           RuntimeHashadd(parameter->objectset, (int) ptr, (int) prevptr);
110           prevptr=parameter->objectset;
111           {
112             struct RuntimeIterator iteratorarray[MAXTASKPARAMS];
113             void * taskpointerarray[MAXTASKPARAMS];
114             int j;
115             int numparams=parameter->task->numParameters;
116             int done=1;
117             struct taskdescriptor * task=parameter->task;
118             int newindex=-1;
119             for(j=0;j<numparams;j++) {
120               struct parameterwrapper *pw=(struct parameterwrapper *)task->descriptorarray[j]->queue;
121               if (parameter==pw) {
122                 taskpointerarray[j]=ptr;
123                 newindex=j;
124               } else {
125                 RuntimeHashiterator(pw->objectset, &iteratorarray[j]);
126                 if (RunhasNext(&iteratorarray[j]))
127                   taskpointerarray[j]=(void *) Runnext(&iteratorarray[j]);
128                 else
129                   break; /* No tasks to dispatch */
130               }
131             }
132             /* Queue task items... */
133
134             while(done) {
135               struct taskparamdescriptor *tpd=RUNMALLOC(sizeof(struct taskparamdescriptor));
136               tpd->task=task;
137               tpd->numParameters=numparams;
138               tpd->parameterArray=RUNMALLOC(sizeof(void *)*numparams);
139               for(j=0;j<numparams;j++)
140                 tpd->parameterArray[j]=taskpointerarray[j];
141               /* Queue task */
142               if (!gencontains(failedtasks, tpd))
143                 addNewItem(activetasks, tpd);
144               
145               /* This loop iterates to the next paramter combination */
146               for(j=0;j<numparams;j++) {
147                 if (j==newindex) {
148                   if ((j+1)==numparams)
149                     done=0;
150                   continue;
151                 }
152                 if (RunhasNext(&iteratorarray[j])) {
153                   taskpointerarray[j]=(void *) Runnext(&iteratorarray[j]);
154                   break;
155                 } else if ((j+1)!=numparams) {
156                   RuntimeHashiterator(task->descriptorarray[j]->queue, &iteratorarray[j]);
157                 } else {
158                   done=0;
159                   break;
160                 }
161               }
162             }
163           }
164           break;
165         }
166       }
167       parameter=parameter->next;
168     }
169     ((struct RuntimeHash **)ptr)[2]=prevptr;
170   }
171 }
172
173 /* Handler for signals */
174 void myhandler(int sig, struct __siginfo *info, void *uap) {
175 #ifdef DEBUG
176   printf("sig=%d\n",sig);
177   printf("signal\n");
178 #endif
179   longjmp(error_handler,1);
180 }
181
182
183 fd_set readfds;
184 int maxreadfd;
185 struct RuntimeHash *fdtoobject;
186
187 void addreadfd(int fd) {
188   if (fd>=maxreadfd)
189     maxreadfd=fd+1;
190   FD_SET(fd, &readfds);
191 }
192
193 void removereadfd(int fd) {
194   FD_CLR(fd, &readfds);
195   if (maxreadfd==(fd+1)) {
196     maxreadfd--;
197     while(maxreadfd>0&&!FD_ISSET(maxreadfd-1, &readfds))
198       maxreadfd--;
199   }
200 }
201
202 void executetasks() {
203   void * taskpointerarray[MAXTASKPARAMS];
204
205   /* Set up signal handlers */
206   struct sigaction sig;
207   sig.sa_sigaction=&myhandler;
208   sig.sa_flags=SA_SIGINFO;
209   sigemptyset(&sig.sa_mask);
210
211   /* Catch bus errors, segmentation faults, and floating point exceptions*/
212   sigaction(SIGBUS,&sig,0);
213   sigaction(SIGSEGV,&sig,0);
214   sigaction(SIGFPE,&sig,0);
215
216   /* Zero fd set */
217   FD_ZERO(&readfds);
218   maxreadfd=0;
219   fdtoobject=allocateRuntimeHash(100);
220
221   /* Map first block of memory to protected, anonymous page */
222   mmap(0, 0x1000, 0, MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
223
224   newtask:
225   while(!isEmpty(activetasks)||(maxreadfd>0)) {
226
227     if (maxreadfd>0) {
228       int i;
229       struct timeval timeout={0,0};
230       fd_set tmpreadfds;
231       int numselect;
232       FD_COPY(&readfds, &tmpreadfds);
233       numselect=select(maxreadfd, &tmpreadfds, NULL, NULL, &timeout);
234       if (numselect>0) {
235         /* Process ready fd's */
236         int fd;
237         for(fd=0;fd<maxreadfd;fd++) {
238           if (FD_ISSET(fd, &tmpreadfds)) {
239             /* Set ready flag on object */
240             void * objptr;
241             if (RuntimeHashget(fdtoobject, fd,(int *) &objptr)) {
242               flagorand(objptr,1,0xFFFFFFFF); /* Set the first flag to 1 */
243             }
244           }
245         }
246       }
247     }
248
249     if (!isEmpty(activetasks)) {
250       int i;
251       struct QueueItem * qi=(struct QueueItem *) getTail(activetasks);
252       struct taskparamdescriptor *tpd=(struct taskparamdescriptor *) qi->objectptr;
253       removeItem(activetasks, qi);
254       
255       for(i=0;i<tpd->task->numParameters;i++) {
256         void * parameter=tpd->parameterArray[i];
257         struct parameterdescriptor * pd=tpd->task->descriptorarray[i];
258         struct parameterwrapper *pw=(struct parameterwrapper *) pd->queue;
259         if (!RuntimeHashcontainskey(pw->objectset, (int) parameter))
260           goto newtask;
261         taskpointerarray[i]=parameter;
262       }
263       {
264         struct RuntimeHash * forward=allocateRuntimeHash(100);
265         struct RuntimeHash * reverse=allocateRuntimeHash(100);
266         void ** checkpoint=makecheckpoint(tpd->task->numParameters, taskpointerarray, forward, reverse);
267         if (setjmp(error_handler)) {
268           /* Recover */
269           int h;
270 #ifdef DEBUG
271           printf("Recovering\n");
272 #endif
273           genputtable(failedtasks,tpd,tpd);
274           restorecheckpoint(tpd->task->numParameters, taskpointerarray, checkpoint, forward, reverse);
275         } else {
276           /* Actually call task */
277           ((void (*) (void **)) tpd->task->taskptr)(taskpointerarray);
278         }
279       }
280     }
281   }
282 }
283
284 void processtasks() {
285   int i;
286   for(i=0;i<numtasks;i++) {
287     struct taskdescriptor * task=taskarray[i];
288     int j;
289
290     for(j=0;j<task->numParameters;j++) {
291       struct parameterdescriptor *param=task->descriptorarray[j];
292       struct parameterwrapper * parameter=RUNMALLOC(sizeof(struct parameterwrapper));
293       struct parameterwrapper ** ptr=&objectqueues[param->type];
294
295       param->queue=parameter;
296       parameter->objectset=allocateRuntimeHash(10);
297       parameter->numberofterms=param->numberterms;
298       parameter->intarray=param->intarray;
299       parameter->task=task;
300       /* Link new queue in */
301       while((*ptr)!=NULL)
302         ptr=&((*ptr)->next);
303       (*ptr)=parameter;
304     }
305   }
306 }
307
308
309
310 int ___ServerSocket______createSocket____I(struct ___ServerSocket___ * sock, int port) {
311   int fd;
312
313   int n=1;
314   struct sockaddr_in sin;
315
316   bzero (&sin, sizeof (sin));
317   sin.sin_family = AF_INET;
318   sin.sin_port = htons (port);
319   sin.sin_addr.s_addr = htonl (INADDR_ANY);
320   fd=socket(AF_INET, SOCK_STREAM, 0);
321   if (fd<0) {
322 #ifdef DEBUG
323     perror(NULL);
324     printf("createSocket error #1\n");
325 #endif
326     longjmp(error_handler,5);
327   }
328
329   if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (char *)&n, sizeof (n)) < 0) {
330     close(fd);
331 #ifdef DEBUG
332     perror(NULL);
333     printf("createSocket error #2\n");
334 #endif
335     longjmp(error_handler, 6);
336   }
337   fcntl(fd, F_SETFD, 1);
338   fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
339
340   /* bind to port */
341   if (bind(fd, (struct sockaddr *) &sin, sizeof(sin))<0) { 
342     close (fd);
343 #ifdef DEBUG
344     perror(NULL);
345     printf("createSocket error #3\n");
346 #endif
347     longjmp(error_handler, 7);
348   }
349
350   /* listen */
351   if (listen(fd, 5)<0) { 
352     close (fd);
353 #ifdef DEBUG
354     perror(NULL);
355     printf("createSocket error #4\n");
356 #endif
357     longjmp(error_handler, 8);
358   }
359
360   /* Store the fd/socket object mapping */
361   RuntimeHashadd(fdtoobject, fd, (int) sock);
362   addreadfd(fd);
363   return fd;
364 }
365
366 int ___ServerSocket______nativeaccept____L___Socket___(struct ___ServerSocket___ * serversock, struct ___Socket___ * sock) {
367   struct sockaddr_in sin;
368   unsigned int sinlen=sizeof(sin);
369   int fd=serversock->___fd___;
370   int newfd;
371   newfd=accept(fd, (struct sockaddr *)&sin, &sinlen);
372
373
374   if (newfd<0) { 
375 #ifdef DEBUG
376     perror(NULL);
377     printf("acceptSocket error #1\n");
378 #endif
379     longjmp(error_handler, 9);
380   }
381   fcntl(newfd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
382
383   RuntimeHashadd(fdtoobject, newfd, (int) sock);
384   addreadfd(newfd);
385   flagorand(serversock,0,0xFFFFFFFE);
386   return newfd;
387 }
388
389
390 void ___Socket______nativeWrite_____AR_B(struct ___Socket___ * sock, struct ArrayObject * ao) {
391   int fd=sock->___fd___;
392   int length=ao->___length___;
393   char * charstr=((char *)& ao->___length___)+sizeof(int);
394   int bytewritten=write(fd, charstr, length);
395   if (bytewritten!=length) {
396     printf("ERROR IN NATIVEWRITE\n");
397   }
398   flagorand(sock,0,0xFFFFFFFE);
399 }
400
401 int ___Socket______nativeRead_____AR_B(struct ___Socket___ * sock, struct ArrayObject * ao) {
402   int fd=sock->___fd___;
403   int length=ao->___length___;
404   char * charstr=((char *)& ao->___length___)+sizeof(int);
405   int byteread=read(fd, charstr, length);
406   
407   if (byteread<0) {
408     printf("ERROR IN NATIVEREAD\n");
409   }
410   flagorand(sock,0,0xFFFFFFFE);
411   return byteread;
412 }
413
414 void ___Socket______nativeClose____(struct ___Socket___ * sock) {
415   int fd=sock->___fd___;
416   int data;
417   RuntimeHashget(fdtoobject, fd, &data);
418   RuntimeHashremove(fdtoobject, fd, data);
419   removereadfd(fd);
420   close(fd);
421   flagorand(sock,0,0xFFFFFFFE);
422 }
423 #endif
424
425 int ___Object______hashcode____(struct ___Object___ * ___this___) {
426   return (int) ___this___;
427 }
428
429 void ___System______printString____L___String___(struct ___String___ * s) {
430     struct ArrayObject * chararray=s->___string___;
431     int i;
432     for(i=0;i<chararray->___length___;i++) {
433         short s= ((short *)(((char *)& chararray->___length___)+sizeof(int)))[i];
434         putchar(s);
435     }
436 }
437
438 void * allocate_new(int type) {
439   void * v=FREEMALLOC(classsize[type]);
440   *((int *)v)=type;
441   return v;
442 }
443
444 struct ArrayObject * allocate_newarray(int type, int length) {
445   struct ArrayObject * v=FREEMALLOC(sizeof(struct ArrayObject)+length*classsize[type]);
446   v->type=type;
447   v->___length___=length;
448   return v;
449 }
450
451 struct ___String___ * NewString(const char *str,int length) {
452   struct ArrayObject * chararray=allocate_newarray(CHARARRAYTYPE, length);
453   struct ___String___ * strobj=allocate_new(STRINGTYPE);
454   int i;
455   strobj->___string___=chararray;
456   for(i=0;i<length;i++) {
457     ((short *)(((char *)& chararray->___length___)+sizeof(int)))[i]=(short)str[i];  }
458   return strobj;
459 }
460
461 void failedboundschk() {
462 #ifndef TASK
463   printf("Array out of bounds\n");
464   exit(-1);
465 #else
466   longjmp(error_handler,2);
467 #endif
468 }
469
470 void failednullptr() {
471 #ifndef TASK
472   printf("Dereferenced a null pointer\n");
473   exit(-1);
474 #else
475   longjmp(error_handler,3);
476 #endif
477 }
478
479 void abort_task() {
480 #ifndef TASK
481   printf("Aborting\n");
482   exit(-1);
483 #else
484   longjmp(error_handler,4);
485 #endif
486 }