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