19 #define STATFREE free(oidrdage);
20 #define STATALLOC oidrdage=malloc(size);
21 #define STATASSIGN oidrdage=rdage;
28 #if defined(STMARRAY)&&defined(DELAYCOMP)
29 #define ARRAYDELAYWRAP(x) x
30 #define ARRAYDELAYWRAP1(x) ,x
32 #define ARRAYDELAYWRAP(x)
33 #define ARRAYDELAYWRAP1(x)
37 #define DUALVIEWWRAP(x) x
39 #define DUALVIEWWRAP(x)
42 /* ================================================================
44 * - This function initiates the transaction commit process
45 * - goes through the transaction cache and decides
47 * ================================================================
51 int transCommit(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
58 TRANSWRAP(numTransCommit++;);
61 /* Look through all the objects in the transaction hash table */
64 if (c_numelements<(c_size>>3))
65 finalResponse=alttraverseCache(commitmethod, primitives, locals, params);
67 finalResponse=traverseCache(commitmethod, primitives, locals, params);
69 if (c_numelements<(c_size>>3))
70 finalResponse=alttraverseCache();
72 finalResponse=traverseCache();
74 if(finalResponse == TRANS_ABORT) {
75 TRANSWRAP(numTransAbort++;if (softaborted) nSoftAbortAbort++;);
77 STMWRAP(freelockedobjs(););
88 #if defined(STMARRAY)&&!defined(DUALVIEW)
98 if(finalResponse == TRANS_COMMIT) {
99 TRANSWRAP(numTransCommit++;if (softaborted) nSoftAbortCommit++;);
101 STMWRAP(freelockedobjs(););
112 #if defined(STMARRAY)&&!defined(DUALVIEW)
119 /* wait a random amount of time before retrying to commit transaction*/
120 if(finalResponse == TRANS_SOFT_ABORT) {
121 TRANSWRAP(nSoftAbort++;);
128 //retry if too many soft aborts
130 STMWRAP(freelockedobjs(););
141 #if defined(STMARRAY)&&!defined(DUALVIEW)
148 printf("Error: in %s() Unknown outcome", __func__);
155 #define freearrays if (c_numelements>=200) { \
159 free(oidrdversion); \
161 if (t_numelements>=200) { \
166 #define freearrays if (c_numelements>=200) { \
170 free(oidrdversion); \
176 #define allocarrays int t_numelements=c_numelements+dc_c_numelements; \
177 if (t_numelements<200) { \
178 oidwrlocked=(struct garbagelist *) &wrlocked; \
179 STMARRAYDELAYASSIGN; \
181 oidwrlocked=malloc(2*sizeof(INTPTR)+t_numelements*(sizeof(void *))); \
182 STMARRAYDELAYALLOC; \
184 if (c_numelements<200) { \
185 oidrdlocked=rdlocked; \
186 oidrdversion=rdversion; \
190 int size=c_numelements*sizeof(void*); \
191 oidrdlocked=malloc(size); \
192 oidrdversion=malloc(size); \
196 dirwrlocked=oidwrlocked->array;
198 #define allocarrays if (c_numelements<200) { \
199 oidrdlocked=rdlocked; \
200 oidrdversion=rdversion; \
201 oidwrlocked=(struct garbagelist *) &wrlocked; \
205 int size=c_numelements*sizeof(void*); \
206 oidrdlocked=malloc(size); \
207 oidrdversion=malloc(size); \
208 oidwrlocked=malloc(size+2*sizeof(INTPTR)); \
212 dirwrlocked=oidwrlocked->array;
216 #define ABORTSTAT1 header->abortCount++; \
217 ObjSeqId = headeraddr->accessCount; \
218 (typesCausingAbort[TYPE(header)]).numabort++; \
219 (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements; \
220 (typesCausingAbort[TYPE(header)]).numtrans+=1; \
221 objtypetraverse[TYPE(header)]=1; \
222 if(getTotalAbortCount(i+1, size, (void *)(curr->next), numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse)) \
225 ObjSeqId = oidrdage[i]; \
226 header->abortCount++; \
227 (typesCausingAbort[TYPE(header)]).numabort++; \
228 (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements; \
229 (typesCausingAbort[TYPE(header)]).numtrans+=1; \
230 objtypetraverse[TYPE(header)]=1; \
231 if (getReadAbortCount(i+1, numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse)) \
234 header->abortCount++; \
235 ObjSeqId = headeraddr->accessCount; \
236 (typesCausingAbort[TYPE(header)]).numabort++; \
237 (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements; \
238 (typesCausingAbort[TYPE(header)]).numtrans+=1; \
239 objtypetraverse[TYPE(header)]=1; \
240 if (getTotalAbortCount2((void *) curr->next, numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse)) \
242 #define ABORTSTAT4 ObjSeqId = oidrdage[i]; \
243 header->abortCount++; \
244 getReadAbortCount(i+1, numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse);
253 #define DELAYWRAP(x) x
254 #define NUMWRTOTAL numoidwrtotal
257 #define NUMWRTOTAL numoidwrlocked
260 #if defined(STMARRAY)
261 #define STMARRAYFREE free(oidrdlockedarray);
262 #define STMARRAYALLOC oidrdlockedarray=malloc(size);
263 #define STMARRAYASSIGN oidrdlockedarray=rdlockedarray;
265 //allocation statements for dirwrindex
266 #define STMARRAYDELAYFREE free(dirwrindex);
267 #define STMARRAYDELAYALLOC dirwrindex=malloc(t_numelements*sizeof(int));
268 #define STMARRAYDELAYASSIGN dirwrindex=wrindex;
270 #define ARRAYDEFINES int numoidrdlockedarray=0; \
271 void * rdlockedarray[200]; \
272 void ** oidrdlockedarray;
275 transAbortProcess(oidwrlocked, numoidwrlocked ARRAYDELAYWRAP1(NULL) ARRAYDELAYWRAP1(numoidwrlocked)); \
278 return TRANS_SOFT_ABORT; \
283 transAbortProcess(oidwrlocked, numoidwrtotal ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked)); \
286 return TRANS_SOFT_ABORT; \
292 for(;j>=lowoffset;j--) { \
293 GETLOCKVAL(status, transao, j); \
294 if (status==STMDIRTY) { \
295 GETLOCKPTR(lockptr, mainao,j); \
296 write_unlock(lockptr); \
302 #define DVGETLOCK(x) if (!addwrobject) { \
303 unsigned int * objlock=&(&((objheader_t *)x)[-1])->lock; \
304 if(!rwread_trylock(objlock)) { \
309 #define DVRELEASELOCK(x) { \
310 unsigned int * objlock=&(&((objheader_t *)x)[-1])->lock; \
311 rwread_unlock(objlock); \
314 //not finished...if we can't get the lock, it is okay if it is in our access set
315 #define DVCHECKLOCK(x) \
316 unsigned int * objlock=&(&((objheader_t *)x)[-1])->lock; \
318 if (dc_t_chashSearch(x)==NULL) { \
324 #define DVCHECKLOCK(x)
325 #define DVRELEASELOCK(x)
328 #if defined(DELAYCOMP)&&!defined(DUALVIEW)
330 else if (dc_t_chashSearchArray(mainao,j)) { \
332 unsigned int localversion; \
333 unsigned int remoteversion; \
334 GETVERSIONVAL(localversion, transao, j); \
335 GETVERSIONVAL(remoteversion, mainao, j); \
336 if (localversion != remoteversion) { \
337 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked)); \
339 return TRANS_ABORT; \
346 #define PROCESSARRAY \
347 int type=((int *)cachedobj)[0]; \
348 if (type>=NUMCLASSES) { \
349 struct ArrayObject *transao=(struct ArrayObject *) cachedobj; \
350 struct ArrayObject *mainao=(struct ArrayObject *) objptr; \
351 int lowoffset=(transao->lowindex); \
352 int highoffset=(transao->highindex); \
354 int addwrobject=0, addrdobject=0; \
355 for(j=lowoffset; j<=highoffset;j++) { \
356 unsigned int status; \
357 GETLOCKVAL(status, transao, j); \
358 if (status==STMDIRTY) { \
360 unsigned int * lockptr; \
361 GETLOCKPTR(lockptr, mainao,j); \
362 if (likely(write_trylock(lockptr))) { \
363 unsigned int localversion; \
364 unsigned int remoteversion; \
365 GETVERSIONVAL(localversion, transao, j); \
366 GETVERSIONVAL(remoteversion, mainao, j); \
367 if (likely(localversion == remoteversion)) { \
370 DVRELEASELOCK(mainao); \
375 DVRELEASELOCK(mainao); \
378 } else if (status==STMCLEAN) { \
383 dirwrlocked[numoidwrlocked++] = objptr; \
386 oidrdlockedarray[numoidrdlockedarray++]=objptr; \
392 #define QUICKCHECK { \
393 objheader_t * head=&((objheader_t *)mainao)[-1]; \
394 if (head->lock==RW_LOCK_BIAS&& \
395 ((objheader_t *)transao)[-1].version==head->version) \
403 for(i=0; i<numoidrdlockedarray; i++) { \
404 struct ArrayObject * transao=(struct ArrayObject *) oidrdlockedarray[i]; \
405 struct ArrayObject * mainao=(struct ArrayObject *) transao->___objlocation___; \
407 DVCHECKLOCK(mainao); \
408 int lowoffset=(transao->lowindex); \
409 int highoffset=(transao->highindex); \
411 for(j=lowoffset; j<=highoffset;j++) { \
412 unsigned int locallock;GETLOCKVAL(locallock,transao,j); \
413 if (locallock==STMCLEAN) { \
414 /* do read check */ \
415 unsigned int mainlock; GETLOCKVAL(mainlock, mainao, j); \
418 unsigned int localversion; \
419 unsigned int remoteversion; \
420 GETVERSIONVAL(localversion, transao, j); \
421 GETVERSIONVAL(remoteversion, mainao, j); \
422 if (localversion != remoteversion) { \
423 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked)); \
425 return TRANS_ABORT; \
430 unsigned int localversion; \
431 unsigned int remoteversion; \
432 GETVERSIONVAL(localversion, transao, j); \
433 GETVERSIONVAL(remoteversion, mainao, j); \
434 if (localversion==remoteversion) \
436 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked)); \
439 return TRANS_SOFT_ABORT; \
441 return TRANS_ABORT; \
451 #define STMARRAYALLOC
452 #define STMARRAYASSIGN
453 #define STMARRAYDELAYFREE
454 #define STMARRAYDELAYALLOC
455 #define STMARRAYDELAYASSIGN
459 #if defined(STMARRAY)&&!defined(DUALVIEW)
461 int intkey=dc_curr->intkey; \
463 unsigned int *lockptr; \
464 GETLOCKPTR(lockptr, objptr, intkey); \
465 if (likely(write_trylock(lockptr))) { \
466 /*have lock on element */ \
467 dirwrlocked[numoidwrtotal]=objptr; \
468 dirwrindex[numoidwrtotal++]=intkey; \
470 unsigned int lockval; \
471 GETLOCKVAL(lockval, valptr, intkey); \
472 if (lockval!=STMDIRTY) { \
473 /*have to abort to avoid deadlock*/ \
474 transAbortProcess(oidwrlocked, numoidwrtotal, dirwrindex, numoidwrlocked); \
478 return TRANS_SOFT_ABORT; \
480 return TRANS_ABORT; \
485 #elif defined(STMARRAY)&&defined(DUALVIEW)
487 if (((struct ___Object___ *)objptr)->type>=NUMCLASSES) { \
488 if (likely(rwwrite_trylock(&header->lock))) { \
489 dirwrindex[numoidwrtotal]=0; \
490 dirwrlocked[numoidwrtotal++] = objptr; \
492 chashlistnode_t *node = &c_table[(((unsigned INTPTR)objptr) & c_mask)>>4]; \
494 if(node->key == objptr) { \
495 objheader_t * headeraddr=&((objheader_t *) node->val)[-1]; \
496 if(STATUS(headeraddr) & DIRTY) { \
497 if (likely(rwconvert_trylock(&header->lock))) { \
498 dirwrindex[numoidwrtotal]=1; \
499 dirwrlocked[numoidwrtotal++] = objptr; \
506 } while(node != NULL); \
515 #define ACCESSLOCKS \
516 unsigned int numoidwrtotal=numoidwrlocked; \
517 dchashlistnode_t *dc_curr = dc_c_list; \
518 /* Inner loop to traverse the linked list of the cache lookupTable */ \
519 while(likely(dc_curr != NULL)) { \
520 /*if the first bin in hash table is empty */ \
521 void *valptr=dc_curr->val; \
522 objheader_t * headeraddr=&((objheader_t *) valptr)[-1]; \
523 void *objptr=dc_curr->key; \
524 objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t)); \
526 if(likely(write_trylock(&header->lock))) { /*can aquire write lock*/ \
527 ARRAYDELAYWRAP(dirwrindex[numoidwrtotal]=-1;) \
528 dirwrlocked[numoidwrtotal++] = objptr; \
530 /* maybe we already have lock*/ \
531 chashlistnode_t *node = &c_table[(((unsigned INTPTR)objptr) & c_mask)>>4]; \
534 if(node->key == objptr) { \
535 objheader_t * headeraddr=&((objheader_t *) node->val)[-1]; \
536 if(STATUS(headeraddr) & DIRTY) { \
542 } while(node != NULL); \
544 /*have to abort to avoid deadlock */ \
545 transAbortProcess(oidwrlocked, numoidwrtotal ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked)); \
549 return TRANS_SOFT_ABORT; \
551 return TRANS_ABORT; \
554 dc_curr = dc_curr->lnext; \
560 /* ==================================================
562 * - goes through the transaction cache and
563 * - decides if a transaction should commit or abort
564 * ==================================================
568 int traverseCache(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
570 int traverseCache() {
572 /* Create info to keep track of objects that can be locked */
573 int numoidrdlocked=0;
574 int numoidwrlocked=0;
575 void * rdlocked[200];
577 struct fixedlist wrlocked;
583 STMWRAP(int rdage[200];int * oidrdage;int ObjSeqId;int objtypetraverse[TOTALNUMCLASSANDARRAY];);
584 struct garbagelist * oidwrlocked;
586 #if defined(STMARRAY)&&defined(DELAYCOMP)
592 STMWRAP(for(i=0; i<TOTALNUMCLASSANDARRAY; i++) objtypetraverse[i] = 0;);
594 chashlistnode_t *ptr = c_table;
595 /* Represents number of bins in the chash table */
596 unsigned int size = c_size;
597 for(i = 0; i<size; i++) {
598 chashlistnode_t *curr = &ptr[i];
599 /* Inner loop to traverse the linked list of the cache lookupTable */
600 while(curr != NULL) {
601 //if the first bin in hash table is empty
602 if(curr->key == NULL)
604 objheader_t * cachedobj=curr->val;
605 objheader_t * headeraddr=&((objheader_t *) cachedobj)[-1]; //cached object
606 void * objptr=curr->key;
607 objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t)); //real object
608 unsigned int version = headeraddr->version;
610 if(STATUS(headeraddr) & DIRTY) {
612 /* Read from the main heap and compare versions */
613 if(likely(write_trylock(&header->lock))) { //can aquire write lock
614 if (likely(version == header->version)) { /* versions match */
615 /* Keep track of objects locked */
616 dirwrlocked[numoidwrlocked++] = objptr;
618 dirwrlocked[numoidwrlocked++] = objptr;
619 transAbortProcess(oidwrlocked, numoidwrlocked ARRAYDELAYWRAP1(NULL) ARRAYDELAYWRAP1(numoidwrlocked));
623 return TRANS_SOFT_ABORT;
628 if(version == header->version) {
632 transAbortProcess(oidwrlocked, numoidwrlocked ARRAYDELAYWRAP1(NULL) ARRAYDELAYWRAP1(numoidwrlocked));
636 return TRANS_SOFT_ABORT;
642 STMWRAP(oidrdage[numoidrdlocked]=headeraddr->accessCount;);
643 oidrdversion[numoidrdlocked]=version;
644 oidrdlocked[numoidrdlocked++]=header;
652 //THIS IS THE SERIALIZATION END POINT (START POINT IS END OF EXECUTION)*****
655 for(i=0; i<numoidrdlocked; i++) {
656 /* Read from the main heap and compare versions */
657 objheader_t *header=oidrdlocked[i];
658 unsigned int version=oidrdversion[i];
659 if(header->lock>0) { //not write locked
661 if(version != header->version) { /* versions do not match */
662 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
668 } else if (dc_t_chashSearch(((char *)header)+sizeof(objheader_t))!=NULL) {
669 //couldn't get lock because we already have it
670 //check if it is the right version number
671 if (version!=header->version) {
672 transAbortProcess(oidwrlocked, numoidwrtotal ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
678 } else { /* cannot aquire lock */
679 //do increment as we didn't get lock
680 if(version == header->version) {
683 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
687 return TRANS_SOFT_ABORT;
694 //need to validate auxilary readset
695 rdchashlistnode_t *rd_curr = rd_c_list;
696 /* Inner loop to traverse the linked list of the cache lookupTable */
697 while(likely(rd_curr != NULL)) {
698 //if the first bin in hash table is empty
699 unsigned int version=rd_curr->version;
700 struct ___Object___ * objptr=rd_curr->key;
701 objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t));
703 int isobject=objptr->type<NUMCLASSES;
704 if(likely((isobject&&header->lock>0)||(!isobject&&header->lock==RW_LOCK_BIAS))) {
708 //object is not locked
709 if (unlikely(version!=header->version)) {
711 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
712 STMWRAP((typesCausingAbort[TYPE(header)])++;);
715 return TRANS_SOFT_ABORT;
720 //maybe we already have lock
721 if (likely(version==header->version)) {
722 void * key=rd_curr->key;
724 //check to see if it is in the delaycomp table
726 dchashlistnode_t *node = &dc_c_table[(((unsigned INTPTR)key) & dc_c_mask)>>4];
728 if(node->key == key) {
732 } while(node != NULL);
737 if (likely(isobject||header->lock==(RW_LOCK_BIAS-1))) {
741 chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
743 if(node->key == key) {
744 objheader_t * headeraddr=&((objheader_t *) node->val)[-1];
745 if(STATUS(headeraddr) & DIRTY) {
750 } while(node != NULL);
753 //have to abort to avoid deadlock
754 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
755 STMWRAP((typesCausingAbort[TYPE(header)])++;);
758 return TRANS_SOFT_ABORT;
763 rd_curr = rd_curr->lnext;
767 /* Decide the final response */
769 transCommitProcess(oidwrlocked ARRAYDELAYWRAP1(dirwrindex), numoidwrlocked, numoidwrtotal, commitmethod, primitives, locals, params);
771 transCommitProcess(oidwrlocked, numoidwrlocked);
777 /* ==================================================
779 * - goes through the transaction cache and
780 * - decides if a transaction should commit or abort
781 * ==================================================
785 int alttraverseCache(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
787 int alttraverseCache() {
789 /* Create info to keep track of objects that can be locked */
790 int numoidrdlocked=0;
791 int numoidwrlocked=0;
792 void * rdlocked[200];
794 struct fixedlist wrlocked;
799 STMWRAP(int rdage[200];int * oidrdage;int ObjSeqId;int objtypetraverse[TOTALNUMCLASSANDARRAY];);
801 struct garbagelist * oidwrlocked;
803 #if defined(STMARRAY)&&defined(DELAYCOMP)
809 STMWRAP(for(i=0; i<TOTALNUMCLASSANDARRAY; i++) objtypetraverse[i] = 0;);
811 chashlistnode_t *curr = c_list;
812 /* Inner loop to traverse the linked list of the cache lookupTable */
813 while(likely(curr != NULL)) {
814 //if the first bin in hash table is empty
815 objheader_t * cachedobj=curr->val;
816 objheader_t * headeraddr=&((objheader_t *) cachedobj)[-1];
817 void *objptr=curr->key;
818 objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t));
819 unsigned int version = headeraddr->version;
821 if(STATUS(headeraddr) & DIRTY) {
823 /* Read from the main heap and compare versions */
824 if(likely(write_trylock(&header->lock))) { //can aquire write lock
825 if (likely(version == header->version)) { /* versions match */
826 /* Keep track of objects locked */
827 dirwrlocked[numoidwrlocked++] = objptr;
829 dirwrlocked[numoidwrlocked++] = objptr;
830 transAbortProcess(oidwrlocked, numoidwrlocked ARRAYDELAYWRAP1(NULL) ARRAYDELAYWRAP1(numoidwrlocked));
835 } else { /* cannot aquire lock */
836 if(version == header->version) {
840 transAbortProcess(oidwrlocked, numoidwrlocked ARRAYDELAYWRAP1(NULL) ARRAYDELAYWRAP1(numoidwrlocked));
844 return TRANS_SOFT_ABORT;
849 /* Read from the main heap and compare versions */
850 oidrdversion[numoidrdlocked]=version;
851 oidrdlocked[numoidrdlocked++] = header;
858 //THIS IS THE SERIALIZATION END POINT (START POINT IS END OF EXECUTION)*****
861 for(i=0; i<numoidrdlocked; i++) {
862 objheader_t * header=oidrdlocked[i];
863 unsigned int version=oidrdversion[i];
864 if(likely(header->lock>0)) {
866 if(unlikely(version != header->version)) {
867 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
873 } else if (dc_t_chashSearch(((char *)header)+sizeof(objheader_t))!=NULL) {
874 //couldn't get lock because we already have it
875 //check if it is the right version number
876 if (version!=header->version) {
877 transAbortProcess(oidwrlocked, numoidwrtotal ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
883 } else { /* cannot aquire lock */
884 if(version == header->version) {
887 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
891 return TRANS_SOFT_ABORT;
898 //need to validate auxilary readset
899 rdchashlistnode_t *rd_curr = rd_c_list;
900 /* Inner loop to traverse the linked list of the cache lookupTable */
901 while(likely(rd_curr != NULL)) {
902 //if the first bin in hash table is empty
903 int version=rd_curr->version;
904 struct ___Object___ * objptr=rd_curr->key;
905 objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t));
907 int isobject=objptr->type<NUMCLASSES;
908 if(likely((isobject&&header->lock>0)||(!isobject&&header->lock==RW_LOCK_BIAS))) {
910 if(likely(header->lock>0)) { //object is not locked
912 if (unlikely(version!=header->version)) {
914 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
915 STMWRAP((typesCausingAbort[TYPE(header)])++;);
918 return TRANS_SOFT_ABORT;
923 if (version==header->version) {
924 void * key=rd_curr->key;
926 //check to see if it is in the delaycomp table
928 dchashlistnode_t *node = &dc_c_table[(((unsigned INTPTR)key) & dc_c_mask)>>4];
933 } while(node != NULL);
938 if (likely(isobject||header->lock==(RW_LOCK_BIAS-1))) {
942 chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
944 if(node->key == key) {
945 objheader_t * headeraddr=&((objheader_t *) node->val)[-1];
946 if(STATUS(headeraddr) & DIRTY) {
951 } while(node != NULL);
954 //have to abort to avoid deadlock
955 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
956 STMWRAP((typesCausingAbort[TYPE(header)])++;);
959 return TRANS_SOFT_ABORT;
964 rd_curr = rd_curr->lnext;
968 /* Decide the final response */
970 transCommitProcess(oidwrlocked ARRAYDELAYWRAP1(dirwrindex), numoidwrlocked, numoidwrtotal, commitmethod, primitives, locals, params);
972 transCommitProcess(oidwrlocked, numoidwrlocked);
978 /* ==================================
981 * =================================
986 #if defined(STMARRAY)&&defined(DELAYCOMP)
987 void transAbortProcess(struct garbagelist *oidwrlocked, int numoidwrtotal, int * dirwrindex, int numoidwrlocked) {
989 void transAbortProcess(struct garbagelist *oidwrlocked, int numoidwrlocked) {
993 /* Release read locks */
994 void ** dirwrlocked=oidwrlocked->array;
995 /* Release write locks */
996 for(i=numoidwrlocked-1; i>=0; i--) {
997 /* Read from the main heap */
998 struct ___Object___ * dst=dirwrlocked[i];
999 header = &((objheader_t *)dst)[-1];
1002 if (type>=NUMCLASSES) {
1003 //have array, do unlocking of bins
1004 struct ArrayObject *src=(struct ArrayObject *)t_chashSearch(dst);
1005 int lowoffset=(src->lowindex);
1006 int highoffset=(src->highindex);
1008 int addwrobject=0, addrdobject=0;
1009 for(j=lowoffset; j<=highoffset;j++) {
1010 unsigned int status;
1011 GETLOCKVAL(status, src, j);
1012 if (status==STMDIRTY) {
1013 unsigned int *lockptr;
1014 GETLOCKPTR(lockptr, ((struct ArrayObject *)dst), j);
1015 write_unlock(lockptr);
1019 //release object array lock
1020 rwread_unlock(&header->lock);
1024 write_unlock(&header->lock);
1026 #if defined(STMARRAY)&&defined(DELAYCOMP)&&!defined(DUALVIEW)
1027 //release access locks
1028 for(i=numoidwrtotal-1; i>=numoidwrlocked; i--) {
1029 struct ___Object___ * dst=dirwrlocked[i];
1030 header = &((objheader_t *)dst)[-1];
1031 int wrindex=dirwrindex[i];
1034 write_unlock(&header->lock);
1037 unsigned int *intptr;
1038 GETLOCKPTR(intptr, ((struct ArrayObject *)dst), wrindex);
1039 write_unlock(intptr);
1043 #if defined(STMARRAY)&&defined(DELAYCOMP)&&defined(DUALVIEW)
1044 //release access locks
1045 for(i=numoidwrtotal-1; i>=numoidwrlocked; i--) {
1046 struct ___Object___ * dst=dirwrlocked[i];
1047 header = &((objheader_t *)dst)[-1];
1048 int wrindex=dirwrindex[i];
1051 write_unlock(&header->lock);
1052 } else if (wrindex==0) {
1054 rwwrite_unlock(&header->lock);
1056 rwconvert_unlock(&header->lock);
1061 /* clear trec and then release objects locked */
1062 struct objlist *ptr=lockedobjs;
1064 int max=ptr->offset;
1065 for(i=max-1; i>=0; i--) {
1066 header = (objheader_t *)ptr->objs[i];
1067 header->trec = NULL;
1068 pthread_mutex_unlock(header->objlock);
1075 /* ==================================
1076 * transCommitProcess
1078 * =================================
1081 void transCommitProcess(struct garbagelist * oidwrlocked ARRAYDELAYWRAP1(int * dirwrindex), int numoidwrlocked, int numoidwrtotal, void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
1083 void transCommitProcess(struct garbagelist * oidwrlocked, int numoidwrlocked) {
1085 objheader_t *header;
1088 struct objlist *ptr=newobjs;
1089 void **dirwrlocked=oidwrlocked->array;
1091 int max=ptr->offset;
1092 for(i=0; i<max; i++) {
1093 //clear the new flag
1094 ((struct ___Object___ *)ptr->objs[i])->___objstatus___=0;
1099 /* Copy from transaction cache -> main object store */
1100 for (i = numoidwrlocked-1; i >=0; i--) {
1101 /* Read from the main heap */
1102 header = &((objheader_t *)dirwrlocked[i])[-1];
1104 GETSIZE(tmpsize, header);
1105 struct ___Object___ *dst=(struct ___Object___*)dirwrlocked[i];
1106 struct ___Object___ *src=t_chashSearch(dst);
1107 dst->___cachedCode___=src->___cachedCode___;
1108 dst->___cachedHash___=src->___cachedHash___;
1111 if (type>=NUMCLASSES) {
1112 //have array, do copying of bins
1113 int lowoffset=(((struct ArrayObject *)src)->lowindex);
1114 int highoffset=(((struct ArrayObject *)src)->highindex);
1116 int addwrobject=0, addrdobject=0;
1117 int elementsize=classsize[type];
1118 int baseoffset=(lowoffset<<INDEXSHIFT)+sizeof(int)+((int)&(((struct ArrayObject *)0)->___length___));
1119 char *dstptr=((char *)dst)+baseoffset;
1120 char *srcptr=((char *)src)+baseoffset;
1121 for(j=lowoffset; j<=highoffset;j++, srcptr+=INDEXLENGTH,dstptr+=INDEXLENGTH) {
1122 unsigned int status;
1123 GETLOCKVAL(status, ((struct ArrayObject *)src), j);
1124 if (status==STMDIRTY) {
1125 A_memcpy(dstptr, srcptr, INDEXLENGTH);
1130 A_memcpy(&dst[1], &src[1], tmpsize-sizeof(struct ___Object___));
1135 // call commit method
1136 ptrstack.maxcount=0;
1138 branchstack.count=0;
1139 #if defined(STMARRAY)&&!defined(DUALVIEW)
1140 arraystack.maxcount=0;
1142 //splice oidwrlocked in
1143 oidwrlocked->size=numoidwrtotal;
1144 oidwrlocked->next=params;
1145 ((struct garbagelist *)locals)->next=oidwrlocked;
1146 if (commitmethod!=NULL)
1147 commitmethod(params, locals, primitives);
1148 ((struct garbagelist *)locals)->next=params;
1151 /* Release write locks */
1152 #if defined(STMARRAY)&&defined(DELAYCOMP)
1153 for(i=numoidwrlocked-1; i>=0; i--) {
1155 for(i=NUMWRTOTAL-1; i>=0; i--) {
1157 struct ___Object___ * dst=dirwrlocked[i];
1158 header = &((objheader_t *)dst)[-1];
1161 if (type>=NUMCLASSES) {
1162 //have array, do unlocking of bins
1163 struct ArrayObject *src=(struct ArrayObject *)t_chashSearch(dst);
1164 int lowoffset=(src->lowindex);
1165 int highoffset=(src->highindex);
1167 int addwrobject=0, addrdobject=0;
1168 for(j=lowoffset; j<=highoffset;j++) {
1169 unsigned int status;
1170 GETLOCKVAL(status, src, j);
1171 if (status==STMDIRTY) {
1172 unsigned int *intptr;
1173 GETVERSIONPTR(intptr, ((struct ArrayObject *)dst), j);
1175 GETLOCKPTR(intptr, ((struct ArrayObject *)dst), j);
1176 write_unlock(intptr);
1179 atomic_inc(&header->version);
1181 rwread_unlock(&header->lock);
1187 write_unlock(&header->lock);
1190 #if defined(STMARRAY)&&defined(DELAYCOMP)&&defined(DUALVIEW)
1191 //release access locks
1192 for(i=numoidwrtotal-1; i>=numoidwrlocked; i--) {
1193 struct ___Object___ * dst=dirwrlocked[i];
1194 int wrlock=dirwrindex[i];
1195 header = &((objheader_t *)dst)[-1];
1198 write_unlock(&header->lock);
1199 } else if (wrlock==0) {
1201 rwwrite_unlock(&header->lock);
1204 rwconvert_unlock(&header->lock);
1208 #if defined(STMARRAY)&&defined(DELAYCOMP)&&!defined(DUALVIEW)
1209 //release access locks
1210 for(i=numoidwrtotal-1; i>=numoidwrlocked; i--) {
1211 struct ___Object___ * dst=dirwrlocked[i];
1212 header = &((objheader_t *)dst)[-1];
1213 int wrindex=dirwrindex[i];
1217 write_unlock(&header->lock);
1220 unsigned int *intptr;
1221 atomic_inc(&header->version);
1222 GETVERSIONPTR(intptr, ((struct ArrayObject *)dst), wrindex);
1224 GETLOCKPTR(intptr, ((struct ArrayObject *)dst), wrindex);
1225 write_unlock(intptr);
1230 /* clear trec and then release objects locked */
1233 int max=ptr->offset;
1234 for(i=max-1; i>=0; i--) {
1235 header = (objheader_t *)ptr->objs[i];
1236 header->trec = NULL;
1237 pthread_mutex_unlock(header->objlock);