changes for modifying the microbenchmarks
[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 #include "dstm.h"
12 #include "prelookup.h"
13 #include "prefetch.h"
14 #endif
15 #ifdef STM
16 #include "tm.h"
17 #include <pthread.h>
18 #endif
19
20 #if defined(THREADS)||defined(STM)
21 /* Global barrier for STM */
22 pthread_barrier_t barrier;
23 pthread_barrierattr_t attr;
24 #endif
25
26 #include <string.h>
27
28 extern int classsize[];
29 extern int typearray[];
30 extern int typearray2[];
31 jmp_buf error_handler;
32 int instructioncount;
33
34 char *options;
35 int injectfailures=0;
36 float failurechance=0;
37 int errors=0;
38 int debugtask=0;
39 int injectinstructionfailures;
40 int failurecount;
41 float instfailurechance=0;
42 int numfailures;
43 int instaccum=0;
44 typedef unsigned long long ticks;
45 #ifdef DMALLOC
46 #include "dmalloc.h"
47 #endif
48
49 int instanceof(struct ___Object___ *ptr, int type) {
50   int i=ptr->type;
51   do {
52     if (i==type)
53       return 1;
54     i=typearray[i];
55   } while(i!=-1);
56   i=ptr->type;
57   if (i>NUMCLASSES) {
58     do {
59       if (i==type)
60         return 1;
61       i=typearray2[i-NUMCLASSES];
62     } while(i!=-1);
63   }
64   return 0;
65 }
66
67 void exithandler(int sig, siginfo_t *info, void * uap) {
68   exit(0);
69 }
70
71 void initializeexithandler() {
72   struct sigaction sig;
73   sig.sa_sigaction=&exithandler;
74   sig.sa_flags=SA_SIGINFO;
75   sigemptyset(&sig.sa_mask);
76   sigaction(SIGUSR2, &sig, 0);
77 }
78
79
80 /* This function inject failures */
81
82 void injectinstructionfailure() {
83 #ifdef TASK
84   if (injectinstructionfailures) {
85     if (numfailures==0)
86       return;
87     instructioncount=failurecount;
88     instaccum+=failurecount;
89     if ((((double)random())/RAND_MAX)<instfailurechance) {
90       if (numfailures>0)
91         numfailures--;
92       printf("FAILURE!!! %d\n",numfailures);
93       longjmp(error_handler,11);
94     }
95   }
96 #else
97 #ifdef THREADS
98   if (injectinstructionfailures) {
99     if (numfailures==0)
100       return;
101     instaccum+=failurecount;
102     if ((((double)random())/RAND_MAX)<instfailurechance) {
103       if (numfailures>0)
104         numfailures--;
105       printf("FAILURE!!! %d\n",numfailures);
106       threadexit();
107     }
108   }
109 #endif
110 #endif
111 }
112
113 #ifdef D___Double______nativeparsedouble____L___String___
114 double CALL01(___Double______nativeparsedouble____L___String___,struct ___String___ * ___str___) {
115   int length=VAR(___str___)->___count___;
116   int maxlength=(length>60)?60:length;
117   char str[maxlength+1];
118   struct ArrayObject * chararray=VAR(___str___)->___value___;
119   int i;
120   int offset=VAR(___str___)->___offset___;
121   for(i=0; i<maxlength; i++) {
122     str[i]=((short *)(((char *)&chararray->___length___)+sizeof(int)))[i+offset];
123   }
124   str[i]=0;
125   double d=atof(str);
126   return d;
127 }
128 #endif
129
130 #ifdef D___String______convertdoubletochar____D__AR_C
131 int CALL12(___String______convertdoubletochar____D__AR_C, double ___val___, double ___val___, struct ArrayObject ___chararray___) {
132   int length=VAR(___chararray___)->___length___;
133   char str[length];
134   int i;
135   int num=snprintf(str, length, "%f",___val___);
136   if (num>=length)
137     num=length-1;
138   for(i=0; i<length; i++) {
139     ((short *)(((char *)&VAR(___chararray___)->___length___)+sizeof(int)))[i]=(short)str[i];
140   }
141   return num;
142 }
143 #endif
144 #ifdef D___System______deepArrayCopy____L___Object____L___Object___
145 void deepArrayCopy(struct ___Object___ * dst, struct ___Object___ * src) {
146   int dsttype=((int *)dst)[0];
147   int srctype=((int *)src)[0];
148   if (dsttype<NUMCLASSES||srctype<NUMCLASSES||srctype!=dsttype)
149     return;
150   struct ArrayObject *aodst=(struct ArrayObject *)dst;
151   struct ArrayObject *aosrc=(struct ArrayObject *)src;
152   int dstlength=aodst->___length___;
153   int srclength=aosrc->___length___;
154   if (dstlength!=srclength)
155     return;
156   unsigned INTPTR *pointer=pointerarray[srctype];
157   if (pointer==0) {
158     int elementsize=classsize[srctype];
159     int size=srclength*elementsize;
160     //primitives
161     memcpy(((char *)&aodst->___length___)+sizeof(int) , ((char *)&aosrc->___length___)+sizeof(int), size);
162   } else {
163     //objects
164     int i;
165     for(i=0;i<srclength;i++) {
166       struct ___Object___ * ptr=((struct ___Object___**)(((char*) &aosrc->___length___)+sizeof(int)))[i];
167       int ptrtype=((int *)ptr)[0];
168       if (ptrtype>=NUMCLASSES) {
169         struct ___Object___ * dstptr=((struct ___Object___**)(((char*) &aodst->___length___)+sizeof(int)))[i];
170         deepArrayCopy(dstptr,ptr);
171       } else {
172         //hit an object
173         ((struct ___Object___ **)(((char*) &aodst->___length___)+sizeof(int)))[i]=ptr;
174       }
175     }
176   }
177 }
178
179 void CALL02(___System______deepArrayCopy____L___Object____L___Object___, struct ___Object___ * ___dst___, struct ___Object___ * ___src___) {
180   deepArrayCopy(VAR(___dst___), VAR(___src___));
181 }
182 #endif
183
184 void CALL11(___System______exit____I,int ___status___, int ___status___) {
185 #ifdef TRANSSTATS
186   printf("numTransCommit = %d\n", numTransCommit);
187   printf("numTransAbort = %d\n", numTransAbort);
188   printf("nSoftAbort = %d\n", nSoftAbort);
189 #ifdef STM
190   printf("nSoftAbortCommit = %d\n", nSoftAbortCommit);
191   printf("nSoftAbortAbort = %d\n", nSoftAbortAbort);
192 #ifdef STMSTATS
193   int i;
194   for(i=0; i<TOTALNUMCLASSANDARRAY; i++) {
195     printf("typesCausingAbort[%2d] numaccess= %5d numabort= %3d\n", i, typesCausingAbort[i].numaccess, typesCausingAbort[i].numabort);
196   }
197 #endif
198 #endif
199 #endif
200   exit(___status___);
201 }
202
203 #ifdef D___Vector______removeElement_____AR_L___Object____I_I
204 void CALL23(___Vector______removeElement_____AR_L___Object____I_I, int ___index___, int ___size___, struct ArrayObject * ___array___, int ___index___, int ___size___) {
205   char* offset=((char *)(&VAR(___array___)->___length___))+sizeof(unsigned int)+sizeof(void *)*___index___;
206   memmove(offset, offset+sizeof(void *),(___size___-___index___-1)*sizeof(void *));
207 }
208 #endif
209
210 void CALL11(___System______printI____I,int ___status___, int ___status___) {
211   printf("%d\n",___status___);
212 }
213
214 long long CALL00(___System______currentTimeMillis____) {
215   struct timeval tv; long long retval;
216   gettimeofday(&tv, NULL);
217   retval = tv.tv_sec; /* seconds */
218   retval*=1000; /* milliseconds */
219   retval+= (tv.tv_usec/1000); /* adjust milliseconds & add them in */
220   return retval;
221 }
222
223 long long CALL00(___System______microTimes____) {
224   struct timeval tv; 
225   long long retval;
226   gettimeofday(&tv, NULL);
227   retval = tv.tv_sec; /* seconds */
228   retval*=1000000; /* microsecs */
229   retval+= (tv.tv_usec); /* adjust microseconds & add them in */
230   return retval;
231 }
232
233 long long CALL00(___System______getticks____) {
234   unsigned a, d;
235   asm("cpuid");
236   asm volatile("rdtsc" : "=a" (a), "=d" (d));
237   return (((ticks)a) | (((ticks)d) << 32));
238 }
239
240 void CALL01(___System______printString____L___String___,struct ___String___ * ___s___) {
241   struct ArrayObject * chararray=VAR(___s___)->___value___;
242   int i;
243   int offset=VAR(___s___)->___offset___;
244   for(i=0; i<VAR(___s___)->___count___; i++) {
245     short sc=((short *)(((char *)&chararray->___length___)+sizeof(int)))[i+offset];
246     putchar(sc);
247   }
248 }
249
250 #ifdef DSTM
251 void CALL00(___System______clearPrefetchCache____) {
252   prehashClear();
253 }
254
255 #ifdef RANGEPREFETCH
256 void CALL02(___System______rangePrefetch____L___Object_____AR_S, struct ___Object___ * ___o___, struct ArrayObject * ___offsets___) {
257   /* Manual Prefetches to be inserted */
258   //printf("DEBUG-> %s() ___Object___ * ___o___ = %x\n", __func__, VAR(___o___));
259   //printf("DEBUG-> %s() ArrayObject * = %x\n", __func__, VAR(___offsets___));
260   int numoffset=VAR(___offsets___)->___length___;
261   int i;
262   short offArry[numoffset+2];
263   offArry[0] = 0;
264   offArry[1] = 0;
265   for(i = 2; i<(numoffset+2); i++) {
266     offArry[i] = *((short *)(((char *)&VAR(___offsets___)->___length___) + sizeof(int) + (i-2) * sizeof(short)));
267     //printf("DEBUG-> offArry[%d] = %d\n", i, offArry[i]);
268   }
269   unsigned int oid;
270   if(((unsigned int)(VAR(___o___)) & 1) != 0) { //odd
271     oid =  (unsigned int) VAR(___o___); //outside transaction therefore just an oid
272   } else { //even
273     oid = (unsigned int) COMPOID(VAR(___o___)); //inside transaction therefore a pointer to oid
274   }
275   rangePrefetch(oid, (short)(numoffset+2), offArry);
276 }
277 #else
278 void CALL02(___System______rangePrefetch____L___Object_____AR_S, struct ___Object___ * ___o___, struct ArrayObject * ___offsets___) {
279   return;
280 }
281 #endif
282
283 #endif
284
285 /* STM Barrier constructs */
286 #ifdef D___Barrier______setBarrier____I
287 void CALL11(___Barrier______setBarrier____I, int nthreads, int nthreads) {
288   // Barrier initialization
289   int ret;
290   if((ret = pthread_barrier_init(&barrier, NULL, nthreads)) != 0) {
291     printf("%s() Could not create a barrier: numthreads = 0 in %s\n", __func__, __FILE__);
292     exit(-1);
293   }
294 }
295 #endif
296
297 #ifdef D___Barrier______enterBarrier____
298 void CALL00(___Barrier______enterBarrier____) {
299   // Synchronization point
300   int ret;
301 #ifdef PRECISE_GC
302   stopforgc((struct garbagelist *)___params___);
303 #endif
304   ret = pthread_barrier_wait(&barrier);
305 #ifdef PRECISE_GC
306   restartaftergc();
307 #endif
308   if(ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) {
309     printf("%s() Could not wait on barrier: error %d in %s\n", __func__, errno, __FILE__);
310     exit(-1);
311   }
312 }
313 #endif
314
315 /* Object allocation function */
316
317 #ifdef DSTM
318 __attribute__((malloc)) void * allocate_newglobal(int type) {
319   struct ___Object___ * v=(struct ___Object___ *) transCreateObj(classsize[type]);
320   v->type=type;
321 #ifdef THREADS
322   v->tid=0;
323   v->lockentry=0;
324   v->lockcount=0;
325 #endif
326   return v;
327 }
328
329 /* Array allocation function */
330
331 __attribute__((malloc)) struct ArrayObject * allocate_newarrayglobal(int type, int length) {
332   struct ArrayObject * v=(struct ArrayObject *)transCreateObj(sizeof(struct ArrayObject)+length*classsize[type]);
333   if (length<0) {
334     printf("ERROR: negative array\n");
335     return NULL;
336   }
337   v->type=type;
338   v->___length___=length;
339 #ifdef THREADS
340   v->tid=0;
341   v->lockentry=0;
342   v->lockcount=0;
343 #endif
344   return v;
345 }
346 #endif
347
348
349 #ifdef STM
350 // STM Versions of allocation functions
351
352 /* Object allocation function */
353 __attribute__((malloc)) void * allocate_newtrans(void * ptr, int type) {
354   struct ___Object___ * v=(struct ___Object___ *) transCreateObj(ptr, classsize[type]);
355   v->type=type;
356   v->___objlocation___=v;
357   return v;
358 }
359
360 /* Array allocation function */
361 __attribute__((malloc)) struct ArrayObject * allocate_newarraytrans(void * ptr, int type, int length) {
362   struct ArrayObject * v=(struct ArrayObject *)transCreateObj(ptr, sizeof(struct ArrayObject)+length*classsize[type]);
363   if (length<0) {
364     printf("ERROR: negative array\n");
365     return NULL;
366   }
367   v->___objlocation___=(struct ___Object___*)v;
368   v->type=type;
369   v->___length___=length;
370   return v;
371 }
372 __attribute__((malloc)) void * allocate_new(void * ptr, int type) {
373   objheader_t *tmp=mygcmalloc((struct garbagelist *) ptr, classsize[type]+sizeof(objheader_t));
374   struct ___Object___ * v=(struct ___Object___ *) &tmp[1];
375   initdsmlocks(&tmp->lock);
376   tmp->version = 1;
377   v->___objlocation___=v;
378   v->type = type;
379   return v;
380 }
381
382 /* Array allocation function */
383
384 __attribute__((malloc)) struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
385   objheader_t *tmp=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+length*classsize[type]+sizeof(objheader_t));
386   struct ArrayObject * v=(struct ArrayObject *) &tmp[1];
387   initdsmlocks(&tmp->lock);
388   tmp->version=1;
389   v->type=type;
390   if (length<0) {
391     printf("ERROR: negative array %d\n", length);
392     return NULL;
393   }
394   v->___objlocation___=(struct ___Object___ *)v;
395   v->___length___=length;
396   return v;
397 }
398 #endif
399
400 #ifndef STM
401 #if defined(PRECISE_GC)
402 __attribute__((malloc)) void * allocate_new(void * ptr, int type) {
403   struct ___Object___ * v=(struct ___Object___ *) mygcmalloc((struct garbagelist *) ptr, classsize[type]);
404   v->type=type;
405 #ifdef THREADS
406   v->tid=0;
407   v->lockentry=0;
408   v->lockcount=0;
409 #endif
410 #ifdef OPTIONAL
411   v->fses=0;
412 #endif
413   return v;
414 }
415
416 /* Array allocation function */
417
418 __attribute__((malloc)) struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
419   struct ArrayObject * v=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+length*classsize[type]);
420   v->type=type;
421   if (length<0) {
422     printf("ERROR: negative array\n");
423     return NULL;
424   }
425   v->___length___=length;
426 #ifdef THREADS
427   v->tid=0;
428   v->lockentry=0;
429   v->lockcount=0;
430 #endif
431 #ifdef OPTIONAL
432   v->fses=0;
433 #endif
434   return v;
435 }
436
437 #else
438 __attribute__((malloc)) void * allocate_new(int type) {
439   struct ___Object___ * v=FREEMALLOC(classsize[type]);
440   v->type=type;
441 #ifdef OPTIONAL
442   v->fses=0;
443 #endif
444   return v;
445 }
446
447 /* Array allocation function */
448
449 __attribute__((malloc)) struct ArrayObject * allocate_newarray(int type, int length) {
450   __attribute__((malloc))  struct ArrayObject * v=FREEMALLOC(sizeof(struct ArrayObject)+length*classsize[type]);
451   v->type=type;
452   v->___length___=length;
453 #ifdef OPTIONAL
454   v->fses=0;
455 #endif
456   return v;
457 }
458 #endif
459 #endif
460
461 /* Converts C character arrays into Java strings */
462 #ifdef PRECISE_GC
463 __attribute__((malloc)) struct ___String___ * NewString(void * ptr, const char *str,int length) {
464 #else
465 __attribute__((malloc)) struct ___String___ * NewString(const char *str,int length) {
466 #endif
467   int i;
468 #ifdef PRECISE_GC
469   struct ArrayObject * chararray=allocate_newarray((struct garbagelist *)ptr, CHARARRAYTYPE, length);
470   INTPTR ptrarray[]={1, (INTPTR) ptr, (INTPTR) chararray};
471   struct ___String___ * strobj=allocate_new((struct garbagelist *) &ptrarray, STRINGTYPE);
472   chararray=(struct ArrayObject *) ptrarray[2];
473 #else
474   struct ArrayObject * chararray=allocate_newarray(CHARARRAYTYPE, length);
475   struct ___String___ * strobj=allocate_new(STRINGTYPE);
476 #endif
477   strobj->___value___=chararray;
478   strobj->___count___=length;
479   strobj->___offset___=0;
480
481   for(i=0; i<length; i++) {
482     ((short *)(((char *)&chararray->___length___)+sizeof(int)))[i]=(short)str[i];
483   }
484   return strobj;
485 }
486
487 /* Generated code calls this if we fail a bounds check */
488
489 void failedboundschk() {
490 #ifndef TASK
491   printf("Array out of bounds\n");
492 #ifdef THREADS
493   threadexit();
494 #else
495   exit(-1);
496 #endif
497 #else
498   longjmp(error_handler,2);
499 #endif
500 }
501
502 /* Abort task call */
503 void abort_task() {
504 #ifdef TASK
505   longjmp(error_handler,4);
506 #else
507   printf("Aborting\n");
508   exit(-1);
509 #endif
510 }