changes to compile
[IRC.git] / Robust / src / Runtime / thread.c
1 #include "runtime.h"
2 #include <sys/types.h>
3 #include <unistd.h>
4 #include <errno.h>
5 #include <stdlib.h>
6 #include "thread.h"
7 #include "option.h"
8 #include <signal.h>
9
10 #ifdef DSTM
11 #include <DSTM/interface/dstm.h>
12 #include <DSTM/interface/llookup.h>
13 #endif
14
15 #ifndef RAW
16 #include <stdio.h>
17 #endif
18 #ifdef STM
19 #include "tm.h"
20 #endif
21
22 int threadcount;
23 pthread_mutex_t gclock;
24 pthread_mutex_t gclistlock;
25 pthread_cond_t gccond;
26 pthread_mutex_t objlock;
27 pthread_cond_t objcond;
28
29 pthread_mutex_t joinlock;
30 pthread_cond_t joincond;
31 pthread_key_t threadlocks;
32 pthread_mutex_t threadnotifylock;
33 pthread_cond_t threadnotifycond;
34 pthread_key_t oidval;
35
36 #if defined(THREADS) || defined(DSTM) || defined(STM)
37 #ifndef MAC
38 extern __thread struct listitem litem;
39 #else
40 pthread_key_t litemkey;
41 #endif
42 extern struct listitem * list;
43 #endif
44
45 void threadexit() {
46 #ifdef DSTM
47   objheader_t* ptr;
48   unsigned int oidvalue;
49 #endif
50   void *value;
51
52 #ifdef THREADS
53   struct ___Object___ *ll=pthread_getspecific(threadlocks);
54   while(ll!=NULL) {
55     struct ___Object___ *llnext=ll->___nextlockobject___;
56     ll->___nextlockobject___=NULL;
57     ll->___prevlockobject___=NULL;
58     ll->lockcount=0;
59     ll->tid=0; //unlock it
60     ll=llnext;
61   }
62   pthread_mutex_lock(&objlock); //wake everyone up
63   pthread_cond_broadcast(&objcond);
64   pthread_mutex_unlock(&objlock);
65 #endif
66   pthread_mutex_lock(&gclistlock);
67 #ifdef THREADS
68   pthread_setspecific(threadlocks, litem->locklist);
69 #endif
70 #ifndef MAC
71   if (litem.prev==NULL) {
72     list=litem.next;
73   } else {
74     litem.prev->next=litem.next;
75   }
76   if (litem.next!=NULL) {
77     litem.next->prev=litem.prev;
78   }
79 #else
80   {
81     struct listitem *litem=pthread_getspecific(litemkey);
82     if (litem->prev==NULL) {
83       list=litem->next;
84     } else {
85       litem->prev->next=litem->next;
86     }
87     if (litem->next!=NULL) {
88       litem->next->prev=litem->prev;
89     }
90   }
91 #endif
92   threadcount--;
93   pthread_cond_signal(&gccond);
94   pthread_mutex_unlock(&gclistlock);
95 #ifdef DSTM
96   /* Add transaction to check if thread finished for join operation */
97   value = pthread_getspecific(oidval);
98   oidvalue = *((unsigned int *)value);
99   goto transstart;
100 transstart:
101   {
102     transStart();
103     ptr = transRead(oidvalue);
104     struct ___Thread___ *p = (struct ___Thread___ *) ptr;
105     p->___threadDone___ = 1;
106     *((unsigned int *)&((struct ___Object___ *) p)->___localcopy___) |=DIRTY;
107     if(transCommit() != 0) {
108       goto transstart;
109     }
110   }
111 #endif
112   pthread_exit(NULL);
113 }
114
115 void threadhandler(int sig, siginfo_t *info, void *uap) {
116 #ifdef DEBUG
117   printf("sig=%d\n",sig);
118   printf("signal\n");
119 #endif
120   threadexit();
121 }
122
123 void initializethreads() {
124   struct sigaction sig;
125   threadcount=1;
126   pthread_mutex_init(&gclock, NULL);
127   pthread_mutex_init(&gclistlock, NULL);
128   pthread_cond_init(&gccond, NULL);
129   pthread_mutex_init(&objlock,NULL);
130   pthread_cond_init(&objcond,NULL);
131   pthread_mutex_init(&joinlock,NULL);
132   pthread_cond_init(&joincond,NULL);
133   pthread_key_create(&threadlocks, NULL);
134 #ifdef MAC
135   pthread_key_create(&litem, NULL);
136 #endif
137   processOptions();
138   initializeexithandler();
139
140   sig.sa_sigaction=&threadhandler;
141   sig.sa_flags=SA_SIGINFO;
142   sigemptyset(&sig.sa_mask);
143
144   /* Catch bus errors, segmentation faults, and floating point exceptions*/
145   sigaction(SIGBUS,&sig,0);
146   sigaction(SIGSEGV,&sig,0);
147   sigaction(SIGFPE,&sig,0);
148   signal(SIGPIPE, SIG_IGN);
149 #ifdef STM
150   newobjs=calloc(1, sizeof(struct objlist));
151   t_cache = objstrCreate(1048576);
152   t_reserve=NULL;
153   t_chashCreate(CHASH_SIZE, CLOADFACTOR);
154 #ifdef STMSTATS
155   trec=calloc(1, sizeof(threadrec_t));
156   trec->blocked = 0;
157   lockedobjs=calloc(1, sizeof(struct objlist));
158   objlockscope = calloc(1, sizeof(objlockstate_t));
159   pthread_mutex_init(&lockedobjstore, NULL);
160   { 
161     int i;
162     for(i=0; i<TOTALNUMCLASSANDARRAY; i++) {
163       typesCausingAbort[i] = 0;
164     }
165   }
166 #endif
167 #endif
168 }
169
170 #if defined(THREADS)||defined(STM)
171 void initthread(struct ___Thread___ * ___this___) {
172 #ifdef PRECISE_GC
173   INTPTR p[]={1, (INTPTR) NULL, (INTPTR) ___this___};
174   //Add our litem to list of threads
175 #ifdef MAC
176   struct listitem litem;
177   pthread_setspecific(litemkey, &litem);
178 #endif
179   litem.prev=NULL;
180   pthread_mutex_lock(&gclistlock);
181   litem.next=list;
182   if(list!=NULL)
183     list->prev=&litem;
184   list=&litem;
185   pthread_mutex_unlock(&gclistlock);
186   
187 #ifdef THREADS
188   ___Thread______staticStart____L___Thread___((struct ___Thread______staticStart____L___Thread____params *)p);
189 #else
190   newobjs=calloc(1, sizeof(struct objlist));
191 #ifdef STMSTATS
192   trec=calloc(1, sizeof(threadrec_t));
193   trec->blocked = 0;
194   lockedobjs=calloc(1, sizeof(struct objlist));
195 #endif
196   t_cache = objstrCreate(1048576);
197   t_reserve=NULL;
198   t_chashCreate(CHASH_SIZE, CLOADFACTOR);
199  ___Thread____NNR____staticStart____L___Thread___((struct ___Thread____NNR____staticStart____L___Thread____params *)p);
200  objstrDelete(t_cache);
201  objstrDelete(t_reserve);
202  t_chashDelete();
203  free(newobjs);
204 #ifdef STMSTATS
205  free(lockedobjs);
206 #endif
207 #endif
208   ___this___=(struct ___Thread___ *) p[2];
209 #else
210   ___Thread______staticStart____L___Thread___(___this___);
211 #endif
212   ___this___->___finished___=1;
213   pthread_mutex_lock(&joinlock);
214   pthread_cond_signal(&joincond);
215   pthread_mutex_unlock(&joinlock);
216
217   pthread_mutex_lock(&gclistlock);
218 #ifdef THREADS
219   pthread_setspecific(threadlocks, litem->locklist);
220 #endif
221   if (litem.prev==NULL) {
222     list=litem.next;
223   } else {
224     litem.prev->next=litem.next;
225   }
226   if (litem.next!=NULL) {
227     litem.next->prev=litem.prev;
228   }
229   threadcount--;
230   pthread_cond_signal(&gccond);
231   pthread_mutex_unlock(&gclistlock);
232 }
233 #endif
234
235 void CALL11(___Thread______sleep____J, long long ___millis___, long long ___millis___) {
236 #if defined(THREADS)||defined(STM)
237 #ifdef PRECISE_GC
238   stopforgc((struct garbagelist *)___params___);
239 #endif
240 #endif
241   usleep(___millis___);
242 #if defined(THREADS)||defined(STM)
243 #ifdef PRECISE_GC
244   restartaftergc();
245 #endif
246 #endif
247 }
248
249 #if defined(DSTM)|| defined(THREADS)||defined(STM)
250 void CALL00(___Thread______yield____) {
251   pthread_yield();
252 }
253 #endif
254
255 #ifdef DSTM
256 /* Add thread join capability */
257 void CALL01(___Thread______join____, struct ___Thread___ * ___this___) {
258   unsigned int *oidarray;
259   unsigned short *versionarray, version;
260   objheader_t *ptr;
261   /* Add transaction to check if thread finished for join operation */
262 transstart:
263   transStart();
264   ptr = transRead((unsigned int) VAR(___this___));
265   struct ___Thread___ *p = (struct ___Thread___ *) ptr;
266 #ifdef THREADJOINDEBUG
267   printf("Start join process for Oid = %x\n", (unsigned int) VAR(___this___));
268 #endif
269   if(p->___threadDone___ == 1) {
270 #ifdef THREADJOINDEBUG
271     printf("Thread oid = %x is done\n", (unsigned int) VAR(___this___));
272 #endif
273     transAbort();
274     return;
275   } else {
276
277     version = (ptr-1)->version;
278     if((oidarray = calloc(1, sizeof(unsigned int))) == NULL) {
279       printf("Calloc error %s, %d\n", __FILE__, __LINE__);
280       return;
281     }
282
283     oidarray[0] = (unsigned int) VAR(___this___);
284
285     if((versionarray = calloc(1, sizeof(unsigned short))) == NULL) {
286       printf("Calloc error %s, %d\n", __FILE__, __LINE__);
287       free(oidarray);
288       return;
289     }
290     versionarray[0] = version;
291     /* Request Notification */
292 #ifdef PRECISE_GC
293     stopforgc((struct garbagelist *)___params___);
294 #endif
295     reqNotify(oidarray, versionarray, 1);
296 #ifdef PRECISE_GC
297     restartaftergc();
298 #endif
299     free(oidarray);
300     free(versionarray);
301     transAbort();
302     goto transstart;
303   }
304   return;
305 }
306 #endif
307
308 #if defined(THREADS)||defined(STM)
309 void CALL01(___Thread______nativeJoin____, struct ___Thread___ * ___this___) {
310 #ifdef PRECISE_GC
311   stopforgc((struct garbagelist *)___params___);
312 #endif
313   pthread_mutex_lock(&joinlock);
314   while(!VAR(___this___)->___finished___)
315     pthread_cond_wait(&joincond, &joinlock);
316   pthread_mutex_unlock(&joinlock);
317 #ifdef PRECISE_GC
318     restartaftergc();
319 #endif
320
321 }
322
323 void CALL01(___Thread______nativeCreate____, struct ___Thread___ * ___this___) {
324   pthread_t thread;
325   int retval;
326   pthread_attr_t nattr;
327
328   pthread_mutex_lock(&gclistlock);
329   threadcount++;
330   pthread_mutex_unlock(&gclistlock);
331   pthread_attr_init(&nattr);
332   pthread_attr_setdetachstate(&nattr, PTHREAD_CREATE_DETACHED);
333
334   do {
335     retval=pthread_create(&thread, &nattr, (void * (*)(void *)) &initthread, VAR(___this___));
336     if (retval!=0)
337       usleep(1);
338   } while(retval!=0);
339   /* This next statement will likely not work on many machines */
340
341   pthread_attr_destroy(&nattr);
342 }
343 #endif
344
345 #ifdef DSTM
346 void CALL12(___Thread______start____I, int ___mid___, struct ___Thread___ * ___this___, int ___mid___) {
347   startRemoteThread((unsigned int)VAR(___this___), ___mid___);
348 }
349 #endif
350
351 #ifdef DSTM
352 void globalDestructor(void *value) {
353   free(value);
354   pthread_setspecific(oidval, NULL);
355 }
356
357 void initDSMthread(int *ptr) {
358   objheader_t *tmp;
359   void *threadData;
360   int oid=ptr[0];
361   int type=ptr[1];
362   free(ptr);
363 #ifdef PRECISE_GC
364   int p[]={1, 0 /* NULL */, oid};
365 #ifdef MAC
366   struct listitem litem;
367   pthread_setspecific(litemkey, &litem);
368 #endif
369
370   //Add our litem to list of threads
371   litem.prev=NULL;
372   pthread_mutex_lock(&gclistlock);
373   litem.next=list;
374   if(list!=NULL)
375     list->prev=&litem;
376   list=&litem;
377   pthread_mutex_unlock(&gclistlock);
378
379   ((void(*) (void *))virtualtable[type*MAXCOUNT+RUNMETHOD])(p);
380 #else
381   ((void(*) (void *))virtualtable[type*MAXCOUNT+RUNMETHOD])(oid);
382 #endif
383   threadData = calloc(1, sizeof(unsigned int));
384   *((unsigned int *) threadData) = oid;
385   pthread_setspecific(oidval, threadData);
386   pthread_mutex_lock(&gclistlock);
387
388 #ifdef THREADS
389   pthread_setspecific(threadlocks, litem->locklist);
390 #endif
391   if (litem.prev==NULL) {
392     list=litem.next;
393   } else {
394     litem.prev->next=litem.next;
395   }
396   if (litem.next!=NULL) {
397     litem.next->prev=litem.prev;
398   }
399   threadcount--;
400   pthread_cond_signal(&gccond);
401   pthread_mutex_unlock(&gclistlock);
402   /* Add transaction to check if thread finished for join operation */
403   goto transstart;
404 transstart:
405   {
406     transStart();
407     tmp  = transRead((unsigned int) oid);
408     ((struct ___Thread___ *)tmp)->___threadDone___ = 1;
409     *((unsigned int *)&((struct ___Object___ *) tmp)->___localcopy___) |=DIRTY;
410     if(transCommit()!= 0) {
411       goto transstart;
412     }
413   }
414   pthread_exit(NULL);
415 }
416
417 void startDSMthread(int oid, int objType) {
418   pthread_t thread;
419   int retval;
420   pthread_attr_t nattr;
421
422   pthread_mutex_lock(&gclistlock);
423   threadcount++;
424   pthread_mutex_unlock(&gclistlock);
425   pthread_attr_init(&nattr);
426   pthread_attr_setdetachstate(&nattr, PTHREAD_CREATE_DETACHED);
427   int * ptr=malloc(sizeof(int)*2);
428   ptr[0]=oid;
429   ptr[1]=objType;
430   pthread_key_create(&oidval, globalDestructor);
431   do {
432     retval=pthread_create(&thread, &nattr, (void * (*)(void *)) &initDSMthread,  ptr);
433     if (retval!=0)
434       usleep(1);
435   } while(retval!=0);
436
437   pthread_attr_destroy(&nattr);
438 }
439
440 #endif