Thread local hack to make transRead faster...
[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 #include <DSTM/interface/dstm.h>
10 #include <DSTM/interface/llookup.h>
11
12 #ifndef RAW
13 #include <stdio.h>
14 #endif
15 int threadcount;
16 pthread_mutex_t gclock;
17 pthread_mutex_t gclistlock;
18 pthread_cond_t gccond;
19 pthread_mutex_t objlock;
20 pthread_cond_t objcond;
21
22 pthread_mutex_t joinlock;
23 pthread_cond_t joincond;
24 pthread_key_t threadlocks;
25 pthread_mutex_t threadnotifylock;
26 pthread_cond_t threadnotifycond;
27 pthread_key_t oidval;
28
29 void threadexit() {
30   objheader_t* ptr;
31   void *value;
32   unsigned int oidvalue;
33
34 #ifdef THREADS
35   struct ___Object___ *ll=pthread_getspecific(threadlocks);
36   while(ll!=NULL) {
37     struct ___Object___ *llnext=ll->___nextlockobject___;
38     ll->___nextlockobject___=NULL;
39     ll->___prevlockobject___=NULL;
40     ll->lockcount=0;
41     ll->tid=0; //unlock it
42     ll=llnext;
43   }
44   pthread_mutex_lock(&objlock); //wake everyone up
45   pthread_cond_broadcast(&objcond);
46   pthread_mutex_unlock(&objlock);
47 #endif
48   pthread_mutex_lock(&gclistlock);
49   threadcount--;
50   pthread_cond_signal(&gccond);
51   pthread_mutex_unlock(&gclistlock);
52 #ifdef DSTM
53   /* Add transaction to check if thread finished for join operation */
54   value = pthread_getspecific(oidval);
55   oidvalue = *((unsigned int *)value);
56   goto transstart;
57 transstart:
58   {
59     transStart();
60     ptr = transRead(oidvalue);
61     struct ___Thread___ *p = (struct ___Thread___ *) ptr;
62     p->___threadDone___ = 1;
63     *((unsigned int *)&((struct ___Object___ *) p)->___localcopy___) |=DIRTY;
64     if(transCommit() != 0) {
65       goto transstart;
66     }
67   }
68 #endif
69   pthread_exit(NULL);
70 }
71
72 void threadhandler(int sig, siginfo_t *info, void *uap) {
73 #ifdef DEBUG
74   printf("sig=%d\n",sig);
75   printf("signal\n");
76 #endif
77   threadexit();
78 }
79
80 void initializethreads() {
81   struct sigaction sig;
82   threadcount=1;
83   pthread_mutex_init(&gclock, NULL);
84   pthread_mutex_init(&gclistlock, NULL);
85   pthread_cond_init(&gccond, NULL);
86   pthread_mutex_init(&objlock,NULL);
87   pthread_cond_init(&objcond,NULL);
88   pthread_mutex_init(&joinlock,NULL);
89   pthread_cond_init(&joincond,NULL);
90   pthread_key_create(&threadlocks, NULL);
91   processOptions();
92   initializeexithandler();
93
94   sig.sa_sigaction=&threadhandler;
95   sig.sa_flags=SA_SIGINFO;
96   sigemptyset(&sig.sa_mask);
97
98   /* Catch bus errors, segmentation faults, and floating point exceptions*/
99   sigaction(SIGBUS,&sig,0);
100   sigaction(SIGSEGV,&sig,0);
101   sigaction(SIGFPE,&sig,0);
102   signal(SIGPIPE, SIG_IGN);
103 }
104
105 #ifdef THREADS
106 void initthread(struct ___Thread___ * ___this___) {
107 #ifdef PRECISE_GC
108   int p[]={1, (int) NULL, (int) ___this___};
109   ___Thread______staticStart____L___Thread___((struct ___Thread______staticStart____L___Thread____params *)p);
110   ___this___=(struct ___Thread___ *) p[2];
111 #else
112   ___Thread______staticStart____L___Thread___(___this___);
113 #endif
114   ___this___->___finished___=1;
115   pthread_mutex_lock(&joinlock);
116   pthread_cond_signal(&joincond);
117   pthread_mutex_unlock(&joinlock);
118
119   pthread_mutex_lock(&gclistlock);
120   threadcount--;
121   pthread_cond_signal(&gccond);
122   pthread_mutex_unlock(&gclistlock);
123 }
124 #endif
125
126 void CALL11(___Thread______sleep____J, long long ___millis___, long long ___millis___) {
127 #ifdef THREADS
128 #ifdef PRECISE_GC
129   struct listitem *tmp=stopforgc((struct garbagelist *)___params___);
130 #endif
131 #endif
132   usleep(___millis___);
133 #ifdef THREADS
134 #ifdef PRECISE_GC
135   restartaftergc(tmp);
136 #endif
137 #endif
138 }
139
140 #if defined(DSTM)|| defined(THREADS)
141 void CALL00(___Thread______yield____) {
142   pthread_yield();
143 }
144 #endif
145
146 #ifdef DSTM
147 /* Add thread join capability */
148 void CALL01(___Thread______join____, struct ___Thread___ * ___this___) {
149   unsigned int *oidarray;
150   unsigned short *versionarray, version;
151   objheader_t *ptr;
152   /* Add transaction to check if thread finished for join operation */
153 transstart:
154   transStart();
155   ptr = transRead((unsigned int) VAR(___this___));
156   struct ___Thread___ *p = (struct ___Thread___ *) ptr;
157 #ifdef THREADJOINDEBUG
158   printf("Start join process for Oid = %x\n", (unsigned int) VAR(___this___));
159 #endif
160   if(p->___threadDone___ == 1) {
161 #ifdef THREADJOINDEBUG
162     printf("Thread oid = %x is done\n", (unsigned int) VAR(___this___));
163 #endif
164     transAbort();
165     return;
166   } else {
167
168     version = (ptr-1)->version;
169     if((oidarray = calloc(1, sizeof(unsigned int))) == NULL) {
170       printf("Calloc error %s, %d\n", __FILE__, __LINE__);
171       return;
172     }
173
174     oidarray[0] = (unsigned int) VAR(___this___);
175
176     if((versionarray = calloc(1, sizeof(unsigned short))) == NULL) {
177       printf("Calloc error %s, %d\n", __FILE__, __LINE__);
178       free(oidarray);
179       return;
180     }
181     versionarray[0] = version;
182     /* Request Notification */
183 #ifdef PRECISE_GC
184     struct listitem *tmp=stopforgc((struct garbagelist *)___params___);
185 #endif
186     reqNotify(oidarray, versionarray, 1);
187 #ifdef PRECISE_GC
188     restartaftergc(tmp);
189 #endif
190     free(oidarray);
191     free(versionarray);
192     transAbort();
193     goto transstart;
194   }
195   return;
196 }
197 #endif
198
199 #ifdef THREADS
200 void CALL01(___Thread______nativeJoin____, struct ___Thread___ * ___this___) {
201   pthread_mutex_lock(&joinlock);
202   while(!VAR(___this___)->___finished___)
203     pthread_cond_wait(&joincond, &joinlock);
204   pthread_mutex_unlock(&joinlock);
205 }
206
207 void CALL01(___Thread______nativeCreate____, struct ___Thread___ * ___this___) {
208   pthread_t thread;
209   int retval;
210   pthread_attr_t nattr;
211
212   pthread_mutex_lock(&gclistlock);
213   threadcount++;
214   pthread_mutex_unlock(&gclistlock);
215   pthread_attr_init(&nattr);
216   pthread_attr_setdetachstate(&nattr, PTHREAD_CREATE_DETACHED);
217
218   do {
219     retval=pthread_create(&thread, &nattr, (void * (*)(void *)) &initthread, VAR(___this___));
220     if (retval!=0)
221       usleep(1);
222   } while(retval!=0);
223   /* This next statement will likely not work on many machines */
224
225   pthread_attr_destroy(&nattr);
226 }
227 #endif
228
229 #ifdef DSTM
230 void CALL12(___Thread______start____I, int ___mid___, struct ___Thread___ * ___this___, int ___mid___) {
231   startRemoteThread((unsigned int)VAR(___this___), ___mid___);
232 }
233 #endif
234
235 #ifdef DSTM
236 void globalDestructor(void *value) {
237   free(value);
238   pthread_setspecific(oidval, NULL);
239 }
240
241 void initDSMthread(int *ptr) {
242   objheader_t *tmp;
243   void *threadData;
244   int oid=ptr[0];
245   int type=ptr[1];
246   free(ptr);
247 #ifdef PRECISE_GC
248   int p[]={1, 0 /* NULL */, oid};
249   ((void(*) (void *))virtualtable[type*MAXCOUNT+RUNMETHOD])(p);
250 #else
251   ((void(*) (void *))virtualtable[type*MAXCOUNT+RUNMETHOD])(oid);
252 #endif
253   threadData = calloc(1, sizeof(unsigned int));
254   *((unsigned int *) threadData) = oid;
255   pthread_setspecific(oidval, threadData);
256   pthread_mutex_lock(&gclistlock);
257   threadcount--;
258   pthread_cond_signal(&gccond);
259   pthread_mutex_unlock(&gclistlock);
260   /* Add transaction to check if thread finished for join operation */
261   goto transstart;
262 transstart:
263   {
264     transStart();
265     tmp  = transRead((unsigned int) oid);
266     ((struct ___Thread___ *)tmp)->___threadDone___ = 1;
267     *((unsigned int *)&((struct ___Object___ *) tmp)->___localcopy___) |=DIRTY;
268     if(transCommit()!= 0) {
269       goto transstart;
270     }
271   }
272   pthread_exit(NULL);
273 }
274
275 void startDSMthread(int oid, int objType) {
276   pthread_t thread;
277   int retval;
278   pthread_attr_t nattr;
279
280   pthread_mutex_lock(&gclistlock);
281   threadcount++;
282   pthread_mutex_unlock(&gclistlock);
283   pthread_attr_init(&nattr);
284   pthread_attr_setdetachstate(&nattr, PTHREAD_CREATE_DETACHED);
285   int * ptr=malloc(sizeof(int)*2);
286   ptr[0]=oid;
287   ptr[1]=objType;
288   pthread_key_create(&oidval, globalDestructor);
289   do {
290     retval=pthread_create(&thread, &nattr, (void * (*)(void *)) &initDSMthread,  ptr);
291     if (retval!=0)
292       usleep(1);
293   } while(retval!=0);
294
295   pthread_attr_destroy(&nattr);
296 }
297
298 #endif