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) {
60 /* Look through all the objects in the transaction hash table */
63 if (c_numelements<(c_size>>3))
64 finalResponse=alttraverseCache(commitmethod, primitives, locals, params);
66 finalResponse=traverseCache(commitmethod, primitives, locals, params);
68 if (c_numelements<(c_size>>3))
69 finalResponse=alttraverseCache();
71 finalResponse=traverseCache();
73 if(finalResponse == TRANS_ABORT) {
74 TRANSWRAP(numTransAbort++;if (softaborted) nSoftAbortAbort++;);
76 STMWRAP(freelockedobjs(););
87 #if defined(STMARRAY)&&!defined(DUALVIEW)
97 if(finalResponse == TRANS_COMMIT) {
98 TRANSWRAP(numTransCommit++;if (softaborted) nSoftAbortCommit++;);
100 STMWRAP(freelockedobjs(););
111 #if defined(STMARRAY)&&!defined(DUALVIEW)
118 /* wait a random amount of time before retrying to commit transaction*/
119 if(finalResponse == TRANS_SOFT_ABORT) {
120 TRANSWRAP(nSoftAbort++;);
127 //retry if too many soft aborts
129 STMWRAP(freelockedobjs(););
140 #if defined(STMARRAY)&&!defined(DUALVIEW)
147 printf("Error: in %s() Unknown outcome", __func__);
154 #define freearrays if (c_numelements>=200) { \
158 free(oidrdversion); \
160 if (t_numelements>=200) { \
165 #define freearrays if (c_numelements>=200) { \
169 free(oidrdversion); \
175 #define allocarrays int t_numelements=c_numelements+dc_c_numelements; \
176 if (t_numelements<200) { \
177 oidwrlocked=(struct garbagelist *) &wrlocked; \
178 STMARRAYDELAYASSIGN; \
180 oidwrlocked=malloc(2*sizeof(INTPTR)+t_numelements*(sizeof(void *))); \
181 STMARRAYDELAYALLOC; \
183 if (c_numelements<200) { \
184 oidrdlocked=rdlocked; \
185 oidrdversion=rdversion; \
189 int size=c_numelements*sizeof(void*); \
190 oidrdlocked=malloc(size); \
191 oidrdversion=malloc(size); \
195 dirwrlocked=oidwrlocked->array;
197 #define allocarrays if (c_numelements<200) { \
198 oidrdlocked=rdlocked; \
199 oidrdversion=rdversion; \
200 oidwrlocked=(struct garbagelist *) &wrlocked; \
204 int size=c_numelements*sizeof(void*); \
205 oidrdlocked=malloc(size); \
206 oidrdversion=malloc(size); \
207 oidwrlocked=malloc(size+2*sizeof(INTPTR)); \
211 dirwrlocked=oidwrlocked->array;
215 #define ABORTSTAT1 header->abortCount++; \
216 ObjSeqId = headeraddr->accessCount; \
217 (typesCausingAbort[TYPE(header)]).numabort++; \
218 (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements; \
219 (typesCausingAbort[TYPE(header)]).numtrans+=1; \
220 objtypetraverse[TYPE(header)]=1; \
221 if(getTotalAbortCount(i+1, size, (void *)(curr->next), numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse)) \
224 ObjSeqId = oidrdage[i]; \
225 header->abortCount++; \
226 (typesCausingAbort[TYPE(header)]).numabort++; \
227 (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements; \
228 (typesCausingAbort[TYPE(header)]).numtrans+=1; \
229 objtypetraverse[TYPE(header)]=1; \
230 if (getReadAbortCount(i+1, numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse)) \
233 header->abortCount++; \
234 ObjSeqId = headeraddr->accessCount; \
235 (typesCausingAbort[TYPE(header)]).numabort++; \
236 (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements; \
237 (typesCausingAbort[TYPE(header)]).numtrans+=1; \
238 objtypetraverse[TYPE(header)]=1; \
239 if (getTotalAbortCount2((void *) curr->next, numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse)) \
241 #define ABORTSTAT4 ObjSeqId = oidrdage[i]; \
242 header->abortCount++; \
243 getReadAbortCount(i+1, numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse);
252 #define DELAYWRAP(x) x
253 #define NUMWRTOTAL numoidwrtotal
256 #define NUMWRTOTAL numoidwrlocked
259 #if defined(STMARRAY)
260 #define STMARRAYFREE free(oidrdlockedarray);
261 #define STMARRAYALLOC oidrdlockedarray=malloc(size);
262 #define STMARRAYASSIGN oidrdlockedarray=rdlockedarray;
264 //allocation statements for dirwrindex
265 #define STMARRAYDELAYFREE free(dirwrindex);
266 #define STMARRAYDELAYALLOC dirwrindex=malloc(t_numelements*sizeof(int));
267 #define STMARRAYDELAYASSIGN dirwrindex=wrindex;
269 #define ARRAYDEFINES int numoidrdlockedarray=0; \
270 void * rdlockedarray[200]; \
271 void ** oidrdlockedarray;
274 transAbortProcess(oidwrlocked, numoidwrlocked ARRAYDELAYWRAP1(NULL) ARRAYDELAYWRAP1(numoidwrlocked)); \
277 return TRANS_SOFT_ABORT; \
282 transAbortProcess(oidwrlocked, numoidwrtotal ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked)); \
285 return TRANS_SOFT_ABORT; \
291 for(;j>=lowoffset;j--) { \
292 GETLOCKVAL(status, transao, j); \
293 if (status==STMDIRTY) { \
294 GETLOCKPTR(lockptr, mainao,j); \
295 write_unlock(lockptr); \
301 /* Try to grab object lock...If we get it, check object access
302 version and abort on mismatch */
304 #define DVGETLOCK if (!addwrobject) { \
305 unsigned int * objlock=&(&((objheader_t *)mainao)[-1])->lock; \
306 if(unlikely(!rwread_trylock(objlock))) { \
311 #define DVRELEASELOCK(x) { \
312 unsigned int * objlock=&(&((objheader_t *)x)[-1])->lock; \
313 rwread_unlock(objlock); \
316 /*not finished...if we can't get the lock, it is okay if it is in our
319 #define DVCHECKLOCK(x) \
320 unsigned int * objlock=&(&((objheader_t *)x)[-1])->lock; \
322 if (!dc_t_chashSearch(x)) { \
328 dirwrindex[numoidwrlocked]=-1;
333 #define DVCHECKLOCK(x)
334 #define DVRELEASELOCK(x)
338 #if defined(DELAYCOMP)&&!defined(DUALVIEW)
340 else if (dc_t_chashSearchArray(mainao,j)) { \
342 unsigned int localversion; \
343 unsigned int remoteversion; \
344 GETVERSIONVAL(localversion, transao, j); \
345 GETVERSIONVAL(remoteversion, mainao, j); \
346 if (localversion != remoteversion) { \
347 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked)); \
349 return TRANS_ABORT; \
356 /* This code checks arrays to try to lock them if dirty or check
357 later if they were only read. */
359 #define PROCESSARRAY \
360 int type=((int *)cachedobj)[0]; \
361 if (type>=NUMCLASSES) { \
362 struct ArrayObject *transao=(struct ArrayObject *) cachedobj; \
363 struct ArrayObject *mainao=(struct ArrayObject *) objptr; \
364 int lowoffset=(transao->lowindex); \
365 int highoffset=(transao->highindex); \
367 int addwrobject=0, addrdobject=0; \
368 for(j=lowoffset; j<=highoffset;j++) { \
369 unsigned int status; \
370 GETLOCKVAL(status, transao, j); \
371 if (status==STMDIRTY) { \
373 unsigned int * lockptr; \
374 GETLOCKPTR(lockptr, mainao,j); \
375 if (likely(write_trylock(lockptr))) { \
376 unsigned int localversion; \
377 unsigned int remoteversion; \
378 GETVERSIONVAL(localversion, transao, j); \
379 GETVERSIONVAL(remoteversion, mainao, j); \
380 if (likely(localversion == remoteversion)) { \
383 DVRELEASELOCK(mainao); \
388 DVRELEASELOCK(mainao); \
391 } else if (status==STMCLEAN) { \
397 dirwrlocked[numoidwrlocked++] = objptr; \
400 oidrdlockedarray[numoidrdlockedarray++]=objptr; \
405 /** This code allows us to skip the expensive checks in some cases */
408 #define QUICKCHECK { \
409 objheader_t * head=&((objheader_t *)mainao)[-1]; \
410 if (head->lock==RW_LOCK_BIAS&& \
411 ((objheader_t *)transao)[-1].version==head->version) \
415 if (transao->arrayversion!=mainao->arrayversion) { \
423 for(i=0; i<numoidrdlockedarray; i++) { \
424 struct ArrayObject * transao=(struct ArrayObject *) oidrdlockedarray[i]; \
425 struct ArrayObject * mainao=(struct ArrayObject *) transao->___objlocation___; \
428 DVCHECKLOCK(mainao); \
429 int lowoffset=(transao->lowindex); \
430 int highoffset=(transao->highindex); \
432 for(j=lowoffset; j<=highoffset;j++) { \
433 unsigned int locallock;GETLOCKVAL(locallock,transao,j); \
434 if (locallock==STMCLEAN) { \
435 /* do read check */ \
436 unsigned int mainlock; GETLOCKVAL(mainlock, mainao, j); \
439 unsigned int localversion; \
440 unsigned int remoteversion; \
441 GETVERSIONVAL(localversion, transao, j); \
442 GETVERSIONVAL(remoteversion, mainao, j); \
443 if (localversion != remoteversion) { \
444 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked)); \
446 return TRANS_ABORT; \
451 unsigned int localversion; \
452 unsigned int remoteversion; \
453 GETVERSIONVAL(localversion, transao, j); \
454 GETVERSIONVAL(remoteversion, mainao, j); \
455 if (localversion==remoteversion) \
457 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked)); \
460 return TRANS_SOFT_ABORT; \
462 return TRANS_ABORT; \
472 #define STMARRAYALLOC
473 #define STMARRAYASSIGN
474 #define STMARRAYDELAYFREE
475 #define STMARRAYDELAYALLOC
476 #define STMARRAYDELAYASSIGN
480 #if defined(STMARRAY)&&!defined(DUALVIEW)
482 int intkey=dc_curr->intkey; \
484 unsigned int *lockptr; \
485 GETLOCKPTR(lockptr, objptr, intkey); \
486 if (likely(write_trylock(lockptr))) { \
487 /*have lock on element */ \
488 dirwrlocked[numoidwrtotal]=objptr; \
489 dirwrindex[numoidwrtotal++]=intkey; \
491 chashlistnode_t *node = &c_table[(((unsigned INTPTR)objptr) & c_mask)>>4]; \
493 if(node->key == objptr) { \
494 unsigned int lockval; \
495 GETLOCKVAL(lockval, ((struct ArrayObject *)node->val), intkey); \
496 if (lockval!=STMDIRTY) { \
497 /*have to abort to avoid deadlock*/ \
498 transAbortProcess(oidwrlocked, numoidwrtotal, dirwrindex, numoidwrlocked); \
502 return TRANS_SOFT_ABORT; \
504 return TRANS_ABORT; \
510 transAbortProcess(oidwrlocked, numoidwrtotal, dirwrindex, numoidwrlocked); \
514 return TRANS_SOFT_ABORT; \
516 return TRANS_ABORT; \
522 #elif defined(STMARRAY)&&defined(DUALVIEW)
524 if (((struct ___Object___ *)objptr)->type>=NUMCLASSES) { \
525 if (likely(rwwrite_trylock(&header->lock))) { \
526 dirwrindex[numoidwrtotal]=0; \
527 dirwrlocked[numoidwrtotal++] = objptr; \
529 chashlistnode_t *node = &c_table[(((unsigned INTPTR)objptr) & c_mask)>>4]; \
531 if(node->key == objptr) { \
532 objheader_t * headeraddr=&((objheader_t *) node->val)[-1]; \
533 if(STATUS(headeraddr) & DIRTY) { \
534 if (likely(rwconvert_trylock(&header->lock))) { \
535 dirwrindex[numoidwrtotal]=1; \
536 dirwrlocked[numoidwrtotal++] = objptr; \
543 } while(node != NULL); \
552 #define ACCESSLOCKS \
553 unsigned int numoidwrtotal=numoidwrlocked; \
554 dchashlistnode_t *dc_curr = dc_c_list; \
555 /* Inner loop to traverse the linked list of the cache lookupTable */ \
556 while(likely(dc_curr != NULL)) { \
557 /*if the first bin in hash table is empty */ \
558 void *objptr=dc_curr->key; \
559 objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t)); \
561 if(likely(write_trylock(&header->lock))) { /*can aquire write lock*/ \
562 ARRAYDELAYWRAP(dirwrindex[numoidwrtotal]=-1;) \
563 dirwrlocked[numoidwrtotal++] = objptr; \
565 /* maybe we already have lock*/ \
566 chashlistnode_t *node = &c_table[(((unsigned INTPTR)objptr) & c_mask)>>4]; \
569 if(node->key == objptr) { \
570 objheader_t * headeraddr=&((objheader_t *) node->val)[-1]; \
571 if(STATUS(headeraddr) & DIRTY) { \
577 } while(node != NULL); \
579 /*have to abort to avoid deadlock */ \
580 transAbortProcess(oidwrlocked, numoidwrtotal ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked)); \
584 return TRANS_SOFT_ABORT; \
586 return TRANS_ABORT; \
589 dc_curr = dc_curr->lnext; \
596 void lwreset(dchashlistnode_t *dc_curr) {
597 dchashlistnode_t *ptr = dc_c_table;
598 dchashlistnode_t *top=&ptr[dc_c_size];
599 dchashlistnode_t *tmpptr=dc_c_list;
601 while(tmpptr!=NULL) {
602 dchashlistnode_t *next=tmpptr->lnext;
604 if (tmpptr==dc_curr) {
607 struct ___Object___ * objptr=tmpptr->key;
608 objheader_t *header=&((objheader_t *)objptr)[-1];
609 if (objptr->type>=NUMCLASSES) {
610 rwwrite_unlock(&header->lock);
612 write_unlock(&header->lock);
616 if (tmpptr>=ptr&&tmpptr<top) {
623 while(dc_c_structs->next!=NULL) {
624 dcliststruct_t *next=dc_c_structs->next;
628 dc_c_structs->num = 0;
629 dc_c_numelements = 0;
637 /* ==================================================
639 * - goes through the transaction cache and
640 * - decides if a transaction should commit or abort
641 * ==================================================
645 int traverseCache(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
647 int traverseCache() {
649 /* Create info to keep track of objects that can be locked */
650 int numoidrdlocked=0;
651 int numoidwrlocked=0;
652 void * rdlocked[200];
654 struct fixedlist wrlocked;
660 STMWRAP(int rdage[200];int * oidrdage;int ObjSeqId;int objtypetraverse[TOTALNUMCLASSANDARRAY];);
661 struct garbagelist * oidwrlocked;
663 #if defined(STMARRAY)&&defined(DELAYCOMP)
669 STMWRAP(for(i=0; i<TOTALNUMCLASSANDARRAY; i++) objtypetraverse[i] = 0;);
671 chashlistnode_t *ptr = c_table;
672 /* Represents number of bins in the chash table */
673 unsigned int size = c_size;
674 for(i = 0; i<size; i++) {
675 chashlistnode_t *curr = &ptr[i];
676 /* Inner loop to traverse the linked list of the cache lookupTable */
677 while(curr != NULL) {
678 //if the first bin in hash table is empty
679 if(curr->key == NULL)
681 objheader_t * cachedobj=curr->val;
682 objheader_t * headeraddr=&((objheader_t *) cachedobj)[-1]; //cached object
683 void * objptr=curr->key;
684 objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t)); //real object
685 unsigned int version = headeraddr->version;
687 if(STATUS(headeraddr) & DIRTY) {
689 /* Read from the main heap and compare versions */
690 if(likely(write_trylock(&header->lock))) { //can aquire write lock
691 if (likely(version == header->version)) { /* versions match */
692 /* Keep track of objects locked */
693 dirwrlocked[numoidwrlocked++] = objptr;
695 dirwrlocked[numoidwrlocked++] = objptr;
696 transAbortProcess(oidwrlocked, numoidwrlocked ARRAYDELAYWRAP1(NULL) ARRAYDELAYWRAP1(numoidwrlocked));
700 return TRANS_SOFT_ABORT;
705 if(version == header->version) {
709 transAbortProcess(oidwrlocked, numoidwrlocked ARRAYDELAYWRAP1(NULL) ARRAYDELAYWRAP1(numoidwrlocked));
713 return TRANS_SOFT_ABORT;
719 STMWRAP(oidrdage[numoidrdlocked]=headeraddr->accessCount;);
720 oidrdversion[numoidrdlocked]=version;
721 oidrdlocked[numoidrdlocked++]=header;
729 //THIS IS THE SERIALIZATION END POINT (START POINT IS END OF EXECUTION)*****
732 for(i=0; i<numoidrdlocked; i++) {
733 /* Read from the main heap and compare versions */
734 objheader_t *header=oidrdlocked[i];
735 unsigned int version=oidrdversion[i];
736 #if defined(STMARRAY)&&defined(DUALVIEW)
737 unsigned int isobject=((struct ___Object___ *)&header[1])->type<NUMCLASSES;
738 if(likely((isobject&&header->lock>0)||(!isobject&&header->lock==RW_LOCK_BIAS))) {
740 if(likely(header->lock>0)) { //not write locked
743 if(version != header->version) { /* versions do not match */
744 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
750 } else if (dc_t_chashSearch(((char *)header)+sizeof(objheader_t))) {
751 //couldn't get lock because we already have it
752 //check if it is the right version number
753 if (version!=header->version) {
754 transAbortProcess(oidwrlocked, numoidwrtotal ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
760 } else { /* cannot aquire lock */
761 //do increment as we didn't get lock
762 if(version == header->version) {
765 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
769 return TRANS_SOFT_ABORT;
776 //need to validate auxilary readset
777 rdchashlistnode_t *rd_curr = rd_c_list;
778 /* Inner loop to traverse the linked list of the cache lookupTable */
779 while(likely(rd_curr != NULL)) {
780 //if the first bin in hash table is empty
781 unsigned int version=rd_curr->version;
782 struct ___Object___ * objptr=rd_curr->key;
783 objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t));
784 #if defined(STMARRAY)&&defined(DUALVIEW)
785 unsigned int isobject=objptr->type<NUMCLASSES;
786 if(likely((isobject&&header->lock>0)||(!isobject&&header->lock==RW_LOCK_BIAS))) {
788 if(likely(header->lock>0)) { //not write locked
790 //object is not write locked
791 if (unlikely(version!=header->version)) {
793 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
794 STMWRAP((typesCausingAbort[TYPE(header)])++;);
797 return TRANS_SOFT_ABORT;
802 //maybe we already have lock
803 if (likely(version==header->version)) {
804 void * key=rd_curr->key;
806 //check to see if it is in the delaycomp table
808 dchashlistnode_t *node = &dc_c_table[(((unsigned INTPTR)key) & dc_c_mask)>>4];
810 if(node->key == key) {
814 } while(node != NULL);
819 if (likely(objptr->type<NUMCLASSES||header->lock==(RW_LOCK_BIAS-1))) {
823 chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
825 if(node->key == key) {
826 objheader_t * headeraddr=&((objheader_t *) node->val)[-1];
827 if(STATUS(headeraddr) & DIRTY) {
832 } while(node != NULL);
835 //have to abort to avoid deadlock
836 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
837 STMWRAP((typesCausingAbort[TYPE(header)])++;);
840 return TRANS_SOFT_ABORT;
845 rd_curr = rd_curr->lnext;
849 /* Decide the final response */
851 transCommitProcess(oidwrlocked ARRAYDELAYWRAP1(dirwrindex), numoidwrlocked, numoidwrtotal, commitmethod, primitives, locals, params);
853 transCommitProcess(oidwrlocked, numoidwrlocked);
859 /* ==================================================
861 * - goes through the transaction cache and
862 * - decides if a transaction should commit or abort
863 * ==================================================
867 int alttraverseCache(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
869 int alttraverseCache() {
871 /* Create info to keep track of objects that can be locked */
872 int numoidrdlocked=0;
873 int numoidwrlocked=0;
874 void * rdlocked[200];
876 struct fixedlist wrlocked;
881 STMWRAP(int rdage[200];int * oidrdage;int ObjSeqId;int objtypetraverse[TOTALNUMCLASSANDARRAY];);
883 struct garbagelist * oidwrlocked;
885 #if defined(STMARRAY)&&defined(DELAYCOMP)
891 STMWRAP(for(i=0; i<TOTALNUMCLASSANDARRAY; i++) objtypetraverse[i] = 0;);
893 chashlistnode_t *curr = c_list;
894 /* Inner loop to traverse the linked list of the cache lookupTable */
895 while(likely(curr != NULL)) {
896 //if the first bin in hash table is empty
897 objheader_t * cachedobj=curr->val;
898 objheader_t * headeraddr=&((objheader_t *) cachedobj)[-1];
899 void *objptr=curr->key;
900 objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t));
901 unsigned int version = headeraddr->version;
903 if(STATUS(headeraddr) & DIRTY) {
905 /* Read from the main heap and compare versions */
906 if(likely(write_trylock(&header->lock))) { //can aquire write lock
907 if (likely(version == header->version)) { /* versions match */
908 /* Keep track of objects locked */
909 dirwrlocked[numoidwrlocked++] = objptr;
911 dirwrlocked[numoidwrlocked++] = objptr;
912 transAbortProcess(oidwrlocked, numoidwrlocked ARRAYDELAYWRAP1(NULL) ARRAYDELAYWRAP1(numoidwrlocked));
917 } else { /* cannot aquire lock */
918 if(version == header->version) {
922 transAbortProcess(oidwrlocked, numoidwrlocked ARRAYDELAYWRAP1(NULL) ARRAYDELAYWRAP1(numoidwrlocked));
926 return TRANS_SOFT_ABORT;
931 /* Read from the main heap and compare versions */
932 oidrdversion[numoidrdlocked]=version;
933 oidrdlocked[numoidrdlocked++] = header;
940 //THIS IS THE SERIALIZATION END POINT (START POINT IS END OF EXECUTION)*****
943 for(i=0; i<numoidrdlocked; i++) {
944 objheader_t * header=oidrdlocked[i];
945 unsigned int version=oidrdversion[i];
946 #if defined(STMARRAY)&&defined(DUALVIEW)
947 unsigned int isobject=((struct ___Object___ *)&header[1])->type<NUMCLASSES;
948 if(likely((isobject&&header->lock>0)||(!isobject&&header->lock==RW_LOCK_BIAS))) {
950 if(likely(header->lock>0)) { //not write locked
953 if(unlikely(version != header->version)) {
954 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
960 } else if (dc_t_chashSearch(((char *)header)+sizeof(objheader_t))) {
961 //couldn't get lock because we already have it
962 //check if it is the right version number
963 if (version!=header->version) {
964 transAbortProcess(oidwrlocked, numoidwrtotal ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
970 } else { /* cannot aquire lock */
971 if(version == header->version) {
974 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
978 return TRANS_SOFT_ABORT;
985 //need to validate auxilary readset
986 rdchashlistnode_t *rd_curr = rd_c_list;
987 /* Inner loop to traverse the linked list of the cache lookupTable */
988 while(likely(rd_curr != NULL)) {
989 //if the first bin in hash table is empty
990 int version=rd_curr->version;
991 struct ___Object___ * objptr=rd_curr->key;
992 objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t));
993 #if defined(STMARRAY)&&defined(DUALVIEW)
994 unsigned int isobject=objptr->type<NUMCLASSES;
995 if(likely((isobject&&header->lock>0)||(!isobject&&header->lock==RW_LOCK_BIAS))) {
997 if(likely(header->lock>0)) { //not write locked
999 if (unlikely(version!=header->version)) {
1001 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
1002 STMWRAP((typesCausingAbort[TYPE(header)])++;);
1005 return TRANS_SOFT_ABORT;
1010 if (version==header->version) {
1011 void * key=rd_curr->key;
1013 //check to see if it is in the delaycomp table
1015 dchashlistnode_t *node = &dc_c_table[(((unsigned INTPTR)key) & dc_c_mask)>>4];
1017 if(node->key == key)
1020 } while(node != NULL);
1023 //check normal table
1025 if (likely(objptr->type<NUMCLASSES||header->lock==(RW_LOCK_BIAS-1))) {
1029 chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
1031 if(node->key == key) {
1032 objheader_t * headeraddr=&((objheader_t *) node->val)[-1];
1033 if(STATUS(headeraddr) & DIRTY) {
1038 } while(node != NULL);
1041 //have to abort to avoid deadlock
1042 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
1043 STMWRAP((typesCausingAbort[TYPE(header)])++;);
1046 return TRANS_SOFT_ABORT;
1051 rd_curr = rd_curr->lnext;
1055 /* Decide the final response */
1057 transCommitProcess(oidwrlocked ARRAYDELAYWRAP1(dirwrindex), numoidwrlocked, numoidwrtotal, commitmethod, primitives, locals, params);
1059 transCommitProcess(oidwrlocked, numoidwrlocked);
1062 return TRANS_COMMIT;
1065 /* ==================================
1068 * =================================
1073 #if defined(STMARRAY)&&defined(DELAYCOMP)
1074 void transAbortProcess(struct garbagelist *oidwrlocked, int numoidwrtotal, int * dirwrindex, int numoidwrlocked) {
1076 void transAbortProcess(struct garbagelist *oidwrlocked, int numoidwrlocked) {
1079 objheader_t *header;
1080 /* Release read locks */
1081 void ** dirwrlocked=oidwrlocked->array;
1082 /* Release write locks */
1083 for(i=numoidwrlocked-1; i>=0; i--) {
1084 /* Read from the main heap */
1085 struct ___Object___ * dst=dirwrlocked[i];
1086 header = &((objheader_t *)dst)[-1];
1089 if (type>=NUMCLASSES) {
1090 //have array, do unlocking of bins
1091 struct ArrayObject *src=(struct ArrayObject *)t_chashSearch(dst);
1092 int lowoffset=(src->lowindex);
1093 int highoffset=(src->highindex);
1095 int addwrobject=0, addrdobject=0;
1096 for(j=lowoffset; j<=highoffset;j++) {
1097 unsigned int status;
1098 GETLOCKVAL(status, src, j);
1099 if (status==STMDIRTY) {
1100 unsigned int *lockptr;
1101 GETLOCKPTR(lockptr, ((struct ArrayObject *)dst), j);
1102 write_unlock(lockptr);
1106 //release object array lock
1107 rwread_unlock(&header->lock);
1111 write_unlock(&header->lock);
1113 #if defined(STMARRAY)&&defined(DELAYCOMP)&&!defined(DUALVIEW)
1114 //release access locks
1115 for(i=numoidwrtotal-1; i>=numoidwrlocked; i--) {
1116 struct ___Object___ * dst=dirwrlocked[i];
1117 header = &((objheader_t *)dst)[-1];
1118 int wrindex=dirwrindex[i];
1121 write_unlock(&header->lock);
1124 unsigned int *intptr;
1125 GETLOCKPTR(intptr, ((struct ArrayObject *)dst), wrindex);
1126 write_unlock(intptr);
1130 #if defined(STMARRAY)&&defined(DELAYCOMP)&&defined(DUALVIEW)
1131 //release access locks
1132 for(i=numoidwrtotal-1; i>=numoidwrlocked; i--) {
1133 struct ___Object___ * dst=dirwrlocked[i];
1134 header = &((objheader_t *)dst)[-1];
1135 int wrindex=dirwrindex[i];
1138 write_unlock(&header->lock);
1139 } else if (wrindex==0) {
1141 rwwrite_unlock(&header->lock);
1143 rwconvert_unlock(&header->lock);
1148 /* clear trec and then release objects locked */
1149 struct objlist *ptr=lockedobjs;
1151 int max=ptr->offset;
1152 for(i=max-1; i>=0; i--) {
1153 header = (objheader_t *)ptr->objs[i];
1154 header->trec = NULL;
1155 pthread_mutex_unlock(header->objlock);
1162 /* ==================================
1163 * transCommitProcess
1165 * =================================
1168 void transCommitProcess(struct garbagelist * oidwrlocked ARRAYDELAYWRAP1(int * dirwrindex), int numoidwrlocked, int numoidwrtotal, void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
1170 void transCommitProcess(struct garbagelist * oidwrlocked, int numoidwrlocked) {
1172 objheader_t *header;
1175 struct objlist *ptr=newobjs;
1176 void **dirwrlocked=oidwrlocked->array;
1178 int max=ptr->offset;
1179 for(i=0; i<max; i++) {
1180 //clear the new flag
1181 ((struct ___Object___ *)ptr->objs[i])->___objstatus___=0;
1186 /* Copy from transaction cache -> main object store */
1187 for (i = numoidwrlocked-1; i >=0; i--) {
1188 /* Read from the main heap */
1189 header = &((objheader_t *)dirwrlocked[i])[-1];
1191 GETSIZE(tmpsize, header);
1192 struct ___Object___ *dst=(struct ___Object___*)dirwrlocked[i];
1193 struct ___Object___ *src=t_chashSearch(dst);
1194 dst->___cachedCode___=src->___cachedCode___;
1195 dst->___cachedHash___=src->___cachedHash___;
1198 if (type>=NUMCLASSES) {
1199 //have array, do copying of bins
1200 int lowoffset=(((struct ArrayObject *)src)->lowindex);
1201 int highoffset=(((struct ArrayObject *)src)->highindex);
1203 int addwrobject=0, addrdobject=0;
1204 int elementsize=classsize[type];
1205 int baseoffset=(lowoffset<<INDEXSHIFT)+sizeof(int)+((int)&(((struct ArrayObject *)0)->___length___));
1206 char *dstptr=((char *)dst)+baseoffset;
1207 char *srcptr=((char *)src)+baseoffset;
1208 for(j=lowoffset; j<=highoffset;j++, srcptr+=INDEXLENGTH,dstptr+=INDEXLENGTH) {
1209 unsigned int status;
1210 GETLOCKVAL(status, ((struct ArrayObject *)src), j);
1211 if (status==STMDIRTY) {
1212 A_memcpy(dstptr, srcptr, INDEXLENGTH);
1217 A_memcpy(&dst[1], &src[1], tmpsize-sizeof(struct ___Object___));
1222 // call commit method
1223 ptrstack.maxcount=0;
1225 branchstack.count=0;
1226 #if defined(STMARRAY)&&!defined(DUALVIEW)
1227 arraystack.maxcount=0;
1229 //splice oidwrlocked in
1230 oidwrlocked->size=numoidwrtotal;
1231 oidwrlocked->next=params;
1232 ((struct garbagelist *)locals)->next=oidwrlocked;
1233 if (commitmethod!=NULL)
1234 commitmethod(params, locals, primitives);
1235 ((struct garbagelist *)locals)->next=params;
1238 /* Release write locks */
1239 #if defined(STMARRAY)&&defined(DELAYCOMP)
1240 for(i=numoidwrlocked-1; i>=0; i--) {
1242 for(i=NUMWRTOTAL-1; i>=0; i--) {
1244 struct ___Object___ * dst=dirwrlocked[i];
1245 header = &((objheader_t *)dst)[-1];
1248 if (type>=NUMCLASSES) {
1249 //have array, do unlocking of bins
1250 struct ArrayObject *src=(struct ArrayObject *)t_chashSearch(dst);
1251 int lowoffset=(src->lowindex);
1252 int highoffset=(src->highindex);
1254 int addwrobject=0, addrdobject=0;
1255 for(j=lowoffset; j<=highoffset;j++) {
1256 unsigned int status;
1257 GETLOCKVAL(status, src, j);
1258 if (status==STMDIRTY) {
1259 unsigned int *intptr;
1260 GETVERSIONPTR(intptr, ((struct ArrayObject *)dst), j);
1262 GETLOCKPTR(intptr, ((struct ArrayObject *)dst), j);
1263 write_unlock(intptr);
1266 atomic_inc(&header->version);
1268 rwread_unlock(&header->lock);
1274 write_unlock(&header->lock);
1277 #if defined(STMARRAY)&&defined(DELAYCOMP)&&defined(DUALVIEW)
1278 //release access locks
1279 for(i=numoidwrtotal-1; i>=numoidwrlocked; i--) {
1280 struct ___Object___ * dst=dirwrlocked[i];
1281 int wrlock=dirwrindex[i];
1282 header = &((objheader_t *)dst)[-1];
1285 write_unlock(&header->lock);
1286 } else if (wrlock==0) {
1288 rwwrite_unlock(&header->lock);
1292 ((struct ArrayObject*)dst)->arrayversion++;
1294 rwconvert_unlock(&header->lock);
1298 #if defined(STMARRAY)&&defined(DELAYCOMP)&&!defined(DUALVIEW)
1299 //release access locks
1300 for(i=numoidwrtotal-1; i>=numoidwrlocked; i--) {
1301 struct ___Object___ * dst=dirwrlocked[i];
1302 header = &((objheader_t *)dst)[-1];
1303 int wrindex=dirwrindex[i];
1307 write_unlock(&header->lock);
1310 unsigned int *intptr;
1311 atomic_inc(&header->version);
1312 GETVERSIONPTR(intptr, ((struct ArrayObject *)dst), wrindex);
1314 GETLOCKPTR(intptr, ((struct ArrayObject *)dst), wrindex);
1315 write_unlock(intptr);
1320 /* clear trec and then release objects locked */
1323 int max=ptr->offset;
1324 for(i=max-1; i>=0; i--) {
1325 header = (objheader_t *)ptr->objs[i];
1326 header->trec = NULL;
1327 pthread_mutex_unlock(header->objlock);