do a make tabbing
[IRC.git] / Robust / src / Runtime / STM / stm.c
1 /* ============================================================
2  * singleTMCommit.c
3  * - single thread commit on local machine
4  * =============================================================
5  * Copyright (c) 2009, University of California, Irvine, USA.
6  * All rights reserved.
7  * Author: Alokika Dash
8  *         adash@uci.edu
9  * =============================================================
10  *
11  */
12
13 #include "tm.h"
14 #include "garbage.h"
15 /* Thread transaction variables */
16 __thread objstr_t *t_cache;
17 __thread objstr_t *t_reserve;
18 __thread struct objlist * newobjs;
19
20 #ifdef TRANSSTATS
21 int numTransCommit = 0;
22 int numTransAbort = 0;
23 int nSoftAbort = 0;
24 int nSoftAbortCommit = 0;
25 int nSoftAbortAbort = 0;
26 #endif
27
28 #ifdef STMSTATS
29 int typesCausingAbort[TOTALNUMCLASSANDARRAY];
30 /******Keep track of objects and types causing aborts******/
31 #define DEBUGSTMSTAT(args...) { \
32     printf(args); \
33     fflush(stdout); \
34 }
35 #else
36 #define DEBUGSTMSTAT(args...)
37 #endif
38
39 #ifdef STMDEBUG
40 #define DEBUGSTM(x...) printf(x);
41 #else
42 #define DEBUGSTM(x...)
43 #endif
44
45
46 /* ==================================================
47  * stmStartup
48  * This function starts up the transaction runtime.
49  * ==================================================
50  */
51 int stmStartup() {
52   return 0;
53 }
54
55 /* ======================================
56  * objstrCreate
57  * - create an object store of given size
58  * ======================================
59  */
60 objstr_t *objstrCreate(unsigned int size) {
61   objstr_t *tmp;
62   if((tmp = calloc(1, (sizeof(objstr_t) + size))) == NULL) {
63     printf("%s() Calloc error at line %d, %s\n", __func__, __LINE__, __FILE__);
64     return NULL;
65   }
66   tmp->size = size;
67   tmp->next = NULL;
68   tmp->top = tmp + 1; //points to end of objstr_t structure!
69   return tmp;
70 }
71
72 void objstrReset() {
73   while(t_cache->next!=NULL) {
74     objstr_t *next=t_cache->next;
75     t_cache->next=t_reserve;
76     t_reserve=t_cache;
77     t_cache=next;
78   }
79   t_cache->top=t_cache+1;
80 }
81
82 //free entire list, starting at store
83 void objstrDelete(objstr_t *store) {
84   objstr_t *tmp;
85   while (store != NULL) {
86     tmp = store->next;
87     free(store);
88     store = tmp;
89   }
90   return;
91 }
92
93 /* =================================================
94  * transStart
95  * This function initializes things required in the
96  * transaction start
97  * =================================================
98  */
99 void transStart() {
100   //Transaction start is currently free...commit and aborting is not
101 }
102
103 /* =======================================================
104  * transCreateObj
105  * This function creates objects in the transaction record
106  * =======================================================
107  */
108 objheader_t *transCreateObj(void * ptr, unsigned int size) {
109   objheader_t *tmp = mygcmalloc(ptr, (sizeof(objheader_t) + size));
110   objheader_t *retval=&tmp[1];
111   tmp->lock=RW_LOCK_BIAS;
112   tmp->version = 1;
113   STATUS(tmp)=NEW;
114   // don't insert into table
115   if (newobjs->offset<MAXOBJLIST) {
116     newobjs->objs[newobjs->offset++]=retval;
117   } else {
118     struct objlist *tmp=malloc(sizeof(struct objlist));
119     tmp->next=newobjs;
120     tmp->objs[0]=retval;
121     tmp->offset=1;
122     newobjs=tmp;
123   }
124   return retval; //want space after object header
125 }
126
127 /* This functions inserts randowm wait delays in the order of msec
128  * Mostly used when transaction commits retry*/
129 void randomdelay(int softaborted) {
130   struct timespec req;
131   struct timeval t;
132
133   gettimeofday(&t,NULL);
134
135   req.tv_sec = 0;
136   req.tv_nsec = (long)((t.tv_usec)%(1<<softaborted))<<1; //1-11 microsec
137   nanosleep(&req, NULL);
138   return;
139 }
140
141 /* ==============================================
142  * objstrAlloc
143  * - allocate space in an object store
144  * ==============================================
145  */
146 void *objstrAlloc(unsigned int size) {
147   void *tmp;
148   int i=0;
149   objstr_t *store=t_cache;
150   if ((size&7)!=0) {
151     size+=(8-(size&7));
152   }
153
154   for(; i<2; i++) {
155     if (OSFREE(store)>=size) {
156       tmp=store->top;
157       store->top +=size;
158       return tmp;
159     }
160     if ((store=store->next)==NULL)
161       break;
162   }
163
164   {
165     unsigned int newsize=size>DEFAULT_OBJ_STORE_SIZE ? size : DEFAULT_OBJ_STORE_SIZE;
166     objstr_t **otmp=&t_reserve;
167     objstr_t *ptr;
168     while((ptr=*otmp)!=NULL) {
169       if (ptr->size>=newsize) {
170         //remove from list
171         *otmp=ptr->next;
172         ptr->next=t_cache;
173         t_cache=ptr;
174         ptr->top=((char *)(&ptr[1]))+size;
175         return &ptr[1];
176       }
177     }
178
179     objstr_t *os=(objstr_t *)calloc(1,(sizeof(objstr_t) + newsize));
180     void *nptr=&os[1];
181     os->next=t_cache;
182     t_cache=os;
183     os->size=newsize;
184     os->top=((char *)nptr)+size;
185     return nptr;
186   }
187 }
188
189 /* =============================================================
190  * transRead
191  * -finds the objects either in main heap
192  * -copies the object into the transaction cache
193  * =============================================================
194  */
195 __attribute__((pure)) void *transRead(void * oid) {
196   objheader_t *tmp, *objheader;
197   objheader_t *objcopy;
198   int size;
199
200   /* Read from the main heap */
201   //No lock for now
202   objheader_t *header = (objheader_t *)(((char *)oid) - sizeof(objheader_t));
203   GETSIZE(size, header);
204   size += sizeof(objheader_t);
205   objcopy = (objheader_t *) objstrAlloc(size);
206   memcpy(objcopy, header, size);
207 #ifdef STMSTATS
208   header->accessCount++;
209 #endif
210   /* Insert into cache's lookup table */
211   STATUS(objcopy)=0;
212   t_chashInsert(oid, &objcopy[1]);
213   return &objcopy[1];
214 }
215
216 void freenewobjs() {
217   struct objlist *ptr=newobjs;
218   while(ptr->next!=NULL) {
219     struct objlist *tmp=ptr->next;
220     free(ptr);
221     ptr=tmp;
222   }
223   ptr->offset=0;
224   newobjs=ptr;
225 }
226
227 /* ================================================================
228  * transCommit
229  * - This function initiates the transaction commit process
230  * - goes through the transaction cache and decides
231  * - a final response
232  * ================================================================
233  */
234 int transCommit() {
235   int softaborted=0;
236   do {
237     /* Look through all the objects in the transaction hash table */
238     int finalResponse;
239     if (c_numelements<(c_size>>3))
240       finalResponse= alttraverseCache();
241     else
242       finalResponse= traverseCache();
243     if(finalResponse == TRANS_ABORT) {
244 #ifdef TRANSSTATS
245       numTransAbort++;
246       if (softaborted) {
247         nSoftAbortAbort++;
248       }
249 #endif
250       freenewobjs();
251       objstrReset();
252       t_chashreset();
253       return TRANS_ABORT;
254     }
255     if(finalResponse == TRANS_COMMIT) {
256 #ifdef TRANSSTATS
257       numTransCommit++;
258       if (softaborted) {
259         nSoftAbortCommit++;
260       }
261 #endif
262       freenewobjs();
263       objstrReset();
264       t_chashreset();
265       return 0;
266     }
267     /* wait a random amount of time before retrying to commit transaction*/
268     if(finalResponse == TRANS_SOFT_ABORT) {
269 #ifdef TRANSSTATS
270       nSoftAbort++;
271 #endif
272       softaborted++;
273       if (softaborted>4) {
274         //retry if too many soft aborts
275         freenewobjs();
276         objstrReset();
277         t_chashreset();
278         return TRANS_ABORT;
279       }
280       randomdelay(softaborted);
281     } else {
282       printf("Error: in %s() Unknown outcome", __func__);
283       exit(-1);
284     }
285   } while (1);
286 }
287
288 /* ==================================================
289  * traverseCache
290  * - goes through the transaction cache and
291  * - decides if a transaction should commit or abort
292  * ==================================================
293  */
294 int traverseCache() {
295   /* Create info to keep track of objects that can be locked */
296   int numoidrdlocked=0;
297   int numoidwrlocked=0;
298   void * rdlocked[200];
299   int rdversion[200];
300   void * wrlocked[200];
301   int softabort=0;
302   int i;
303   void ** oidrdlocked;
304   void ** oidwrlocked;
305   int * oidrdversion;
306   if (c_numelements<200) {
307     oidrdlocked=rdlocked;
308     oidrdversion=rdversion;
309     oidwrlocked=wrlocked;
310   } else {
311     int size=c_numelements*sizeof(void*);
312     oidrdlocked=malloc(size);
313     oidrdversion=malloc(size);
314     oidwrlocked=malloc(size);
315   }
316   chashlistnode_t *ptr = c_table;
317   /* Represents number of bins in the chash table */
318   unsigned int size = c_size;
319   for(i = 0; i<size; i++) {
320     chashlistnode_t *curr = &ptr[i];
321     /* Inner loop to traverse the linked list of the cache lookupTable */
322     while(curr != NULL) {
323       //if the first bin in hash table is empty
324       if(curr->key == NULL)
325         break;
326       objheader_t * headeraddr=&((objheader_t *) curr->val)[-1];
327       objheader_t *header=(objheader_t *)(((char *)curr->key)-sizeof(objheader_t));
328       unsigned int version = headeraddr->version;
329
330       if(STATUS(headeraddr) & DIRTY) {
331         /* Read from the main heap  and compare versions */
332         if(write_trylock(&header->lock)) { //can aquire write lock
333           if (version == header->version) { /* versions match */
334             /* Keep track of objects locked */
335             oidwrlocked[numoidwrlocked++] = OID(header);
336           } else {
337             oidwrlocked[numoidwrlocked++] = OID(header);
338             transAbortProcess(oidwrlocked, numoidwrlocked);
339 #ifdef STMSTATS
340             header->abortCount++;
341             (typesCausingAbort[TYPE(header)])++;
342             getTotalAbortCount(i+1, size, (void *)(curr->next), NULL, 'w');
343 #endif
344             DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
345             DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
346             if (c_numelements>=200) {
347               free(oidrdlocked);
348               free(oidrdversion);
349               free(oidwrlocked);
350             }
351             return TRANS_ABORT;
352           }
353         } else { /* cannot aquire lock */
354           if(version == header->version) {
355             /* versions match */
356             softabort=1;
357           } else {
358             transAbortProcess(oidwrlocked, numoidwrlocked);
359 #ifdef STMSTATS
360             header->abortCount++;
361             (typesCausingAbort[TYPE(header)])++;
362             getTotalAbortCount(i+1, size, (void *)(curr->next), NULL, 'w');
363 #endif
364             DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
365             DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
366             if (c_numelements>=200) {
367               free(oidrdlocked);
368               free(oidrdversion);
369               free(oidwrlocked);
370             }
371             return TRANS_ABORT;
372           }
373         }
374       } else {
375         oidrdversion[numoidrdlocked]=version;
376         oidrdlocked[numoidrdlocked++] = header;
377       }
378       curr = curr->next;
379     }
380   } //end of for
381
382   //THIS IS THE SERIALIZATION POINT *****
383
384   for(i=0; i<numoidrdlocked; i++) {
385     /* Read from the main heap  and compare versions */
386     objheader_t *header=oidrdlocked[i];
387     unsigned int version=oidrdversion[i];
388     if(header->lock>0) { //not write locked
389       if(version != header->version) { /* versions do not match */
390         oidrdlocked[numoidrdlocked++] = OID(header);
391         transAbortProcess(oidwrlocked, numoidwrlocked);
392 #ifdef STMSTATS
393         header->abortCount++;
394         (typesCausingAbort[TYPE(header)])++;
395         getTotalAbortCount(i+1, numoidrdlocked, oidrdlocked, (void *) oidrdversion, 'r');
396 #endif
397         DEBUGSTM("RD Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
398         DEBUGSTMSTAT("RD Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
399         if (c_numelements>=200) {
400           free(oidrdlocked);
401           free(oidrdversion);
402           free(oidwrlocked);
403         }
404         return TRANS_ABORT;
405       }
406     } else { /* cannot aquire lock */
407       //do increment as we didn't get lock
408       if(version == header->version) {
409         softabort=1;
410       } else {
411         transAbortProcess(oidwrlocked, numoidwrlocked);
412 #ifdef STMSTATS
413         header->abortCount++;
414         (typesCausingAbort[TYPE(header)])++;
415         getTotalAbortCount(i+1, numoidrdlocked, oidrdlocked, (void *) oidrdversion, 'r');
416 #endif
417         DEBUGSTM("RD Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
418         DEBUGSTMSTAT("RD Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
419         if (c_numelements>=200) {
420           free(oidrdlocked);
421           free(oidrdversion);
422           free(oidwrlocked);
423         }
424         return TRANS_ABORT;
425       }
426     }
427   }
428
429   /* Decide the final response */
430   if (softabort) {
431     transAbortProcess(oidwrlocked, numoidwrlocked);
432     DEBUGSTM("Soft Abort: rd: %u wr: %u tot: %u\n", numoidrdlocked, numoidwrlocked, c_numelements);
433     if (c_numelements>=200) {
434       free(oidrdlocked);
435       free(oidrdversion);
436       free(oidwrlocked);
437     }
438     return TRANS_SOFT_ABORT;
439   } else {
440     transCommitProcess(oidwrlocked, numoidwrlocked);
441     DEBUGSTM("Commit: rd: %u wr: %u tot: %u\n", numoidrdlocked, numoidwrlocked, c_numelements);
442     if (c_numelements>=200) {
443       free(oidrdlocked);
444       free(oidrdversion);
445       free(oidwrlocked);
446     }
447     return TRANS_COMMIT;
448   }
449 }
450
451 /* ==================================================
452  * alttraverseCache
453  * - goes through the transaction cache and
454  * - decides if a transaction should commit or abort
455  * ==================================================
456  */
457 int alttraverseCache() {
458   /* Create info to keep track of objects that can be locked */
459   int numoidrdlocked=0;
460   int numoidwrlocked=0;
461   void * rdlocked[200];
462   int rdversion[200];
463   void * wrlocked[200];
464   int softabort=0;
465   int i;
466   void ** oidrdlocked;
467   int * oidrdversion;
468   void ** oidwrlocked;
469   if (c_numelements<200) {
470     oidrdlocked=rdlocked;
471     oidrdversion=rdversion;
472     oidwrlocked=wrlocked;
473   } else {
474     int size=c_numelements*sizeof(void*);
475     oidrdlocked=malloc(size);
476     oidrdversion=malloc(size);
477     oidwrlocked=malloc(size);
478   }
479   chashlistnode_t *curr = c_list;
480   /* Inner loop to traverse the linked list of the cache lookupTable */
481   while(curr != NULL) {
482     //if the first bin in hash table is empty
483     objheader_t * headeraddr=&((objheader_t *) curr->val)[-1];
484     objheader_t *header=(objheader_t *)(((char *)curr->key)-sizeof(objheader_t));
485     unsigned int version = headeraddr->version;
486
487     if(STATUS(headeraddr) & DIRTY) {
488       /* Read from the main heap  and compare versions */
489       if(write_trylock(&header->lock)) { //can aquire write lock
490         if (version == header->version) { /* versions match */
491           /* Keep track of objects locked */
492           oidwrlocked[numoidwrlocked++] = OID(header);
493         } else {
494           oidwrlocked[numoidwrlocked++] = OID(header);
495           transAbortProcess(oidwrlocked, numoidwrlocked);
496 #ifdef STMSTATS
497           header->abortCount++;
498           (typesCausingAbort[TYPE(header)])++;
499           getTotalAbortCount(0, 1, (void *) curr->next, NULL, 'w');
500 #endif
501           DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
502           DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
503           if (c_numelements>=200) {
504             free(oidrdlocked);
505             free(oidrdversion);
506             free(oidwrlocked);
507           }
508           return TRANS_ABORT;
509         }
510       } else { /* cannot aquire lock */
511         if(version == header->version) {
512           /* versions match */
513           softabort=1;
514         } else {
515           transAbortProcess(oidwrlocked, numoidwrlocked);
516 #ifdef STMSTATS
517           header->abortCount++;
518           (typesCausingAbort[TYPE(header)])++;
519           getTotalAbortCount(0, 1, (void *) curr->next, NULL, 'w');
520 #endif
521           DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
522           DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
523           if (c_numelements>=200) {
524             free(oidrdlocked);
525             free(oidrdversion);
526             free(oidwrlocked);
527           }
528           return TRANS_ABORT;
529         }
530       }
531     } else {
532       /* Read from the main heap  and compare versions */
533       oidrdversion[numoidrdlocked]=version;
534       oidrdlocked[numoidrdlocked++] = header;
535     }
536     curr = curr->lnext;
537   }
538   //THIS IS THE SERIALIZATION POINT *****
539   for(i=0; i<numoidrdlocked; i++) {
540     objheader_t * header = oidrdlocked[i];
541     unsigned int version=oidrdversion[i];
542     if(header->lock>=0) {
543       if(version != header->version) {
544         transAbortProcess(oidwrlocked, numoidwrlocked);
545 #ifdef STMSTATS
546         header->abortCount++;
547         (typesCausingAbort[TYPE(header)])++;
548         getTotalAbortCount(i+1, numoidrdlocked, oidrdlocked, (void *)oidrdversion, 'r');
549 #endif
550         DEBUGSTM("RD Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
551         DEBUGSTMSTAT("RD Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
552         if (c_numelements>=200) {
553           free(oidrdlocked);
554           free(oidrdversion);
555           free(oidwrlocked);
556         }
557         return TRANS_ABORT;
558       }
559     } else { /* cannot aquire lock */
560       if(version == header->version) {
561         softabort=1;
562       } else {
563         transAbortProcess(oidwrlocked, numoidwrlocked);
564 #ifdef STMSTATS
565         header->abortCount++;
566         (typesCausingAbort[TYPE(header)])++;
567         getTotalAbortCount(i+1, numoidrdlocked, oidrdlocked, (void *)oidrdversion, 'r');
568 #endif
569         DEBUGSTM("RD Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
570         DEBUGSTMSTAT("RD Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
571         if (c_numelements>=200) {
572           free(oidrdlocked);
573           free(oidrdversion);
574           free(oidwrlocked);
575         }
576         return TRANS_ABORT;
577       }
578     }
579   }
580
581   /* Decide the final response */
582   if (softabort) {
583     transAbortProcess(oidwrlocked, numoidwrlocked);
584     DEBUGSTM("Soft Abort: rd: %u wr: %u tot: %u\n", numoidrdlocked, numoidwrlocked, c_numelements);
585     if (c_numelements>=200) {
586       free(oidrdlocked);
587       free(oidrdversion);
588       free(oidwrlocked);
589     }
590     return TRANS_SOFT_ABORT;
591   } else {
592     transCommitProcess(oidwrlocked, numoidwrlocked);
593     DEBUGSTM("Commit: rd: %u wr: %u tot: %u\n", numoidrdlocked, numoidwrlocked, c_numelements);
594     if (c_numelements>=200) {
595       free(oidrdlocked);
596       free(oidrdversion);
597       free(oidwrlocked);
598     }
599     return TRANS_COMMIT;
600   }
601 }
602
603
604 /* ==================================
605  * transAbortProcess
606  *
607  * =================================
608  */
609 int transAbortProcess(void **oidwrlocked, int numoidwrlocked) {
610   int i;
611   objheader_t *header;
612   /* Release read locks */
613
614   /* Release write locks */
615   for(i=0; i< numoidwrlocked; i++) {
616     /* Read from the main heap */
617     header = (objheader_t *)(((char *)(oidwrlocked[i])) - sizeof(objheader_t));
618     write_unlock(&header->lock);
619   }
620 }
621
622 /* ==================================
623  * transCommitProcess
624  *
625  * =================================
626  */
627 int transCommitProcess(void ** oidwrlocked, int numoidwrlocked) {
628   objheader_t *header;
629   void *ptrcreate;
630   int i;
631   struct objlist *ptr=newobjs;
632   while(ptr!=NULL) {
633     int max=ptr->offset;
634     for(i=0; i<max; i++) {
635       //clear the new flag
636       ((struct ___Object___ *)ptr->objs[i])->___objstatus___=0;
637     }
638     ptr=ptr->next;
639   }
640
641   /* Copy from transaction cache -> main object store */
642   for (i = 0; i < numoidwrlocked; i++) {
643     /* Read from the main heap */
644     header = (objheader_t *)(((char *)(oidwrlocked[i])) - sizeof(objheader_t));
645     int tmpsize;
646     GETSIZE(tmpsize, header);
647     struct ___Object___ *dst=(struct ___Object___*)oidwrlocked[i];
648     struct ___Object___ *src=t_chashSearch(oidwrlocked[i]);
649     dst->___cachedCode___=src->___cachedCode___;
650     dst->___cachedHash___=src->___cachedHash___;
651     memcpy(&dst[1], &src[1], tmpsize-sizeof(struct ___Object___));
652     header->version += 1;
653   }
654
655   /* Release write locks */
656   for(i=0; i< numoidwrlocked; i++) {
657     header = (objheader_t *)(((char *)(oidwrlocked[i])) - sizeof(objheader_t));
658     write_unlock(&header->lock);
659   }
660   return 0;
661 }
662
663 /** ========================================================================================
664  * getTotalAbortCount
665  * params : start: start index of the loop
666  *        : stop: stop index of the loop
667  *        : startptr: pointer that points to where to start looking in the array/ linked list
668  *          'r'/'w' if found when visiting objects read/ objects modified
669  * =========================================================================================
670  **/
671 #ifdef STMSTATS
672 void getTotalAbortCount(int start, int stop, void *startptr, void *checkptr, char type) {
673   printf("Inside %s()\n", __func__);
674   int i;
675   if(type == 'w') {
676     int isFirstTime = 0;
677     chashlistnode_t *curr = (chashlistnode_t *) startptr;
678     chashlistnode_t *ptr = c_table;
679     for(i = start; i < stop; i++) {
680       if(!isFirstTime)
681         curr = &ptr[i];
682       /* Inner loop to traverse the linked list of the cache lookupTable */
683       while(curr != NULL) {
684         if(curr->key == NULL)
685           break;
686         objheader_t * headeraddr=&((objheader_t *) curr->val)[-1];
687         objheader_t *header=(objheader_t *)(((char *)curr->key)-sizeof(objheader_t));
688         unsigned int version = headeraddr->version;
689         /* versions do not match */
690         if(version != header->version) {
691           header->abortCount++;
692           (typesCausingAbort[TYPE(header)])++;
693         }
694         curr = curr->next;
695       }
696       isFirstTime = 1;
697     }
698   } else {
699     /* Go through oids read that are locked */
700     for(i = start; i < stop; i++) {
701       objheader_t *header = ((void **)startptr)[i];
702       unsigned int version = ((int *)checkptr)[i];
703       if(version != header->version) { /* versions do not match */
704         header->abortCount++;
705         (typesCausingAbort[TYPE(header)])++;
706       }
707     }
708   }
709 }
710 #else
711 void getTotalAbortCount(int start, int stop, void *startptr, void *checkptr, char type) {
712   return;
713 }
714 #endif