try to organize code more...
[IRC.git] / Robust / src / Runtime / runtime.c
1 #include "runtime.h"
2 #include "structdefs.h"
3 #include <signal.h>
4 #include "mem.h"
5 #include <fcntl.h>
6 #include <errno.h>
7 #include <stdio.h>
8 #include "option.h"
9 #include "methodheaders.h"
10 #ifdef DSTM
11 #ifdef RECOVERY
12 #include "DSTM/interface_recovery/dstm.h"
13 #include "DSTM/interface_recovery/prelookup.h"
14 #else
15 #include "DSTM/interface/dstm.h"
16 #include "DSTM/interface/prelookup.h"
17 #include "DSTM/interface/prefetch.h"
18 #endif
19 #endif
20 #ifdef STM
21 #include "tm.h"
22 #include <pthread.h>
23 #endif
24 #ifdef STMLOG
25 #define ARRAY_LENGTH 700003
26 __thread int counter;
27 __thread int event[ARRAY_LENGTH];
28 __thread unsigned long long clkticks[ARRAY_LENGTH];
29 unsigned long long beginClock=0;
30 #define FILENAME  "log"
31 #endif
32
33 #if defined(THREADS)||defined(STM)
34 /* Global barrier for STM */
35 pthread_barrier_t barrier;
36 pthread_barrierattr_t attr;
37 #endif
38
39 #include <string.h>
40
41 extern int classsize[];
42 extern int typearray[];
43 extern int typearray2[];
44 jmp_buf error_handler;
45 int instructioncount;
46
47 char *options;
48 int injectfailures=0;
49 float failurechance=0;
50 int errors=0;
51 int debugtask=0;
52 int injectinstructionfailures;
53 int failurecount;
54 float instfailurechance=0;
55 int numfailures;
56 int instaccum=0;
57 typedef unsigned long long ticks;
58 #ifdef DMALLOC
59 #include "dmalloc.h"
60 #endif
61
62 int instanceof(struct ___Object___ *ptr, int type) {
63   int i=ptr->type;
64   do {
65     if (i==type)
66       return 1;
67     i=typearray[i];
68   } while(i!=-1);
69   i=ptr->type;
70   if (i>NUMCLASSES) {
71     do {
72       if (i==type)
73         return 1;
74       i=typearray2[i-NUMCLASSES];
75     } while(i!=-1);
76   }
77   return 0;
78 }
79
80 void exithandler(int sig, siginfo_t *info, void * uap) {
81   exit(0);
82 }
83
84 void initializeexithandler() {
85   struct sigaction sig;
86   sig.sa_sigaction=&exithandler;
87   sig.sa_flags=SA_SIGINFO;
88   sigemptyset(&sig.sa_mask);
89   sigaction(SIGUSR2, &sig, 0);
90 }
91
92
93 /* This function inject failures */
94
95 void injectinstructionfailure() {
96 #ifdef TASK
97   if (injectinstructionfailures) {
98     if (numfailures==0)
99       return;
100     instructioncount=failurecount;
101     instaccum+=failurecount;
102     if ((((double)random())/RAND_MAX)<instfailurechance) {
103       if (numfailures>0)
104         numfailures--;
105       printf("FAILURE!!! %d\n",numfailures);
106       longjmp(error_handler,11);
107     }
108   }
109 #else
110 #ifdef THREADS
111   if (injectinstructionfailures) {
112     if (numfailures==0)
113       return;
114     instaccum+=failurecount;
115     if ((((double)random())/RAND_MAX)<instfailurechance) {
116       if (numfailures>0)
117         numfailures--;
118       printf("FAILURE!!! %d\n",numfailures);
119       threadexit();
120     }
121   }
122 #endif
123 #endif
124 }
125
126 #ifdef D___Double______nativeparsedouble____L___String___
127 double CALL01(___Double______nativeparsedouble____L___String___,struct ___String___ * ___str___) {
128   int length=VAR(___str___)->___count___;
129   int maxlength=(length>60)?60:length;
130   char str[maxlength+1];
131   struct ArrayObject * chararray=VAR(___str___)->___value___;
132   int i;
133   int offset=VAR(___str___)->___offset___;
134   for(i=0; i<maxlength; i++) {
135     str[i]=((short *)(((char *)&chararray->___length___)+sizeof(int)))[i+offset];
136   }
137   str[i]=0;
138   double d=atof(str);
139   return d;
140 }
141 #endif
142
143 #ifdef D___String______convertdoubletochar____D__AR_C
144 int CALL12(___String______convertdoubletochar____D__AR_C, double ___val___, double ___val___, struct ArrayObject ___chararray___) {
145   int length=VAR(___chararray___)->___length___;
146   char str[length];
147   int i;
148   int num=snprintf(str, length, "%f",___val___);
149   if (num>=length)
150     num=length-1;
151   for(i=0; i<length; i++) {
152     ((short *)(((char *)&VAR(___chararray___)->___length___)+sizeof(int)))[i]=(short)str[i];
153   }
154   return num;
155 }
156 #endif
157 #ifdef D___System______deepArrayCopy____L___Object____L___Object___
158 void deepArrayCopy(struct ___Object___ * dst, struct ___Object___ * src) {
159   int dsttype=((int *)dst)[0];
160   int srctype=((int *)src)[0];
161   if (dsttype<NUMCLASSES||srctype<NUMCLASSES||srctype!=dsttype)
162     return;
163   struct ArrayObject *aodst=(struct ArrayObject *)dst;
164   struct ArrayObject *aosrc=(struct ArrayObject *)src;
165   int dstlength=aodst->___length___;
166   int srclength=aosrc->___length___;
167   if (dstlength!=srclength)
168     return;
169   unsigned INTPTR *pointer=pointerarray[srctype];
170   if (pointer==0) {
171     int elementsize=classsize[srctype];
172     int size=srclength*elementsize;
173     //primitives
174     memcpy(((char *)&aodst->___length___)+sizeof(int) , ((char *)&aosrc->___length___)+sizeof(int), size);
175   } else {
176     //objects
177     int i;
178     for(i=0;i<srclength;i++) {
179       struct ___Object___ * ptr=((struct ___Object___**)(((char*) &aosrc->___length___)+sizeof(int)))[i];
180       int ptrtype=((int *)ptr)[0];
181       if (ptrtype>=NUMCLASSES) {
182         struct ___Object___ * dstptr=((struct ___Object___**)(((char*) &aodst->___length___)+sizeof(int)))[i];
183         deepArrayCopy(dstptr,ptr);
184       } else {
185         //hit an object
186         ((struct ___Object___ **)(((char*) &aodst->___length___)+sizeof(int)))[i]=ptr;
187       }
188     }
189   }
190 }
191
192 void CALL02(___System______deepArrayCopy____L___Object____L___Object___, struct ___Object___ * ___dst___, struct ___Object___ * ___src___) {
193   deepArrayCopy(VAR(___dst___), VAR(___src___));
194 }
195 #endif
196
197 void CALL11(___System______exit____I,int ___status___, int ___status___) {
198 #ifdef TRANSSTATS
199   printf("numTransCommit = %d\n", numTransCommit);
200   printf("numTransAbort = %d\n", numTransAbort);
201   printf("nSoftAbort = %d\n", nSoftAbort);
202 #ifdef STM
203   printf("nSoftAbortCommit = %d\n", nSoftAbortCommit);
204   printf("nSoftAbortAbort = %d\n", nSoftAbortAbort);
205 #ifdef STMSTATS
206   int i;
207   for(i=0; i<TOTALNUMCLASSANDARRAY; i++) {
208     printf("typesCausingAbort[%2d] numaccess= %5d numabort= %3d\n", i, typesCausingAbort[i].numaccess, typesCausingAbort[i].numabort);
209   }
210 #endif
211 #endif
212 #endif
213   exit(___status___);
214 }
215
216 #if defined(__i386__)
217
218 static __inline__ unsigned long long rdtsc(void)
219 {
220   unsigned long long int x;
221   __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
222   return x;
223 }
224 #elif defined(__x86_64__)
225
226 static __inline__ unsigned long long rdtsc(void)
227 {
228   unsigned hi, lo;
229   __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
230   return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
231 }
232
233 #elif defined(__powerpc__)
234
235 typedef unsigned long long int unsigned long long;
236
237 static __inline__ unsigned long long rdtsc(void)
238 {
239   unsigned long long int result=0;
240   unsigned long int upper, lower,tmp;
241   __asm__ volatile(
242       "0:                  \n"
243       "\tmftbu   %0           \n"
244       "\tmftb    %1           \n"
245       "\tmftbu   %2           \n"
246       "\tcmpw    %2,%0        \n"
247       "\tbne     0b         \n"
248       : "=r"(upper),"=r"(lower),"=r"(tmp)
249       );
250   result = upper;
251   result = result<<32;
252   result = result|lower;
253
254   return(result);
255 }
256 #endif
257
258 void CALL11(___System______logevent____I,int ___event___, int ___event___) {
259 #ifdef STMLOG
260   event[counter] = ___event___;
261   clkticks[counter] = rdtsc();
262   counter++;
263 #endif
264   return;
265 }
266
267 void CALL00(___System______logevent____) {
268 #ifdef STMLOG
269   beginClock= rdtsc();
270 #endif
271   return;
272 }
273
274 void CALL11(___System______flushToFile____I, int ___threadid___, int ___threadid___) {
275 #ifdef STMLOG
276   FILE *fp;
277   /* Flush to file */
278   char filename[20];
279   memset(filename, 0, 20);
280   sprintf(filename, "%s_%d", FILENAME, ___threadid___);
281   if ((fp = fopen(filename, "w+")) == NULL) {
282     perror("fopen");
283     return;
284   }
285   int i;
286   for (i = 0; i < counter-1; i++) {
287     fprintf(fp, "%d %lld %lld\n", event[i], clkticks[i]-beginClock, clkticks[i+1]-beginClock);
288   }
289   fprintf(fp, "%d %lld\n", event[i], clkticks[i]-beginClock);
290
291   fclose(fp);
292 #endif
293   return;
294 }
295
296 void CALL00(___System______initLog____) {
297 #ifdef STMLOG
298   counter=0;
299   int i;
300   for(i=0; i<ARRAY_LENGTH; i++) {
301     event[i] = 0;
302     clkticks[i] = 0;
303   }
304
305 #endif
306   return;
307 }
308
309 #ifdef D___Vector______removeElement_____AR_L___Object____I_I
310 void CALL23(___Vector______removeElement_____AR_L___Object____I_I, int ___index___, int ___size___, struct ArrayObject * ___array___, int ___index___, int ___size___) {
311   char* offset=((char *)(&VAR(___array___)->___length___))+sizeof(unsigned int)+sizeof(void *)*___index___;
312   memmove(offset, offset+sizeof(void *),(___size___-___index___-1)*sizeof(void *));
313 }
314 #endif
315
316 void CALL11(___System______printI____I,int ___status___, int ___status___) {
317   printf("%d\n",___status___);
318 }
319
320 long long CALL00(___System______currentTimeMillis____) {
321   struct timeval tv; long long retval;
322   gettimeofday(&tv, NULL);
323   retval = tv.tv_sec; /* seconds */
324   retval*=1000; /* milliseconds */
325   retval+= (tv.tv_usec/1000); /* adjust milliseconds & add them in */
326   return retval;
327 }
328
329 long long CALL00(___System______microTimes____) {
330   struct timeval tv; 
331   long long retval;
332   gettimeofday(&tv, NULL);
333   retval = tv.tv_sec; /* seconds */
334   retval*=1000000; /* microsecs */
335   retval+= (tv.tv_usec); /* adjust microseconds & add them in */
336   return retval;
337 }
338
339 long long CALL00(___System______getticks____) {
340   unsigned a, d;
341   asm("cpuid");
342   asm volatile("rdtsc" : "=a" (a), "=d" (d));
343   return (((ticks)a) | (((ticks)d) << 32));
344 }
345
346 void CALL01(___System______printString____L___String___,struct ___String___ * ___s___) {
347   struct ArrayObject * chararray=VAR(___s___)->___value___;
348   int i;
349   int offset=VAR(___s___)->___offset___;
350   for(i=0; i<VAR(___s___)->___count___; i++) {
351     short sc=((short *)(((char *)&chararray->___length___)+sizeof(int)))[i+offset];
352     putchar(sc);
353   }
354 }
355
356 #ifdef DSTM
357 void CALL00(___System______clearPrefetchCache____) {
358   prehashClear();
359 }
360
361 #ifdef RANGEPREFETCH
362 void CALL02(___System______rangePrefetch____L___Object_____AR_S, struct ___Object___ * ___o___, struct ArrayObject * ___offsets___) {
363   /* Manual Prefetches to be inserted */
364   //printf("DEBUG-> %s() ___Object___ * ___o___ = %x\n", __func__, VAR(___o___));
365   //printf("DEBUG-> %s() ArrayObject * = %x\n", __func__, VAR(___offsets___));
366   int numoffset=VAR(___offsets___)->___length___;
367   int i;
368   short offArry[numoffset+2];
369   offArry[0] = 0;
370   offArry[1] = 0;
371   for(i = 2; i<(numoffset+2); i++) {
372     offArry[i] = *((short *)(((char *)&VAR(___offsets___)->___length___) + sizeof(int) + (i-2) * sizeof(short)));
373     //printf("DEBUG-> offArry[%d] = %d\n", i, offArry[i]);
374   }
375   unsigned int oid;
376   if(((unsigned int)(VAR(___o___)) & 1) != 0) { //odd
377     oid =  (unsigned int) VAR(___o___); //outside transaction therefore just an oid
378   } else { //even
379     oid = (unsigned int) COMPOID(VAR(___o___)); //inside transaction therefore a pointer to oid
380   }
381   rangePrefetch(oid, (short)(numoffset+2), offArry);
382 }
383 #else
384 void CALL02(___System______rangePrefetch____L___Object_____AR_S, struct ___Object___ * ___o___, struct ArrayObject * ___offsets___) {
385   return;
386 }
387 #endif
388
389 #ifdef D___Task______execution____ 
390 extern void* virtualtable[];
391 // associated with Task.execution(). finds proper execute method and call it
392 void CALL01(___Task______execution____,struct ___Task___ * ___this___)
393 {
394   unsigned int oid;
395   oid = (unsigned int) VAR(___this___);   // object id
396   int type = getObjType(oid);             // object type
397
398 #ifdef PRECISE_GC
399   int p[] = {1,0 , oid};
400    
401   ((void(*) (void *))virtualtable[type*MAXCOUNT + EXECUTEMETHOD])(p);
402 #else
403   // call the proper execute method
404   ((void(*) (void *))virtualtable[type*MAXCOUNT + EXECUTEMETHOD])(oid);
405 #endif
406 }
407 #endif
408
409 #endif // DSTM
410
411 /* STM Barrier constructs */
412 #ifdef D___Barrier______setBarrier____I
413 void CALL11(___Barrier______setBarrier____I, int nthreads, int nthreads) {
414   // Barrier initialization
415   int ret;
416   if((ret = pthread_barrier_init(&barrier, NULL, nthreads)) != 0) {
417     printf("%s() Could not create a barrier: numthreads = 0 in %s\n", __func__, __FILE__);
418     exit(-1);
419   }
420 }
421 #endif
422
423 #ifdef D___Barrier______enterBarrier____
424 void CALL00(___Barrier______enterBarrier____) {
425   // Synchronization point
426   int ret;
427 #ifdef PRECISE_GC
428   stopforgc((struct garbagelist *)___params___);
429 #endif
430   ret = pthread_barrier_wait(&barrier);
431 #ifdef PRECISE_GC
432   restartaftergc();
433 #endif
434   if(ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) {
435     printf("%s() Could not wait on barrier: error %d in %s\n", __func__, errno, __FILE__);
436     exit(-1);
437   }
438 }
439 #endif
440
441 /* Object allocation function */
442
443 #ifdef DSTM
444 __attribute__((malloc)) void * allocate_newglobal(int type) {
445   struct ___Object___ * v=(struct ___Object___ *) transCreateObj(classsize[type]);
446   v->type=type;
447   //printf("DEBUG %s(), type= %x\n", __func__, type);
448 #ifdef THREADS
449   v->tid=0;
450   v->lockentry=0;
451   v->lockcount=0;
452 #endif
453   return v;
454 }
455
456 /* Array allocation function */
457
458 __attribute__((malloc)) struct ArrayObject * allocate_newarrayglobal(int type, int length) {
459   struct ArrayObject * v=(struct ArrayObject *)transCreateObj(sizeof(struct ArrayObject)+length*classsize[type]);
460   if (length<0) {
461     printf("ERROR: negative array\n");
462     return NULL;
463   }
464   v->type=type;
465   v->___length___=length;
466 #ifdef THREADS
467   v->tid=0;
468   v->lockentry=0;
469   v->lockcount=0;
470 #endif
471   return v;
472 }
473 #endif
474
475
476 #ifdef STM
477 // STM Versions of allocation functions
478
479 /* Object allocation function */
480 __attribute__((malloc)) void * allocate_newtrans(void * ptr, int type) {
481 #ifdef STMARRAY
482   struct ___Object___ * v=(struct ___Object___ *) transCreateObj(ptr, classsize[type], 0);
483 #else
484   struct ___Object___ * v=(struct ___Object___ *) transCreateObj(ptr, classsize[type]);
485 #endif
486   v->type=type;
487   v->___objlocation___=v;
488   return v;
489 }
490
491 /* Array allocation function */
492 __attribute__((malloc)) struct ArrayObject * allocate_newarraytrans(void * ptr, int type, int length) {
493 #ifdef STMARRAY
494   int basesize=length*classsize[type];
495   //round the base size up
496   basesize=(basesize+LOWMASK)&HIGHMASK;
497   int bookkeepsize=(basesize>>INDEXSHIFT)*2*sizeof(int);
498   struct ArrayObject * v=(struct ArrayObject *)transCreateObj(ptr, sizeof(struct ArrayObject)+basesize+bookkeepsize, bookkeepsize);
499   v->highindex=-1;
500   v->lowindex=MAXARRAYSIZE;
501 #else
502   struct ArrayObject * v=(struct ArrayObject *)transCreateObj(ptr, sizeof(struct ArrayObject)+length*classsize[type]);
503 #endif
504   if (length<0) {
505     printf("ERROR: negative array\n");
506     return NULL;
507   }
508   v->___objlocation___=(struct ___Object___*)v;
509   v->type=type;
510   v->___length___=length;
511   return v;
512 }
513
514 __attribute__((malloc)) void * allocate_new(void * ptr, int type) {
515   objheader_t *tmp=mygcmalloc((struct garbagelist *) ptr, classsize[type]+sizeof(objheader_t));
516   struct ___Object___ * v=(struct ___Object___ *) &tmp[1];
517   initdsmlocks(&tmp->lock);
518   tmp->version = 1;
519   v->___objlocation___=v;
520   v->type = type;
521   return v;
522 }
523
524 /* Array allocation function */
525
526 __attribute__((malloc)) struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
527 #ifdef STMARRAY
528   int basesize=length*classsize[type];
529   //round the base size up
530   basesize=(basesize+LOWMASK)&HIGHMASK;
531   int bookkeepsize=(basesize>>INDEXSHIFT)*2*sizeof(int);
532   int *tmpint=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+basesize+sizeof(objheader_t)+bookkeepsize);
533   objheader_t *tmp=(objheader_t *)(tmpint+bookkeepsize);
534   struct ArrayObject * v=(struct ArrayObject *) &tmp[1];
535   v->highindex=-1;
536   v->lowindex=MAXARRAYSIZE;
537 #else
538   objheader_t *tmp=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+length*classsize[type]+sizeof(objheader_t));
539   struct ArrayObject * v=(struct ArrayObject *) &tmp[1];
540 #endif
541   initdsmlocks(&tmp->lock);
542   tmp->version=1;
543   v->type=type;
544   if (length<0) {
545     printf("ERROR: negative array %d\n", length);
546     return NULL;
547   }
548   v->___objlocation___=(struct ___Object___ *)v;
549   v->___length___=length;
550   return v;
551 }
552 #endif
553
554 #ifndef STM
555 #if defined(PRECISE_GC)
556 __attribute__((malloc)) void * allocate_new(void * ptr, int type) {
557   struct ___Object___ * v=(struct ___Object___ *) mygcmalloc((struct garbagelist *) ptr, classsize[type]);
558   v->type=type;
559 #ifdef THREADS
560   v->tid=0;
561   v->lockentry=0;
562   v->lockcount=0;
563 #endif
564 #ifdef OPTIONAL
565   v->fses=0;
566 #endif
567   return v;
568 }
569
570 /* Array allocation function */
571
572 __attribute__((malloc)) struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
573   struct ArrayObject * v=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+length*classsize[type]);
574   v->type=type;
575   if (length<0) {
576     printf("ERROR: negative array\n");
577     return NULL;
578   }
579   v->___length___=length;
580 #ifdef THREADS
581   v->tid=0;
582   v->lockentry=0;
583   v->lockcount=0;
584 #endif
585 #ifdef OPTIONAL
586   v->fses=0;
587 #endif
588   return v;
589 }
590
591 #else
592 __attribute__((malloc)) void * allocate_new(int type) {
593   struct ___Object___ * v=FREEMALLOC(classsize[type]);
594   v->type=type;
595 #ifdef OPTIONAL
596   v->fses=0;
597 #endif
598   return v;
599 }
600
601 /* Array allocation function */
602
603 __attribute__((malloc)) struct ArrayObject * allocate_newarray(int type, int length) {
604   __attribute__((malloc))  struct ArrayObject * v=FREEMALLOC(sizeof(struct ArrayObject)+length*classsize[type]);
605   v->type=type;
606   v->___length___=length;
607 #ifdef OPTIONAL
608   v->fses=0;
609 #endif
610   return v;
611 }
612 #endif
613 #endif
614
615 /* Converts C character arrays into Java strings */
616 #ifdef PRECISE_GC
617 __attribute__((malloc)) struct ___String___ * NewString(void * ptr, const char *str,int length) {
618 #else
619 __attribute__((malloc)) struct ___String___ * NewString(const char *str,int length) {
620 #endif
621   int i;
622 #ifdef PRECISE_GC
623   struct ArrayObject * chararray=allocate_newarray((struct garbagelist *)ptr, CHARARRAYTYPE, length);
624   INTPTR ptrarray[]={1, (INTPTR) ptr, (INTPTR) chararray};
625   struct ___String___ * strobj=allocate_new((struct garbagelist *) &ptrarray, STRINGTYPE);
626   chararray=(struct ArrayObject *) ptrarray[2];
627 #else
628   struct ArrayObject * chararray=allocate_newarray(CHARARRAYTYPE, length);
629   struct ___String___ * strobj=allocate_new(STRINGTYPE);
630 #endif
631   strobj->___value___=chararray;
632   strobj->___count___=length;
633   strobj->___offset___=0;
634
635   for(i=0; i<length; i++) {
636     ((short *)(((char *)&chararray->___length___)+sizeof(int)))[i]=(short)str[i];
637   }
638   return strobj;
639 }
640
641 /* Generated code calls this if we fail a bounds check */
642
643 void failedboundschk() {
644 #ifndef TASK
645   printf("Array out of bounds\n");
646 #ifdef THREADS
647   threadexit();
648 #else
649   exit(-1);
650 #endif
651 #else
652   longjmp(error_handler,2);
653 #endif
654 }
655
656 /* Abort task call */
657 void abort_task() {
658 #ifdef TASK
659   longjmp(error_handler,4);
660 #else
661   printf("Aborting\n");
662   exit(-1);
663 #endif
664 }