a0aa9f6845f5945aa4f9733a11cefde3418866de
[IRC.git] / Robust / src / Runtime / STM / commit.c
1 #include<tm.h>
2 #ifdef DELAYCOMP
3 #include<delaycomp.h>
4 #endif
5
6 #ifdef TRANSSTATS
7 #define TRANSWRAP(x) x
8 #else
9 #define TRANSWRAP(x)
10 #endif
11
12 #ifdef STMSTATS
13 #define STMWRAP(x) x
14 #else
15 #define STMWRAP(x)
16 #endif
17
18 #ifdef STMSTATS
19 #define STATFREE free(oidrdage);
20 #define STATALLOC oidrdage=malloc(size);
21 #define STATASSIGN oidrdage=rdage;
22 #else
23 #define STATFREE
24 #define STATALLOC
25 #define STATASSIGN
26 #endif
27
28 #if defined(STMARRAY)&&defined(DELAYCOMP)
29 #define ARRAYDELAYWRAP(x) x
30 #define ARRAYDELAYWRAP1(x) ,x
31 #else
32 #define ARRAYDELAYWRAP(x)
33 #define ARRAYDELAYWRAP1(x)
34 #endif
35
36 #ifdef DUALVIEW
37 #define DUALVIEWWRAP(x) x
38 #else
39 #define DUALVIEWWRAP(x)
40 #endif
41
42 /* ================================================================
43  * transCommit
44  * - This function initiates the transaction commit process
45  * - goes through the transaction cache and decides
46  * - a final response
47  * ================================================================
48  */
49
50 #ifdef DELAYCOMP
51 int transCommit(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
52 #else
53 int transCommit() {
54 #endif
55 #ifdef SANDBOX
56   abortenabled=0;
57 #endif
58   TRANSWRAP(numTransCommit++;);
59   int softaborted=0;
60   do {
61     /* Look through all the objects in the transaction hash table */
62     int finalResponse;
63 #ifdef DELAYCOMP
64     if (c_numelements<(c_size>>3))
65       finalResponse=alttraverseCache(commitmethod, primitives, locals, params);
66     else
67       finalResponse=traverseCache(commitmethod, primitives, locals, params);
68 #else
69     if (c_numelements<(c_size>>3))
70       finalResponse=alttraverseCache();
71     else
72       finalResponse=traverseCache();
73 #endif
74     if(finalResponse == TRANS_ABORT) {
75       TRANSWRAP(numTransAbort++;if (softaborted) nSoftAbortAbort++;);
76       freenewobjs();
77       STMWRAP(freelockedobjs(););
78       objstrReset();
79       t_chashreset();
80 #ifdef READSET
81       rd_t_chashreset();
82 #endif
83 #ifdef DELAYCOMP
84       dc_t_chashreset();
85       ptrstack.count=0;
86       primstack.count=0;
87       branchstack.count=0;
88 #if defined(STMARRAY)&&!defined(DUALVIEW)
89       arraystack.count=0;
90 #endif
91 #endif
92 #ifdef SANDBOX
93       abortenabled=1;
94 #endif
95
96       return TRANS_ABORT;
97     }
98     if(finalResponse == TRANS_COMMIT) {
99       TRANSWRAP(numTransCommit++;if (softaborted) nSoftAbortCommit++;);
100       freenewobjs();
101       STMWRAP(freelockedobjs(););
102       objstrReset();
103       t_chashreset();
104 #ifdef READSET
105       rd_t_chashreset();
106 #endif
107 #ifdef DELAYCOMP
108       dc_t_chashreset();
109       ptrstack.count=0;
110       primstack.count=0;
111       branchstack.count=0;
112 #if defined(STMARRAY)&&!defined(DUALVIEW)
113       arraystack.count=0;
114 #endif
115 #endif
116       return 0;
117     }
118
119     /* wait a random amount of time before retrying to commit transaction*/
120     if(finalResponse == TRANS_SOFT_ABORT) {
121       TRANSWRAP(nSoftAbort++;);
122       softaborted++;
123 #ifdef SOFTABORT
124       if (softaborted>1) {
125 #else
126       if (1) {
127 #endif
128         //retry if too many soft aborts
129         freenewobjs();
130         STMWRAP(freelockedobjs(););
131         objstrReset();
132         t_chashreset();
133 #ifdef READSET
134         rd_t_chashreset();
135 #endif
136 #ifdef DELAYCOMP
137         dc_t_chashreset();
138         ptrstack.count=0;
139         primstack.count=0;
140         branchstack.count=0;
141 #if defined(STMARRAY)&&!defined(DUALVIEW)
142       arraystack.count=0;
143 #endif
144 #endif
145         return TRANS_ABORT;
146       }
147     } else {
148       printf("Error: in %s() Unknown outcome", __func__);
149       exit(-1);
150     }
151   } while (1);
152 }
153
154 #ifdef DELAYCOMP
155 #define freearrays if (c_numelements>=200) { \
156     STATFREE;                                \
157     STMARRAYFREE;                            \
158     free(oidrdlocked);                       \
159     free(oidrdversion);                      \
160   }                                          \
161   if (t_numelements>=200) {                  \
162     free(oidwrlocked);                       \
163     STMARRAYDELAYFREE;                       \
164   }
165 #else
166 #define freearrays   if (c_numelements>=200) { \
167     STATFREE;                                  \
168     STMARRAYFREE;                              \
169     free(oidrdlocked);                         \
170     free(oidrdversion);                        \
171     free(oidwrlocked);                         \
172   }
173 #endif
174
175 #ifdef DELAYCOMP
176 #define allocarrays int t_numelements=c_numelements+dc_c_numelements;   \
177   if (t_numelements<200) {                                              \
178     oidwrlocked=(struct garbagelist *) &wrlocked;                       \
179     STMARRAYDELAYASSIGN;                                                \
180   } else {                                                              \
181     oidwrlocked=malloc(2*sizeof(INTPTR)+t_numelements*(sizeof(void *))); \
182     STMARRAYDELAYALLOC;                                                 \
183   }                                                                     \
184   if (c_numelements<200) {                                              \
185     oidrdlocked=rdlocked;                                               \
186     oidrdversion=rdversion;                                             \
187     STATASSIGN;                                                         \
188     STMARRAYASSIGN;                                                     \
189   } else {                                                              \
190     int size=c_numelements*sizeof(void*);                               \
191     oidrdlocked=malloc(size);                                           \
192     oidrdversion=malloc(size);                                          \
193     STATALLOC;                                                          \
194     STMARRAYALLOC;                                                      \
195   }                                                                     \
196   dirwrlocked=oidwrlocked->array;
197 #else
198 #define allocarrays if (c_numelements<200) {      \
199     oidrdlocked=rdlocked;                         \
200     oidrdversion=rdversion;                       \
201     oidwrlocked=(struct garbagelist *) &wrlocked; \
202     STATASSIGN;                                   \
203     STMARRAYASSIGN;                               \
204   } else {                                        \
205     int size=c_numelements*sizeof(void*);         \
206     oidrdlocked=malloc(size);                     \
207     oidrdversion=malloc(size);                    \
208     oidwrlocked=malloc(size+2*sizeof(INTPTR));    \
209     STATALLOC;                                    \
210     STMARRAYALLOC;                                \
211   }                                               \
212   dirwrlocked=oidwrlocked->array;
213 #endif
214
215 #ifdef STMSTATS
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)) \
223     softabort=0;
224 #define ABORTSTAT2                                                      \
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)) \
232     softabort=0;
233 #define ABORTSTAT3                                                      \
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)) \
241     softabort=0;
242 #define ABORTSTAT4 ObjSeqId = oidrdage[i];                              \
243   header->abortCount++;                                                 \
244   getReadAbortCount(i+1, numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse);
245 #else
246 #define ABORTSTAT1
247 #define ABORTSTAT2
248 #define ABORTSTAT3
249 #define ABORTSTAT4
250 #endif
251
252 #ifdef DELAYCOMP
253 #define DELAYWRAP(x) x
254 #define NUMWRTOTAL numoidwrtotal
255 #else
256 #define DELAYWRAP(x)
257 #define NUMWRTOTAL numoidwrlocked
258 #endif
259
260 #if defined(STMARRAY)
261 #define STMARRAYFREE free(oidrdlockedarray);
262 #define STMARRAYALLOC oidrdlockedarray=malloc(size);
263 #define STMARRAYASSIGN oidrdlockedarray=rdlockedarray;
264
265 //allocation statements for dirwrindex
266 #define STMARRAYDELAYFREE free(dirwrindex);
267 #define STMARRAYDELAYALLOC dirwrindex=malloc(t_numelements*sizeof(int));
268 #define STMARRAYDELAYASSIGN dirwrindex=wrindex;
269
270 #define ARRAYDEFINES int numoidrdlockedarray=0; \
271   void * rdlockedarray[200];                    \
272   void ** oidrdlockedarray;
273
274 #define ABORT                                   \
275   transAbortProcess(oidwrlocked, numoidwrlocked ARRAYDELAYWRAP1(NULL) ARRAYDELAYWRAP1(numoidwrlocked)); \
276   freearrays;                                                           \
277   if (softabort)                                                        \
278     return TRANS_SOFT_ABORT;                                            \
279   else                                                                  \
280     return TRANS_ABORT;
281   
282 #define ABORTREAD                                                       \
283   transAbortProcess(oidwrlocked, numoidwrtotal ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked)); \
284   freearrays;                                                           \
285   if (softabort)                                                        \
286     return TRANS_SOFT_ABORT;                                            \
287   else                                                                  \
288     return TRANS_ABORT;
289
290
291 #define ARRAYABORT                                                      \
292   for(;j>=lowoffset;j--) {                                              \
293     GETLOCKVAL(status, transao, j);                                     \
294     if  (status==STMDIRTY) {                                            \
295       GETLOCKPTR(lockptr, mainao,j);                                    \
296       write_unlock(lockptr);                                            \
297     }                                                                   \
298   }                                                                     \
299   ABORT
300
301 #ifdef DUALVIEW
302 /* Try to grab object lock...If we get it, check object access
303    version and abort on mismatch */
304   
305 #define DVGETLOCK if (!addwrobject) {                           \
306     unsigned int * objlock=&(&((objheader_t *)mainao)[-1])->lock;       \
307     if(!rwread_trylock(objlock)) {                                      \
308       ABORT;                                                            \
309     }                                                                   \
310 }
311
312 #define DVRELEASELOCK(x) {                                              \
313     unsigned int * objlock=&(&((objheader_t *)x)[-1])->lock;            \
314     rwread_unlock(objlock);                                             \
315   }
316
317 /*not finished...if we can't get the lock, it is okay if it is in our
318     access set*/
319
320 #define DVCHECKLOCK(x)                                                  \
321   unsigned int * objlock=&(&((objheader_t *)x)[-1])->lock;              \
322   if (objlock<=0) {                                                     \
323     if (!dc_t_chashSearch(x)) {                                         \
324       ABORTREAD;                                                        \
325     }                                                                   \
326   }
327
328 #define DVSETINDEX                                                      \
329   dirwrindex[numoidwrlocked]=-1;
330
331 #else
332 #define DVSETINDEX
333 #define DVGETLOCK
334 #define DVCHECKLOCK(x)
335 #define DVRELEASELOCK(x)
336 #endif
337
338
339 #if defined(DELAYCOMP)&&!defined(DUALVIEW)
340 #define READCHECK                                                       \
341   else if (dc_t_chashSearchArray(mainao,j)) {                           \
342     CFENCE;                                                             \
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)); \
349       freearrays;                                                       \
350       return TRANS_ABORT;                                               \
351     }                                                                   \
352   }
353 #else
354 #define READCHECK
355 #endif
356
357   /* This code checks arrays to try to lock them if dirty or check
358      later if they were only read. */
359
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);                                \
367     int j;                                                              \
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) {                                           \
373         DVGETLOCK;                                                      \
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)) {                  \
382             addwrobject=1;                                              \
383           } else {                                                      \
384             DVRELEASELOCK(mainao);                                      \
385             ARRAYABORT;                                                 \
386           }                                                             \
387         } else {                                                        \
388           j--;                                                          \
389           DVRELEASELOCK(mainao);                                        \
390           ARRAYABORT;                                                   \
391         }                                                               \
392       } else if (status==STMCLEAN) {                                    \
393         addrdobject=1;                                                  \
394       }                                                                 \
395     }                                                                   \
396     if (addwrobject) {                                                  \
397       DVSETINDEX                                                        \
398       dirwrlocked[numoidwrlocked++] = objptr;                           \
399     }                                                                   \
400     if (addrdobject) {                                                  \
401       oidrdlockedarray[numoidrdlockedarray++]=objptr;                   \
402     }                                                                   \
403   } else
404
405
406   /** This code allows us to skip the expensive checks in some cases */
407
408 #ifdef DUALVIEW 
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)            \
413       continue;                                                         \
414   }
415 #define ARRAYCHECK                                      \
416   if (transao->arrayversion!=mainao->arrayversion)      \
417     ABORT
418 #else
419 #define QUICKCHECK
420 #define ARRAYCHECK
421 #endif
422   
423 #define READARRAYS                                                      \
424   for(i=0; i<numoidrdlockedarray; i++) {                                \
425     struct ArrayObject * transao=(struct ArrayObject *) oidrdlockedarray[i]; \
426     struct ArrayObject * mainao=(struct ArrayObject *) transao->___objlocation___; \
427     ARRAYCHECK;                                                         \
428     QUICKCHECK;                                                         \
429     DVCHECKLOCK(mainao);                                                \
430     int lowoffset=(transao->lowindex);                                  \
431     int highoffset=(transao->highindex);                                \
432     int j;                                                              \
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);         \
438         if (mainlock>0) {                                               \
439           CFENCE;                                                       \
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)); \
446             freearrays;                                                 \
447             return TRANS_ABORT;                                         \
448           }                                                             \
449         }                                                               \
450         READCHECK                                                       \
451         else {                                                          \
452           unsigned int localversion;                                    \
453           unsigned int remoteversion;                                   \
454           GETVERSIONVAL(localversion, transao, j);                      \
455           GETVERSIONVAL(remoteversion, mainao, j);                      \
456           if (localversion==remoteversion)                              \
457             softabort=1;                                                \
458           transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked)); \
459           freearrays;                                                   \
460           if (softabort)                                                \
461             return TRANS_SOFT_ABORT;                                    \
462           else                                                          \
463             return TRANS_ABORT;                                         \
464         }                                                               \
465       }                                                                 \
466     }                                                                   \
467   }
468 #else
469 #define ARRAYDEFINES
470 #define PROCESSARRAY
471 #define READARRAYS
472 #define STMARRAYFREE
473 #define STMARRAYALLOC
474 #define STMARRAYASSIGN
475 #define STMARRAYDELAYFREE
476 #define STMARRAYDELAYALLOC
477 #define STMARRAYDELAYASSIGN
478 #endif
479
480 #ifdef DELAYCOMP
481 #if defined(STMARRAY)&&!defined(DUALVIEW)
482 #define ARRAYLOCK                                                       \
483   int intkey=dc_curr->intkey;                                           \
484   if (intkey!=-1) {                                                     \
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;                               \
491     } else {                                                            \
492       chashlistnode_t *node = &c_table[(((unsigned INTPTR)objptr) & c_mask)>>4]; \
493       do {                                                              \
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); \
500             ABORTSTAT1;                                                 \
501             freearrays;                                                 \
502             if (softabort)                                              \
503               return TRANS_SOFT_ABORT;                                  \
504             else                                                        \
505               return TRANS_ABORT;                                       \
506           }                                                             \
507           break;                                                        \
508         }                                                               \
509         node = node->next;                                              \
510         if(node==NULL) {                                                \
511           transAbortProcess(oidwrlocked, numoidwrtotal, dirwrindex, numoidwrlocked); \
512           ABORTSTAT1;                                                   \
513           freearrays;                                                   \
514           if (softabort)                                                \
515             return TRANS_SOFT_ABORT;                                    \
516           else                                                          \
517             return TRANS_ABORT;                                         \
518         }                                                               \
519        } while(1);                                                      \
520     }                                                                   \
521   } else
522
523 #elif defined(STMARRAY)&&defined(DUALVIEW)
524 #define ARRAYLOCK                                                       \
525   if (((struct ___Object___ *)objptr)->type>=NUMCLASSES) {              \
526     if (likely(rwwrite_trylock(&header->lock))) {                       \
527       dirwrindex[numoidwrtotal]=0;                                      \
528       dirwrlocked[numoidwrtotal++] = objptr;                            \
529     } else {                                                            \
530       chashlistnode_t *node = &c_table[(((unsigned INTPTR)objptr) & c_mask)>>4]; \
531       do {                                                              \
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;                    \
538               goto nextloop;                                            \
539             }                                                           \
540           }                                                             \
541           break;                                                        \
542         }                                                               \
543         node = node->next;                                              \
544       } while(node != NULL);                                            \
545       ABORTREAD;                                                        \
546     }                                                                   \
547   } else
548 #else
549 #define ARRAYLOCK
550 #endif
551
552
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)); \
561     ARRAYLOCK                                                           \
562     if(likely(write_trylock(&header->lock))) { /*can aquire write lock*/ \
563       ARRAYDELAYWRAP(dirwrindex[numoidwrtotal]=-1;)                     \
564       dirwrlocked[numoidwrtotal++] = objptr;                            \
565     } else {                                                            \
566       /* maybe we already have lock*/                                   \
567       chashlistnode_t *node = &c_table[(((unsigned INTPTR)objptr) & c_mask)>>4]; \
568                                                                         \
569       do {                                                              \
570         if(node->key == objptr) {                                       \
571           objheader_t * headeraddr=&((objheader_t *) node->val)[-1];    \
572           if(STATUS(headeraddr) & DIRTY) {                              \
573             goto nextloop;                                              \
574           } else                                                        \
575             break;                                                      \
576         }                                                               \
577         node = node->next;                                              \
578       } while(node != NULL);                                            \
579                                                                         \
580       /*have to abort to avoid deadlock */                              \
581       transAbortProcess(oidwrlocked, numoidwrtotal ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked)); \
582       ABORTSTAT1;                                                       \
583       freearrays;                                                       \
584       if (softabort)                                                    \
585         return TRANS_SOFT_ABORT;                                        \
586       else                                                              \
587         return TRANS_ABORT;                                             \
588     }                                                                   \
589   nextloop:                                                             \
590     dc_curr = dc_curr->lnext;                                           \
591   }                                                     
592 #else
593 #define ACCESSLOCKS
594 #endif
595
596 #ifdef DELAYCOMP
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;                           
601   int reset=1;
602   while(tmpptr!=NULL) {                                         
603     dchashlistnode_t *next=tmpptr->lnext;                       
604     if (reset) {
605       if (tmpptr==dc_curr) {
606         reset=0;
607       } else {
608         struct ___Object___ * objptr=tmpptr->key;               
609         objheader_t *header=&((objheader_t *)objptr)[-1];       
610         if (objptr->type>=NUMCLASSES) {                 
611           rwwrite_unlock(&header->lock);
612         } else {
613           write_unlock(&header->lock);
614         }
615       }
616     }
617     if (tmpptr>=ptr&&tmpptr<top) {                              
618       //zero in list                                            
619       tmpptr->key=NULL;                                         
620       tmpptr->next=NULL;                                        
621     }                                                           
622     tmpptr=next;
623   }                                                             
624   while(dc_c_structs->next!=NULL) {                             
625     dcliststruct_t *next=dc_c_structs->next;                    
626     free(dc_c_structs);                                         
627     dc_c_structs=next;                                          
628   }                                                             
629   dc_c_structs->num = 0;                                        
630   dc_c_numelements = 0;                                        
631   dc_c_list=NULL;
632   ptrstack.count=0;
633   primstack.count=0;
634   branchstack.count=0;
635 }
636 #endif
637
638 /* ==================================================
639  * traverseCache
640  * - goes through the transaction cache and
641  * - decides if a transaction should commit or abort
642  * ==================================================
643  */
644
645 #ifdef DELAYCOMP
646 int traverseCache(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
647 #else
648 int traverseCache() {
649 #endif
650   /* Create info to keep track of objects that can be locked */
651   int numoidrdlocked=0;
652   int numoidwrlocked=0;
653   void * rdlocked[200];
654   int rdversion[200];
655   struct fixedlist wrlocked;
656   int softabort=0;
657   int i;
658   void ** oidrdlocked;
659   int * oidrdversion;
660   ARRAYDEFINES;
661   STMWRAP(int rdage[200];int * oidrdage;int ObjSeqId;int objtypetraverse[TOTALNUMCLASSANDARRAY];);
662   struct garbagelist * oidwrlocked;
663   void ** dirwrlocked;
664 #if defined(STMARRAY)&&defined(DELAYCOMP)
665   int wrindex[200];
666   int * dirwrindex;
667 #endif
668   allocarrays;
669
670   STMWRAP(for(i=0; i<TOTALNUMCLASSANDARRAY; i++) objtypetraverse[i] = 0;);
671
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)
681         break;
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;
687
688       if(STATUS(headeraddr) & DIRTY) {
689         PROCESSARRAY
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;
695           } else {
696             dirwrlocked[numoidwrlocked++] = objptr;
697             transAbortProcess(oidwrlocked, numoidwrlocked ARRAYDELAYWRAP1(NULL) ARRAYDELAYWRAP1(numoidwrlocked));
698             ABORTSTAT1;
699             freearrays;
700             if (softabort)
701               return TRANS_SOFT_ABORT;
702             else 
703               return TRANS_ABORT;
704           }
705         } else {
706           if(version == header->version) {
707             /* versions match */
708             softabort=1;
709           }
710           transAbortProcess(oidwrlocked, numoidwrlocked ARRAYDELAYWRAP1(NULL) ARRAYDELAYWRAP1(numoidwrlocked));
711           ABORTSTAT1;
712           freearrays;
713           if (softabort)
714             return TRANS_SOFT_ABORT;
715           else 
716             return TRANS_ABORT;
717       
718         }
719       } else {
720         STMWRAP(oidrdage[numoidrdlocked]=headeraddr->accessCount;);
721         oidrdversion[numoidrdlocked]=version;
722         oidrdlocked[numoidrdlocked++]=header;
723       }
724       curr = curr->next;
725     }
726   } //end of for
727   
728   ACCESSLOCKS;
729
730   //THIS IS THE SERIALIZATION END POINT (START POINT IS END OF EXECUTION)*****
731   READARRAYS;
732
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
738       CFENCE;
739       if(version != header->version) { /* versions do not match */
740         transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
741         ABORTSTAT2;
742         freearrays;
743         return TRANS_ABORT;
744       }
745 #if DELAYCOMP
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));
751         ABORTSTAT2;
752         freearrays;
753         return TRANS_ABORT;
754       }
755 #endif
756     } else { /* cannot aquire lock */
757       //do increment as we didn't get lock
758       if(version == header->version) {
759         softabort=1;
760       }
761       transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
762       ABORTSTAT2;
763       freearrays;
764       if (softabort)
765         return TRANS_SOFT_ABORT;
766       else 
767         return TRANS_ABORT;
768     }
769   }
770
771 #ifdef READSET
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));
780     if(header->lock>0) {
781       //object is not write locked
782       if (unlikely(version!=header->version)) {
783         //have to abort
784         transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
785         STMWRAP((typesCausingAbort[TYPE(header)])++;);
786         freearrays;
787         if (softabort)
788           return TRANS_SOFT_ABORT;
789         else
790           return TRANS_ABORT;
791       }
792     } else {
793       //maybe we already have lock
794       if (likely(version==header->version)) {
795         void * key=rd_curr->key;
796 #ifdef DELAYCOMP
797         //check to see if it is in the delaycomp table
798         {
799           dchashlistnode_t *node = &dc_c_table[(((unsigned INTPTR)key) & dc_c_mask)>>4];
800           do {
801             if(node->key == key) {
802               goto nextloopread;
803             }
804             node = node->next;
805           } while(node != NULL);
806         }
807 #endif
808         //check normal table
809 #ifdef STMARRAY
810       if (likely(objptr->type>=NUMCLASSES||header->lock==(RW_LOCK_BIAS-1))) {   
811 #else
812         {
813 #endif
814           chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
815           do {
816             if(node->key == key) {
817               objheader_t * headeraddr=&((objheader_t *) node->val)[-1];          
818               if(STATUS(headeraddr) & DIRTY) {
819                 goto nextloopread;
820               }
821             }
822             node = node->next;
823           } while(node != NULL);
824         }
825       }
826       //have to abort to avoid deadlock
827       transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
828       STMWRAP((typesCausingAbort[TYPE(header)])++;);
829       freearrays;
830       if (softabort)
831         return TRANS_SOFT_ABORT;
832       else
833         return TRANS_ABORT;
834     }
835   nextloopread:
836     rd_curr = rd_curr->lnext;
837   }
838 #endif
839   
840   /* Decide the final response */
841 #ifdef DELAYCOMP
842   transCommitProcess(oidwrlocked ARRAYDELAYWRAP1(dirwrindex), numoidwrlocked, numoidwrtotal, commitmethod, primitives, locals, params);
843 #else
844   transCommitProcess(oidwrlocked, numoidwrlocked);
845 #endif
846   freearrays;
847   return TRANS_COMMIT;
848 }
849
850 /* ==================================================
851  * alttraverseCache
852  * - goes through the transaction cache and
853  * - decides if a transaction should commit or abort
854  * ==================================================
855  */
856
857 #ifdef DELAYCOMP
858 int alttraverseCache(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
859 #else
860 int alttraverseCache() {
861 #endif
862   /* Create info to keep track of objects that can be locked */
863   int numoidrdlocked=0;
864   int numoidwrlocked=0;
865   void * rdlocked[200];
866   int rdversion[200];
867   struct fixedlist wrlocked;
868   int softabort=0;
869   int i;
870   void ** oidrdlocked;
871   int * oidrdversion;
872   STMWRAP(int rdage[200];int * oidrdage;int ObjSeqId;int objtypetraverse[TOTALNUMCLASSANDARRAY];);
873   ARRAYDEFINES;
874   struct garbagelist * oidwrlocked;
875   void ** dirwrlocked;
876 #if defined(STMARRAY)&&defined(DELAYCOMP)
877   int wrindex[200];
878   int * dirwrindex;
879 #endif
880   allocarrays;
881
882   STMWRAP(for(i=0; i<TOTALNUMCLASSANDARRAY; i++) objtypetraverse[i] = 0;);
883
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;
893
894     if(STATUS(headeraddr) & DIRTY) {
895       PROCESSARRAY
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;
901         } else {
902           dirwrlocked[numoidwrlocked++] = objptr;
903           transAbortProcess(oidwrlocked, numoidwrlocked ARRAYDELAYWRAP1(NULL) ARRAYDELAYWRAP1(numoidwrlocked));
904           ABORTSTAT3;
905           freearrays;
906           return TRANS_ABORT;
907         }
908       } else { /* cannot aquire lock */
909         if(version == header->version) {
910           /* versions match */
911           softabort=1;
912         }
913         transAbortProcess(oidwrlocked, numoidwrlocked ARRAYDELAYWRAP1(NULL) ARRAYDELAYWRAP1(numoidwrlocked));
914         ABORTSTAT3;
915         freearrays;
916         if (softabort)
917           return TRANS_SOFT_ABORT;
918         else 
919           return TRANS_ABORT;
920       }
921     } else {
922       /* Read from the main heap  and compare versions */
923       oidrdversion[numoidrdlocked]=version;
924       oidrdlocked[numoidrdlocked++] = header;
925     }
926     curr = curr->lnext;
927   }
928
929   ACCESSLOCKS;
930
931   //THIS IS THE SERIALIZATION END POINT (START POINT IS END OF EXECUTION)*****
932   READARRAYS;
933
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)) {
938       CFENCE;
939       if(unlikely(version != header->version)) {
940         transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
941         ABORTSTAT2;
942         freearrays;
943         return TRANS_ABORT;
944       }
945 #ifdef DELAYCOMP
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));
951         ABORTSTAT4;
952         freearrays;
953         return TRANS_ABORT;
954       }
955 #endif
956     } else { /* cannot aquire lock */
957       if(version == header->version) {
958         softabort=1;
959       }
960       transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
961       ABORTSTAT2;
962       freearrays;
963       if (softabort)
964         return TRANS_SOFT_ABORT;
965       else 
966         return TRANS_ABORT;
967     }
968   }
969
970 #ifdef READSET
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)) {
981         //have to abort
982         transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
983         STMWRAP((typesCausingAbort[TYPE(header)])++;);
984         freearrays;
985         if (softabort)
986           return TRANS_SOFT_ABORT;
987         else
988           return TRANS_ABORT;   
989       }
990     } else {
991       if (version==header->version) {
992         void * key=rd_curr->key;
993 #ifdef DELAYCOMP
994         //check to see if it is in the delaycomp table
995         {
996           dchashlistnode_t *node = &dc_c_table[(((unsigned INTPTR)key) & dc_c_mask)>>4];
997           do {
998             if(node->key == key)
999               goto nextloopread;
1000             node = node->next;
1001           } while(node != NULL);
1002         }
1003 #endif
1004         //check normal table
1005 #ifdef STMARRAY
1006         if (likely(objptr->type>=NUMCLASSES||header->lock==(RW_LOCK_BIAS-1))) { 
1007 #else
1008           {
1009 #endif
1010           chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
1011           do {
1012             if(node->key == key) {
1013               objheader_t * headeraddr=&((objheader_t *) node->val)[-1];          
1014               if(STATUS(headeraddr) & DIRTY) {
1015                 goto nextloopread;
1016               }
1017             }
1018             node = node->next;
1019           } while(node != NULL);
1020         }
1021       }
1022       //have to abort to avoid deadlock
1023       transAbortProcess(oidwrlocked, NUMWRTOTAL ARRAYDELAYWRAP1(dirwrindex) ARRAYDELAYWRAP1(numoidwrlocked));
1024       STMWRAP((typesCausingAbort[TYPE(header)])++;);
1025       freearrays;
1026       if (softabort)
1027         return TRANS_SOFT_ABORT;
1028       else
1029         return TRANS_ABORT;
1030     }
1031   nextloopread:
1032     rd_curr = rd_curr->lnext;
1033   }
1034 #endif
1035
1036   /* Decide the final response */
1037 #ifdef DELAYCOMP
1038   transCommitProcess(oidwrlocked ARRAYDELAYWRAP1(dirwrindex), numoidwrlocked, numoidwrtotal, commitmethod, primitives, locals, params);
1039 #else
1040   transCommitProcess(oidwrlocked, numoidwrlocked);
1041 #endif
1042   freearrays;
1043   return TRANS_COMMIT;
1044 }
1045
1046 /* ==================================
1047  * transAbortProcess
1048  *
1049  * =================================
1050  */
1051
1052 int logflag=1;
1053  
1054 #if defined(STMARRAY)&&defined(DELAYCOMP)
1055 void transAbortProcess(struct garbagelist *oidwrlocked, int numoidwrtotal, int * dirwrindex, int numoidwrlocked) {
1056 #else
1057 void transAbortProcess(struct garbagelist *oidwrlocked, int numoidwrlocked) {
1058 #endif
1059   int i;
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];
1068 #ifdef STMARRAY
1069     int type=dst->type;
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);
1075       int j;
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);
1084         }
1085       }
1086 #ifdef DUALVIEW
1087       //release object array lock
1088       rwread_unlock(&header->lock);
1089 #endif
1090     } else
1091 #endif
1092       write_unlock(&header->lock);
1093   }
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];
1100     if (wrindex==-1) {
1101       //normal object
1102       write_unlock(&header->lock);
1103     } else {
1104       //array element
1105       unsigned int *intptr;
1106       GETLOCKPTR(intptr, ((struct ArrayObject *)dst), wrindex);
1107       write_unlock(intptr);
1108     }
1109   }
1110 #endif
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];
1117     if (wrindex==-1) {
1118       //normal object
1119       write_unlock(&header->lock);
1120     } else if (wrindex==0) {
1121       //array element
1122       rwwrite_unlock(&header->lock);
1123     } else {
1124       rwconvert_unlock(&header->lock);
1125     }
1126   }
1127 #endif
1128 #ifdef STMSTATS
1129   /* clear trec and then release objects locked */
1130   struct objlist *ptr=lockedobjs;
1131   while(ptr!=NULL) {
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);
1137     }
1138     ptr=ptr->next;
1139   }
1140 #endif
1141 }
1142
1143 /* ==================================
1144  * transCommitProcess
1145  *
1146  * =================================
1147  */
1148 #ifdef DELAYCOMP
1149 void transCommitProcess(struct garbagelist * oidwrlocked ARRAYDELAYWRAP1(int * dirwrindex), int numoidwrlocked, int numoidwrtotal, void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
1150 #else
1151 void transCommitProcess(struct garbagelist * oidwrlocked, int numoidwrlocked) {
1152 #endif
1153   objheader_t *header;
1154   void *ptrcreate;
1155   int i;
1156   struct objlist *ptr=newobjs;
1157   void **dirwrlocked=oidwrlocked->array;
1158   while(ptr!=NULL) {
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;
1163     }
1164     ptr=ptr->next;
1165   }
1166
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];
1171     int tmpsize;
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___;
1177 #ifdef STMARRAY
1178     int type=dst->type;
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);
1183       int j;
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);
1194         }
1195       }
1196     } else
1197 #endif 
1198       A_memcpy(&dst[1], &src[1], tmpsize-sizeof(struct ___Object___));
1199   }
1200   CFENCE;
1201
1202 #ifdef DELAYCOMP
1203   //  call commit method
1204   ptrstack.maxcount=0;
1205   primstack.count=0;
1206   branchstack.count=0;
1207 #if defined(STMARRAY)&&!defined(DUALVIEW)
1208   arraystack.maxcount=0;
1209 #endif
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;
1217 #endif
1218
1219   /* Release write locks */
1220 #if defined(STMARRAY)&&defined(DELAYCOMP)
1221   for(i=numoidwrlocked-1; i>=0; i--) {
1222 #else
1223   for(i=NUMWRTOTAL-1; i>=0; i--) {
1224 #endif
1225     struct ___Object___ * dst=dirwrlocked[i];
1226     header = &((objheader_t *)dst)[-1];
1227 #ifdef STMARRAY
1228     int type=dst->type;
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);
1234       int j;
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);
1242           (*intptr)++;
1243           GETLOCKPTR(intptr, ((struct ArrayObject *)dst), j);
1244           write_unlock(intptr);
1245         }
1246       }
1247       atomic_inc(&header->version);
1248 #ifdef DUALVIEW
1249       rwread_unlock(&header->lock);
1250 #endif
1251     } else
1252 #endif
1253     {
1254       header->version++;
1255       write_unlock(&header->lock);
1256     }
1257   }
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];
1264     if (wrlock==-1) {
1265       header->version++;
1266       write_unlock(&header->lock);
1267     } else if (wrlock==0) {
1268       header->version++;
1269       rwwrite_unlock(&header->lock);
1270     } else {
1271       header->version++;
1272 #ifdef DUALVIEW
1273       ((struct ArrayObject*)dst)->arrayversion++;
1274 #endif
1275       rwconvert_unlock(&header->lock);
1276     }
1277   }
1278 #endif
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];
1285     if (wrindex==-1) {
1286       //normal object
1287       header->version++;
1288       write_unlock(&header->lock);
1289     } else {
1290       //array element
1291       unsigned int *intptr;
1292       atomic_inc(&header->version);
1293       GETVERSIONPTR(intptr, ((struct ArrayObject *)dst), wrindex);
1294       (*intptr)++;
1295       GETLOCKPTR(intptr, ((struct ArrayObject *)dst), wrindex);
1296       write_unlock(intptr);
1297     }
1298   }
1299 #endif
1300 #ifdef STMSTATS
1301   /* clear trec and then release objects locked */
1302   ptr=lockedobjs;
1303   while(ptr!=NULL) {
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);
1309     }
1310     ptr=ptr->next;
1311   }
1312 #endif
1313 }