/* ============================================================
- * singleTMCommit.c
+ * singleTMCommit.c
* - single thread commit on local machine
* =============================================================
* Copyright (c) 2009, University of California, Irvine, USA.
* All rights reserved.
- * Author: Alokika Dash
+ * Author: Alokika Dash
* adash@uci.edu
* =============================================================
*
#include "tm.h"
#include "garbage.h"
-/* Thread transaction variables */
+
+/* Per thread transaction variables */
__thread objstr_t *t_cache;
__thread objstr_t *t_reserve;
__thread struct objlist * newobjs;
+#ifdef SANDBOX
+#include "sandbox.h"
+#endif
+
+#ifdef DELAYCOMP
+#include "delaycomp.h"
+__thread struct pointerlist ptrstack;
+__thread struct primitivelist primstack;
+__thread struct branchlist branchstack;
+struct pointerlist *c_ptrstack;
+struct primitivelist *c_primstack;
+struct branchlist *c_branchstack;
+#endif
+
#ifdef TRANSSTATS
int numTransCommit = 0;
int numTransAbort = 0;
int nSoftAbortAbort = 0;
#endif
+void * A_memcpy (void * dest, const void * src, size_t count) {
+ int off=0;
+ INTPTR *desti=(INTPTR *)dest;
+ INTPTR *srci=(INTPTR *)src;
+
+ //word copy
+ while(count>=sizeof(INTPTR)) {
+ desti[off]=srci[off];
+ off+=1;
+ count-=sizeof(INTPTR);
+ }
+ off*=sizeof(INTPTR);
+ //byte copy
+ while(count>0) {
+ ((char *)dest)[off]=((char *)src)[off];
+ off++;
+ count--;
+ }
+}
/* ==================================================
* stmStartup
- * This function starts up the transaction runtime.
+ * This function starts up the transaction runtime.
* ==================================================
*/
int stmStartup() {
return 0;
}
-/* ======================================
- * objstrCreate
- * - create an object store of given size
- * ======================================
- */
-objstr_t *objstrCreate(unsigned int size) {
- objstr_t *tmp;
- if((tmp = calloc(1, (sizeof(objstr_t) + size))) == NULL) {
- printf("%s() Calloc error at line %d, %s\n", __func__, __LINE__, __FILE__);
- return NULL;
- }
- tmp->size = size;
- tmp->next = NULL;
- tmp->top = tmp + 1; //points to end of objstr_t structure!
- return tmp;
-}
-
-void objstrReset() {
- while(t_cache->next!=NULL) {
- objstr_t *next=t_cache->next;
- t_cache->next=t_reserve;
- t_reserve=t_cache;
- t_cache=next;
- }
- t_cache->top=t_cache+1;
-}
-
-//free entire list, starting at store
-void objstrDelete(objstr_t *store) {
- objstr_t *tmp;
- while (store != NULL) {
- tmp = store->next;
- free(store);
- store = tmp;
- }
- return;
-}
-
/* =================================================
* transStart
- * This function initializes things required in the
+ * This function initializes things required in the
* transaction start
* =================================================
*/
void transStart() {
//Transaction start is currently free...commit and aborting is not
+#ifdef DELAYCOMP
+ c_ptrstack=&ptrstack;
+ c_primstack=&primstack;
+ c_branchstack=&branchstack;
+#endif
}
/* =======================================================
* transCreateObj
- * This function creates objects in the transaction record
+ * This function creates objects in the transaction record
* =======================================================
*/
+#ifdef STMARRAY
+objheader_t *transCreateObj(void * ptr, unsigned int size, int bytelength) {
+ char *tmpchar = mygcmalloc(ptr, (sizeof(objheader_t) + size));
+ objheader_t *tmp = (objheader_t *) (tmpchar+bytelength);
+#else
objheader_t *transCreateObj(void * ptr, unsigned int size) {
objheader_t *tmp = mygcmalloc(ptr, (sizeof(objheader_t) + size));
- objheader_t *retval=&tmp[1];
- tmp->lock=RW_LOCK_BIAS;
+#endif
+ objheader_t *retval=tmp+1;
+ tmp->lock=SWAP_LOCK_BIAS;
tmp->version = 1;
+ //initialize obj lock to the header
STATUS(tmp)=NEW;
// don't insert into table
if (newobjs->offset<MAXOBJLIST) {
return;
}
-/* ==============================================
- * objstrAlloc
- * - allocate space in an object store
- * ==============================================
- */
-void *objstrAlloc(unsigned int size) {
- void *tmp;
- int i=0;
- objstr_t *store=t_cache;
- if ((size&7)!=0) {
- size+=(8-(size&7));
- }
-
- for(;i<2;i++) {
- if (OSFREE(store)>=size) {
- tmp=store->top;
- store->top +=size;
- return tmp;
- }
- if ((store=store->next)==NULL)
- break;
- }
-
- {
- unsigned int newsize=size>DEFAULT_OBJ_STORE_SIZE?size:DEFAULT_OBJ_STORE_SIZE;
- objstr_t **otmp=&t_reserve;
- objstr_t *ptr;
- while((ptr=*otmp)!=NULL) {
- if (ptr->size>=newsize) {
- //remove from list
- *otmp=ptr->next;
- ptr->next=t_cache;
- t_cache=ptr;
- ptr->top=((char *)(&ptr[1]))+size;
- return &ptr[1];
- }
- }
-
- objstr_t *os=(objstr_t *)calloc(1,(sizeof(objstr_t) + newsize));
- void *nptr=&os[1];
- os->next=t_cache;
- t_cache=os;
- os->size=newsize;
- os->top=((char *)nptr)+size;
- return nptr;
- }
-}
-
/* =============================================================
* transRead
* -finds the objects either in main heap
* -copies the object into the transaction cache
* =============================================================
*/
-__attribute__((pure)) void *transRead(void * oid) {
+
+//void *TR(void *x, void * y, void *z) {
+// void * inputvalue;
+// if ((inputvalue=y)==NULL) x=NULL;
+// else {
+// chashlistnode_t * cnodetmp=&c_table[(((unsigned INTPTR)inputvalue)&c_mask)>>4];
+// do {
+// if (cnodetmp->key==inputvalue) {x=cnodetmp->val; break;}
+// cnodetmp=cnodetmp->next;
+// if (cnodetmp==NULL) {if (((struct ___Object___*)inputvalue)->___objstatus___&NEW) {x=inputvalue; break;} else
+// {x=transRead(inputvalue,z); asm volatile ("" : "=m" (c_table),"\=m" (c_mask)); break;}}
+// } while(1);
+// }
+// return x;
+//}
+
+//__attribute__ ((pure))
+void *transRead(void * oid, void *gl) {
objheader_t *tmp, *objheader;
objheader_t *objcopy;
int size;
- //quick case for new objects
- if (((struct ___Object___ *)oid)->___objstatus___ & NEW)
- return oid;
-
- /* Read from the main heap */
- //No lock for now
- objheader_t *header = (objheader_t *)(((char *)oid) - sizeof(objheader_t));
+ objheader_t *header = (objheader_t *)(((char *)oid) - sizeof(objheader_t));
+#ifdef STMSTATS
+ header->accessCount++;
+ if(header->riskyflag) {
+ header=needLock(header,gl);
+ }
+#endif
+#ifdef STMARRAY
+ int type=TYPE(header);
+ if (type>=NUMCLASSES) {
+ int basesize=((struct ArrayObject *)oid)->___length___*classsize[type];
+ basesize=(basesize+LOWMASK)&HIGHMASK;
+ int metasize=sizeof(int)*2*(basesize>>INDEXSHIFT);
+ size = basesize + sizeof(objheader_t)+metasize+sizeof(struct ArrayObject);
+ char *tmpptr = (char *) objstrAlloc(size);
+ bzero(tmpptr, metasize);//clear out stm data
+ objcopy=(objheader_t *) (tmpptr+metasize);
+ A_memcpy(objcopy, header, sizeof(objheader_t)+sizeof(struct ArrayObject)); //copy the metadata and base array info
+ } else {
+ GETSIZE(size, header);
+ size += sizeof(objheader_t);
+ objcopy = (objheader_t *) objstrAlloc(size);
+ A_memcpy(objcopy, header, size);
+ }
+#else
GETSIZE(size, header);
size += sizeof(objheader_t);
objcopy = (objheader_t *) objstrAlloc(size);
- memcpy(objcopy, header, size);
+ A_memcpy(objcopy, header, size);
+#endif
+#ifdef STMSTATS
+ /* keep track of the object's access sequence in a transaction */
+ objheader_t *tmpheader = objcopy;
+ tmpheader->accessCount = ++t_objnumcount;
+#endif
/* Insert into cache's lookup table */
STATUS(objcopy)=0;
+ if (((unsigned INTPTR)oid)<((unsigned INTPTR ) curr_heapbase)|| ((unsigned INTPTR)oid) >((unsigned INTPTR) curr_heapptr))
+ printf("ERROR! Bad object address!\n");
t_chashInsert(oid, &objcopy[1]);
return &objcopy[1];
}
+#ifdef STMARRAY
+//caller needs to mark data as present
+ void arraycopy(struct ArrayObject *oid, int byteindex) {
+ struct ArrayObject * orig=(struct ArrayObject *) oid->___objlocation___;
+ int baseoffset=byteindex&HIGHMASK;
+ unsigned int mainversion;
+ int baseindex=baseoffset>>INDEXSHIFT;
+ GETVERSIONVAL(mainversion, orig, baseindex);
+ SETVERSION(oid, baseindex, mainversion);
+ A_memcpy(((char *)&oid[1])+baseoffset, ((char *)&orig[1])+baseoffset, INDEXLENGTH);
+ if (oid->lowindex>baseoffset)
+ oid->lowindex=baseoffset;
+ if (oid->highindex<baseoffset)
+ oid->highindex=baseoffset;
+ }
+#endif
+
void freenewobjs() {
struct objlist *ptr=newobjs;
while(ptr->next!=NULL) {
newobjs=ptr;
}
-/* ================================================================
- * transCommit
- * - This function initiates the transaction commit process
- * - goes through the transaction cache and decides
- * - a final response
- * ================================================================
- */
-int transCommit() {
-#ifdef TRANSSTATS
- int softaborted=0;
-#endif
- do {
- /* Look through all the objects in the transaction hash table */
- int finalResponse;
- if (c_numelements<(c_size>>3))
- finalResponse= alttraverseCache();
- else
- finalResponse= traverseCache();
- if(finalResponse == TRANS_ABORT) {
-#ifdef TRANSSTATS
- numTransAbort++;
- if (softaborted) {
- nSoftAbortAbort++;
- }
-#endif
- freenewobjs();
- objstrReset();
- t_chashreset();
- return TRANS_ABORT;
- }
- if(finalResponse == TRANS_COMMIT) {
-#ifdef TRANSSTATS
- numTransCommit++;
- if (softaborted) {
- nSoftAbortCommit++;
- }
-#endif
- freenewobjs();
- objstrReset();
- t_chashreset();
- return 0;
- }
- /* wait a random amount of time before retrying to commit transaction*/
- if(finalResponse == TRANS_SOFT_ABORT) {
-#ifdef TRANSSTATS
- nSoftAbort++;
- softaborted++;
-#endif
- if (softaborted>4) {
- //retry if to many soft aborts
- freenewobjs();
- objstrReset();
- t_chashreset();
- return TRANS_ABORT;
- }
- randomdelay(softaborted);
- } else {
- printf("Error: in %s() Unknown outcome", __func__);
- exit(-1);
- }
- } while (1);
-}
-
-/* ==================================================
- * traverseCache
- * - goes through the transaction cache and
- * - decides if a transaction should commit or abort
- * ==================================================
- */
-int traverseCache() {
- /* Create info to keep track of objects that can be locked */
- int numoidrdlocked=0;
- int numoidwrlocked=0;
- void * rdlocked[200];
- void * wrlocked[200];
- int softabort=0;
- int i;
- void ** oidrdlocked;
- void ** oidwrlocked;
- if (c_numelements<200) {
- oidrdlocked=rdlocked;
- oidwrlocked=wrlocked;
- } else {
- int size=c_numelements*sizeof(void*);
- oidrdlocked=malloc(size);
- oidwrlocked=malloc(size);
- }
- chashlistnode_t *ptr = c_table;
- /* Represents number of bins in the chash table */
- unsigned int size = c_size;
- for(i = 0; i<size; i++) {
- chashlistnode_t *curr = &ptr[i];
- /* Inner loop to traverse the linked list of the cache lookupTable */
- while(curr != NULL) {
- //if the first bin in hash table is empty
- if(curr->key == NULL)
- break;
- objheader_t * headeraddr=&((objheader_t *) curr->val)[-1];
-
- unsigned int version = headeraddr->version;
- objheader_t *header=(objheader_t *) (((char *)curr->key)-sizeof(objheader_t));
-
- if(STATUS(headeraddr) & DIRTY) {
- /* Read from the main heap and compare versions */
- if(write_trylock(&header->lock)) { //can aquire write lock
- if (version == header->version) {/* versions match */
- /* Keep track of objects locked */
- oidwrlocked[numoidwrlocked++] = OID(header);
- } else {
- oidwrlocked[numoidwrlocked++] = OID(header);
- transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
- return TRANS_ABORT;
- }
- } else { /* cannot aquire lock */
- if(version == header->version) {
- /* versions match */
- softabort=1;
- } else {
- transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
- return TRANS_ABORT;
- }
- }
- } else {
- /* Read from the main heap and compare versions */
- if(read_trylock(&header->lock)) { //can further acquire read locks
- if(version == header->version) {/* versions match */
- oidrdlocked[numoidrdlocked++] = OID(header);
- } else {
- oidrdlocked[numoidrdlocked++] = OID(header);
- transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
- return TRANS_ABORT;
- }
- } else { /* cannot aquire lock */
- if(version == header->version) {
- softabort=1;
- } else {
- transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
- return TRANS_ABORT;
- }
- }
- }
-
- curr = curr->next;
- }
- } //end of for
-
- /* Decide the final response */
- if (softabort) {
- transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
- return TRANS_SOFT_ABORT;
- } else {
- transCommitProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
- return TRANS_COMMIT;
- }
-}
-
-/* ==================================================
- * traverseCache
- * - goes through the transaction cache and
- * - decides if a transaction should commit or abort
- * ==================================================
- */
-int alttraverseCache() {
- /* Create info to keep track of objects that can be locked */
- int numoidrdlocked=0;
- int numoidwrlocked=0;
- void * rdlocked[200];
- void * wrlocked[200];
- int softabort=0;
- int i;
- void ** oidrdlocked;
- void ** oidwrlocked;
- if (c_numelements<200) {
- oidrdlocked=rdlocked;
- oidwrlocked=wrlocked;
- } else {
- int size=c_numelements*sizeof(void*);
- oidrdlocked=malloc(size);
- oidwrlocked=malloc(size);
- }
- chashlistnode_t *curr = c_list;
- /* Inner loop to traverse the linked list of the cache lookupTable */
- while(curr != NULL) {
- //if the first bin in hash table is empty
- objheader_t * headeraddr=&((objheader_t *) curr->val)[-1];
-
- unsigned int version = headeraddr->version;
- objheader_t *header=(objheader_t *) (((char *)curr->key)-sizeof(objheader_t));
-
- if(STATUS(headeraddr) & DIRTY) {
- /* Read from the main heap and compare versions */
- if(write_trylock(&header->lock)) { //can aquire write lock
- if (version == header->version) {/* versions match */
- /* Keep track of objects locked */
- oidwrlocked[numoidwrlocked++] = OID(header);
- } else {
- oidwrlocked[numoidwrlocked++] = OID(header);
- transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
- return TRANS_ABORT;
- }
- } else { /* cannot aquire lock */
- if(version == header->version) {
- /* versions match */
- softabort=1;
- } else {
- transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
- return TRANS_ABORT;
- }
- }
- } else {
- /* Read from the main heap and compare versions */
- if(read_trylock(&header->lock)) { //can further aquire read locks
- if(version == header->version) {/* versions match */
- oidrdlocked[numoidrdlocked++] = OID(header);
- } else {
- oidrdlocked[numoidrdlocked++] = OID(header);
- transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
- return TRANS_ABORT;
- }
- } else { /* cannot aquire lock */
- if(version == header->version) {
- softabort=1;
- } else {
- transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
- return TRANS_ABORT;
- }
- }
- }
-
- curr = curr->lnext;
- }
-
- /* Decide the final response */
- if (softabort) {
- transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
- return TRANS_SOFT_ABORT;
- } else {
- transCommitProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
- return TRANS_COMMIT;
- }
-}
-
-
-/* ==================================
- * transAbortProcess
- *
- * =================================
- */
-int transAbortProcess(void **oidrdlocked, int *numoidrdlocked, void **oidwrlocked, int *numoidwrlocked) {
- int i;
- objheader_t *header;
- /* Release read locks */
- for(i=0; i< *numoidrdlocked; i++) {
- /* Read from the main heap */
- header = (objheader_t *)(((char *)(oidrdlocked[i])) - sizeof(objheader_t));
- read_unlock(&header->lock);
- }
-
- /* Release write locks */
- for(i=0; i< *numoidwrlocked; i++) {
- /* Read from the main heap */
- header = (objheader_t *)(((char *)(oidwrlocked[i])) - sizeof(objheader_t));
- write_unlock(&header->lock);
- }
- if (c_numelements>=200) {
- free(oidrdlocked);
- free(oidwrlocked);
- }
-}
-
-/* ==================================
- * transCommitProcess
- *
- * =================================
- */
-int transCommitProcess(void ** oidrdlocked, int *numoidrdlocked,
- void ** oidwrlocked, int *numoidwrlocked) {
- objheader_t *header;
- void *ptrcreate;
- int i;
- struct objlist *ptr=newobjs;
- while(ptr!=NULL) {
- int max=ptr->offset;
- for(i=0;i<max;i++) {
- //clear the new flag
- ((struct ___Object___ *)ptr->objs[i])->___objstatus___=0;
- }
- ptr=ptr->next;
- }
-
- /* Copy from transaction cache -> main object store */
- for (i = 0; i < *numoidwrlocked; i++) {
- /* Read from the main heap */
- header = (objheader_t *)(((char *)(oidwrlocked[i])) - sizeof(objheader_t));
- int tmpsize;
- GETSIZE(tmpsize, header);
- struct ___Object___ *dst=(struct ___Object___*)oidwrlocked[i];
- struct ___Object___ *src=t_chashSearch(oidwrlocked[i]);
- dst->___cachedCode___=src->___cachedCode___;
- dst->___cachedHash___=src->___cachedHash___;
- memcpy(&dst[1], &src[1], tmpsize-sizeof(struct ___Object___));
- header->version += 1;
- }
-
- /* Release read locks */
- for(i=0; i< *numoidrdlocked; i++) {
- /* Read from the main heap */
- header = (objheader_t *)(((char *)(oidrdlocked[i])) - sizeof(objheader_t));
- read_unlock(&header->lock);
- }
-
- /* Release write locks */
- for(i=0; i< *numoidwrlocked; i++) {
- header = (objheader_t *)(((char *)(oidwrlocked[i])) - sizeof(objheader_t));
- write_unlock(&header->lock);
- }
- if (c_numelements>=200) {
- free(oidrdlocked);
- free(oidwrlocked);
- }
- return 0;
-}
-