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