bug fixes
[IRC.git] / Robust / src / Runtime / STM / commit.c
1 #include<tm.h>
2 #ifdef DELAYCOMP
3 #include<delaycomp.h>
4 #endif
5
6 #ifdef TRANSSTATS
7 #define TRANSWRAP(x) x
8 #else
9 #define TRANSWRAP(x)
10 #endif
11
12 #ifdef STMSTATS
13 #define STMWRAP(x) x
14 #else
15 #define STMWRAP(x)
16 #endif
17
18 #ifdef STMSTATS
19 #define STATFREE free(oidrdage);
20 #define STATALLOC oidrdage=malloc(size);
21 #define STATASSIGN oidrdage=rdage;
22 #else
23 #define STATFREE
24 #define STATALLOC
25 #define STATASSIGN
26 #endif
27
28 /* ================================================================
29  * transCommit
30  * - This function initiates the transaction commit process
31  * - goes through the transaction cache and decides
32  * - a final response
33  * ================================================================
34  */
35 #ifdef DELAYCOMP
36 int transCommit(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
37 #else
38 int transCommit() {
39 #endif
40 #ifdef SANDBOX
41   abortenabled=0;
42 #endif
43   TRANSWRAP(numTransCommit++;);
44   int softaborted=0;
45   do {
46     /* Look through all the objects in the transaction hash table */
47     int finalResponse;
48 #ifdef DELAYCOMP
49     if (c_numelements<(c_size>>3))
50       finalResponse=alttraverseCache(commitmethod, primitives, locals, params);
51     else
52       finalResponse=traverseCache(commitmethod, primitives, locals, params);
53 #else
54     if (c_numelements<(c_size>>3))
55       finalResponse=alttraverseCache();
56     else
57       finalResponse=traverseCache();
58 #endif
59     if(finalResponse == TRANS_ABORT) {
60       TRANSWRAP(numTransAbort++;if (softaborted) nSoftAbortAbort++;);
61       freenewobjs();
62       STMWRAP(freelockedobjs(););
63       objstrReset();
64       t_chashreset();
65 #ifdef READSET
66       rd_t_chashreset();
67 #endif
68 #ifdef DELAYCOMP
69       dc_t_chashreset();
70       ptrstack.count=0;
71       primstack.count=0;
72       branchstack.count=0;
73 #endif
74 #ifdef SANDBOX
75       abortenabled=1;
76 #endif
77       return TRANS_ABORT;
78     }
79     if(finalResponse == TRANS_COMMIT) {
80       TRANSWRAP(numTransCommit++;if (softaborted) nSoftAbortCommit++;);
81       freenewobjs();
82       STMWRAP(freelockedobjs(););
83       objstrReset();
84       t_chashreset();
85 #ifdef READSET
86       rd_t_chashreset();
87 #endif
88 #ifdef DELAYCOMP
89       dc_t_chashreset();
90       ptrstack.count=0;
91       primstack.count=0;
92       branchstack.count=0;
93 #endif
94       return 0;
95     }
96
97     /* wait a random amount of time before retrying to commit transaction*/
98     if(finalResponse == TRANS_SOFT_ABORT) {
99       TRANSWRAP(nSoftAbort++;);
100       softaborted++;
101 #ifdef SOFTABORT
102       if (softaborted>1) {
103 #else
104       if (1) {
105 #endif
106         //retry if too many soft aborts
107         freenewobjs();
108         STMWRAP(freelockedobjs(););
109         objstrReset();
110         t_chashreset();
111 #ifdef READSET
112         rd_t_chashreset();
113 #endif
114 #ifdef DELAYCOMP
115         dc_t_chashreset();
116         ptrstack.count=0;
117         primstack.count=0;
118         branchstack.count=0;
119 #endif
120         return TRANS_ABORT;
121       }
122     } else {
123       printf("Error: in %s() Unknown outcome", __func__);
124       exit(-1);
125     }
126   } while (1);
127 }
128
129 #ifdef DELAYCOMP
130 #define freearrays if (c_numelements>=200) { \
131     STATFREE;                                \
132     STMARRAYFREE;                            \
133     free(oidrdlocked);                       \
134     free(oidrdversion);                      \
135   }                                          \
136   if (t_numelements>=200) {                  \
137     free(oidwrlocked);                       \
138   }
139 #else
140 #define freearrays   if (c_numelements>=200) { \
141     STATFREE;                                  \
142     STMARRAYFREE;                              \
143     free(oidrdlocked);                         \
144     free(oidrdversion);                        \
145     free(oidwrlocked);                         \
146   }
147 #endif
148
149 #ifdef DELAYCOMP
150 #define allocarrays int t_numelements=c_numelements+dc_c_numelements; \
151   if (t_numelements<200) { \
152     oidwrlocked=(struct garbagelist *) &wrlocked;                       \
153   } else { \
154     oidwrlocked=malloc(2*sizeof(INTPTR)+t_numelements*sizeof(void *));  \
155   } \
156   if (c_numelements<200) { \
157     oidrdlocked=rdlocked; \
158     oidrdversion=rdversion; \
159     STATASSIGN;             \
160     STMARRAYASSIGN;         \
161   } else { \
162     int size=c_numelements*sizeof(void*); \
163     oidrdlocked=malloc(size); \
164     oidrdversion=malloc(size); \
165     STATALLOC;                 \
166     STMARRAYALLOC;             \
167   }\
168   dirwrlocked=oidwrlocked->array;
169 #else
170 #define allocarrays if (c_numelements<200) { \
171     oidrdlocked=rdlocked; \
172     oidrdversion=rdversion; \
173     oidwrlocked=(struct garbagelist *) &wrlocked; \
174     STATASSIGN;                                   \
175     STMARRAYASSIGN;                               \
176   } else { \
177     int size=c_numelements*sizeof(void*); \
178     oidrdlocked=malloc(size); \
179     oidrdversion=malloc(size); \
180     oidwrlocked=malloc(size+2*sizeof(INTPTR));  \
181     STATALLOC;                                  \
182     STMARRAYALLOC;                              \
183   } \
184   dirwrlocked=oidwrlocked->array;
185 #endif
186
187 #ifdef STMSTATS
188 #define ABORTSTAT1 header->abortCount++;        \
189   ObjSeqId = headeraddr->accessCount;                           \
190   (typesCausingAbort[TYPE(header)]).numabort++;                         \
191   (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements;           \
192   (typesCausingAbort[TYPE(header)]).numtrans+=1;                        \
193   objtypetraverse[TYPE(header)]=1;                                      \
194   if(getTotalAbortCount(i+1, size, (void *)(curr->next), numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse)) \
195     softabort=0;
196 #define ABORTSTAT2                              \
197   ObjSeqId = oidrdage[i];\
198   header->abortCount++;                                 \
199   (typesCausingAbort[TYPE(header)]).numabort++;                 \
200   (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements;   \
201   (typesCausingAbort[TYPE(header)]).numtrans+=1;                \
202   objtypetraverse[TYPE(header)]=1;                                      \
203   if (getReadAbortCount(i+1, numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse)) \
204     softabort=0;
205 #define ABORTSTAT3                              \
206   header->abortCount++;                         \
207   ObjSeqId = headeraddr->accessCount;           \
208   (typesCausingAbort[TYPE(header)]).numabort++;                 \
209   (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements;   \
210   (typesCausingAbort[TYPE(header)]).numtrans+=1;                \
211   objtypetraverse[TYPE(header)]=1;                                      \
212   if (getTotalAbortCount2((void *) curr->next, numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse)) \
213     softabort=0;
214 #define ABORTSTAT4 ObjSeqId = oidrdage[i];      \
215   header->abortCount++;                                                 \
216   getReadAbortCount(i+1, numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse);
217 #else
218 #define ABORTSTAT1
219 #define ABORTSTAT2
220 #define ABORTSTAT3
221 #define ABORTSTAT4
222 #endif
223
224 #ifdef DELAYCOMP
225 #define DELAYWRAP(x) x
226 #define NUMWRTOTAL numoidwrtotal
227 #else
228 #define DELAYWRAP(x)
229 #define NUMWRTOTAL numoidwrlocked
230 #endif
231
232 #ifdef STMARRAY
233 #define STMARRAYFREE free(oidrdlockedarray);
234 #define STMARRAYALLOC oidrdlockedarray=malloc(size);
235 #define STMARRAYASSIGN oidrdlockedarray=rdlockedarray;
236
237 #define ARRAYDEFINES int numoidrdlockedarray=0; \
238   void * rdlockedarray[200];                    \
239   void ** oidrdlockedarray;
240
241 #define ARRAYABORT                                                      \
242   for(;j>=lowoffset;j--) {                                              \
243     GETLOCKVAL(status, transao, j);                                     \
244     if  (status==STMDIRTY) {                                            \
245       GETLOCKPTR(lockptr, mainao,j);                                    \
246       write_unlock(lockptr);                                            \
247     }                                                                   \
248   }                                                                     \
249   transAbortProcess(oidwrlocked, numoidwrlocked);                       \
250   freearrays;                                                           \
251   if (softabort)                                                        \
252     return TRANS_SOFT_ABORT;                                            \
253   else                                                                  \
254     return TRANS_ABORT;
255   
256
257 #define PROCESSARRAY                                                    \
258   int type=((int *)cachedobj)[0];                                       \
259   if (type>=NUMCLASSES) {                                               \
260     struct ArrayObject *transao=(struct ArrayObject *) cachedobj;       \
261     struct ArrayObject *mainao=(struct ArrayObject *) objptr;           \
262     int lowoffset=(transao->lowindex)>>INDEXSHIFT;                      \
263     int highoffset=(transao->highindex)>>INDEXSHIFT;                    \
264     int j;                                                              \
265     int addwrobject=0, addrdobject=0;                                   \
266     for(j=lowoffset; j<=highoffset;j++) {                               \
267       unsigned int status;                                              \
268       GETLOCKVAL(status, transao, j);                                   \
269       if (status==STMDIRTY) {                                           \
270         unsigned int * lockptr;                                         \
271         GETLOCKPTR(lockptr, mainao,j);                                  \
272         if (write_trylock(lockptr)) {                                   \
273           unsigned int localversion;                                    \
274           unsigned int remoteversion;                                   \
275           GETVERSIONVAL(localversion, transao, j);                      \
276           GETVERSIONVAL(remoteversion, mainao, j);                      \
277           if (localversion == remoteversion) {                          \
278             addwrobject=1;                                              \
279           } else {                                                      \
280             ARRAYABORT;                                                 \
281           }                                                             \
282         } else {                                                        \
283           j--;                                                          \
284           ARRAYABORT;                                                   \
285         }                                                               \
286       } else if (status==STMCLEAN) {                                    \
287         addrdobject=1;                                                  \
288       }                                                                 \
289     }                                                                   \
290     if (addwrobject) {                                                  \
291       dirwrlocked[numoidwrlocked++] = objptr;                           \
292     }                                                                   \
293     if (addrdobject) {                                                  \
294       rdlockedarray[numoidrdlockedarray++]=objptr;                      \
295     }                                                                   \
296   } else                                                                
297
298 #define READARRAYS                                                      \
299   for(i=0; i<numoidrdlockedarray; i++) {                                \
300     objheader_t * transheader=oidrdlockedarray[i];                      \
301     struct ArrayObject * transao=(struct ArrayObject *)&transheader[1]; \
302     objheader_t * mainheader=OID(transheader);                          \
303     struct ArrayObject * mainao=(struct ArrayObject *)&transheader[1];  \
304     int lowoffset=(transao->lowindex)>>INDEXSHIFT;                      \
305     int highoffset=(transao->highindex)>>INDEXSHIFT;                    \
306     int j;                                                              \
307     for(j=lowoffset; j<=highoffset;j++) {                               \
308       unsigned int locallock;GETLOCKVAL(locallock,transao,j);           \
309       if (locallock==STMCLEAN) {                                        \
310         /* do read check */                                             \
311         unsigned int mainlock; GETLOCKVAL(mainlock, mainao, j);         \
312         if (mainlock>0) {                                               \
313           CFENCE;                                                       \
314           unsigned int localversion;                                    \
315           unsigned int remoteversion;                                   \
316           GETVERSIONVAL(localversion, transao, j);                      \
317           GETVERSIONVAL(remoteversion, mainao, j);                      \
318           if (localversion != remoteversion) {                          \
319             transAbortProcess(oidwrlocked, NUMWRTOTAL);                 \
320             freearrays;                                                 \
321             return TRANS_ABORT;                                         \
322           }                                                             \
323         }                                                               \
324       }                                                                 \
325     }                                                                   \
326   }                                                                    
327 #else
328 #define ARRAYDEFINES
329 #define PROCESSARRAY
330 #define READARRAYS
331 #define STMARRAYFREE
332 #define STMARRAYALLOC
333 #define STMARRAYASSIGN
334 #endif
335
336 /* ==================================================
337  * traverseCache
338  * - goes through the transaction cache and
339  * - decides if a transaction should commit or abort
340  * ==================================================
341  */
342
343 #ifdef DELAYCOMP
344   int traverseCache(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
345 #else
346   int traverseCache() {
347 #endif
348   /* Create info to keep track of objects that can be locked */
349   int numoidrdlocked=0;
350   int numoidwrlocked=0;
351   void * rdlocked[200];
352   int rdversion[200];
353   struct fixedlist wrlocked;
354   int softabort=0;
355   int i;
356   void ** oidrdlocked;
357   int * oidrdversion;
358   ARRAYDEFINES;
359   STMWRAP(int rdage[200];int * oidrdage;int ObjSeqId;int objtypetraverse[TOTALNUMCLASSANDARRAY];);
360   struct garbagelist * oidwrlocked;
361   void ** dirwrlocked;
362   allocarrays;
363
364   STMWRAP(for(i=0; i<TOTALNUMCLASSANDARRAY; i++) objtypetraverse[i] = 0;);
365
366   chashlistnode_t *ptr = c_table;
367   /* Represents number of bins in the chash table */
368   unsigned int size = c_size;
369   for(i = 0; i<size; i++) {
370     chashlistnode_t *curr = &ptr[i];
371     /* Inner loop to traverse the linked list of the cache lookupTable */
372     while(curr != NULL) {
373       //if the first bin in hash table is empty
374       if(curr->key == NULL)
375         break;
376       objheader_t * cachedobj=curr->val;
377       objheader_t * headeraddr=&((objheader_t *) cachedobj)[-1]; //cached object
378       void * objptr=curr->key;
379       objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t)); //real object
380       unsigned int version = headeraddr->version;
381
382       PROCESSARRAY;
383
384       if(STATUS(headeraddr) & DIRTY) {
385         /* Read from the main heap  and compare versions */
386         if(write_trylock(&header->lock)) { //can aquire write lock
387           if (version == header->version) { /* versions match */
388             /* Keep track of objects locked */
389             dirwrlocked[numoidwrlocked++] = objptr;
390           } else {
391             dirwrlocked[numoidwrlocked++] = objptr;
392             transAbortProcess(oidwrlocked, numoidwrlocked);
393             ABORTSTAT1;
394             freearrays;
395             if (softabort)
396               return TRANS_SOFT_ABORT;
397             else 
398               return TRANS_ABORT;
399           }
400         } else {
401           if(version == header->version) {
402             /* versions match */
403             softabort=1;
404           }
405           transAbortProcess(oidwrlocked, numoidwrlocked);
406           ABORTSTAT1;
407           freearrays;
408           if (softabort)
409             return TRANS_SOFT_ABORT;
410           else 
411             return TRANS_ABORT;
412       
413         }
414       } else {
415         STMWRAP(oidrdage[numoidrdlocked]=headeraddr->accessCount;);
416         oidrdversion[numoidrdlocked]=version;
417         oidrdlocked[numoidrdlocked++]=header;
418       }
419       curr = curr->next;
420     }
421   } //end of for
422   
423 #ifdef DELAYCOMP
424   //acquire access set locks
425   unsigned int numoidwrtotal=numoidwrlocked;
426
427   chashlistnode_t *dc_curr = dc_c_list;
428   /* Inner loop to traverse the linked list of the cache lookupTable */
429   while(likely(dc_curr != NULL)) {
430     //if the first bin in hash table is empty
431     objheader_t * headeraddr=&((objheader_t *) dc_curr->val)[-1];
432     void *objptr=dc_curr->key;
433     objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t));
434     if(write_trylock(&header->lock)) { //can aquire write lock    
435       dirwrlocked[numoidwrtotal++] = objptr;
436     } else {
437       //maybe we already have lock
438       void * key=dc_curr->key;
439       chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
440       
441       do {
442         if(node->key == key) {
443           objheader_t * headeraddr=&((objheader_t *) node->val)[-1];      
444           if(STATUS(headeraddr) & DIRTY) {
445             goto nextloop;
446           } else
447             break;
448         }
449         node = node->next;
450       } while(node != NULL);
451
452       //have to abort to avoid deadlock
453       transAbortProcess(oidwrlocked, numoidwrtotal);
454       ABORTSTAT1;
455       freearrays;
456       if (softabort)
457         return TRANS_SOFT_ABORT;
458       else
459         return TRANS_ABORT;
460     }
461   nextloop:
462     dc_curr = dc_curr->lnext;
463   }
464 #endif
465
466   //THIS IS THE SERIALIZATION END POINT (START POINT IS END OF EXECUTION)*****
467
468   READARRAYS;
469
470   for(i=0; i<numoidrdlocked; i++) {
471     /* Read from the main heap  and compare versions */
472     objheader_t *header=oidrdlocked[i];
473     unsigned int version=oidrdversion[i];
474     if(header->lock>0) { //not write locked
475       CFENCE;
476       if(version != header->version) { /* versions do not match */
477         transAbortProcess(oidwrlocked, NUMWRTOTAL);
478         ABORTSTAT2;
479         freearrays;
480         return TRANS_ABORT;
481       }
482 #if DELAYCOMP
483     } else if (dc_t_chashSearch(((char *)header)+sizeof(objheader_t))!=NULL) {
484       //couldn't get lock because we already have it
485       //check if it is the right version number
486       if (version!=header->version) {
487         transAbortProcess(oidwrlocked, numoidwrtotal);
488         ABORTSTAT2;
489         freearrays;
490         return TRANS_ABORT;
491       }
492 #endif
493     } else { /* cannot aquire lock */
494       //do increment as we didn't get lock
495       if(version == header->version) {
496         softabort=1;
497       }
498       transAbortProcess(oidwrlocked, NUMWRTOTAL);
499       ABORTSTAT2;
500       freearrays;
501       if (softabort)
502         return TRANS_SOFT_ABORT;
503       else 
504         return TRANS_ABORT;
505     }
506   }
507
508 #ifdef READSET
509   //need to validate auxilary readset
510   rdchashlistnode_t *rd_curr = rd_c_list;
511   /* Inner loop to traverse the linked list of the cache lookupTable */
512   while(likely(rd_curr != NULL)) {
513     //if the first bin in hash table is empty
514     unsigned int version=rd_curr->version;
515     objheader_t *header=(objheader_t *)(((char *)rd_curr->key)-sizeof(objheader_t));
516     if(header->lock>0) { //object is not locked
517       if (version!=header->version) {
518         //have to abort
519         transAbortProcess(oidwrlocked, NUMWRTOTAL);
520         STMWRAP((typesCausingAbort[TYPE(header)])++;);
521         freearrays;
522         if (softabort)
523           return TRANS_SOFT_ABORT;
524         else
525           return TRANS_ABORT;   
526       }
527     } else {
528       //maybe we already have lock
529       if (version==header->version) {
530         void * key=rd_curr->key;
531 #ifdef DELAYCOMP
532         //check to see if it is in the delaycomp table
533         {
534           chashlistnode_t *node = &dc_c_table[(((unsigned INTPTR)key) & dc_c_mask)>>4];
535           do {
536             if(node->key == key)
537               goto nextloopread;
538             node = node->next;
539           } while(node != NULL);
540         }
541 #endif
542         //check normal table
543         {
544           chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
545           do {
546             if(node->key == key) {
547               objheader_t * headeraddr=&((objheader_t *) node->val)[-1];          
548               if(STATUS(headeraddr) & DIRTY) {
549                 goto nextloopread;
550               }
551             }
552             node = node->next;
553           } while(node != NULL);
554         }
555       }
556       //have to abort to avoid deadlock
557       transAbortProcess(oidwrlocked, NUMWRTOTAL);
558       STMWRAP((typesCausingAbort[TYPE(header)])++;);
559       freearrays;
560       if (softabort)
561         return TRANS_SOFT_ABORT;
562       else
563         return TRANS_ABORT;
564     }
565   nextloopread:
566     rd_curr = rd_curr->lnext;
567   }
568 #endif
569   
570   /* Decide the final response */
571 #ifdef DELAYCOMP
572   transCommitProcess(oidwrlocked, numoidwrlocked, numoidwrtotal, commitmethod, primitives, locals, params);
573 #else
574   transCommitProcess(oidwrlocked, numoidwrlocked);
575 #endif
576   freearrays;
577   return TRANS_COMMIT;
578 }
579
580 /* ==================================================
581  * alttraverseCache
582  * - goes through the transaction cache and
583  * - decides if a transaction should commit or abort
584  * ==================================================
585  */
586
587 #ifdef DELAYCOMP
588 int alttraverseCache(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
589 #else
590 int alttraverseCache() {
591 #endif
592   /* Create info to keep track of objects that can be locked */
593   int numoidrdlocked=0;
594   int numoidwrlocked=0;
595   void * rdlocked[200];
596   int rdversion[200];
597   struct fixedlist wrlocked;
598   int softabort=0;
599   int i;
600   void ** oidrdlocked;
601   int * oidrdversion;
602   STMWRAP(int rdage[200];int * oidrdage;int ObjSeqId;int objtypetraverse[TOTALNUMCLASSANDARRAY];);
603   ARRAYDEFINES;
604   struct garbagelist * oidwrlocked;
605   void ** dirwrlocked;
606   allocarrays;
607
608   STMWRAP(for(i=0; i<TOTALNUMCLASSANDARRAY; i++) objtypetraverse[i] = 0;);
609
610   chashlistnode_t *curr = c_list;
611   /* Inner loop to traverse the linked list of the cache lookupTable */
612   while(likely(curr != NULL)) {
613     //if the first bin in hash table is empty
614       objheader_t * cachedobj=curr->val;
615     objheader_t * headeraddr=&((objheader_t *) cachedobj)[-1];
616     void *objptr=curr->key;
617     objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t));
618     unsigned int version = headeraddr->version;
619
620     PROCESSARRAY;
621
622     if(STATUS(headeraddr) & DIRTY) {
623       /* Read from the main heap  and compare versions */
624       if(likely(write_trylock(&header->lock))) { //can aquire write lock
625         if (likely(version == header->version)) { /* versions match */
626           /* Keep track of objects locked */
627           dirwrlocked[numoidwrlocked++] = objptr;
628         } else {
629           dirwrlocked[numoidwrlocked++] = objptr;
630           transAbortProcess(oidwrlocked, numoidwrlocked);
631           ABORTSTAT3;
632           freearrays;
633           return TRANS_ABORT;
634         }
635       } else { /* cannot aquire lock */
636         if(version == header->version) {
637           /* versions match */
638           softabort=1;
639         }
640         transAbortProcess(oidwrlocked, numoidwrlocked);
641         ABORTSTAT3;
642         freearrays;
643         if (softabort)
644           return TRANS_SOFT_ABORT;
645         else 
646           return TRANS_ABORT;
647       }
648     } else {
649       /* Read from the main heap  and compare versions */
650       oidrdversion[numoidrdlocked]=version;
651       oidrdlocked[numoidrdlocked++] = header;
652     }
653     curr = curr->lnext;
654   }
655
656 #ifdef DELAYCOMP
657   //acquire other locks
658   unsigned int numoidwrtotal=numoidwrlocked;
659   chashlistnode_t *dc_curr = dc_c_list;
660   /* Inner loop to traverse the linked list of the cache lookupTable */
661   while(likely(dc_curr != NULL)) {
662     //if the first bin in hash table is empty
663     objheader_t * headeraddr=&((objheader_t *) dc_curr->val)[-1];
664     void *objptr=dc_curr->key;
665     objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t));
666     if(write_trylock(&header->lock)) { //can aquire write lock
667       dirwrlocked[numoidwrtotal++] = objptr;
668     } else {
669       //maybe we already have lock
670       void * key=dc_curr->key;
671       chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
672       
673       do {
674         if(node->key == key) {
675           objheader_t * headeraddr=&((objheader_t *) node->val)[-1];
676           if(STATUS(headeraddr) & DIRTY) {
677             goto nextloop;
678           }
679         }
680         node = node->next;
681       } while(node != NULL);
682
683       //have to abort to avoid deadlock
684       transAbortProcess(oidwrlocked, numoidwrtotal);
685       ABORTSTAT3;
686       freearrays;
687       if (softabort)
688         return TRANS_SOFT_ABORT;
689       else
690         return TRANS_ABORT;
691     }
692   nextloop:
693     dc_curr = dc_curr->lnext;
694   }
695 #endif
696
697   //THIS IS THE SERIALIZATION END POINT (START POINT IS END OF EXECUTION)*****
698
699   READARRAYS;
700
701   for(i=0; i<numoidrdlocked; i++) {
702     objheader_t * header=oidrdlocked[i];
703     unsigned int version=oidrdversion[i];
704     if(header->lock>0) {
705       CFENCE;
706       if(version != header->version) {
707         transAbortProcess(oidwrlocked, NUMWRTOTAL);
708         ABORTSTAT2;
709         freearrays;
710         return TRANS_ABORT;
711       }
712 #ifdef DELAYCOMP
713     } else if (dc_t_chashSearch(((char *)header)+sizeof(objheader_t))!=NULL) {
714       //couldn't get lock because we already have it
715       //check if it is the right version number
716       if (version!=header->version) {
717         transAbortProcess(oidwrlocked, numoidwrtotal);
718         ABORTSTAT4;
719         freearrays;
720         return TRANS_ABORT;
721       }
722 #endif
723     } else { /* cannot aquire lock */
724       if(version == header->version) {
725         softabort=1;
726       }
727       transAbortProcess(oidwrlocked, NUMWRTOTAL);
728       ABORTSTAT2;
729       freearrays;
730       if (softabort)
731         return TRANS_SOFT_ABORT;
732       else 
733         return TRANS_ABORT;
734     }
735   }
736
737 #ifdef READSET
738   //need to validate auxilary readset
739   rdchashlistnode_t *rd_curr = rd_c_list;
740   /* Inner loop to traverse the linked list of the cache lookupTable */
741   while(likely(rd_curr != NULL)) {
742     //if the first bin in hash table is empty
743     int version=rd_curr->version;
744     objheader_t *header=(objheader_t *)(((char *)rd_curr->key)-sizeof(objheader_t));
745     if(header->lock>0) { //object is not locked
746       if (version!=header->version) {
747         //have to abort
748         transAbortProcess(oidwrlocked, NUMWRTOTAL);
749         STMWRAP((typesCausingAbort[TYPE(header)])++;);
750         freearrays;
751         if (softabort)
752           return TRANS_SOFT_ABORT;
753         else
754           return TRANS_ABORT;   
755       }
756     } else {
757       if (version==header->version) {
758         void * key=rd_curr->key;
759 #ifdef DELAYCOMP
760         //check to see if it is in the delaycomp table
761         {
762           chashlistnode_t *node = &dc_c_table[(((unsigned INTPTR)key) & dc_c_mask)>>4];
763           do {
764             if(node->key == key)
765               goto nextloopread;
766             node = node->next;
767           } while(node != NULL);
768         }
769 #endif
770         //check normal table
771         {
772           chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
773           do {
774             if(node->key == key) {
775               objheader_t * headeraddr=&((objheader_t *) node->val)[-1];          
776               if(STATUS(headeraddr) & DIRTY) {
777                 goto nextloopread;
778               }
779             }
780             node = node->next;
781           } while(node != NULL);
782         }
783       }
784       //have to abort to avoid deadlock
785       transAbortProcess(oidwrlocked, NUMWRTOTAL);
786       STMWRAP((typesCausingAbort[TYPE(header)])++;);
787       freearrays;
788       if (softabort)
789         return TRANS_SOFT_ABORT;
790       else
791         return TRANS_ABORT;
792     }
793   nextloopread:
794     rd_curr = rd_curr->lnext;
795   }
796 #endif
797
798   /* Decide the final response */
799 #ifdef DELAYCOMP
800   transCommitProcess(oidwrlocked, numoidwrlocked, numoidwrtotal, commitmethod, primitives, locals, params);
801 #else
802   transCommitProcess(oidwrlocked, numoidwrlocked);
803 #endif
804   freearrays;
805   return TRANS_COMMIT;
806 }
807
808 /* ==================================
809  * transAbortProcess
810  *
811  * =================================
812  */
813
814 int logflag=1;
815
816 void transAbortProcess(struct garbagelist *oidwrlocked, int numoidwrlocked) {
817   int i;
818   objheader_t *header;
819   /* Release read locks */
820   void ** dirwrlocked=oidwrlocked->array;
821   /* Release write locks */
822   for(i=numoidwrlocked-1; i>=0; i--) {
823     /* Read from the main heap */
824     struct ___Object___ * dst=dirwrlocked[i];
825     header = &((objheader_t *)dst)[-1];
826 #ifdef STMARRAY
827     int type=dst->type;
828     if (type>=NUMCLASSES) {
829       //have array, do unlocking of bins
830       struct ArrayObject *src=(struct ArrayObject *)t_chashSearch(dst);
831       int lowoffset=(src->lowindex)>>INDEXSHIFT;
832       int highoffset=(src->highindex)>>INDEXSHIFT;
833       int j;
834       int addwrobject=0, addrdobject=0;
835       for(j=lowoffset; j<=highoffset;j++) {
836         unsigned int status;
837         GETLOCKVAL(status, src, j);
838         if (status==STMDIRTY) {
839           unsigned int *lockptr;
840           GETLOCKPTR(lockptr, ((struct ArrayObject *)dst), j);
841           write_unlock(lockptr);
842         }
843       }
844     } else
845 #endif
846     write_unlock(&header->lock);
847   }
848 #ifdef STMSTATS
849   /* clear trec and then release objects locked */
850   struct objlist *ptr=lockedobjs;
851   while(ptr!=NULL) {
852     int max=ptr->offset;
853     for(i=max-1; i>=0; i--) {
854       header = (objheader_t *)ptr->objs[i];
855       header->trec = NULL;
856       pthread_mutex_unlock(header->objlock);
857     }
858     ptr=ptr->next;
859   }
860 #endif
861 }
862
863 /* ==================================
864  * transCommitProcess
865  *
866  * =================================
867  */
868 #ifdef DELAYCOMP
869  void transCommitProcess(struct garbagelist * oidwrlocked, int numoidwrlocked, int numoidwrtotal, void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
870 #else
871 void transCommitProcess(struct garbagelist * oidwrlocked, int numoidwrlocked) {
872 #endif
873   objheader_t *header;
874   void *ptrcreate;
875   int i;
876   struct objlist *ptr=newobjs;
877   void **dirwrlocked=oidwrlocked->array;
878   while(ptr!=NULL) {
879     int max=ptr->offset;
880     for(i=0; i<max; i++) {
881       //clear the new flag
882       ((struct ___Object___ *)ptr->objs[i])->___objstatus___=0;
883     }
884     ptr=ptr->next;
885   }
886
887   /* Copy from transaction cache -> main object store */
888   for (i = numoidwrlocked-1; i >=0; i--) {
889     /* Read from the main heap */
890     header = &((objheader_t *)dirwrlocked[i])[-1];
891     int tmpsize;
892     GETSIZE(tmpsize, header);
893     struct ___Object___ *dst=(struct ___Object___*)dirwrlocked[i];
894     struct ___Object___ *src=t_chashSearch(dst);
895     dst->___cachedCode___=src->___cachedCode___;
896     dst->___cachedHash___=src->___cachedHash___;
897 #ifdef STMARRAY
898     int type=dst->type;
899     if (type>=NUMCLASSES) {
900       //have array, do copying of bins
901       int lowoffset=(((struct ArrayObject *)src)->lowindex)>>INDEXSHIFT;
902       int highoffset=(((struct ArrayObject *)src)->highindex)>>INDEXSHIFT;
903       int j;
904       int addwrobject=0, addrdobject=0;
905       int elementsize=classsize[type];
906       int baseoffset=(lowoffset<<INDEXSHIFT)+sizeof(int)+((int)&(((struct ArrayObject *)0)->___length___));
907       char *dstptr=((char *)dst)+baseoffset;
908       char *srcptr=((char *)src)+baseoffset;
909       for(j=lowoffset; j<=highoffset;j++, srcptr+=INDEXLENGTH,dstptr+=INDEXLENGTH) {
910         unsigned int status;
911         GETLOCKVAL(status, ((struct ArrayObject *)src), j);
912         if (status==STMDIRTY) {
913           A_memcpy(dstptr, srcptr, INDEXLENGTH);
914         }
915       }
916     } else
917 #endif 
918       A_memcpy(&dst[1], &src[1], tmpsize-sizeof(struct ___Object___));
919   }
920   CFENCE;
921
922 #ifdef DELAYCOMP
923   //  call commit method
924   ptrstack.count=0;
925   primstack.count=0;
926   branchstack.count=0;
927   //splice oidwrlocked in
928   oidwrlocked->size=numoidwrtotal;
929   oidwrlocked->next=params;
930   ((struct garbagelist *)locals)->next=oidwrlocked;
931   commitmethod(params, locals, primitives);
932   ((struct garbagelist *)locals)->next=params;
933 #endif
934
935   /* Release write locks */
936   for(i=NUMWRTOTAL-1; i>=0; i--) {
937     struct ___Object___ * dst=dirwrlocked[i];
938     header = &((objheader_t *)dst)[-1];
939 #ifdef STMARRAY
940     int type=dst->type;
941     if (type>=NUMCLASSES) {
942       //have array, do unlocking of bins
943       struct ArrayObject *src=(struct ArrayObject *)t_chashSearch(dst);
944       int lowoffset=(src->lowindex)>>INDEXSHIFT;
945       int highoffset=(src->highindex)>>INDEXSHIFT;
946       int j;
947       int addwrobject=0, addrdobject=0;
948       for(j=lowoffset; j<=highoffset;j++) {
949         unsigned int status;
950         GETLOCKVAL(status, src, j);
951         if (status==STMDIRTY) {
952           unsigned int *intptr;
953           GETVERSIONPTR(intptr, ((struct ArrayObject *)dst), j);
954           (*intptr)++;
955           GETLOCKPTR(intptr, ((struct ArrayObject *)dst), j);
956           write_unlock(intptr);
957         }
958       }
959     } else
960 #endif
961     {
962       header->version++;
963       write_unlock(&header->lock);
964     }
965   }
966
967 #ifdef STMSTATS
968   /* clear trec and then release objects locked */
969   ptr=lockedobjs;
970   while(ptr!=NULL) {
971     int max=ptr->offset;
972     for(i=max-1; i>=0; i--) {
973       header = (objheader_t *)ptr->objs[i];
974       header->trec = NULL;
975       pthread_mutex_unlock(header->objlock);
976     }
977     ptr=ptr->next;
978   }
979 #endif
980 }
981