changes to manual prefetching (combine severals sends/recvs)
[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   struct ArrayObject * v=(struct ArrayObject *)transCreateObj(ptr, sizeof(struct ArrayObject)+length*classsize[type]+sizeof(int)*(((length*classsize[type])>>DBLINDEXSHIFT)), (length*classsize[type])>>DBLINDEXSHIFT);
495 #else
496   struct ArrayObject * v=(struct ArrayObject *)transCreateObj(ptr, sizeof(struct ArrayObject)+length*classsize[type]);
497 #endif
498   if (length<0) {
499     printf("ERROR: negative array\n");
500     return NULL;
501   }
502   v->___objlocation___=(struct ___Object___*)v;
503   v->type=type;
504   v->___length___=length;
505   return v;
506 }
507
508 __attribute__((malloc)) void * allocate_new(void * ptr, int type) {
509   objheader_t *tmp=mygcmalloc((struct garbagelist *) ptr, classsize[type]+sizeof(objheader_t));
510   struct ___Object___ * v=(struct ___Object___ *) &tmp[1];
511   initdsmlocks(&tmp->lock);
512   tmp->version = 1;
513   v->___objlocation___=v;
514   v->type = type;
515   return v;
516 }
517
518 /* Array allocation function */
519
520 __attribute__((malloc)) struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
521 #ifdef STMARRAY
522   int *tmpint=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+length*classsize[type]+sizeof(objheader_t)+sizeof(int)*(((length*classsize[type])>>DBLINDEXSHIFT)));
523   objheader_t *tmp=(objheader_t *)(tmpint+((length*classsize[type])>>DBLINDEXSHIFT));
524 #else
525   objheader_t *tmp=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+length*classsize[type]+sizeof(objheader_t));
526 #endif
527   struct ArrayObject * v=(struct ArrayObject *) &tmp[1];
528   initdsmlocks(&tmp->lock);
529   tmp->version=1;
530   v->type=type;
531   if (length<0) {
532     printf("ERROR: negative array %d\n", length);
533     return NULL;
534   }
535   v->___objlocation___=(struct ___Object___ *)v;
536   v->___length___=length;
537   return v;
538 }
539 #endif
540
541 #ifndef STM
542 #if defined(PRECISE_GC)
543 __attribute__((malloc)) void * allocate_new(void * ptr, int type) {
544   struct ___Object___ * v=(struct ___Object___ *) mygcmalloc((struct garbagelist *) ptr, classsize[type]);
545   v->type=type;
546 #ifdef THREADS
547   v->tid=0;
548   v->lockentry=0;
549   v->lockcount=0;
550 #endif
551 #ifdef OPTIONAL
552   v->fses=0;
553 #endif
554   return v;
555 }
556
557 /* Array allocation function */
558
559 __attribute__((malloc)) struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
560   struct ArrayObject * v=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+length*classsize[type]);
561   v->type=type;
562   if (length<0) {
563     printf("ERROR: negative array\n");
564     return NULL;
565   }
566   v->___length___=length;
567 #ifdef THREADS
568   v->tid=0;
569   v->lockentry=0;
570   v->lockcount=0;
571 #endif
572 #ifdef OPTIONAL
573   v->fses=0;
574 #endif
575   return v;
576 }
577
578 #else
579 __attribute__((malloc)) void * allocate_new(int type) {
580   struct ___Object___ * v=FREEMALLOC(classsize[type]);
581   v->type=type;
582 #ifdef OPTIONAL
583   v->fses=0;
584 #endif
585   return v;
586 }
587
588 /* Array allocation function */
589
590 __attribute__((malloc)) struct ArrayObject * allocate_newarray(int type, int length) {
591   __attribute__((malloc))  struct ArrayObject * v=FREEMALLOC(sizeof(struct ArrayObject)+length*classsize[type]);
592   v->type=type;
593   v->___length___=length;
594 #ifdef OPTIONAL
595   v->fses=0;
596 #endif
597   return v;
598 }
599 #endif
600 #endif
601
602 /* Converts C character arrays into Java strings */
603 #ifdef PRECISE_GC
604 __attribute__((malloc)) struct ___String___ * NewString(void * ptr, const char *str,int length) {
605 #else
606 __attribute__((malloc)) struct ___String___ * NewString(const char *str,int length) {
607 #endif
608   int i;
609 #ifdef PRECISE_GC
610   struct ArrayObject * chararray=allocate_newarray((struct garbagelist *)ptr, CHARARRAYTYPE, length);
611   INTPTR ptrarray[]={1, (INTPTR) ptr, (INTPTR) chararray};
612   struct ___String___ * strobj=allocate_new((struct garbagelist *) &ptrarray, STRINGTYPE);
613   chararray=(struct ArrayObject *) ptrarray[2];
614 #else
615   struct ArrayObject * chararray=allocate_newarray(CHARARRAYTYPE, length);
616   struct ___String___ * strobj=allocate_new(STRINGTYPE);
617 #endif
618   strobj->___value___=chararray;
619   strobj->___count___=length;
620   strobj->___offset___=0;
621
622   for(i=0; i<length; i++) {
623     ((short *)(((char *)&chararray->___length___)+sizeof(int)))[i]=(short)str[i];
624   }
625   return strobj;
626 }
627
628 /* Generated code calls this if we fail a bounds check */
629
630 void failedboundschk() {
631 #ifndef TASK
632   printf("Array out of bounds\n");
633 #ifdef THREADS
634   threadexit();
635 #else
636   exit(-1);
637 #endif
638 #else
639   longjmp(error_handler,2);
640 #endif
641 }
642
643 /* Abort task call */
644 void abort_task() {
645 #ifdef TASK
646   longjmp(error_handler,4);
647 #else
648   printf("Aborting\n");
649   exit(-1);
650 #endif
651 }