X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=Robust%2Fsrc%2FRuntime%2FSTM%2Fstm.c;h=76e6ac7206b330fc22e60da9fd7e4bb6d9cbb3ff;hb=d1d21f290da37027c584fd789722939e0889e281;hp=79f15a9369876c4a3589dac80ffc7279c8afd103;hpb=925b581c273ef0ce3e1fd895ff63a3b4c84d7596;p=IRC.git diff --git a/Robust/src/Runtime/STM/stm.c b/Robust/src/Runtime/STM/stm.c index 79f15a93..76e6ac72 100644 --- a/Robust/src/Runtime/STM/stm.c +++ b/Robust/src/Runtime/STM/stm.c @@ -1,425 +1,226 @@ /* ============================================================ - * 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->offsetobjs[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<=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; ikey == 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->highoffsethighoffset=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; }