/* ============================================================
- * 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"
-/* Thread transaction variables */
+#include "garbage.h"
+
+/* 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 nSoftAbort = 0;
+int nSoftAbortCommit = 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;
-}
-
/* =================================================
* transStart
- * This function initializes things required in the
+ * This function initializes things required in the
* transaction start
* =================================================
*/
void transStart() {
- t_cache = objstrCreate(1048576);
- t_chashCreate(CHASH_SIZE, CLOADFACTOR);
+ //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
* =======================================================
*/
-objheader_t *transCreateObj(unsigned int size) {
- objheader_t *tmp = (objheader_t *) objstrAlloc(&t_cache, (sizeof(objheader_t) + size));
- OID(tmp) = getNewOID();
- tmp->version = 1;
- STATUS(tmp) = NEW;
- t_chashInsert(OID(tmp), tmp);
-
-#ifdef COMPILER
- return &tmp[1]; //want space after object header
+#ifdef STMARRAY
+objheader_t *transCreateObj(void * ptr, unsigned int size, int bytelength) {
+ int *tmpint = mygcmalloc(ptr, (sizeof(objheader_t) + size));
+ objheader_t *tmp = (objheader_t *) (tmpint+bytelength);
#else
- return tmp;
+objheader_t *transCreateObj(void * ptr, unsigned int size) {
+ objheader_t *tmp = mygcmalloc(ptr, (sizeof(objheader_t) + size));
#endif
+ objheader_t *retval=tmp+1;
+ tmp->lock=RW_LOCK_BIAS;
+ tmp->version = 1;
+ //initialize obj lock to the header
+ STATUS(tmp)=NEW;
+ // don't insert into table
+ if (newobjs->offset<MAXOBJLIST) {
+ newobjs->objs[newobjs->offset++]=retval;
+ } else {
+ struct objlist *tmp=malloc(sizeof(struct objlist));
+ tmp->next=newobjs;
+ tmp->objs[0]=retval;
+ tmp->offset=1;
+ newobjs=tmp;
+ }
+ return retval; //want space after object header
}
/* This functions inserts randowm wait delays in the order of msec
* Mostly used when transaction commits retry*/
-void randomdelay() {
+void randomdelay(int softaborted) {
struct timespec req;
- time_t t;
+ struct timeval t;
+
+ gettimeofday(&t,NULL);
- t = time(NULL);
req.tv_sec = 0;
- req.tv_nsec = (long)(1000 + (t%10000)); //1-11 microsec
+ req.tv_nsec = (long)((t.tv_usec)%(1<<softaborted))<<1; //1-11 microsec
nanosleep(&req, NULL);
return;
}
-/* ==============================================
- * objstrAlloc
- * - allocate space in an object store
- * ==============================================
- */
-void *objstrAlloc(objstr_t **osptr, unsigned int size) {
- void *tmp;
- int i=0;
- objstr_t *store=*osptr;
- if ((size&7)!=0) {
- size+=(8-(size&7));
- }
-
- for(;i<3;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 *os=(objstr_t *)calloc(1,(sizeof(objstr_t) + newsize));
- void *ptr=&os[1];
- os->next=store;
- (*osptr)=os;
- os->size=newsize;
- os->top=((char *)ptr)+size;
- return ptr;
- }
-}
-
/* =============================================================
* transRead
* -finds the objects either in main heap
* -copies the object into the transaction cache
* =============================================================
*/
-__attribute__((pure)) objheader_t *transRead(unsigned int oid) {
- unsigned int machinenumber;
+
+//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;
- /* Read from the main heap */
- objheader_t *header = (objheader_t *)(((char *)(&oid)) - sizeof(objheader_t));
- if(read_trylock(STATUSPTR(header))) { //Can further acquire read locks
+ 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;
+ char *tmpptr = (char *) objstrAlloc(size);
+ bzero(objcopy, 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(&t_cache, size);
- memcpy(objcopy, header, size);
- /* Insert into cache's lookup table */
- STATUS(objcopy)=0;
- t_chashInsert(OID(header), objcopy);
-#ifdef COMPILER
- return &objcopy[1];
+ objcopy = (objheader_t *) objstrAlloc(size);
+ A_memcpy(objcopy, header, size);
+ }
#else
- return objcopy;
+ GETSIZE(size, header);
+ size += sizeof(objheader_t);
+ objcopy = (objheader_t *) objstrAlloc(size);
+ A_memcpy(objcopy, header, size);
#endif
- }
- read_unlock(STATUSPTR(header));
-}
-
-/* ================================================================
- * transCommit
- * - This function initiates the transaction commit process
- * - goes through the transaction cache and decides
- * - a final response
- * ================================================================
- */
-int transCommit() {
- char finalResponse;
- char treplyretry; /* keeps track of the common response that needs to be sent */
-
- do {
- treplyretry = 0;
- /* Look through all the objects in the transaction hash table */
- finalResponse = traverseCache(&treplyretry);
- if(finalResponse == TRANS_ABORT) {
- break;
- }
- if(finalResponse == TRANS_COMMIT) {
- break;
- }
- /* wait a random amount of time before retrying to commit transaction*/
- if(treplyretry && (finalResponse == TRANS_SOFT_ABORT)) {
- randomdelay();
- }
- if(finalResponse != TRANS_ABORT || finalResponse != TRANS_COMMIT || finalResponse != TRANS_SOFT_ABORT) {
- printf("Error: in %s() Unknown outcome", __func__);
- exit(-1);
- }
- /* Retry trans commit procedure during soft_abort case */
- } while (treplyretry);
-
- if(finalResponse == TRANS_ABORT) {
- /* Free Resources */
- objstrDelete(t_cache);
- t_chashDelete();
- return TRANS_ABORT;
- } else if(finalResponse == TRANS_COMMIT) {
- /* Free Resources */
- objstrDelete(t_cache);
- t_chashDelete();
- return 0;
- } else {
- //TODO Add other cases
- printf("Error: in %s() THIS SHOULD NOT HAPPEN.....EXIT PROGRAM\n", __func__);
- exit(-1);
- }
- return 0;
-}
-
-/* ==================================================
- * traverseCache
- * - goes through the transaction cache and
- * - decides if a transaction should commit or abort
- * ==================================================
- */
-char traverseCache(char *treplyretry) {
- /* Create info for newly creately objects */
- int numcreated=0;
- unsigned int oidcreated[c_numelements];
- /* Create info to keep track of objects that can be locked */
- int numoidrdlocked=0;
- int numoidwrlocked=0;
- unsigned int oidrdlocked[c_numelements];
- unsigned int oidwrlocked[c_numelements];
- /* Counters to decide final response of this transaction */
- int vmatch_lock;
- int vmatch_nolock;
- int vnomatch;
- int numoidread;
- int numoidmod;
- char response;
-
- int i;
- 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 == 0)
- break;
- objheader_t * headeraddr=(objheader_t *) curr->val;
- response = decideResponse(headeraddr, oidcreated, &numcreated, oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked,
- &vmatch_lock, &vmatch_nolock, &vnomatch, &numoidmod, &numoidread);
- if(response == TRANS_ABORT) {
- *treplyretry = 0;
- transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
- return TRANS_ABORT;
- }
- curr = curr->next;
- }
- } //end of for
-
- /* Decide the final response */
- if(vmatch_nolock == (numoidread + numoidmod)) {
- *treplyretry = 0;
- transCommitProcess(oidcreated, &numcreated, oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
- response = TRANS_COMMIT;
- }
- if(vmatch_lock > 0 && vnomatch == 0) {
- *treplyretry = 1;
- response = TRANS_SOFT_ABORT;
- }
- return response;
-}
-
-/* ===========================================================================
- * decideResponse
- * - increments counters that keep track of objects read, modified or locked
- * - updates the oids locked and oids newly created
- * ===========================================================================
- */
-char decideResponse(objheader_t *headeraddr, unsigned int *oidcreated, int *numcreated, unsigned int* oidrdlocked, int *numoidrdlocked,
- unsigned int*oidwrlocked, int *numoidwrlocked, int *vmatch_lock, int *vmatch_nolock, int *vnomatch, int *numoidmod, int *numoidread) {
- unsigned short version = headeraddr->version;
- unsigned int oid = OID(headeraddr);
- if(STATUS(headeraddr) & NEW) {
- oidcreated[(*numcreated)++] = OID(headeraddr);
- } else if(STATUS(headeraddr) & DIRTY) {
- (*numoidmod)++;
- /* Read from the main heap and compare versions */
- objheader_t *header = (objheader_t *)(((char *)(&oid)) - sizeof(objheader_t));
- if(write_trylock(STATUSPTR(header))) { //can aquire write lock
- if (version == header->version) {/* versions match */
- /* Keep track of objects locked */
- (*vmatch_nolock)++;
- oidwrlocked[(*numoidwrlocked)++] = OID(header);
- } else {
- (*vnomatch)++;
- oidwrlocked[(*numoidwrlocked)++] = OID(header);
- return TRANS_ABORT;
- }
- } else { /* cannot aquire lock */
- if(version == header->version) /* versions match */
- (*vmatch_lock)++;
- else {
- (*vnomatch)++;
- return TRANS_ABORT;
- }
- }
- } else {
- (*numoidread)++;
- /* Read from the main heap and compare versions */
- objheader_t *header = (objheader_t *)(((char *)(&oid)) - sizeof(objheader_t));
- if(read_trylock(STATUSPTR(header))) { //can further aquire read locks
- if(version == header->version) {/* versions match */
- (*vmatch_nolock)++;
- oidrdlocked[(*numoidrdlocked)++] = OID(header);
- } else {
- (*vnomatch)++;
- oidrdlocked[(*numoidrdlocked)++] = OID(header);
- return TRANS_ABORT;
- }
- } else { /* cannot aquire lock */
- if(version == header->version)
- (*vmatch_lock)++;
- else {
- (*vnomatch)++;
- return TRANS_ABORT;
- }
- }
- }
- return 0;
-}
-
-/* ==================================
- * transAbortProcess
- *
- * =================================
- */
-int transAbortProcess(unsigned int *oidrdlocked, int *numoidrdlocked, unsigned int *oidwrlocked, int *numoidwrlocked) {
- int i;
- objheader_t *header;
- /* Release read locks */
- for(i=0; i< *numoidrdlocked; i++) {
- /* Read from the main heap */
- if((header = (objheader_t *)(((char *)(&oidrdlocked[i])) - sizeof(objheader_t))) == NULL) {
- printf("Error: %s() main heap returned NULL at %s, %d\n", __func__, __FILE__, __LINE__);
- return 1;
- }
- read_unlock(STATUSPTR(header));
- }
-
- /* Release write locks */
- for(i=0; i< *numoidwrlocked; i++) {
- /* Read from the main heap */
- if((header = (objheader_t *)(((char *)(&oidwrlocked[i])) - sizeof(objheader_t))) == NULL) {
- printf("Error: %s() main heap returned NULL at %s, %d\n", __func__, __FILE__, __LINE__);
- return 1;
- }
- write_unlock(STATUSPTR(header));
- }
+#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];
}
-/* ==================================
- * transCommitProcess
- *
- * =================================
- */
-int transCommmitProcess(unsigned int *oidcreated, int *numoidcreated, unsigned int *oidrdlocked, int *numoidrdlocked,
- unsigned int *oidwrlocked, int *numoidwrlocked) {
- objheader_t *header, *tcptr;
- void *ptrcreate;
-
- int i;
- /* If object is newly created inside transaction then commit it */
- for (i = 0; i < *numoidcreated; i++) {
- if ((header = ((objheader_t *) t_chashSearch(oidcreated[i]))) == NULL) {
- printf("Error: %s() chashSearch returned NULL for oid = %x at %s, %d\n", __func__, oidcreated[i], __FILE__, __LINE__);
- return 1;
- }
- int tmpsize;
- GETSIZE(tmpsize, header);
- tmpsize += sizeof(objheader_t);
- /* FIXME Is this correct? */
-#ifdef PRECISE_GC
- ptrcreate = mygcmalloc((struct garbagelist *)header, tmpsize);
-#else
- ptrcreate = FREEMALLOC(tmpsize);
+#ifdef STMARRAY
+//caller needs to mark data as present
+ void arraycopy(struct ArrayObject *oid, int byteindex) {
+ struct ArrayObject * orig=oid->___objlocation___;
+ int baseoffset=byteindex&HIGHMASK;
+ A_memcpy(((char *)&oid[1])+baseoffset, ((char *)&orig[1])+baseoffset, INDEXLENGTH);
+ if (oid->lowoffset>baseoffset)
+ oid->lowoffset=baseoffset;
+ if (oid->highoffset<baseoffset)
+ oid->highoffset=baseoffset;
+ }
#endif
- /* Initialize read and write locks */
- initdsmlocks(STATUSPTR(header));
- memcpy(ptrcreate, header, tmpsize);
- }
-
- /* Copy from transaction cache -> main object store */
- for (i = 0; i < *numoidwrlocked; i++) {
- /* Read from the main heap */
- if((header = (objheader_t *)(((char *)(&oidwrlocked[i])) - sizeof(objheader_t))) == NULL) {
- printf("Error: %s() main heap returns NULL at %s, %d\n", __func__, __FILE__, __LINE__);
- return 1;
- }
- if ((tcptr = ((objheader_t *) t_chashSearch(oidwrlocked[i]))) == NULL) {
- printf("Error: %s() chashSearch returned NULL at %s, %d\n", __func__, __FILE__, __LINE__);
- return 1;
- }
- int tmpsize;
- GETSIZE(tmpsize, header);
- char *tmptcptr = (char *) tcptr;
- {
- struct ___Object___ *dst=(struct ___Object___*)((char*)header+sizeof(objheader_t));
- struct ___Object___ *src=(struct ___Object___*)((char*)tmptcptr+sizeof(objheader_t));
- dst->___cachedCode___=src->___cachedCode___;
- dst->___cachedHash___=src->___cachedHash___;
- memcpy(&dst[1], &src[1], tmpsize-sizeof(struct ___Object___));
- }
-
- header->version += 1;
- if(header->notifylist != NULL) {
- notifyAll(&header->notifylist, OID(header), header->version);
- }
- }
-
- /* 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(STATUSPTR(header));
+void freenewobjs() {
+ struct objlist *ptr=newobjs;
+ while(ptr->next!=NULL) {
+ struct objlist *tmp=ptr->next;
+ free(ptr);
+ ptr=tmp;
}
-
- /* Release write locks */
- for(i=0; i< *numoidwrlocked; i++) {
- header = (objheader_t *)(((char *)(&oidwrlocked[i])) - sizeof(objheader_t));
- write_unlock(STATUSPTR(header));
- }
-
- return 0;
+ ptr->offset=0;
+ newobjs=ptr;
}