Fix tabbing.... Please fix your editors so they do tabbing correctly!!! (Spaces...
[IRC.git] / Robust / src / Runtime / DSTM / interface / sandbox.c
1 #include "sandbox.h"
2 #include "runtime.h"
3 #include "methodheaders.h"
4 __thread int transaction_check_counter;
5 __thread jmp_buf aborttrans;
6 __thread int abortenabled;
7 __thread int * counter_reset_pointer;
8 extern unsigned int myIpAddr;
9 extern sockPoolHashTable_t *transRequestSockPool;
10
11 /* Do sandboxing */
12 void errorhandler(int sig, struct sigcontext ctx) {
13   if (abortenabled&&checktrans()) {
14     sigset_t toclear;
15     sigemptyset(&toclear);
16     sigaddset(&toclear, sig);
17     sigprocmask(SIG_UNBLOCK, &toclear,NULL);
18 #ifdef TRANSSTATS
19     numTransAbort++;
20 #endif
21     objstrDelete(t_cache);
22     t_chashDelete();
23     _longjmp(aborttrans, 1);
24   }
25   printf("Error in System at %s, %s(), %d\n", __FILE__, __func__, __LINE__);
26   print_trace();
27   threadhandler(sig, ctx);
28 }
29
30
31 /*
32  * returns 0 when read set objects are consistent
33  * returns 1 when objects are inconsistent
34  */
35 int checktrans() {
36   /* Create info to keep track of numelements */
37   unsigned int size = c_size;
38   chashlistnode_t *ptr = c_table;
39   int i;
40   nodeElem_t *head=NULL;
41
42   numNode = 0;
43   for(i = 0; i< size; i++) {
44     chashlistnode_t *curr = &ptr[i];
45     /* Inner loop to traverse the linked list of the cache lookupTable */
46     while(curr != NULL) {
47       if (curr->key == 0)
48         break;
49       objheader_t *headeraddr=(objheader_t*) curr->val;
50       unsigned int machinenum;
51       objheader_t *tmp;
52
53       if (STATUS(headeraddr) & NEW) {
54         //new objects cannot be stale
55       } else if ((tmp=mhashSearch(curr->key)) != NULL) {
56         //memory barrier
57         CFENCE;
58         if (tmp->version!=headeraddr->version) {
59           //version mismatch
60           deletehead(head);
61           return 1; //return 1 when objects are inconsistent
62         }
63       } else {
64         machinenum = lhashSearch(curr->key);
65         head = createList(head, headeraddr, machinenum, c_numelements);
66       }
67
68       curr = curr->next;
69     }
70   }
71   /* Send oid and versions for checking */
72   if(head == NULL)
73     return 0;
74
75   int retval = verify(head);
76   deletehead(head);
77   return retval==0;
78 }
79
80 nodeElem_t * createList(nodeElem_t *head, objheader_t *headeraddr, unsigned int mid,
81                         unsigned int c_numelements) {
82
83   nodeElem_t *ptr, *tmp;
84   int found = 0, offset = 0;
85   tmp = head;
86
87   while(tmp != NULL) {
88     if(tmp->mid == mid) {
89       if (STATUS(headeraddr) & DIRTY) {
90         offset = (sizeof(unsigned int) + sizeof(short)) * tmp->nummod;
91         *((unsigned int *)(((char *)tmp->objmod) + offset))=OID(headeraddr);
92         offset += sizeof(unsigned int);
93         *((unsigned short *)(((char *)tmp->objmod) + offset)) = headeraddr->version;
94         tmp->nummod++;
95       } else {
96         offset = (sizeof(unsigned int) + sizeof(short)) * tmp->numread;
97         *((unsigned int *)(((char *)tmp->objread) + offset))=OID(headeraddr);
98         offset += sizeof(unsigned int);
99         *((unsigned short *)(((char *)tmp->objread) + offset)) = headeraddr->version;
100         tmp->numread++;
101       }
102       found = 1;
103       break;
104     }
105     tmp = tmp->next;
106   }
107   //Add oid for any new machine
108   if (!found) {
109     numNode++;
110     ptr = makehead(c_numelements);
111     if((ptr = makehead(c_numelements)) == NULL) {
112       printf("Error in Allocating memory %s, %d\n", __func__, __LINE__);
113       return NULL;
114     }
115     ptr->mid = mid;
116     if (STATUS(headeraddr) & DIRTY) {
117       offset = (sizeof(unsigned int) + sizeof(short)) * ptr->nummod;
118       *((unsigned int *)(((char *)ptr->objmod) + offset))=OID(headeraddr);
119       offset += sizeof(unsigned int);
120       *((unsigned short *)(((char *)ptr->objmod) + offset)) = headeraddr->version;
121       ptr->nummod++;
122     } else {
123       offset = (sizeof(unsigned int) + sizeof(short)) * ptr->numread;
124       *((unsigned int *)(((char *)ptr->objread) + offset))=OID(headeraddr);
125       offset += sizeof(unsigned int);
126       *((unsigned short *)(((char *)ptr->objread) + offset)) = headeraddr->version;
127       ptr->numread++;
128     }
129     ptr->next = head;
130     head = ptr;
131   }
132   return head;
133 }
134
135 nodeElem_t * makehead(unsigned int numelements) {
136   nodeElem_t *head;
137   //Create the first element
138   if((head = calloc(1, sizeof(nodeElem_t))) == NULL) {
139     printf("Calloc error %s %d\n", __func__, __LINE__);
140     return NULL;
141   }
142
143   if ((head->objmod = calloc(numelements,sizeof(unsigned int) + sizeof(unsigned short))) == NULL) {
144     printf("Calloc error %s %d\n", __func__, __LINE__);
145     free(head);
146     return NULL;
147   }
148
149   if ((head->objread = calloc(numelements,sizeof(unsigned int) + sizeof(unsigned short))) == NULL) {
150     printf("Calloc error %s %d\n", __func__, __LINE__);
151     free(head);
152     free(head->objmod);
153     return NULL;
154   }
155
156   head->mid = 0;
157   head->nummod = head->numread = 0;
158   head->next = NULL;
159   return head;
160 }
161
162 //Delete the entire list
163 void deletehead(nodeElem_t *head) {
164   nodeElem_t *next, *tmp;
165   tmp = head;
166   while(tmp != NULL) {
167     next = tmp->next;
168     free(tmp->objmod);
169     free(tmp->objread);
170     free(tmp);
171     tmp = next;
172   }
173   return;
174 }
175
176
177 /* returns 0 => Inconsistent Objects found, abort transaction */
178 /* returns 1 => consistent objects found, error in system */
179 /* Process the linked list of objects */
180 int verify(nodeElem_t *pile) {
181   /* create and initialize an array of sockets and reply receiving buffer */
182   int sock[numNode];
183   char getReplyCtrl[numNode];
184   int i;
185   for(i=0; i<numNode; i++) {
186     sock[i] = 0;
187     getReplyCtrl[i] = 0;
188   }
189
190   /* send objects for consistency check to remote machine */
191   objData_t tosend[numNode];
192   int pilecount = 0;
193   while(pile != NULL) {
194     /* send total bytes */
195     tosend[pilecount].control = CHECK_OBJECTS;
196     tosend[pilecount].numread = pile->numread;
197     tosend[pilecount].nummod = pile->nummod;
198     int sd = 0;
199     if((sd = getSock2WithLock(transRequestSockPool, pile->mid)) < 0) {
200       printf("Error: Getting a socket descriptor at %s(), %s(), %d\n", __FILE__, __func__, __LINE__);
201       exit(-1);
202     }
203     sock[pilecount] = sd;
204
205     /* Send starting information of data */
206     send_data(sd, &(tosend[pilecount]), sizeof(objData_t));
207
208     int size;
209     /* Send objetcs that are read */
210     {
211       size=(sizeof(unsigned int)+sizeof(unsigned short)) * pile->numread;
212       send_data(sd, (char *)pile->objread, size);
213     }
214
215     /* Send objects that are modified */
216     {
217       size=(sizeof(unsigned int)+sizeof(unsigned short)) * pile->nummod;
218       send_data(sd, (char *)pile->objmod, size);
219     }
220     pilecount++;
221     pile = pile->next;
222   } // end of pile processing
223
224   int checkObj = 0;
225   int countConsistent = 0;
226
227   /* Recv replies from remote machines */
228   for(i = 0; i<numNode; i++) {
229     int sd = sock[i];
230     if(sd != 0) {
231       char control;
232       recv_data(sd, &control, sizeof(char));
233       getReplyCtrl[i] = control;
234       if(control == OBJ_INCONSISTENT) { /* Inconsistent */
235         checkObj = 1;
236         break;
237       }
238       countConsistent++;
239     }
240   }
241
242   /* Decide final response */
243   if(checkObj) {
244     printf("Inconsistent Object-> Abort Transaction\n");
245     return 0;
246   }
247
248   if(countConsistent == numNode) {
249     return 1;
250   }
251
252   return -1;
253 }
254
255 /* Check looping */
256 void checkObjects() {
257   if (abortenabled&&checktrans()) {
258     printf("Loop Abort\n");
259     transaction_check_counter=(*counter_reset_pointer=HIGH_CHECK_FREQUENCY);
260 #ifdef TRANSSTATS
261     numTransAbort++;
262 #endif
263     objstrDelete(t_cache);
264     t_chashDelete();
265     _longjmp(aborttrans, 1);
266   }
267   transaction_check_counter=*counter_reset_pointer;
268 }
269
270 /* Check excessive memory allocation */
271 void check_mem_alloc() {
272   if (abortenabled&&checktrans()) {
273     printf("Excessive Allocation\n");
274     trans_allocation_bytes=0;
275     transaction_check_counter=(*counter_reset_pointer=HIGH_CHECK_FREQUENCY);
276 #ifdef TRANSSTATS
277     numTransAbort++;
278 #endif
279     objstrDelete(t_cache);
280     t_chashDelete();
281     _longjmp(aborttrans, 1);
282   }
283   trans_allocation_bytes=0;
284 }
285
286 /* Obtain a backtrace and print it to stdout */
287 void print_trace() {
288   void *array[100];
289   size_t size;
290   char ** strings;
291   size_t i;
292
293   size = backtrace(array, 100);
294   strings = backtrace_symbols(array, size);
295
296   printf("Obtained %zd stack frames.\n", size);
297   for (i = 0; i < size; i++)
298     printf("%s\n", strings[i]);
299   free(strings);
300 }
301
302 void checkObjVersion(struct readstruct * readbuffer, int sd, unsigned int numread, unsigned int nummod) {
303
304   int v_match=0;
305
306   /* Recv objects read with versions */
307   int size=(sizeof(unsigned int)+sizeof(unsigned short)) * numread;
308   char objread[size];
309   if(numread != 0) {
310     recv_data_buf(sd, readbuffer, objread, size);
311   }
312
313   /* Recv objects modified with versions */
314   size=(sizeof(unsigned int)+sizeof(unsigned short)) * nummod;
315   char objmod[size];
316   if(nummod != 0) {
317     recv_data_buf(sd, readbuffer, objmod, size);
318   }
319
320   int i;
321   char control;
322   for(i=0; i<numread; i++) {
323     size = sizeof(unsigned int)+sizeof(unsigned short);
324     size *= i;
325     unsigned int oid = *((unsigned int *)(objread + size));
326     size += sizeof(unsigned int);
327     unsigned short version = *((unsigned short *)(objread + size));
328     objheader_t *header;
329     if((header = mhashSearch(oid)) == NULL) {    /* Obj not found */
330       control = OBJ_INCONSISTENT;
331       send_data(sd, &control, sizeof(char));
332       return;
333     } else {
334       if(is_write_locked(STATUSPTR(header))) { //object write locked
335         control = OBJ_INCONSISTENT;
336         send_data(sd, &control, sizeof(char));
337         return;
338       }
339       CFENCE;
340       //compare versions
341       if(version == header->version)
342         v_match++;
343       else {
344         control = OBJ_INCONSISTENT;
345         send_data(sd, &control, sizeof(char));
346         return;
347       }
348     }
349   } // end of objects read
350
351   for(i=0; i<nummod; i++) {
352     //unsigned int oid = objmod[i].oid;
353     //unsigned short version = objmod[i].version;
354     size = sizeof(unsigned int)+sizeof(unsigned short);
355     size *= i;
356     unsigned int oid = *((unsigned int *)(objmod + size));
357     size += sizeof(unsigned int);
358     unsigned short version = *((unsigned short *)(objmod + size));
359     objheader_t *header;
360     if((header = mhashSearch(oid)) == NULL) {    /* Obj not found */
361       control = OBJ_INCONSISTENT;
362       send_data(sd, &control, sizeof(char));
363       return;
364     } else {
365       if(is_write_locked(STATUSPTR(header))) { //object write locked
366         control = OBJ_INCONSISTENT;
367         send_data(sd, &control, sizeof(char));
368         return;
369       }
370       //compare versions
371       if(version == header->version)
372         v_match++;
373       else {
374         control = OBJ_INCONSISTENT;
375         send_data(sd, &control, sizeof(char));
376         return;
377       }
378     }
379   } // end of objects modified
380
381   if(v_match = (numread + nummod)) {
382     control = OBJ_CONSISTENT;
383     send_data(sd, &control, sizeof(char));
384   }
385   return;
386 }