try to simplify garbage collector lock
[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 #ifdef DMALLOC
45 #include "dmalloc.h"
46 #endif
47
48 int instanceof(struct ___Object___ *ptr, int type) {
49   int i=ptr->type;
50   do {
51     if (i==type)
52       return 1;
53     i=typearray[i];
54   } while(i!=-1);
55   i=ptr->type;
56   if (i>NUMCLASSES) {
57     do {
58       if (i==type)
59         return 1;
60       i=typearray2[i-NUMCLASSES];
61     } while(i!=-1);
62   }
63   return 0;
64 }
65
66 void exithandler(int sig, siginfo_t *info, void * uap) {
67   exit(0);
68 }
69
70 void initializeexithandler() {
71   struct sigaction sig;
72   sig.sa_sigaction=&exithandler;
73   sig.sa_flags=SA_SIGINFO;
74   sigemptyset(&sig.sa_mask);
75   sigaction(SIGUSR2, &sig, 0);
76 }
77
78
79 /* This function inject failures */
80
81 void injectinstructionfailure() {
82 #ifdef TASK
83   if (injectinstructionfailures) {
84     if (numfailures==0)
85       return;
86     instructioncount=failurecount;
87     instaccum+=failurecount;
88     if ((((double)random())/RAND_MAX)<instfailurechance) {
89       if (numfailures>0)
90         numfailures--;
91       printf("FAILURE!!! %d\n",numfailures);
92       longjmp(error_handler,11);
93     }
94   }
95 #else
96 #ifdef THREADS
97   if (injectinstructionfailures) {
98     if (numfailures==0)
99       return;
100     instaccum+=failurecount;
101     if ((((double)random())/RAND_MAX)<instfailurechance) {
102       if (numfailures>0)
103         numfailures--;
104       printf("FAILURE!!! %d\n",numfailures);
105       threadexit();
106     }
107   }
108 #endif
109 #endif
110 }
111
112 void CALL11(___System______exit____I,int ___status___, int ___status___) {
113 #ifdef TRANSSTATS
114   printf("numTransCommit = %d\n", numTransCommit);
115   printf("numTransAbort = %d\n", numTransAbort);
116   printf("nSoftAbort = %d\n", nSoftAbort);
117 #ifdef STM
118   printf("nSoftAbortCommit = %d\n", nSoftAbortCommit);
119   printf("nSoftAbortAbort = %d\n", nSoftAbortAbort);
120 #ifdef STMSTATS
121   int i;
122   for(i=0; i<TOTALNUMCLASSANDARRAY; i++) {
123     printf("typesCausingAbort[%d]= %d\n", i, typesCausingAbort[i]);
124   }
125 #endif
126 #endif
127 #endif
128   exit(___status___);
129 }
130
131 #ifdef D___Vector______removeElement_____AR_L___Object____I_I
132 void CALL23(___Vector______removeElement_____AR_L___Object____I_I, int ___index___, int ___size___, struct ArrayObject * ___array___, int ___index___, int ___size___) {
133   char* offset=((char *)(&VAR(___array___)->___length___))+sizeof(unsigned int)+sizeof(void *)*___index___;
134   memmove(offset, offset+sizeof(void *),(___size___-___index___-1)*sizeof(void *));
135 }
136 #endif
137
138 void CALL11(___System______printI____I,int ___status___, int ___status___) {
139   printf("%d\n",___status___);
140 }
141
142 long long CALL00(___System______currentTimeMillis____) {
143   struct timeval tv; long long retval;
144   gettimeofday(&tv, NULL);
145   retval = tv.tv_sec; /* seconds */
146   retval*=1000; /* milliseconds */
147   retval+= (tv.tv_usec/1000); /* adjust milliseconds & add them in */
148   return retval;
149 }
150
151 void CALL01(___System______printString____L___String___,struct ___String___ * ___s___) {
152   struct ArrayObject * chararray=VAR(___s___)->___value___;
153   int i;
154   int offset=VAR(___s___)->___offset___;
155   for(i=0; i<VAR(___s___)->___count___; i++) {
156     short sc=((short *)(((char *)&chararray->___length___)+sizeof(int)))[i+offset];
157     putchar(sc);
158   }
159 }
160
161 #ifdef DSTM
162 void CALL00(___System______clearPrefetchCache____) {
163   prehashClear();
164 }
165
166 #ifdef RANGEPREFETCH
167 void CALL02(___System______rangePrefetch____L___Object_____AR_S, struct ___Object___ * ___o___, struct ArrayObject * ___offsets___) {
168   /* Manual Prefetches to be inserted */
169   //printf("DEBUG-> %s() ___Object___ * ___o___ = %x\n", __func__, VAR(___o___));
170   //printf("DEBUG-> %s() ArrayObject * = %x\n", __func__, VAR(___offsets___));
171   int numoffset=VAR(___offsets___)->___length___;
172   int i;
173   short offArry[numoffset+2];
174   offArry[0] = 0;
175   offArry[1] = 0;
176   for(i = 2; i<(numoffset+2); i++) {
177     offArry[i] = *((short *)(((char *)&VAR(___offsets___)->___length___) + sizeof(int) + (i-2) * sizeof(short)));
178     //printf("DEBUG-> offArry[%d] = %d\n", i, offArry[i]);
179   }
180   unsigned int oid;
181   if(((unsigned int)(VAR(___o___)) & 1) != 0) { //odd
182     oid =  (unsigned int) VAR(___o___); //outside transaction therefore just an oid
183   } else { //even
184     oid = (unsigned int) COMPOID(VAR(___o___)); //inside transaction therefore a pointer to oid
185   }
186   rangePrefetch(oid, (short)(numoffset+2), offArry);
187 }
188 #else
189 void CALL02(___System______rangePrefetch____L___Object_____AR_S, struct ___Object___ * ___o___, struct ArrayObject * ___offsets___) {
190   return;
191 }
192 #endif
193
194 #endif
195
196 /* STM Barrier constructs */
197 #ifdef D___Barrier______setBarrier____I
198 void CALL11(___Barrier______setBarrier____I, int nthreads, int nthreads) {
199   // Barrier initialization
200   int ret;
201   if((ret = pthread_barrier_init(&barrier, NULL, nthreads)) != 0) {
202     printf("%s() Could not create a barrier: numthreads = 0 in %s\n", __func__, __FILE__);
203     exit(-1);
204   }
205 }
206 #endif
207
208 #ifdef D___Barrier______enterBarrier____
209 void CALL00(___Barrier______enterBarrier____) {
210   // Synchronization point
211   int ret;
212 #ifdef PRECISE_GC
213   stopforgc((struct garbagelist *)___params___);
214 #endif
215   ret = pthread_barrier_wait(&barrier);
216 #ifdef PRECISE_GC
217   restartaftergc();
218 #endif
219   if(ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) {
220     printf("%s() Could not wait on barrier: error %d in %s\n", __func__, errno, __FILE__);
221     exit(-1);
222   }
223 }
224 #endif
225
226 /* Object allocation function */
227
228 #ifdef DSTM
229 __attribute__((malloc)) void * allocate_newglobal(int type) {
230   struct ___Object___ * v=(struct ___Object___ *) transCreateObj(classsize[type]);
231   v->type=type;
232 #ifdef THREADS
233   v->tid=0;
234   v->lockentry=0;
235   v->lockcount=0;
236 #endif
237   return v;
238 }
239
240 /* Array allocation function */
241
242 __attribute__((malloc)) struct ArrayObject * allocate_newarrayglobal(int type, int length) {
243   struct ArrayObject * v=(struct ArrayObject *)transCreateObj(sizeof(struct ArrayObject)+length*classsize[type]);
244   if (length<0) {
245     printf("ERROR: negative array\n");
246     return NULL;
247   }
248   v->type=type;
249   v->___length___=length;
250 #ifdef THREADS
251   v->tid=0;
252   v->lockentry=0;
253   v->lockcount=0;
254 #endif
255   return v;
256 }
257 #endif
258
259
260 #ifdef STM
261 // STM Versions of allocation functions
262
263 /* Object allocation function */
264 __attribute__((malloc)) void * allocate_newtrans(void * ptr, int type) {
265   struct ___Object___ * v=(struct ___Object___ *) transCreateObj(ptr, classsize[type]);
266   v->type=type;
267   v->___objlocation___=v;
268   return v;
269 }
270
271 /* Array allocation function */
272 __attribute__((malloc)) struct ArrayObject * allocate_newarraytrans(void * ptr, int type, int length) {
273   struct ArrayObject * v=(struct ArrayObject *)transCreateObj(ptr, sizeof(struct ArrayObject)+length*classsize[type]);
274   if (length<0) {
275     printf("ERROR: negative array\n");
276     return NULL;
277   }
278   v->___objlocation___=(struct ___Object___*)v;
279   v->type=type;
280   v->___length___=length;
281   return v;
282 }
283 __attribute__((malloc)) void * allocate_new(void * ptr, int type) {
284   objheader_t *tmp=mygcmalloc((struct garbagelist *) ptr, classsize[type]+sizeof(objheader_t));
285   struct ___Object___ * v=(struct ___Object___ *) &tmp[1];
286   initdsmlocks(&tmp->lock);
287   tmp->version = 1;
288   v->___objlocation___=v;
289   v->type = type;
290   return v;
291 }
292
293 /* Array allocation function */
294
295 __attribute__((malloc)) struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
296   objheader_t *tmp=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+length*classsize[type]+sizeof(objheader_t));
297   struct ArrayObject * v=(struct ArrayObject *) &tmp[1];
298   initdsmlocks(&tmp->lock);
299   tmp->version=1;
300   v->type=type;
301   if (length<0) {
302     printf("ERROR: negative array %d\n", length);
303     return NULL;
304   }
305   v->___objlocation___=(struct ___Object___ *)v;
306   v->___length___=length;
307   return v;
308 }
309 #endif
310
311 #ifndef STM
312 #if defined(PRECISE_GC)
313 __attribute__((malloc)) void * allocate_new(void * ptr, int type) {
314   struct ___Object___ * v=(struct ___Object___ *) mygcmalloc((struct garbagelist *) ptr, classsize[type]);
315   v->type=type;
316 #ifdef THREADS
317   v->tid=0;
318   v->lockentry=0;
319   v->lockcount=0;
320 #endif
321 #ifdef OPTIONAL
322   v->fses=0;
323 #endif
324   return v;
325 }
326
327 /* Array allocation function */
328
329 __attribute__((malloc)) struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
330   struct ArrayObject * v=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+length*classsize[type]);
331   v->type=type;
332   if (length<0) {
333     printf("ERROR: negative array\n");
334     return NULL;
335   }
336   v->___length___=length;
337 #ifdef THREADS
338   v->tid=0;
339   v->lockentry=0;
340   v->lockcount=0;
341 #endif
342 #ifdef OPTIONAL
343   v->fses=0;
344 #endif
345   return v;
346 }
347
348 #else
349 __attribute__((malloc)) void * allocate_new(int type) {
350   struct ___Object___ * v=FREEMALLOC(classsize[type]);
351   v->type=type;
352 #ifdef OPTIONAL
353   v->fses=0;
354 #endif
355   return v;
356 }
357
358 /* Array allocation function */
359
360 __attribute__((malloc)) struct ArrayObject * allocate_newarray(int type, int length) {
361   __attribute__((malloc))  struct ArrayObject * v=FREEMALLOC(sizeof(struct ArrayObject)+length*classsize[type]);
362   v->type=type;
363   v->___length___=length;
364 #ifdef OPTIONAL
365   v->fses=0;
366 #endif
367   return v;
368 }
369 #endif
370 #endif
371
372
373 /* Converts C character arrays into Java strings */
374 #ifdef PRECISE_GC
375 __attribute__((malloc)) struct ___String___ * NewString(void * ptr, const char *str,int length) {
376 #else
377 __attribute__((malloc)) struct ___String___ * NewString(const char *str,int length) {
378 #endif
379   int i;
380 #ifdef PRECISE_GC
381   struct ArrayObject * chararray=allocate_newarray((struct garbagelist *)ptr, CHARARRAYTYPE, length);
382   INTPTR ptrarray[]={1, (INTPTR) ptr, (INTPTR) chararray};
383   struct ___String___ * strobj=allocate_new((struct garbagelist *) &ptrarray, STRINGTYPE);
384   chararray=(struct ArrayObject *) ptrarray[2];
385 #else
386   struct ArrayObject * chararray=allocate_newarray(CHARARRAYTYPE, length);
387   struct ___String___ * strobj=allocate_new(STRINGTYPE);
388 #endif
389   strobj->___value___=chararray;
390   strobj->___count___=length;
391   strobj->___offset___=0;
392
393   for(i=0; i<length; i++) {
394     ((short *)(((char *)&chararray->___length___)+sizeof(int)))[i]=(short)str[i];
395   }
396   return strobj;
397 }
398
399 /* Generated code calls this if we fail a bounds check */
400
401 void failedboundschk() {
402 #ifndef TASK
403   printf("Array out of bounds\n");
404 #ifdef THREADS
405   threadexit();
406 #else
407   exit(-1);
408 #endif
409 #else
410   longjmp(error_handler,2);
411 #endif
412 }
413
414 /* Abort task call */
415 void abort_task() {
416 #ifdef TASK
417   longjmp(error_handler,4);
418 #else
419   printf("Aborting\n");
420   exit(-1);
421 #endif
422 }