* - a final response
* ================================================================
*/
+#ifdef DELAYCOMP
+int transCommit(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
+#else
int transCommit() {
+#endif
int softaborted=0;
do {
/* Look through all the objects in the transaction hash table */
int finalResponse;
if (c_numelements<(c_size>>3))
- finalResponse= alttraverseCache();
+ finalResponse= alttraverseCache(commitmethod, primitives, locals, params);
else
- finalResponse= traverseCache();
+ finalResponse= traverseCache(commitmethod, primitives, locals, params);
if(finalResponse == TRANS_ABORT) {
#ifdef TRANSSTATS
numTransAbort++;
} while (1);
}
+#ifdef DELAYCOMP
+#define freearrays if (c_numelements>=200) { \
+ free(oidrdlocked); \
+ free(oidrdversion); \
+ } \
+ if (t_numelements>=200) { \
+ free(oidwrlocked); \
+ }
+#else
+#define freearrays if (c_numelements>=200) { \
+ free(oidrdlocked); \
+ free(oidrdversion); \
+ free(oidwrlocked); \
+ }
+#endif
/* ==================================================
* traverseCache
* - goes through the transaction cache and
* - decides if a transaction should commit or abort
* ==================================================
*/
+#ifdef DELAYCOMP
+int traverseCache(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
+#else
int traverseCache() {
+#endif
/* Create info to keep track of objects that can be locked */
int numoidrdlocked=0;
int numoidwrlocked=0;
void ** oidrdlocked;
void ** oidwrlocked;
int * oidrdversion;
+#ifdef DELAYCOMP
+ int t_numelements=c_numelements+dc_c_numelements;
+ if (t_numelements<200) {
+ oidwrlocked=wrlocked;
+ } else {
+ oidwrlocked=malloc(t_numelements*sizeof(void *));
+ }
+ if (c_numelements<200) {
+ oidrdlocked=rdlocked;
+ oidrdversion=rdversion;
+ } else {
+ int size=c_numelements*sizeof(void*);
+ oidrdlocked=malloc(size);
+ oidrdversion=malloc(size);
+ }
+#else
if (c_numelements<200) {
oidrdlocked=rdlocked;
oidrdversion=rdversion;
oidrdversion=malloc(size);
oidwrlocked=malloc(size);
}
+#endif
chashlistnode_t *ptr = c_table;
/* Represents number of bins in the chash table */
unsigned int size = c_size;
#endif
DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
- if (c_numelements>=200) {
- free(oidrdlocked);
- free(oidrdversion);
- free(oidwrlocked);
- }
+ freearrays;
if (softabort)
return TRANS_SOFT_ABORT;
else
#endif
DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
- if (c_numelements>=200) {
- free(oidrdlocked);
- free(oidrdversion);
- free(oidwrlocked);
- }
+ freearrays;
if (softabort)
return TRANS_SOFT_ABORT;
else
}
} //end of for
+#ifdef DELAYCOMP
+ //acquire other locks
+ chashlistnode_t *dc_curr = dc_c_list;
+ /* Inner loop to traverse the linked list of the cache lookupTable */
+ while(likely(dc_curr != NULL)) {
+ //if the first bin in hash table is empty
+ objheader_t * headeraddr=&((objheader_t *) dc_curr->val)[-1];
+ objheader_t *header=(objheader_t *)(((char *)dc_curr->key)-sizeof(objheader_t));
+ if(write_trylock(&header->lock)) { //can aquire write lock
+ oidwrlocked[numoidwrlocked++] = header;
+ } else {
+ //maybe we already have lock
+ chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
+
+ do {
+ if(node->key == key) {
+ goto nextloop;
+ }
+ node = node->next;
+ } while(node != NULL);
+
+ //have to abort to avoid deadlock
+ transAbortProcess(oidwrlocked, numoidwrlocked);
+#ifdef STMSTATS
+ ABORTCOUNT(header);
+ (typesCausingAbort[TYPE(header)])++;
+#endif
+#if defined(STMSTATS)||defined(SOFTABORT)
+ if (getTotalAbortCount(i+1, size, (void *)(curr->next), NULL, 1))
+ softabort=0;
+#endif
+ DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
+ DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
+ freearrays;
+ if (softabort)
+ return TRANS_SOFT_ABORT;
+ else
+ return TRANS_ABORT;
+ }
+ nextloop:
+ dc_curr = dc_curr->lnext;
+ }
+#endif
+
//THIS IS THE SERIALIZATION END POINT (START POINT IS END OF EXECUTION)*****
for(i=0; i<numoidrdlocked; i++) {
#endif
DEBUGSTM("RD Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
DEBUGSTMSTAT("RD Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
- if (c_numelements>=200) {
- free(oidrdlocked);
- free(oidrdversion);
- free(oidwrlocked);
- }
+ freearrays;
return TRANS_ABORT;
}
} else { /* cannot aquire lock */
#endif
DEBUGSTM("RD Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
DEBUGSTMSTAT("RD Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
- if (c_numelements>=200) {
- free(oidrdlocked);
- free(oidrdversion);
- free(oidwrlocked);
- }
+ freearrays;
if (softabort)
return TRANS_SOFT_ABORT;
else
}
/* Decide the final response */
+#ifdef DELAYCOMP
+ transCommitProcess(oidwrlocked, numoidwrlocked, commitmethod, primitives, locals, params);
+#else
transCommitProcess(oidwrlocked, numoidwrlocked);
+#endif
DEBUGSTM("Commit: rd: %u wr: %u tot: %u\n", numoidrdlocked, numoidwrlocked, c_numelements);
- if (c_numelements>=200) {
- free(oidrdlocked);
- free(oidrdversion);
- free(oidwrlocked);
- }
+ freearrays;
return TRANS_COMMIT;
}
* - decides if a transaction should commit or abort
* ==================================================
*/
+
+#ifdef DELAYCOMP
+int alttraverseCache(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
+#else
int alttraverseCache() {
+#endif
/* Create info to keep track of objects that can be locked */
int numoidrdlocked=0;
int numoidwrlocked=0;
void ** oidrdlocked;
int * oidrdversion;
void ** oidwrlocked;
+#ifdef DELAYCOMP
+ int t_numelements=c_numelements+dc_c_numelements;
+ if (t_numelements<200) {
+ oidwrlocked=wrlocked;
+ } else {
+ oidwrlocked=malloc(t_numelements*sizeof(void *));
+ }
+ if (c_numelements<200) {
+ oidrdlocked=rdlocked;
+ oidrdversion=rdversion;
+ } else {
+ int size=c_numelements*sizeof(void*);
+ oidrdlocked=malloc(size);
+ oidrdversion=malloc(size);
+ }
+#else
if (c_numelements<200) {
oidrdlocked=rdlocked;
oidrdversion=rdversion;
oidrdversion=malloc(size);
oidwrlocked=malloc(size);
}
+#endif
chashlistnode_t *curr = c_list;
/* Inner loop to traverse the linked list of the cache lookupTable */
while(likely(curr != NULL)) {
#endif
DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
- if (c_numelements>=200) {
- free(oidrdlocked);
- free(oidrdversion);
- free(oidwrlocked);
- }
+ freearrays;
return TRANS_ABORT;
}
} else { /* cannot aquire lock */
#endif
DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
- if (c_numelements>=200) {
- free(oidrdlocked);
- free(oidrdversion);
- free(oidwrlocked);
- }
+ freearrays;
if (softabort)
return TRANS_SOFT_ABORT;
else
curr = curr->lnext;
}
+#ifdef DELAYCOMP
+ //acquire other locks
+ chashlistnode_t *dc_curr = dc_c_list;
+ /* Inner loop to traverse the linked list of the cache lookupTable */
+ while(likely(dc_curr != NULL)) {
+ //if the first bin in hash table is empty
+ objheader_t * headeraddr=&((objheader_t *) dc_curr->val)[-1];
+ objheader_t *header=(objheader_t *)(((char *)dc_curr->key)-sizeof(objheader_t));
+ if(write_trylock(&header->lock)) { //can aquire write lock
+ oidwrlocked[numoidwrlocked++] = header;
+ } else {
+ //maybe we already have lock
+ chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
+
+ do {
+ if(node->key == key) {
+ goto nextloop;
+ }
+ node = node->next;
+ } while(node != NULL);
+
+ //have to abort to avoid deadlock
+ transAbortProcess(oidwrlocked, numoidwrlocked);
+#ifdef STMSTATS
+ ABORTCOUNT(header);
+ (typesCausingAbort[TYPE(header)])++;
+#endif
+#if defined(STMSTATS)||defined(SOFTABORT)
+ if (getTotalAbortCount(i+1, size, (void *)(curr->next), NULL, 1))
+ softabort=0;
+#endif
+ DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
+ DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
+ freearrays;
+ if (softabort)
+ return TRANS_SOFT_ABORT;
+ else
+ return TRANS_ABORT;
+ }
+ nextloop:
+ dc_curr = dc_curr->lnext;
+ }
+#endif
//THIS IS THE SERIALIZATION END POINT (START POINT IS END OF EXECUTION)*****
#endif
DEBUGSTM("RD Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
DEBUGSTMSTAT("RD Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
- if (c_numelements>=200) {
- free(oidrdlocked);
- free(oidrdversion);
- free(oidwrlocked);
- }
+ freearrays;
return TRANS_ABORT;
}
} else { /* cannot aquire lock */
#endif
DEBUGSTM("RD Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
DEBUGSTMSTAT("RD Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
- if (c_numelements>=200) {
- free(oidrdlocked);
- free(oidrdversion);
- free(oidwrlocked);
- }
+ freearrays;
if (softabort)
return TRANS_SOFT_ABORT;
else
}
/* Decide the final response */
+#ifdef DELAYCOMP
+ transCommitProcess(oidwrlocked, numoidwrlocked, commitmethod, primitives, locals, params);
+#else
transCommitProcess(oidwrlocked, numoidwrlocked);
+#endif
DEBUGSTM("Commit: rd: %u wr: %u tot: %u\n", numoidrdlocked, numoidwrlocked, c_numelements);
- if (c_numelements>=200) {
- free(oidrdlocked);
- free(oidrdversion);
- free(oidwrlocked);
- }
+ freearrays;
return TRANS_COMMIT;
}
*
* =================================
*/
-void transCommitProcess(void ** oidwrlocked, int numoidwrlocked) {
+#ifdef DELAYCOMP
+ void transCommitProcess(void ** oidwrlocked, int numoidwrlocked, void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
+#else
+ void transCommitProcess(void ** oidwrlocked, int numoidwrlocked) {
+#endif
objheader_t *header;
void *ptrcreate;
int i;
}
__asm__ __volatile__("": : :"memory");
+#ifdef DELAYCOMP
+ // call commit method
+ commitmethod(primitives, locals, params);
+#endif
+
/* Release write locks */
for(i=numoidwrlocked-1; i>=0; i--) {
header = (objheader_t *)oidwrlocked[i];
__thread double c_loadfactor;
__thread cliststruct_t *c_structs;
+#ifdef DELAYCOMP
+__thread chashlistnode_t *dc_c_table;
+__thread chashlistnode_t *dc_c_list;
+__thread unsigned int dc_c_size;
+__thread unsigned INTPTR dc_c_mask;
+__thread unsigned int dc_c_numelements;
+__thread unsigned int dc_c_threshold;
+__thread double dc_c_loadfactor;
+__thread cliststruct_t *dc_c_structs;
+
+void dc_t_chashCreate(unsigned int size, double loadfactor) {
+ chashtable_t *ctable;
+ chashlistnode_t *nodes;
+ int i;
+
+ // Allocate space for the hash table
+
+ dc_c_table = calloc(size, sizeof(chashlistnode_t));
+ dc_c_loadfactor = loadfactor;
+ dc_c_size = size;
+ dc_c_threshold=size*loadfactor;
+ dc_c_mask = (size << 4)-1;
+ dc_c_structs=calloc(1, sizeof(cliststruct_t));
+ dc_c_numelements = 0; // Initial number of elements in the hash
+ dc_c_list=NULL;
+}
+
+void dc_t_chashreset() {
+ chashlistnode_t *ptr = dc_c_table;
+ int i;
+
+ if (dc_c_numelements<(dc_c_size>>4)) {
+ chashlistnode_t *top=&ptr[dc_c_size];
+ chashlistnode_t *tmpptr=dc_c_list;
+ while(tmpptr!=NULL) {
+ chashlistnode_t *next=tmpptr->lnext;
+ if (tmpptr>=ptr&&tmpptr<top) {
+ //zero in list
+ tmpptr->key=0;
+ tmpptr->next=NULL;
+ }
+ tmpptr=next;
+ }
+ } else {
+ bzero(dc_c_table, sizeof(chashlistnode_t)*dc_c_size);
+ }
+ while(dc_c_structs->next!=NULL) {
+ cliststruct_t *next=dc_c_structs->next;
+ free(dc_c_structs);
+ dc_c_structs=next;
+ }
+ dc_c_structs->num = 0;
+ dc_c_numelements = 0;
+ dc_c_list=NULL;
+}
+
+//Store objects and their pointers into hash
+void dc_t_chashInsertOnce(void * key, void *val) {
+ chashlistnode_t *ptr;
+
+
+ if(dc_c_numelements > (dc_c_threshold)) {
+ //Resize
+ unsigned int newsize = dc_c_size << 1;
+ dc_t_chashResize(newsize);
+ }
+
+ ptr = &dc_c_table[(((unsigned INTPTR)key)&dc_c_mask)>>4];
+
+ if(ptr->key==0) {
+ ptr->key=key;
+ ptr->val=val;
+ ptr->lnext=dc_c_list;
+ dc_c_list=ptr;
+ dc_c_numelements++;
+ } else { // Insert in the beginning of linked list
+ chashlistnode_t * node;
+ chashlistnode_t *search=ptr;
+
+ //make sure it isn't here
+ do {
+ if(search->key == key) {
+ return;
+ }
+ search=search->next;
+ } while(search != NULL);
+
+ dc_c_numelements++;
+ if (dc_c_structs->num<NUMCLIST) {
+ node=&dc_c_structs->array[dc_c_structs->num];
+ dc_c_structs->num++;
+ } else {
+ //get new list
+ cliststruct_t *tcl=calloc(1,sizeof(cliststruct_t));
+ tcl->next=dc_c_structs;
+ dc_c_structs=tcl;
+ node=&tcl->array[0];
+ tcl->num=1;
+ }
+ node->key = key;
+ node->val = val;
+ node->next = ptr->next;
+ ptr->next=node;
+ node->lnext=dc_c_list;
+ dc_c_list=node;
+ }
+}
+
+unsigned int dc_t_chashResize(unsigned int newsize) {
+ chashlistnode_t *node, *ptr, *curr; // curr and next keep track of the current and the next chashlistnodes in a linked list
+ unsigned int oldsize;
+ int isfirst; // Keeps track of the first element in the chashlistnode_t for each bin in hashtable
+ unsigned int i,index;
+ unsigned int mask;
+
+ ptr = dc_c_table;
+ oldsize = dc_c_size;
+ dc_c_list=NULL;
+
+ if((node = calloc(newsize, sizeof(chashlistnode_t))) == NULL) {
+ printf("Calloc error %s %d\n", __FILE__, __LINE__);
+ return 1;
+ }
+
+ dc_c_table = node; //Update the global hashtable upon resize()
+ dc_c_size = newsize;
+ dc_c_threshold = newsize * dc_c_loadfactor;
+ mask=dc_c_mask = (newsize << 4)-1;
+
+ for(i = 0; i < oldsize; i++) { //Outer loop for each bin in hash table
+ curr = &ptr[i];
+ isfirst = 1;
+ do { //Inner loop to go through linked lists
+ void * key;
+ chashlistnode_t *tmp,*next;
+
+ if ((key=curr->key) == 0) { //Exit inner loop if there the first element is 0
+ break; //key = val =0 for element if not present within the hash table
+ }
+ index = (((unsigned INTPTR)key) & mask) >>4;
+ tmp=&node[index];
+ next = curr->next;
+ // Insert into the new table
+ if(tmp->key == 0) {
+ tmp->key = key;
+ tmp->val = curr->val;
+ tmp->lnext=dc_c_list;
+ dc_c_list=tmp;
+ } /*
+ NOTE: Add this case if you change this...
+ This case currently never happens because of the way things rehash....
+ else if (isfirst) {
+ chashlistnode_t *newnode= calloc(1, sizeof(chashlistnode_t));
+ newnode->key = curr->key;
+ newnode->val = curr->val;
+ newnode->next = tmp->next;
+ tmp->next=newnode;
+ } */
+ else {
+ curr->next=tmp->next;
+ tmp->next=curr;
+ curr->lnext=dc_c_list;
+ dc_c_list=curr;
+ }
+
+ isfirst = 0;
+ curr = next;
+ } while(curr!=NULL);
+ }
+
+ free(ptr); //Free the memory of the old hash table
+ return 0;
+}
+
+//Delete the entire hash table
+void dc_t_chashDelete() {
+ int i;
+ cliststruct_t *ptr=dc_c_structs;
+ while(ptr!=NULL) {
+ cliststruct_t *next=ptr->next;
+ free(ptr);
+ ptr=next;
+ }
+ free(dc_c_table);
+ dc_c_table=NULL;
+ dc_c_structs=NULL;
+ dc_c_list=NULL;
+}
+#endif
+
void t_chashCreate(unsigned int size, double loadfactor) {
chashtable_t *ctable;
chashlistnode_t *nodes;