a9cdb3e0d377a812d20a0297efe9d447b8802d6b
[IRC.git] / Robust / src / Runtime / mlp_runtime.c
1 #include "runtime.h"
2
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <assert.h>
6
7 #include "mem.h"
8 #include "mlp_runtime.h"
9 #include "workschedule.h"
10 #include "methodheaders.h"
11
12
13
14 /*
15 __thread struct Queue* seseCallStack;
16 __thread pthread_once_t mlpOnceObj = PTHREAD_ONCE_INIT;
17 void mlpInitOncePerThread() { 
18   seseCallStack = createQueue();
19 }
20 */
21 __thread SESEcommon_p seseCaller;
22
23
24 void* mlpAllocSESErecord( int size ) {
25   void* newrec = RUNMALLOC( size );  
26   if( newrec == 0 ) {
27     printf( "mlpAllocSESErecord did not obtain memory!\n" );
28     exit( -1 );
29   }
30   return newrec;
31 }
32
33
34 void mlpFreeSESErecord( void* seseRecord ) {
35   RUNFREE( seseRecord );
36 }
37
38 MemoryQueue** mlpCreateMemoryQueueArray(int numMemoryQueue){
39   int i;
40   MemoryQueue** newMemoryQueue=(MemoryQueue**)RUNMALLOC( sizeof( MemoryQueue* ) * numMemoryQueue );
41   for(i=0; i<numMemoryQueue; i++){
42     newMemoryQueue[i]=createMemoryQueue();
43   }
44   return newMemoryQueue;
45 }
46
47 REntry* mlpCreateREntryArray(){
48   REntry* newREntryArray=(REntry*)RUNMALLOC(sizeof(REntry)*NUMRENTRY);
49   return newREntryArray;
50 }
51
52 REntry* mlpCreateFineREntry(int type, void* seseToIssue, void* dynID){
53   REntry* newREntry=(REntry*)RUNMALLOC(sizeof(REntry));
54   newREntry->type=type;
55   newREntry->seseRec=seseToIssue;
56   newREntry->pointer=dynID;
57   if((*newREntry->pointer)!=0){// make sure it is not unresolved address.
58     struct ___Object___ * obj=(struct ___Object___*)((unsigned INTPTR)*newREntry->pointer);
59     newREntry->oid=obj->oid;
60   }
61   return newREntry;
62 }
63
64 REntry* mlpCreateREntry(int type, void* seseToIssue){
65   REntry* newREntry=(REntry*)RUNMALLOC(sizeof(REntry));
66   newREntry->type=type;
67   newREntry->seseRec=seseToIssue;
68   return newREntry;
69 }
70
71 int isParent(REntry *r) {
72   if (r->type==PARENTREAD || r->type==PARENTWRITE || r->type==PARENTCOARSE) {
73     return TRUE;
74   } else {
75     return FALSE;
76   }
77 }
78
79 int isParentCoarse(REntry *r){
80   if (r->type==PARENTCOARSE){
81     return TRUE;
82   }else{
83     return FALSE;
84   }
85 }
86
87 int isFineRead(REntry *r) {
88   if (r->type==READ || r->type==PARENTREAD) {
89     return TRUE;
90   } else {
91     return FALSE;
92   }
93 }
94
95 int isFineWrite(REntry *r) {
96   if (r->type==WRITE || r->type==PARENTWRITE) {
97     return TRUE;
98   } else {
99     return FALSE;
100   }
101 }
102
103 int isCoarse(REntry *r){
104   if(r->type==COARSE || r->type==PARENTCOARSE){
105     return TRUE;
106   } else {
107     return FALSE;
108   }
109 }
110
111 int isSCC(REntry *r){
112   if(r->type==SCCITEM){
113     return TRUE;
114   } else {
115     return FALSE;
116   }
117 }
118
119 int isSingleItem(MemoryQueueItem *qItem){
120   if(qItem->type==SINGLEITEM){
121     return TRUE;
122   } else {
123     return FALSE;
124   }
125 }
126
127 int isHashtable(MemoryQueueItem *qItem){
128   if(qItem->type==HASHTABLE){
129     return TRUE;
130   } else {
131     return FALSE;
132   }
133 }
134
135 int isVector(MemoryQueueItem *qItem){
136   if(qItem->type==VECTOR){
137     return TRUE;
138   } else {
139     return FALSE;
140   }
141 }
142
143 int isReadBinItem(BinItem* b){
144   if(b->type==READBIN){
145     return TRUE;
146   }else{
147     return FALSE;
148   }
149 }
150
151 int isWriteBinItem(BinItem* b){
152   if(b->type==WRITEBIN){
153     return TRUE;
154   }else{
155     return FALSE;
156   }
157 }
158
159 int generateKey(unsigned int data){
160   return (data&H_MASK)>> 4;
161 }
162
163 Hashtable* createHashtable(){
164   int i=0;
165   Hashtable* newTable=(Hashtable*)RUNMALLOC(sizeof(Hashtable));
166   newTable->item.type=HASHTABLE;
167   for(i=0;i<NUMBINS;i++){
168     newTable->array[i]=(BinElement*)RUNMALLOC(sizeof(BinElement));
169     newTable->array[i]->head=NULL;
170     newTable->array[i]->tail=NULL;
171   }
172   newTable->unresolvedQueue=NULL;
173   return newTable;
174 }
175
176 WriteBinItem* createWriteBinItem(){
177   WriteBinItem* binitem=(WriteBinItem*)RUNMALLOC(sizeof(WriteBinItem));
178   binitem->item.type=WRITEBIN;
179   return binitem;
180 }
181
182 ReadBinItem* createReadBinItem(){
183   ReadBinItem* binitem=(ReadBinItem*)RUNMALLOC(sizeof(ReadBinItem));
184   binitem->index=0;
185   binitem->item.type=READBIN;
186   return binitem;
187 }
188
189 Vector* createVector(){
190   Vector* vector=(Vector*)RUNMALLOC(sizeof(Vector));
191   vector->index=0;
192   vector->item.type=VECTOR;
193   return vector;
194 }
195
196 SCC* createSCC(){
197   SCC* scc=(SCC*)RUNMALLOC(sizeof(SCC));
198   scc->item.type=SINGLEITEM;
199   return scc;
200 }
201
202 MemoryQueue* createMemoryQueue(){
203   MemoryQueue* queue = (MemoryQueue*)RUNMALLOC(sizeof(MemoryQueue));
204   MemoryQueueItem* dummy=(MemoryQueueItem*)RUNMALLOC(sizeof(MemoryQueueItem));
205   dummy->type=3; // dummy type
206   dummy->total=0;
207   dummy->status=READY;
208   queue->head = dummy;
209   queue->tail = dummy;
210   return queue;
211 }
212
213 int ADDRENTRY(MemoryQueue * q, REntry * r) {
214   if (isFineRead(r) || isFineWrite(r)) { 
215     return ADDTABLE(q, r);
216   } else if (isCoarse(r)) {
217     return ADDVECTOR(q, r);
218   } else if (isSCC(r)) {
219     return ADDSCC(q, r);
220   }
221 }
222
223 int ADDTABLE(MemoryQueue *q, REntry *r) {
224   if(!isHashtable(q->tail)) {
225     //Fast Case
226     MemoryQueueItem* tail=q->tail;
227     if (isParent(r) && tail->total==0 && q->tail==q->head) {
228       return READY;
229     }
230
231     //Add table
232     Hashtable* h=createHashtable();
233     tail->next=(MemoryQueueItem*)h;
234     //************NEED memory barrier here to ensure compiler does not cache Q.tail.status********
235     if (BARRIER() && tail->status==READY && tail->total==0 && q->tail==q->head) { 
236       //previous Q item is finished
237       h->item.status=READY;
238     }
239     q->tail=(MemoryQueueItem*)h;
240     // handle the the queue item case
241     if(q->head->type==3){
242       q->head=(MemoryQueueItem*)h;
243     }
244   }
245
246   //at this point, have table
247   Hashtable* table=(Hashtable*)q->tail;
248   r->hashtable=table; // set rentry's hashtable
249   if((*(r->pointer)==0 || (*(r->pointer)!=0 && BARRIER() && table->unresolvedQueue!=NULL))){
250     struct Queue* val;
251     // grab lock on the queue    
252     do {  
253       val=(struct Queue*)0x1;       
254       val=(struct Queue*)LOCKXCHG((unsigned INTPTR*)&(table->unresolvedQueue), (unsigned INTPTR)val);
255     } while(val==(struct Queue*)0x1);     
256     if(val==NULL){
257       //queue is null, first case
258       if(*(r->pointer)!=0){
259         // check whether pointer is already resolved, or not.
260         table->unresolvedQueue=NULL; //released lock;
261         return ADDTABLEITEM(table,r,TRUE);
262       }
263       struct Queue* queue=createQueue();
264       addNewItemBack(queue,r);
265       atomic_inc(&table->item.total); 
266       table->unresolvedQueue=queue; // expose new queue     
267     }else{ 
268       // add unresolved rentry at the end of the queue.
269       addNewItemBack(val,r);
270       atomic_inc(&table->item.total);    
271       table->unresolvedQueue=val; // released lock
272     }   
273     return NOTREADY;
274   }
275   BinItem * val;
276   //int key=generateKey((unsigned int)(unsigned INTPTR)*(r->pointer));  
277   int key=generateKey(r->oid);
278   do {  
279     val=(BinItem*)0x1;       
280     BinElement* bin=table->array[key];
281     val=(BinItem*)LOCKXCHG((unsigned INTPTR*)&(bin->head), (unsigned INTPTR)val);//note...talk to me about optimizations here. 
282   } while(val==(BinItem*)0x1);
283   //at this point have locked bin
284   if (val==NULL) {
285     return EMPTYBINCASE(table, table->array[key], r, TRUE);
286   } else {
287     if (isFineWrite(r)) {
288       return WRITEBINCASE(table, r, val, key, TRUE);
289     } else if (isFineRead(r)) {
290       return READBINCASE(table, r, val, key, TRUE);
291     }
292   }
293 }
294
295 int ADDTABLEITEM(Hashtable* table, REntry* r, int inc){
296  
297   BinItem * val;
298   //  int key=generateKey((unsigned int)(unsigned INTPTR)*(r->pointer));
299   int key=generateKey(r->oid);
300   do {  
301     val=(BinItem*)0x1;       
302     BinElement* bin=table->array[key];
303     val=(BinItem*)LOCKXCHG((unsigned INTPTR*)&(bin->head), (unsigned INTPTR)val); 
304   } while(val==(BinItem*)0x1);
305   //at this point have locked bin
306   if (val==NULL) {
307     return EMPTYBINCASE(table, table->array[key], r, inc);
308   } else {
309     if (isFineWrite(r)) {
310       return WRITEBINCASE(table, r, val, key, inc);
311     } else if (isFineRead(r)) {
312       return READBINCASE(table, r, val, key, inc);
313     }
314   }
315 }
316
317 int EMPTYBINCASE(Hashtable *T, BinElement* be, REntry *r, int inc) {
318   int retval;
319   BinItem* b;
320   if (isFineWrite(r)) {
321     b=(BinItem*)createWriteBinItem();
322     ((WriteBinItem*)b)->val=r;//<-only different statement
323   } else if (isFineRead(r)) {
324     b=(BinItem*)createReadBinItem();
325     ReadBinItem* readbin=(ReadBinItem*)b;
326     readbin->array[readbin->index++]=r;
327   }
328   b->total=1;
329
330   if (T->item.status==READY) { 
331     //current entry is ready
332     b->status=READY;
333     retval=READY;
334     if (isParent(r)) {
335       be->head=NULL; // released lock
336       return retval;
337     }
338   } else {
339     b->status=NOTREADY;
340     retval=NOTREADY;
341   }
342
343   if(inc){
344     atomic_inc(&T->item.total);
345   }
346   r->hashtable=T;
347   r->binitem=b;
348   be->tail=b;
349   be->head=b;//released lock
350   return retval;
351 }
352
353 int WRITEBINCASE(Hashtable *T, REntry *r, BinItem *val, int key, int inc) {
354   //chain of bins exists => tail is valid
355   //if there is something in front of us, then we are not ready
356
357   int retval=NOTREADY;
358   BinElement* be=T->array[key];
359
360   BinItem *bintail=be->tail;
361
362   WriteBinItem *b=createWriteBinItem();
363   b->val=r;
364   b->item.total=1;
365
366   // note: If current table clears all dependencies, then write bin is ready
367   
368   
369   if(inc){
370     atomic_inc(&T->item.total);
371   }
372
373   r->hashtable=T;
374   r->binitem=(BinItem*)b;
375
376   be->tail->next=(BinItem*)b;
377   //need to check if we can go...
378   BARRIER();
379   if (T->item.status==READY) {
380     for(;val!=NULL;val=val->next) {
381       if (val==((BinItem *)b)) {
382         //ready to retire
383         retval=READY;
384         if (isParent(r)) {
385           b->item.status=retval;//unsure if really needed at this point..
386           be->head=NULL; // released lock
387           return retval;
388         }
389         break;
390       } else if (val->total!=0) {
391         break;
392       }
393     }
394   }
395   
396   b->item.status=retval;
397   be->tail=(BinItem*)b;
398   be->head=val;
399   return retval;
400 }
401
402 READBINCASE(Hashtable *T, REntry *r, BinItem *val, int key, int inc) {
403   BinItem * bintail=T->array[key]->tail;
404   if (isReadBinItem(bintail)) {
405     return TAILREADCASE(T, r, val, bintail, key, inc);
406   } else if (!isReadBinItem(bintail)) {
407     TAILWRITECASE(T, r, val, bintail, key, inc);
408     return NOTREADY;
409   }
410 }
411
412 int TAILREADCASE(Hashtable *T, REntry *r, BinItem *val, BinItem *bintail, int key, int inc) {
413   ReadBinItem * readbintail=(ReadBinItem*)T->array[key]->tail;
414   int status, retval;
415   if (readbintail->item.status==READY) { 
416     status=READY;
417     retval=READY;
418     if (isParent(r)) {
419       T->array[key]->head=val;//released lock
420       return READY;
421     }
422   } else {
423     status=NOTREADY;
424     retval=NOTREADY;
425   }
426
427   if (readbintail->index==NUMREAD) { // create new read group
428     ReadBinItem* rb=createReadBinItem();
429     rb->array[rb->index++]=r;
430     rb->item.total=1;//safe only because item could not have started
431     rb->item.status=status;
432     T->array[key]->tail->next=(BinItem*)rb;
433     T->array[key]->tail=(BinItem*)rb;
434     r->binitem=(BinItem*)rb;
435   } else { // group into old tail
436     readbintail->array[readbintail->index++]=r;
437     atomic_inc(&readbintail->item.total);
438     r->binitem=(BinItem*)readbintail;
439     //printf("grouping with %d\n",readbintail->index);
440   }
441   if(inc){
442     atomic_inc(&T->item.total);
443   }
444   r->hashtable=T;
445   T->array[key]->head=val;//released lock
446   return retval;
447 }
448
449 TAILWRITECASE(Hashtable *T, REntry *r, BinItem *val, BinItem *bintail, int key, int inc) {
450   //  WriteBinItem* wb=createWriteBinItem();
451   //wb->val=r;
452   //wb->item.total=1;//safe because item could not have started
453   //wb->item.status=NOTREADY;
454   ReadBinItem* rb=createReadBinItem();
455   rb->array[rb->index++]=r;
456   rb->item.total=1;//safe because item could not have started
457   rb->item.status=NOTREADY;
458   if(inc){
459     atomic_inc(&T->item.total);
460   }
461   r->hashtable=T;
462   r->binitem=(BinItem*)rb;
463   T->array[key]->tail->next=(BinItem*)rb;
464   T->array[key]->tail=(BinItem*)rb;
465   T->array[key]->head=val;//released lock
466 }
467
468 ADDVECTOR(MemoryQueue *Q, REntry *r) {
469   if(!isVector(Q->tail)) {
470     //Fast Case
471     if (isParentCoarse(r) && Q->tail->total==0 && Q->tail==Q->head) { 
472       return READY;
473     }
474
475     //added vector
476     Vector* V=createVector();
477     Q->tail->next=(MemoryQueueItem*)V;     
478     //************NEED memory barrier here to ensure compiler does not cache Q.tail.status******
479     if (BARRIER() && Q->tail->status==READY&&Q->tail->total==0) { 
480       //previous Q item is finished
481       V->item.status=READY;
482     }
483     Q->tail=(MemoryQueueItem*)V;
484     // handle the the queue item case
485     if(Q->head->type==3){
486       Q->head=(MemoryQueueItem*)V;
487     }
488   }
489   //at this point, have vector
490   Vector* V=(Vector*)Q->tail;
491   if (V->index==NUMITEMS) {
492     //vector is full
493     //added vector
494     V=createVector();
495     V->item.status=NOTREADY;
496     Q->tail->next=(MemoryQueueItem*)V;
497     //***NEED memory barrier here to ensure compiler does not cache Q.tail.status******
498     if (BARRIER() && Q->tail->status==READY) { 
499       V->item.status=READY;
500     }
501     Q->tail=(MemoryQueueItem*)V;
502   }
503
504   atomic_inc(&V->item.total);
505   //expose entry
506   int index=V->index;
507   V->array[index]=r;
508   //*****NEED memory barrier here to ensure compiler does not reorder writes to V.array and V.index
509   BARRIER();
510   V->index++;
511   //*****NEED memory barrier here to ensure compiler does not cache V.status*********
512   r->vector=V;
513   if (BARRIER() && V->item.status==READY) {
514     void* flag=NULL;
515     flag=(void*)LOCKXCHG((unsigned INTPTR*)&(V->array[index]), (unsigned INTPTR)flag); 
516     if (flag!=NULL) {
517       if (isParentCoarse(r)) { //parent's retire immediately
518         atomic_dec(&V->item.total);   
519       }
520       return READY;
521     } else {
522       return NOTREADY;//<- means that some other dispatcher got this one...so need to do accounting correctly
523     }
524   } else {
525     return NOTREADY;
526   }
527 }
528
529
530 //SCC's don't come in parent variety
531 ADDSCC(MemoryQueue *Q, REntry *r) {
532   //added SCC
533   SCC* S=createSCC();
534   S->item.total=1; 
535   S->val=r;
536   r->scc=S;
537   Q->tail->next=(MemoryQueueItem*)S;
538   //*** NEED BARRIER HERE
539   if (BARRIER() && Q->tail->status==READY && Q->tail->total==0 && Q->tail==Q->head) {
540     //previous Q item is finished
541     S->item.status=READY;
542     Q->tail=(MemoryQueueItem*)S;
543     // handle the the queue item case
544     if(Q->head->type==3){
545       Q->head=(MemoryQueueItem*)S;
546     }
547     void* flag=NULL;
548     flag=(void*)LOCKXCHG((unsigned INTPTR*)&(S->val), (unsigned INTPTR)flag);
549     if (flag!=NULL) {
550       return READY;
551     } else {
552       return NOTREADY;//<- means that some other dispatcher got this one...so need to do accounting correctly
553     }
554   } else {
555     Q->tail=(MemoryQueueItem*)S;
556     return NOTREADY;
557   }
558 }
559
560
561 void RETIRERENTRY(MemoryQueue* Q, REntry * r) {
562   if (isFineWrite(r)||isFineRead(r)) {
563     RETIREHASHTABLE(Q, r);
564   } else if (isCoarse(r)) {
565     RETIREVECTOR(Q, r);
566   } else if (isSCC(r)) {
567     RETIRESCC(Q, r);
568   }
569 }
570
571 RETIRESCC(MemoryQueue *Q, REntry *r) {
572   SCC* s=r->scc;
573   s->item.total=0;//don't need atomicdec
574   RESOLVECHAIN(Q);
575 }
576
577
578 RETIREHASHTABLE(MemoryQueue *q, REntry *r) {
579   Hashtable *T=r->hashtable;
580   BinItem *b=r->binitem;
581   RETIREBIN(T,r,b);
582   atomic_dec(&T->item.total);
583   if (T->item.next!=NULL && T->item.total==0) { 
584     RESOLVECHAIN(q);
585   }
586 }
587
588 RETIREBIN(Hashtable *T, REntry *r, BinItem *b) {
589   //  int key=generateKey((unsigned int)(unsigned INTPTR)*(r->pointer));
590   int key=generateKey(r->oid);
591   if(isFineRead(r)) {
592     atomic_dec(&b->total);
593   }
594   if (isFineWrite(r) || (isFineRead(r) && b->next!=NULL && b->total==0)) {
595       // CHECK FIRST IF next is nonnull to guarantee that b.total cannot change
596     BinItem * val;
597     do {  
598       val=(BinItem*)0x1;
599       val=(BinItem*)LOCKXCHG((unsigned INTPTR*)&(T->array[key]->head), (unsigned INTPTR)val);
600     } while(val==(BinItem*)0x1);
601     // at this point have locked bin
602     BinItem *ptr=val;
603     int haveread=FALSE;
604     int i;
605     while (ptr!=NULL) {
606        if (isReadBinItem(ptr)) {
607         ReadBinItem* rptr=(ReadBinItem*)ptr;
608         if (rptr->item.status==NOTREADY) {
609           for (i=0;i<rptr->index;i++) {     
610             resolveDependencies(rptr->array[i]);
611             if (isParent(rptr->array[i])) {
612               //parents go immediately
613               atomic_dec(&rptr->item.total);
614               atomic_dec(&T->item.total);
615             }
616           }
617         }
618         rptr->item.status=READY; 
619         if (rptr->item.next==NULL) {
620           break;
621         }
622         if (rptr->item.total!=0) {
623           haveread=TRUE; 
624         } else if ((BinItem*)rptr==val) {
625           val=val->next;
626         }
627       } else if(isWriteBinItem(ptr)) {
628         if (haveread)  
629           break;
630         if(ptr->status==NOTREADY){
631           resolveDependencies(((WriteBinItem*)ptr)->val);
632           ptr->status=READY;
633           if(isParent(((WriteBinItem*)ptr)->val)){
634             atomic_dec(&T->item.total);
635             val=val->next;        
636           }else
637             break;
638         }else{ // write bin is already resolved
639           val=val->next;
640         }
641         /*
642         if(ptr->status==NOTREADY) {   
643           resolveDependencies(((WriteBinItem*)ptr)->val);
644         }        
645           ptr->status=READY;      
646           if (isParent(((WriteBinItem*)ptr)->val)) {  
647             atomic_dec(&T->item.total);
648             //val=val->next;
649             val=ptr->next;
650           } else
651             break;
652         } 
653         */
654       } 
655       ptr=ptr->next;
656     }
657     T->array[key]->head=val; // release lock
658   }
659 }
660
661
662 RETIREVECTOR(MemoryQueue *Q, REntry *r) {
663   Vector* V=r->vector;
664   atomic_dec(&V->item.total);
665   if (V->item.next!=NULL && V->item.total==0) { //NOTE: ORDERING CRUCIAL HERE
666     RESOLVECHAIN(Q);
667   }
668 }
669
670 RESOLVECHAIN(MemoryQueue *Q) {
671   while(TRUE) {
672     MemoryQueueItem* head=Q->head;
673     if (head->next==NULL||head->total!=0) { 
674       //item is not finished
675       if (head->status!=READY) {  
676         //need to update status
677         head->status=READY;
678         if (isHashtable(head)) {
679           RESOLVEHASHTABLE(Q, head);
680         } else if (isVector(head)) {
681           RESOLVEVECTOR(Q, head);
682         } else if (isSingleItem(head)) {
683           RESOLVESCC(head);
684         }
685         if (head->next==NULL)
686           break;
687         if (head->total!=0)
688           break;
689       } else
690         break;
691     }
692     MemoryQueueItem* nextitem=head->next;
693     CAS((unsigned INTPTR*)&(Q->head), (unsigned INTPTR)head, (unsigned INTPTR)nextitem);
694     //oldvalue not needed...  if we fail we just repeat
695   }
696 }
697
698
699 RESOLVEHASHTABLE(MemoryQueue *Q, Hashtable *T) {  
700   int binidx;
701   for (binidx=0;binidx<NUMBINS;binidx++) {    
702     BinElement* bin=T->array[binidx];
703     BinItem* val;
704     do {
705       val=(BinItem*)1;
706       val=(BinItem*)LOCKXCHG((unsigned INTPTR*)&(bin->head), (unsigned INTPTR)val);
707     } while (val==(BinItem*)1);
708     //at this point have locked bin    
709     int haveread=FALSE; 
710     BinItem* ptr=val;
711     if(ptr!=NULL&&ptr->status==NOTREADY) {
712       do {
713         if (isWriteBinItem(ptr)) {
714           if (haveread)
715             break;        
716           resolveDependencies(((WriteBinItem*)ptr)->val);
717           ptr->status=READY;  
718           if (isParent(((WriteBinItem*)ptr)->val)) {
719             atomic_dec(&T->item.total);
720             val=val->next;
721           } else
722             break;
723         } else if (isReadBinItem(ptr)) {
724           int i;
725           ReadBinItem* rptr=(ReadBinItem*)ptr;
726           for(i=0;i<rptr->index;i++) {
727             resolveDependencies(rptr->array[i]);
728             if (isParent(rptr->array[i])) {
729               atomic_dec(&rptr->item.total);
730               atomic_dec(&T->item.total);
731             }
732           }
733           if (rptr->item.next==NULL||rptr->item.total!=0) {
734             haveread=TRUE;
735           } else if((BinItem*)rptr==val) {
736             val=val->next;
737           }
738           rptr->item.status=READY; 
739         } 
740         ptr=ptr->next;  
741       }while(ptr!=NULL);   
742     }
743     bin->head=val; // released lock;
744   }
745 }
746
747 RESOLVEVECTOR(MemoryQueue *q, Vector *V) {
748   int i;
749   Vector* tmp=V;
750   //handle ready cases
751   while(TRUE) {
752     //enqueue everything
753     for (i=0;i<NUMITEMS;i++) {
754       REntry* val=NULL;
755       val=(REntry*)LOCKXCHG((unsigned INTPTR*)&(tmp->array[i]), (unsigned INTPTR)val); 
756       if (val!=NULL) { 
757         resolveDependencies(val);
758         if (isParent(val)) {
759           atomic_dec(&tmp->item.total);
760         }
761       }
762     }
763     if (tmp->item.next!=NULL&&isVector(tmp->item.next)) {
764       tmp=(Vector*)tmp->item.next;
765     } else {
766       break;
767     }
768   }
769 }
770
771 RESOLVESCC(SCC *S) {
772   //precondition: SCC's state is READY
773   void* flag=NULL;
774   flag=(void*)LOCKXCHG((unsigned INTPTR*)&(S->val), (unsigned INTPTR)flag); 
775   if (flag!=NULL) {
776     resolveDependencies(flag);
777   }
778 }
779
780
781 resolveDependencies(REntry* rentry){
782   SESEcommon* seseCommon=(SESEcommon*)rentry->seseRec;
783   if(rentry->type==READ || rentry->type==WRITE || rentry->type==COARSE || rentry->type==SCCITEM){   
784     if( atomic_sub_and_test(1, &(seseCommon->unresolvedDependencies)) ){
785       workScheduleSubmit(seseCommon);
786     }   
787   }else if(rentry->type==PARENTREAD || rentry->type==PARENTWRITE ||rentry->type==PARENTCOARSE){
788      psem_give(&(rentry->parentStallSem));
789   }
790 }
791
792 void INITIALIZEBUF(MemoryQueue * q){  
793   int i=0;
794   for(i=0; i<NUMBINS; i++){
795     q->binbuf[i]=NULL;
796   }
797   q->bufcount=0;
798 }
799
800 void ADDRENTRYTOBUF(MemoryQueue * q, REntry * r){
801   q->buf[q->bufcount]=r;
802   q->bufcount++;
803 }
804
805 int RESOLVEBUFFORHASHTABLE(MemoryQueue * q, Hashtable* table, SESEcommon *seseCommon){  
806   int i;
807  // first phase: only consider write rentry
808   for(i=0; i<q->bufcount;i++){
809     REntry *r=q->buf[i];
810     if(r->type==WRITE){
811       int key=generateKey(r->oid);
812       if(q->binbuf[key]==NULL){
813         // for multiple writes, add only the first write that hashes to the same bin
814         q->binbuf[key]=r;  
815       }else{
816         q->buf[i]=NULL;
817       }
818     }
819   }
820   // second phase: enqueue read items if it is eligible
821   for(i=0; i<q->bufcount;i++){
822     REntry *r=q->buf[i];    
823     if(r!=NULL && r->type==READ){
824       int key=generateKey(r->oid);
825       if(q->binbuf[key]==NULL){
826         // read item that hashes to the bin which doen't contain any write
827         seseCommon->rentryArray[seseCommon->rentryIdx++]=r;
828         if(ADDTABLEITEM(table, r, FALSE)==READY){
829           resolveDependencies(r);
830         }
831       }
832       q->buf[i]=NULL;
833     }
834   }
835   
836   // then, add only one of write items that hashes to the same bin
837   for(i=0; i<q->bufcount;i++){
838     REntry *r=q->buf[i];   
839     if(r!=NULL){
840       seseCommon->rentryArray[seseCommon->rentryIdx++]=r;
841       if(ADDTABLEITEM(table, r, FALSE)==READY){
842         resolveDependencies(r);
843       }      
844     }
845   }
846 }
847
848 int RESOLVEBUF(MemoryQueue * q, SESEcommon *seseCommon){
849   int localCount=0;
850   int i;
851   // check if every waiting entry is resolved
852   // if not, defer every items for hashtable until it is resolved.
853   int unresolved=FALSE;
854   for(i=0; i<q->bufcount;i++){
855      REntry *r=q->buf[i];
856      if(*(r->pointer)==0){
857        unresolved=TRUE;
858      }
859   }
860   if(unresolved==TRUE){
861     for(i=0; i<q->bufcount;i++){
862       REntry *r=q->buf[i];
863       r->queue=q;
864       r->isBufMode=TRUE;
865       if(ADDRENTRY(q,r)==NOTREADY){
866         localCount++;
867       }
868     }
869     return localCount;
870   }
871
872   // first phase: only consider write rentry
873   for(i=0; i<q->bufcount;i++){
874     REntry *r=q->buf[i];
875     if(r->type==WRITE){
876       int key=generateKey(r->oid);
877       if(q->binbuf[key]==NULL){
878         // for multiple writes, add only the first write that hashes to the same bin
879         q->binbuf[key]=r;  
880       }else{
881         q->buf[i]=NULL;
882       }
883     }
884   }
885   // second phase: enqueue read items if it is eligible
886   for(i=0; i<q->bufcount;i++){
887     REntry *r=q->buf[i];    
888     if(r!=NULL && r->type==READ){
889       int key=generateKey(r->oid);
890       if(q->binbuf[key]==NULL){
891         // read item that hashes to the bin which doen't contain any write
892         seseCommon->rentryArray[seseCommon->rentryIdx++]=r;
893         if(ADDRENTRY(q,r)==NOTREADY){
894           localCount++;
895         }
896       }
897       q->buf[i]=NULL;
898     }
899   }
900   
901   // then, add only one of write items that hashes to the same bin
902   for(i=0; i<q->bufcount;i++){
903     REntry *r=q->buf[i];   
904     if(r!=NULL){
905       seseCommon->rentryArray[seseCommon->rentryIdx++]=r;
906       if(ADDRENTRY(q,r)==NOTREADY){
907         localCount++;
908       }
909     }
910   }
911   return localCount;
912 }
913
914
915 resolvePointer(REntry* rentry){  
916  
917   Hashtable* table=rentry->hashtable;
918   MemoryQueue* queue;
919   if(table==NULL){
920     //resolved already before related rentry is enqueued to the waiting queue
921     return;
922   }
923   struct Queue* val;
924   do {  
925     val=(struct Queue*)0x1;       
926     val=(struct Queue*)LOCKXCHG((unsigned INTPTR*)&(table->unresolvedQueue), (unsigned INTPTR)val);
927   } while(val==(struct Queue*)0x1); 
928   if(val!=NULL && getHead(val)->objectptr==rentry){
929     // handling pointer is the first item of the queue
930     // start to resolve until it reaches unresolved pointer or end of queue
931     INTPTR currentSESE=0;
932     do{
933       struct QueueItem* head=getHead(val);
934       if(head!=NULL){
935         REntry* rentry=(REntry*)head->objectptr;  
936         if(*(rentry->pointer)==0){
937           // encounters following unresolved pointer
938           table->unresolvedQueue=val;//released lock
939           break;
940         }
941         removeItem(val,head);
942         //now, address is resolved. update OID field.
943         struct ___Object___ * obj=(struct ___Object___*)((unsigned INTPTR)*rentry->pointer);
944         rentry->oid=obj->oid;
945         
946         //check if rentry is buffer mode
947         if(rentry->isBufMode==TRUE){
948           if(currentSESE==0){
949             queue=rentry->queue;
950             INITIALIZEBUF(queue);
951             currentSESE=(INTPTR)rentry;
952             ADDRENTRYTOBUF(queue,rentry);
953           } else if(currentSESE==(INTPTR)rentry){
954             ADDRENTRYTOBUF(queue,rentry);
955           } else if(currentSESE!=(INTPTR)rentry){
956             RESOLVEBUFFORHASHTABLE(queue,table,(SESEcommon*)rentry->seseRec);
957             currentSESE=(INTPTR)rentry;
958             INITIALIZEBUF(queue);
959             ADDRENTRYTOBUF(rentry->queue,rentry);
960           }
961         }else{
962           if(currentSESE!=0){ 
963             //previous SESE has buf mode, need to invoke resolve buffer
964             RESOLVEBUFFORHASHTABLE(queue,table,(SESEcommon*)rentry->seseRec);
965             currentSESE=0;
966           }
967           //normal mode
968           if(ADDTABLEITEM(table, rentry, FALSE)==READY){
969             resolveDependencies(rentry);
970           }
971         }
972       }else{
973         table->unresolvedQueue=NULL; // set hashtable as normal-mode.
974         break;
975       }
976     }while(TRUE);
977   }else{
978     // resolved rentry is not head of queue
979     table->unresolvedQueue=val;//released lock;
980   }  
981 }
982
983 void rehashMemoryQueue(SESEcommon_p seseParent){    
984 #if 0
985   // update memory queue
986   int i,binidx;
987   for(i=0; i<seseParent->numMemoryQueue; i++){
988     MemoryQueue *memoryQueue=seseParent->memoryQueueArray[i];
989     MemoryQueueItem *memoryItem=memoryQueue->head;
990     MemoryQueueItem *prevItem=NULL;
991     while(memoryItem!=NULL){
992       if(memoryItem->type==HASHTABLE){
993         //do re-hash!
994         Hashtable* ht=(Hashtable*)memoryItem;
995         Hashtable* newht=createHashtable();     
996         int binidx;
997         for(binidx=0; binidx<NUMBINS; binidx++){
998           BinElement *bin=ht->array[binidx];
999           BinItem *binItem=bin->head;
1000           //traverse over the list of each bin
1001           while(binItem!=NULL){
1002             if(binItem->type==READBIN){
1003               ReadBinItem* readBinItem=(ReadBinItem*)binItem;
1004               int ridx;
1005               for(ridx=0; ridx<readBinItem->index; ridx++){
1006                 REntry *rentry=readBinItem->array[ridx];
1007                 int newkey=generateKey((unsigned int)(unsigned INTPTR)*(rentry->pointer));      
1008                 int status=rentry->binitem->status;           
1009                 ADDTABLEITEM(newht,rentry,TRUE);
1010                 rentry->binitem->status=status; // update bin status as before rehash
1011               }
1012             }else{//write bin
1013               REntry *rentry=((WriteBinItem*)binItem)->val;
1014               int newkey=generateKey((unsigned int)(unsigned INTPTR)*(rentry->pointer));        
1015               int status=rentry->binitem->status;             
1016               ADDTABLEITEM(newht,rentry,TRUE);                
1017               int newstatus=rentry->binitem->status;
1018               //printf("[%d]old status=%d new status=%d\n",i,status,newstatus);
1019               rentry->binitem->status=status; // update bin status as before rehash
1020             }
1021             binItem=binItem->next;
1022           }
1023         }
1024         newht->item.status=ht->item.status; // update hashtable status
1025         if(prevItem!=NULL){
1026           prevItem->next=(MemoryQueueItem*)newht;
1027         }else{
1028           if(memoryQueue->head==memoryQueue->tail){
1029             memoryQueue->tail=(MemoryQueueItem*)newht;
1030           }
1031           memoryQueue->head=(MemoryQueueItem*)newht;
1032         }
1033         newht->item.next=ht->item.next; 
1034       }
1035       prevItem=memoryItem;
1036       memoryItem=memoryItem->next;
1037     }
1038   }
1039 #endif
1040 }