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 /* Try to grab object lock...If we get it, check object access
303 version and abort on mismatch */
305 #define DVGETLOCK if (!addwrobject) { \
306 unsigned int * objlock=&(&((objheader_t *)mainao)[-1])->lock; \
307 if(!rwread_trylock(objlock)) { \
312 #define DVRELEASELOCK(x) { \
313 unsigned int * objlock=&(&((objheader_t *)x)[-1])->lock; \
314 rwread_unlock(objlock); \
317 /*not finished...if we can't get the lock, it is okay if it is in our
320 #define DVCHECKLOCK(x) \
321 unsigned int * objlock=&(&((objheader_t *)x)[-1])->lock; \
323 if (!dc_t_chashSearch(x)) { \
329 dirwrindex[numoidwrlocked]=-1;
334 #define DVCHECKLOCK(x)
335 #define DVRELEASELOCK(x)
339 #if defined(DELAYCOMP)&&!defined(DUALVIEW)
341 else if (dc_t_chashSearchArray(mainao,j)) { \
343 unsigned int localversion; \
344 unsigned int remoteversion; \
345 GETVERSIONVAL(localversion, transao, j); \
346 GETVERSIONVAL(remoteversion, mainao, j); \
347 if (localversion != remoteversion) { \
348 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked)); \
350 return TRANS_ABORT; \
357 /* This code checks arrays to try to lock them if dirty or check
358 later if they were only read. */
360 #define PROCESSARRAY \
361 int type=((int *)cachedobj)[0]; \
362 if (type>=NUMCLASSES) { \
363 struct ArrayObject *transao=(struct ArrayObject *) cachedobj; \
364 struct ArrayObject *mainao=(struct ArrayObject *) objptr; \
365 int lowoffset=(transao->lowindex); \
366 int highoffset=(transao->highindex); \
368 int addwrobject=0, addrdobject=0; \
369 for(j=lowoffset; j<=highoffset;j++) { \
370 unsigned int status; \
371 GETLOCKVAL(status, transao, j); \
372 if (status==STMDIRTY) { \
374 unsigned int * lockptr; \
375 GETLOCKPTR(lockptr, mainao,j); \
376 if (likely(write_trylock(lockptr))) { \
377 unsigned int localversion; \
378 unsigned int remoteversion; \
379 GETVERSIONVAL(localversion, transao, j); \
380 GETVERSIONVAL(remoteversion, mainao, j); \
381 if (likely(localversion == remoteversion)) { \
384 DVRELEASELOCK(mainao); \
389 DVRELEASELOCK(mainao); \
392 } else if (status==STMCLEAN) { \
398 dirwrlocked[numoidwrlocked++] = objptr; \
401 oidrdlockedarray[numoidrdlockedarray++]=objptr; \
406 /** This code allows us to skip the expensive checks in some cases */
409 #define QUICKCHECK { \
410 objheader_t * head=&((objheader_t *)mainao)[-1]; \
411 if (head->lock==RW_LOCK_BIAS&& \
412 ((objheader_t *)transao)[-1].version==head->version) \
416 if (transao->arrayversion!=mainao->arrayversion) \
424 for(i=0; i<numoidrdlockedarray; i++) { \
425 struct ArrayObject * transao=(struct ArrayObject *) oidrdlockedarray[i]; \
426 struct ArrayObject * mainao=(struct ArrayObject *) transao->___objlocation___; \
429 DVCHECKLOCK(mainao); \
430 int lowoffset=(transao->lowindex); \
431 int highoffset=(transao->highindex); \
433 for(j=lowoffset; j<=highoffset;j++) { \
434 unsigned int locallock;GETLOCKVAL(locallock,transao,j); \
435 if (locallock==STMCLEAN) { \
436 /* do read check */ \
437 unsigned int mainlock; GETLOCKVAL(mainlock, mainao, j); \
440 unsigned int localversion; \
441 unsigned int remoteversion; \
442 GETVERSIONVAL(localversion, transao, j); \
443 GETVERSIONVAL(remoteversion, mainao, j); \
444 if (localversion != remoteversion) { \
445 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked)); \
447 return TRANS_ABORT; \
452 unsigned int localversion; \
453 unsigned int remoteversion; \
454 GETVERSIONVAL(localversion, transao, j); \
455 GETVERSIONVAL(remoteversion, mainao, j); \
456 if (localversion==remoteversion) \
458 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked)); \
461 return TRANS_SOFT_ABORT; \
463 return TRANS_ABORT; \
473 #define STMARRAYALLOC
474 #define STMARRAYASSIGN
475 #define STMARRAYDELAYFREE
476 #define STMARRAYDELAYALLOC
477 #define STMARRAYDELAYASSIGN
481 #if defined(STMARRAY)&&!defined(DUALVIEW)
483 int intkey=dc_curr->intkey; \
485 unsigned int *lockptr; \
486 GETLOCKPTR(lockptr, objptr, intkey); \
487 if (likely(write_trylock(lockptr))) { \
488 /*have lock on element */ \
489 dirwrlocked[numoidwrtotal]=objptr; \
490 dirwrindex[numoidwrtotal++]=intkey; \
492 chashlistnode_t *node = &c_table[(((unsigned INTPTR)objptr) & c_mask)>>4]; \
494 if(node->key == objptr) { \
495 unsigned int lockval; \
496 GETLOCKVAL(lockval, ((struct ArrayObject *)node->val), intkey); \
497 if (lockval!=STMDIRTY) { \
498 /*have to abort to avoid deadlock*/ \
499 transAbortProcess(oidwrlocked, numoidwrtotal, dirwrindex, numoidwrlocked); \
503 return TRANS_SOFT_ABORT; \
505 return TRANS_ABORT; \
511 transAbortProcess(oidwrlocked, numoidwrtotal, dirwrindex, numoidwrlocked); \
515 return TRANS_SOFT_ABORT; \
517 return TRANS_ABORT; \
523 #elif defined(STMARRAY)&&defined(DUALVIEW)
525 if (((struct ___Object___ *)objptr)->type>=NUMCLASSES) { \
526 if (likely(rwwrite_trylock(&header->lock))) { \
527 dirwrindex[numoidwrtotal]=0; \
528 dirwrlocked[numoidwrtotal++] = objptr; \
530 chashlistnode_t *node = &c_table[(((unsigned INTPTR)objptr) & c_mask)>>4]; \
532 if(node->key == objptr) { \
533 objheader_t * headeraddr=&((objheader_t *) node->val)[-1]; \
534 if(STATUS(headeraddr) & DIRTY) { \
535 if (likely(rwconvert_trylock(&header->lock))) { \
536 dirwrindex[numoidwrtotal]=1; \
537 dirwrlocked[numoidwrtotal++] = objptr; \
544 } while(node != NULL); \
553 #define ACCESSLOCKS \
554 unsigned int numoidwrtotal=numoidwrlocked; \
555 dchashlistnode_t *dc_curr = dc_c_list; \
556 /* Inner loop to traverse the linked list of the cache lookupTable */ \
557 while(likely(dc_curr != NULL)) { \
558 /*if the first bin in hash table is empty */ \
559 void *objptr=dc_curr->key; \
560 objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t)); \
562 if(likely(write_trylock(&header->lock))) { /*can aquire write lock*/ \
563 ARRAYDELAYWRAP(dirwrindex[numoidwrtotal]=-1;) \
564 dirwrlocked[numoidwrtotal++] = objptr; \
566 /* maybe we already have lock*/ \
567 chashlistnode_t *node = &c_table[(((unsigned INTPTR)objptr) & c_mask)>>4]; \
570 if(node->key == objptr) { \
571 objheader_t * headeraddr=&((objheader_t *) node->val)[-1]; \
572 if(STATUS(headeraddr) & DIRTY) { \
578 } while(node != NULL); \
580 /*have to abort to avoid deadlock */ \
581 transAbortProcess(oidwrlocked, numoidwrtotal ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked)); \
585 return TRANS_SOFT_ABORT; \
587 return TRANS_ABORT; \
590 dc_curr = dc_curr->lnext; \
597 void lwreset(dchashlistnode_t *dc_curr) {
598 dchashlistnode_t *ptr = dc_c_table;
599 dchashlistnode_t *top=&ptr[dc_c_size];
600 dchashlistnode_t *tmpptr=dc_c_list;
602 while(tmpptr!=NULL) {
603 dchashlistnode_t *next=tmpptr->lnext;
605 if (tmpptr==dc_curr) {
608 struct ___Object___ * objptr=tmpptr->key;
609 objheader_t *header=&((objheader_t *)objptr)[-1];
610 if (objptr->type>=NUMCLASSES) {
611 rwwrite_unlock(&header->lock);
613 write_unlock(&header->lock);
617 if (tmpptr>=ptr&&tmpptr<top) {
624 while(dc_c_structs->next!=NULL) {
625 dcliststruct_t *next=dc_c_structs->next;
629 dc_c_structs->num = 0;
630 dc_c_numelements = 0;
638 /* ==================================================
640 * - goes through the transaction cache and
641 * - decides if a transaction should commit or abort
642 * ==================================================
646 int traverseCache(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
648 int traverseCache() {
650 /* Create info to keep track of objects that can be locked */
651 int numoidrdlocked=0;
652 int numoidwrlocked=0;
653 void * rdlocked[200];
655 struct fixedlist wrlocked;
661 STMWRAP(int rdage[200];int * oidrdage;int ObjSeqId;int objtypetraverse[TOTALNUMCLASSANDARRAY];);
662 struct garbagelist * oidwrlocked;
664 #if defined(STMARRAY)&&defined(DELAYCOMP)
670 STMWRAP(for(i=0; i<TOTALNUMCLASSANDARRAY; i++) objtypetraverse[i] = 0;);
672 chashlistnode_t *ptr = c_table;
673 /* Represents number of bins in the chash table */
674 unsigned int size = c_size;
675 for(i = 0; i<size; i++) {
676 chashlistnode_t *curr = &ptr[i];
677 /* Inner loop to traverse the linked list of the cache lookupTable */
678 while(curr != NULL) {
679 //if the first bin in hash table is empty
680 if(curr->key == NULL)
682 objheader_t * cachedobj=curr->val;
683 objheader_t * headeraddr=&((objheader_t *) cachedobj)[-1]; //cached object
684 void * objptr=curr->key;
685 objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t)); //real object
686 unsigned int version = headeraddr->version;
688 if(STATUS(headeraddr) & DIRTY) {
690 /* Read from the main heap and compare versions */
691 if(likely(write_trylock(&header->lock))) { //can aquire write lock
692 if (likely(version == header->version)) { /* versions match */
693 /* Keep track of objects locked */
694 dirwrlocked[numoidwrlocked++] = objptr;
696 dirwrlocked[numoidwrlocked++] = objptr;
697 transAbortProcess(oidwrlocked, numoidwrlocked ARRAYDELAYWRAP1(NULL) ARRAYDELAYWRAP1(numoidwrlocked));
701 return TRANS_SOFT_ABORT;
706 if(version == header->version) {
710 transAbortProcess(oidwrlocked, numoidwrlocked ARRAYDELAYWRAP1(NULL) ARRAYDELAYWRAP1(numoidwrlocked));
714 return TRANS_SOFT_ABORT;
720 STMWRAP(oidrdage[numoidrdlocked]=headeraddr->accessCount;);
721 oidrdversion[numoidrdlocked]=version;
722 oidrdlocked[numoidrdlocked++]=header;
730 //THIS IS THE SERIALIZATION END POINT (START POINT IS END OF EXECUTION)*****
733 for(i=0; i<numoidrdlocked; i++) {
734 /* Read from the main heap and compare versions */
735 objheader_t *header=oidrdlocked[i];
736 unsigned int version=oidrdversion[i];
737 if(header->lock>0) { //not write locked
739 if(version != header->version) { /* versions do not match */
740 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
746 } else if (dc_t_chashSearch(((char *)header)+sizeof(objheader_t))) {
747 //couldn't get lock because we already have it
748 //check if it is the right version number
749 if (version!=header->version) {
750 transAbortProcess(oidwrlocked, numoidwrtotal ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
756 } else { /* cannot aquire lock */
757 //do increment as we didn't get lock
758 if(version == header->version) {
761 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
765 return TRANS_SOFT_ABORT;
772 //need to validate auxilary readset
773 rdchashlistnode_t *rd_curr = rd_c_list;
774 /* Inner loop to traverse the linked list of the cache lookupTable */
775 while(likely(rd_curr != NULL)) {
776 //if the first bin in hash table is empty
777 unsigned int version=rd_curr->version;
778 struct ___Object___ * objptr=rd_curr->key;
779 objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t));
781 //object is not write locked
782 if (unlikely(version!=header->version)) {
784 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
785 STMWRAP((typesCausingAbort[TYPE(header)])++;);
788 return TRANS_SOFT_ABORT;
793 //maybe we already have lock
794 if (likely(version==header->version)) {
795 void * key=rd_curr->key;
797 //check to see if it is in the delaycomp table
799 dchashlistnode_t *node = &dc_c_table[(((unsigned INTPTR)key) & dc_c_mask)>>4];
801 if(node->key == key) {
805 } while(node != NULL);
810 if (likely(objptr->type>=NUMCLASSES||header->lock==(RW_LOCK_BIAS-1))) {
814 chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
816 if(node->key == key) {
817 objheader_t * headeraddr=&((objheader_t *) node->val)[-1];
818 if(STATUS(headeraddr) & DIRTY) {
823 } while(node != NULL);
826 //have to abort to avoid deadlock
827 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
828 STMWRAP((typesCausingAbort[TYPE(header)])++;);
831 return TRANS_SOFT_ABORT;
836 rd_curr = rd_curr->lnext;
840 /* Decide the final response */
842 transCommitProcess(oidwrlocked ARRAYDELAYWRAP1(dirwrindex), numoidwrlocked, numoidwrtotal, commitmethod, primitives, locals, params);
844 transCommitProcess(oidwrlocked, numoidwrlocked);
850 /* ==================================================
852 * - goes through the transaction cache and
853 * - decides if a transaction should commit or abort
854 * ==================================================
858 int alttraverseCache(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
860 int alttraverseCache() {
862 /* Create info to keep track of objects that can be locked */
863 int numoidrdlocked=0;
864 int numoidwrlocked=0;
865 void * rdlocked[200];
867 struct fixedlist wrlocked;
872 STMWRAP(int rdage[200];int * oidrdage;int ObjSeqId;int objtypetraverse[TOTALNUMCLASSANDARRAY];);
874 struct garbagelist * oidwrlocked;
876 #if defined(STMARRAY)&&defined(DELAYCOMP)
882 STMWRAP(for(i=0; i<TOTALNUMCLASSANDARRAY; i++) objtypetraverse[i] = 0;);
884 chashlistnode_t *curr = c_list;
885 /* Inner loop to traverse the linked list of the cache lookupTable */
886 while(likely(curr != NULL)) {
887 //if the first bin in hash table is empty
888 objheader_t * cachedobj=curr->val;
889 objheader_t * headeraddr=&((objheader_t *) cachedobj)[-1];
890 void *objptr=curr->key;
891 objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t));
892 unsigned int version = headeraddr->version;
894 if(STATUS(headeraddr) & DIRTY) {
896 /* Read from the main heap and compare versions */
897 if(likely(write_trylock(&header->lock))) { //can aquire write lock
898 if (likely(version == header->version)) { /* versions match */
899 /* Keep track of objects locked */
900 dirwrlocked[numoidwrlocked++] = objptr;
902 dirwrlocked[numoidwrlocked++] = objptr;
903 transAbortProcess(oidwrlocked, numoidwrlocked ARRAYDELAYWRAP1(NULL) ARRAYDELAYWRAP1(numoidwrlocked));
908 } else { /* cannot aquire lock */
909 if(version == header->version) {
913 transAbortProcess(oidwrlocked, numoidwrlocked ARRAYDELAYWRAP1(NULL) ARRAYDELAYWRAP1(numoidwrlocked));
917 return TRANS_SOFT_ABORT;
922 /* Read from the main heap and compare versions */
923 oidrdversion[numoidrdlocked]=version;
924 oidrdlocked[numoidrdlocked++] = header;
931 //THIS IS THE SERIALIZATION END POINT (START POINT IS END OF EXECUTION)*****
934 for(i=0; i<numoidrdlocked; i++) {
935 objheader_t * header=oidrdlocked[i];
936 unsigned int version=oidrdversion[i];
937 if(likely(header->lock>0)) {
939 if(unlikely(version != header->version)) {
940 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
946 } else if (dc_t_chashSearch(((char *)header)+sizeof(objheader_t))) {
947 //couldn't get lock because we already have it
948 //check if it is the right version number
949 if (version!=header->version) {
950 transAbortProcess(oidwrlocked, numoidwrtotal ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
956 } else { /* cannot aquire lock */
957 if(version == header->version) {
960 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
964 return TRANS_SOFT_ABORT;
971 //need to validate auxilary readset
972 rdchashlistnode_t *rd_curr = rd_c_list;
973 /* Inner loop to traverse the linked list of the cache lookupTable */
974 while(likely(rd_curr != NULL)) {
975 //if the first bin in hash table is empty
976 int version=rd_curr->version;
977 struct ___Object___ * objptr=rd_curr->key;
978 objheader_t *header=(objheader_t *)(((char *)objptr)-sizeof(objheader_t));
979 if(likely(header->lock>0)) { //object is not write locked
980 if (unlikely(version!=header->version)) {
982 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
983 STMWRAP((typesCausingAbort[TYPE(header)])++;);
986 return TRANS_SOFT_ABORT;
991 if (version==header->version) {
992 void * key=rd_curr->key;
994 //check to see if it is in the delaycomp table
996 dchashlistnode_t *node = &dc_c_table[(((unsigned INTPTR)key) & dc_c_mask)>>4];
1001 } while(node != NULL);
1004 //check normal table
1006 if (likely(objptr->type>=NUMCLASSES||header->lock==(RW_LOCK_BIAS-1))) {
1010 chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
1012 if(node->key == key) {
1013 objheader_t * headeraddr=&((objheader_t *) node->val)[-1];
1014 if(STATUS(headeraddr) & DIRTY) {
1019 } while(node != NULL);
1022 //have to abort to avoid deadlock
1023 transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
1024 STMWRAP((typesCausingAbort[TYPE(header)])++;);
1027 return TRANS_SOFT_ABORT;
1032 rd_curr = rd_curr->lnext;
1036 /* Decide the final response */
1038 transCommitProcess(oidwrlocked ARRAYDELAYWRAP1(dirwrindex), numoidwrlocked, numoidwrtotal, commitmethod, primitives, locals, params);
1040 transCommitProcess(oidwrlocked, numoidwrlocked);
1043 return TRANS_COMMIT;
1046 /* ==================================
1049 * =================================
1054 #if defined(STMARRAY)&&defined(DELAYCOMP)
1055 void transAbortProcess(struct garbagelist *oidwrlocked, int numoidwrtotal, int * dirwrindex, int numoidwrlocked) {
1057 void transAbortProcess(struct garbagelist *oidwrlocked, int numoidwrlocked) {
1060 objheader_t *header;
1061 /* Release read locks */
1062 void ** dirwrlocked=oidwrlocked->array;
1063 /* Release write locks */
1064 for(i=numoidwrlocked-1; i>=0; i--) {
1065 /* Read from the main heap */
1066 struct ___Object___ * dst=dirwrlocked[i];
1067 header = &((objheader_t *)dst)[-1];
1070 if (type>=NUMCLASSES) {
1071 //have array, do unlocking of bins
1072 struct ArrayObject *src=(struct ArrayObject *)t_chashSearch(dst);
1073 int lowoffset=(src->lowindex);
1074 int highoffset=(src->highindex);
1076 int addwrobject=0, addrdobject=0;
1077 for(j=lowoffset; j<=highoffset;j++) {
1078 unsigned int status;
1079 GETLOCKVAL(status, src, j);
1080 if (status==STMDIRTY) {
1081 unsigned int *lockptr;
1082 GETLOCKPTR(lockptr, ((struct ArrayObject *)dst), j);
1083 write_unlock(lockptr);
1087 //release object array lock
1088 rwread_unlock(&header->lock);
1092 write_unlock(&header->lock);
1094 #if defined(STMARRAY)&&defined(DELAYCOMP)&&!defined(DUALVIEW)
1095 //release access locks
1096 for(i=numoidwrtotal-1; i>=numoidwrlocked; i--) {
1097 struct ___Object___ * dst=dirwrlocked[i];
1098 header = &((objheader_t *)dst)[-1];
1099 int wrindex=dirwrindex[i];
1102 write_unlock(&header->lock);
1105 unsigned int *intptr;
1106 GETLOCKPTR(intptr, ((struct ArrayObject *)dst), wrindex);
1107 write_unlock(intptr);
1111 #if defined(STMARRAY)&&defined(DELAYCOMP)&&defined(DUALVIEW)
1112 //release access locks
1113 for(i=numoidwrtotal-1; i>=numoidwrlocked; i--) {
1114 struct ___Object___ * dst=dirwrlocked[i];
1115 header = &((objheader_t *)dst)[-1];
1116 int wrindex=dirwrindex[i];
1119 write_unlock(&header->lock);
1120 } else if (wrindex==0) {
1122 rwwrite_unlock(&header->lock);
1124 rwconvert_unlock(&header->lock);
1129 /* clear trec and then release objects locked */
1130 struct objlist *ptr=lockedobjs;
1132 int max=ptr->offset;
1133 for(i=max-1; i>=0; i--) {
1134 header = (objheader_t *)ptr->objs[i];
1135 header->trec = NULL;
1136 pthread_mutex_unlock(header->objlock);
1143 /* ==================================
1144 * transCommitProcess
1146 * =================================
1149 void transCommitProcess(struct garbagelist * oidwrlocked ARRAYDELAYWRAP1(int * dirwrindex), int numoidwrlocked, int numoidwrtotal, void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
1151 void transCommitProcess(struct garbagelist * oidwrlocked, int numoidwrlocked) {
1153 objheader_t *header;
1156 struct objlist *ptr=newobjs;
1157 void **dirwrlocked=oidwrlocked->array;
1159 int max=ptr->offset;
1160 for(i=0; i<max; i++) {
1161 //clear the new flag
1162 ((struct ___Object___ *)ptr->objs[i])->___objstatus___=0;
1167 /* Copy from transaction cache -> main object store */
1168 for (i = numoidwrlocked-1; i >=0; i--) {
1169 /* Read from the main heap */
1170 header = &((objheader_t *)dirwrlocked[i])[-1];
1172 GETSIZE(tmpsize, header);
1173 struct ___Object___ *dst=(struct ___Object___*)dirwrlocked[i];
1174 struct ___Object___ *src=t_chashSearch(dst);
1175 dst->___cachedCode___=src->___cachedCode___;
1176 dst->___cachedHash___=src->___cachedHash___;
1179 if (type>=NUMCLASSES) {
1180 //have array, do copying of bins
1181 int lowoffset=(((struct ArrayObject *)src)->lowindex);
1182 int highoffset=(((struct ArrayObject *)src)->highindex);
1184 int addwrobject=0, addrdobject=0;
1185 int elementsize=classsize[type];
1186 int baseoffset=(lowoffset<<INDEXSHIFT)+sizeof(int)+((int)&(((struct ArrayObject *)0)->___length___));
1187 char *dstptr=((char *)dst)+baseoffset;
1188 char *srcptr=((char *)src)+baseoffset;
1189 for(j=lowoffset; j<=highoffset;j++, srcptr+=INDEXLENGTH,dstptr+=INDEXLENGTH) {
1190 unsigned int status;
1191 GETLOCKVAL(status, ((struct ArrayObject *)src), j);
1192 if (status==STMDIRTY) {
1193 A_memcpy(dstptr, srcptr, INDEXLENGTH);
1198 A_memcpy(&dst[1], &src[1], tmpsize-sizeof(struct ___Object___));
1203 // call commit method
1204 ptrstack.maxcount=0;
1206 branchstack.count=0;
1207 #if defined(STMARRAY)&&!defined(DUALVIEW)
1208 arraystack.maxcount=0;
1210 //splice oidwrlocked in
1211 oidwrlocked->size=numoidwrtotal;
1212 oidwrlocked->next=params;
1213 ((struct garbagelist *)locals)->next=oidwrlocked;
1214 if (commitmethod!=NULL)
1215 commitmethod(params, locals, primitives);
1216 ((struct garbagelist *)locals)->next=params;
1219 /* Release write locks */
1220 #if defined(STMARRAY)&&defined(DELAYCOMP)
1221 for(i=numoidwrlocked-1; i>=0; i--) {
1223 for(i=NUMWRTOTAL-1; i>=0; i--) {
1225 struct ___Object___ * dst=dirwrlocked[i];
1226 header = &((objheader_t *)dst)[-1];
1229 if (type>=NUMCLASSES) {
1230 //have array, do unlocking of bins
1231 struct ArrayObject *src=(struct ArrayObject *)t_chashSearch(dst);
1232 int lowoffset=(src->lowindex);
1233 int highoffset=(src->highindex);
1235 int addwrobject=0, addrdobject=0;
1236 for(j=lowoffset; j<=highoffset;j++) {
1237 unsigned int status;
1238 GETLOCKVAL(status, src, j);
1239 if (status==STMDIRTY) {
1240 unsigned int *intptr;
1241 GETVERSIONPTR(intptr, ((struct ArrayObject *)dst), j);
1243 GETLOCKPTR(intptr, ((struct ArrayObject *)dst), j);
1244 write_unlock(intptr);
1247 atomic_inc(&header->version);
1249 rwread_unlock(&header->lock);
1255 write_unlock(&header->lock);
1258 #if defined(STMARRAY)&&defined(DELAYCOMP)&&defined(DUALVIEW)
1259 //release access locks
1260 for(i=numoidwrtotal-1; i>=numoidwrlocked; i--) {
1261 struct ___Object___ * dst=dirwrlocked[i];
1262 int wrlock=dirwrindex[i];
1263 header = &((objheader_t *)dst)[-1];
1266 write_unlock(&header->lock);
1267 } else if (wrlock==0) {
1269 rwwrite_unlock(&header->lock);
1273 ((struct ArrayObject*)dst)->arrayversion++;
1275 rwconvert_unlock(&header->lock);
1279 #if defined(STMARRAY)&&defined(DELAYCOMP)&&!defined(DUALVIEW)
1280 //release access locks
1281 for(i=numoidwrtotal-1; i>=numoidwrlocked; i--) {
1282 struct ___Object___ * dst=dirwrlocked[i];
1283 header = &((objheader_t *)dst)[-1];
1284 int wrindex=dirwrindex[i];
1288 write_unlock(&header->lock);
1291 unsigned int *intptr;
1292 atomic_inc(&header->version);
1293 GETVERSIONPTR(intptr, ((struct ArrayObject *)dst), wrindex);
1295 GETLOCKPTR(intptr, ((struct ArrayObject *)dst), wrindex);
1296 write_unlock(intptr);
1301 /* clear trec and then release objects locked */
1304 int max=ptr->offset;
1305 for(i=max-1; i>=0; i--) {
1306 header = (objheader_t *)ptr->objs[i];
1307 header->trec = NULL;
1308 pthread_mutex_unlock(header->objlock);