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