}
#define STMGETARRAY(dst, array, index, type) { \
- int byteindex=index*sizeof(type); \
- int * lengthoff=&array->___length___; \
if (((char *)array)!=((char *)array->___objlocation___)) { \
if(!(array->___objstatus___&NEW)) { \
+ int byteindex=index*sizeof(type); \
int *status; \
- GETLOCKPTR(status, array, byteindex>>INDEXSHIFT); \
- if ((*status)==STMNONE) { \
+ int metaindex=(byteindex&HIGHMASK)>>INDEXSHIFT; \
+ GETLOCKPTR(status, array, metaindex); \
+ if (metaindex<array->lowindex||metaindex>array->highindex \
+ ||(*status)==STMNONE) { \
arraycopy(array, byteindex); \
- *status=STMCLEAN;} \
+ (*status)=STMCLEAN;} \
} \
} \
- dst=((type *)(((char *) lengthoff)+sizeof(int)))[index]; \
+ dst=((type *)(((char *) &array->___length___)+sizeof(int)))[index]; \
}
#define STMSETARRAY(array, index, src, type) { \
- int byteindex=index*sizeof(type); \
- int * lengthoff=&array->___length___; \
if (!(array->___objstatus___&NEW)) { \
int *status; \
- GETLOCKPTR(status, array, byteindex>>INDEXSHIFT); \
- if ((*status)==STMNONE) \
+ int byteindex=index*sizeof(type); \
+ int metaindex=(byteindex&HIGHMASK)>>INDEXSHIFT; \
+ GETLOCKPTR(status, array, metaindex); \
+ if (metaindex<array->lowindex||metaindex>array->highindex \
+ ||(*status)==STMNONE) { \
arraycopy(array, byteindex); \
- *status=STMDIRTY; \
+ } \
+ (*status)=STMDIRTY; \
} \
- ((type *)(((char *) lengthoff)+sizeof(int)))[index]=src; \
+ ((type *)(((char *) &array->___length___)+sizeof(int)))[index]=src; \
}
#endif
-#define VERSIONINCREMENT(array, index, type) { \
- unsigned int * versionptr; \
+#define VERSIONINCREMENT(array, index, type) { \
+ unsigned int * versionptr; \
GETVERSIONPTR(versionptr, array,((sizeof(type)*index)>>INDEXSHIFT)); \
- (*versionptr)++; \
+ (*versionptr)++; \
}
/* Look through all the objects in the transaction hash table */
int finalResponse;
#ifdef DELAYCOMP
- if (c_numelements<(c_size>>3))
+ if (c_numelements<(c_size>>1))
finalResponse=alttraverseCache(commitmethod, primitives, locals, params);
else
finalResponse=traverseCache(commitmethod, primitives, locals, params);
#else
- if (c_numelements<(c_size>>3))
+ if (c_numelements<(c_size>>1))
finalResponse=alttraverseCache();
else
finalResponse=traverseCache();
else \
return TRANS_ABORT;
+#define ABORTREAD \
+ transAbortProcess(oidwrlocked, numoidwrtotal ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked)); \
+ freearrays; \
+ if (softabort) \
+ return TRANS_SOFT_ABORT; \
+ else \
+ return TRANS_ABORT;
+
#define ARRAYABORT \
for(;j>=lowoffset;j--) { \
ABORT
#ifdef DUALVIEW
-#define DVGETLOCK(x) \
- unsigned int * objlock=&(&((objheader_t *)x)[-1])->lock; \
- if(!rwread_trylock(objlock)) { \
- ABORT; \
+#define DVGETLOCK(x) if (!addwrobject) { \
+ unsigned int * objlock=&(&((objheader_t *)x)[-1])->lock; \
+ if(!rwread_trylock(objlock)) { \
+ ABORT; \
+ } \
+}
+
+#define DVRELEASELOCK(x) { \
+ unsigned int * objlock=&(&((objheader_t *)x)[-1])->lock; \
+ rwread_unlock(objlock); \
}
//not finished...if we can't get the lock, it is okay if it is in our access set
#define DVCHECKLOCK(x) \
- unsigned int * objlock=&(&((objheader_t *)x)[-1])->lock; \
+ unsigned int * objlock=&(&((objheader_t *)x)[-1])->lock; \
if (objlock<=0) { \
if (dc_t_chashSearch(x)==NULL) { \
- ABORT; \
+ ABORTREAD; \
} \
}
#else
#define DVGETLOCK(x)
#define DVCHECKLOCK(x)
+#define DVRELEASELOCK(x)
#endif
#if defined(DELAYCOMP)&&!defined(DUALVIEW)
if (type>=NUMCLASSES) { \
struct ArrayObject *transao=(struct ArrayObject *) cachedobj; \
struct ArrayObject *mainao=(struct ArrayObject *) objptr; \
- DVGETLOCK(mainao); \
- int lowoffset=(transao->lowindex)>>INDEXSHIFT; \
- int highoffset=(transao->highindex)>>INDEXSHIFT; \
+ int lowoffset=(transao->lowindex); \
+ int highoffset=(transao->highindex); \
int j; \
int addwrobject=0, addrdobject=0; \
for(j=lowoffset; j<=highoffset;j++) { \
unsigned int status; \
GETLOCKVAL(status, transao, j); \
if (status==STMDIRTY) { \
+ DVGETLOCK(mainao); \
unsigned int * lockptr; \
GETLOCKPTR(lockptr, mainao,j); \
if (likely(write_trylock(lockptr))) { \
if (likely(localversion == remoteversion)) { \
addwrobject=1; \
} else { \
+ DVRELEASELOCK(mainao); \
ARRAYABORT; \
} \
} else { \
j--; \
+ DVRELEASELOCK(mainao); \
ARRAYABORT; \
} \
} else if (status==STMCLEAN) { \
} \
if (addwrobject) { \
dirwrlocked[numoidwrlocked++] = objptr; \
- DUALVIEWWRAP(transao->___objstatus___ |=DIRTY;) \
- } \
+ } \
if (addrdobject) { \
oidrdlockedarray[numoidrdlockedarray++]=objptr; \
} \
} else
+
+#ifdef DUALVIEW
+#define QUICKCHECK { \
+ objheader_t * head=&((objheader_t *)mainao)[-1]; \
+ if (head->lock==RW_LOCK_BIAS&& \
+ ((objheader_t *)transao)[-1].version==head->version) \
+ continue; \
+ }
+#else
+#define QUICKCHECK
+#endif
+
#define READARRAYS \
for(i=0; i<numoidrdlockedarray; i++) { \
struct ArrayObject * transao=(struct ArrayObject *) oidrdlockedarray[i]; \
struct ArrayObject * mainao=(struct ArrayObject *) transao->___objlocation___; \
+ QUICKCHECK; \
DVCHECKLOCK(mainao); \
- int lowoffset=(transao->lowindex)>>INDEXSHIFT; \
- int highoffset=(transao->highindex)>>INDEXSHIFT; \
+ int lowoffset=(transao->lowindex); \
+ int highoffset=(transao->highindex); \
int j; \
for(j=lowoffset; j<=highoffset;j++) { \
unsigned int locallock;GETLOCKVAL(locallock,transao,j); \
#elif defined(STMARRAY)&&defined(DUALVIEW)
#define ARRAYLOCK \
if (((struct ___Object___ *)objptr)->type>=NUMCLASSES) { \
- if (!rwwrite_trylock(&header->lock)) { \
- ARRAYDELAYWRAP(dirwrindex[numoidwrtotal]=0;); \
+ if (likely(rwwrite_trylock(&header->lock))) { \
+ dirwrindex[numoidwrtotal]=0; \
dirwrlocked[numoidwrtotal++] = objptr; \
} else { \
chashlistnode_t *node = &c_table[(((unsigned INTPTR)objptr) & c_mask)>>4]; \
if(node->key == objptr) { \
objheader_t * headeraddr=&((objheader_t *) node->val)[-1]; \
if(STATUS(headeraddr) & DIRTY) { \
- if (rwconvert_trylock(&header->lock)) { \
- ARRAYDELAYWRAP(dirwrindex[numoidwrtotal]=1;); \
+ if (likely(rwconvert_trylock(&header->lock))) { \
+ dirwrindex[numoidwrtotal]=1; \
dirwrlocked[numoidwrtotal++] = objptr; \
goto nextloop; \
} \
} \
node = node->next; \
} while(node != NULL); \
- ABORT; \
+ ABORTREAD; \
} \
} else
#else
objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t)); //real object
unsigned int version = headeraddr->version;
- PROCESSARRAY;
-
if(STATUS(headeraddr) & DIRTY) {
+ PROCESSARRAY
/* Read from the main heap and compare versions */
if(likely(write_trylock(&header->lock))) { //can aquire write lock
if (likely(version == header->version)) { /* versions match */
while(likely(rd_curr != NULL)) {
//if the first bin in hash table is empty
unsigned int version=rd_curr->version;
- objheader_t *header=(objheader_t *)(((char *)rd_curr->key)-sizeof(objheader_t));
- if(header->lock>0) { //object is not locked
- if (version!=header->version) {
+ struct ___Object___ * objptr=rd_curr->key;
+ objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t));
+#ifdef STMARRAY
+ int isobject=objptr->type<NUMCLASSES;
+ if(likely((isobject&&header->lock>0)||(!isobject&&header->lock==RW_LOCK_BIAS))) {
+#else
+ if(header->lock>0) {
+#endif
+ //object is not locked
+ if (unlikely(version!=header->version)) {
//have to abort
transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
STMWRAP((typesCausingAbort[TYPE(header)])++;);
if (softabort)
return TRANS_SOFT_ABORT;
else
- return TRANS_ABORT;
+ return TRANS_ABORT;
}
} else {
//maybe we already have lock
- if (version==header->version) {
+ if (likely(version==header->version)) {
void * key=rd_curr->key;
#ifdef DELAYCOMP
//check to see if it is in the delaycomp table
{
dchashlistnode_t *node = &dc_c_table[(((unsigned INTPTR)key) & dc_c_mask)>>4];
do {
- if(node->key == key)
+ if(node->key == key) {
goto nextloopread;
+ }
node = node->next;
} while(node != NULL);
}
#endif
//check normal table
+#ifdef STMARRAY
+ if (likely(isobject||header->lock==(RW_LOCK_BIAS-1))) {
+#else
{
+#endif
chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
do {
if(node->key == key) {
objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t));
unsigned int version = headeraddr->version;
- PROCESSARRAY;
-
if(STATUS(headeraddr) & DIRTY) {
+ PROCESSARRAY
/* Read from the main heap and compare versions */
if(likely(write_trylock(&header->lock))) { //can aquire write lock
if (likely(version == header->version)) { /* versions match */
for(i=0; i<numoidrdlocked; i++) {
objheader_t * header=oidrdlocked[i];
unsigned int version=oidrdversion[i];
- if(header->lock>0) {
+ if(likely(header->lock>0)) {
CFENCE;
- if(version != header->version) {
+ if(unlikely(version != header->version)) {
transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
ABORTSTAT2;
freearrays;
while(likely(rd_curr != NULL)) {
//if the first bin in hash table is empty
int version=rd_curr->version;
- objheader_t *header=(objheader_t *)(((char *)rd_curr->key)-sizeof(objheader_t));
- if(header->lock>0) { //object is not locked
- if (version!=header->version) {
+ struct ___Object___ * objptr=rd_curr->key;
+ objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t));
+#ifdef STMARRAY
+ int isobject=objptr->type<NUMCLASSES;
+ if(likely((isobject&&header->lock>0)||(!isobject&&header->lock==RW_LOCK_BIAS))) {
+#else
+ if(likely(header->lock>0)) { //object is not locked
+#endif
+ if (unlikely(version!=header->version)) {
//have to abort
transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
STMWRAP((typesCausingAbort[TYPE(header)])++;);
}
#endif
//check normal table
- {
+#ifdef STMARRAY
+ if (likely(isobject||header->lock==(RW_LOCK_BIAS-1))) {
+#else
+ {
+#endif
chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
do {
if(node->key == key) {
if (type>=NUMCLASSES) {
//have array, do unlocking of bins
struct ArrayObject *src=(struct ArrayObject *)t_chashSearch(dst);
- int lowoffset=(src->lowindex)>>INDEXSHIFT;
- int highoffset=(src->highindex)>>INDEXSHIFT;
+ int lowoffset=(src->lowindex);
+ int highoffset=(src->highindex);
int j;
int addwrobject=0, addrdobject=0;
for(j=lowoffset; j<=highoffset;j++) {
int type=dst->type;
if (type>=NUMCLASSES) {
//have array, do copying of bins
- int lowoffset=(((struct ArrayObject *)src)->lowindex)>>INDEXSHIFT;
- int highoffset=(((struct ArrayObject *)src)->highindex)>>INDEXSHIFT;
+ int lowoffset=(((struct ArrayObject *)src)->lowindex);
+ int highoffset=(((struct ArrayObject *)src)->highindex);
int j;
int addwrobject=0, addrdobject=0;
int elementsize=classsize[type];
if (type>=NUMCLASSES) {
//have array, do unlocking of bins
struct ArrayObject *src=(struct ArrayObject *)t_chashSearch(dst);
- int lowoffset=(src->lowindex)>>INDEXSHIFT;
- int highoffset=(src->highindex)>>INDEXSHIFT;
+ int lowoffset=(src->lowindex);
+ int highoffset=(src->highindex);
int j;
int addwrobject=0, addrdobject=0;
for(j=lowoffset; j<=highoffset;j++) {
write_unlock(intptr);
}
}
+ atomic_inc(&header->version);
#ifdef DUALVIEW
rwread_unlock(&header->lock);
#endif
int wrlock=dirwrindex[i];
header = &((objheader_t *)dst)[-1];
if (wrlock==-1) {
- //problem...what if we are double locked
header->version++;
write_unlock(&header->lock);
} else if (wrlock==0) {
+ header->version++;
rwwrite_unlock(&header->lock);
} else {
- //normal object
+ header->version++;
rwconvert_unlock(&header->lock);
}
}
} else {
//array element
unsigned int *intptr;
+ atomic_inc(&header->version);
GETVERSIONPTR(intptr, ((struct ArrayObject *)dst), wrindex);
(*intptr)++;
GETLOCKPTR(intptr, ((struct ArrayObject *)dst), wrindex);
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
+ // 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 {
int baseoffset=byteindex&HIGHMASK;
unsigned int mainversion;
int baseindex=baseoffset>>INDEXSHIFT;
+ if (oid->lowindex>baseindex) {
+ unsigned int * ptr;
+ if (oid->lowindex==MAXARRAYSIZE) {
+ GETLOCKPTR(ptr, oid, baseindex);
+ bzero(ptr, sizeof(int)*2);
+ } else {
+ GETLOCKPTR(ptr, oid, oid->lowindex-1);
+ int length=oid->lowindex-baseindex;
+ bzero(ptr, sizeof(int)*2*length);
+ }
+ oid->lowindex=baseindex;
+ }
+ if (oid->highindex<baseindex) {
+ unsigned int * ptr;
+ if (oid->highindex==-1) {
+ GETLOCKPTR(ptr, oid, baseindex);
+ bzero(ptr, 2*sizeof(int));
+ } else {
+ GETLOCKPTR(ptr, oid, baseindex);
+ bzero(ptr, 2*sizeof(int)*(baseindex-oid->highindex));
+ }
+ oid->highindex=baseindex;
+ }
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