// set up related allocation sites's waiting queues
// eom
- output.println(" /* set up waiting queues */");
- output.println(" int numRelatedWaitingQueue=0;");
- output.println(" int waitingQueueItemID=0;");
- ConflictGraph graph=null;
- graph=mlpa.getConflictGraphResults().get(fm);
- if(graph!=null){
- HashSet<SESELock> lockSet=mlpa.getConflictGraphLockMap().get(graph);
-
- if(lockSet.size()>0){
- output.println(" numRelatedWaitingQueue="+lockSet.size()+";");
- output.println(" seseCaller->numRelatedWaitingQueue=numRelatedWaitingQueue;");
- output.println(" seseCaller->allocSiteArray=mlpCreateAllocSiteArray(numRelatedWaitingQueue);");
- int idx=0;
- for (Iterator iterator = lockSet.iterator(); iterator.hasNext();) {
- SESELock seseLock = (SESELock) iterator.next();
- output.println(" seseCaller->allocSiteArray["+idx+"].id="+seseLock.getID()+";");
- idx++;
- }
- output.println();
- }
- }
-
+ output.println(" /* set up waiting queues */");
+ output.println(" int numMemoryQueue=0;");
+ output.println(" int memoryQueueItemID=0;");
+ ConflictGraph graph = null;
+ graph = mlpa.getConflictGraphResults().get(fm);
+ if (graph != null) {
+ HashSet<SESELock> lockSet = mlpa.getConflictGraphLockMap().get(
+ graph);
+
+ if (lockSet.size() > 0) {
+ output.println(" numMemoryQueue=" + lockSet.size() + ";");
+ output
+ .println(" seseCaller->numMemoryQueue=numMemoryQueue;");
+ output
+ .println(" seseCaller->memoryQueueArray=mlpCreateMemoryQueueArray(numMemoryQueue);");
+ output.println();
+ }
+ }
}
}
}
- // set up related allocation sites's waiting queues
+ // setup memory queue
// eom
- output.println(" /* set up waiting queues */");
- output.println(" int numRelatedWaitingQueue=0;");
- output.println(" int waitingQueueItemID=0;");
- ConflictGraph graph=null;
- graph=mlpa.getConflictGraphResults().get(fsen);
+ output.println(" // set up memory queues ");
+ output.println(" int numMemoryQueue=0;");
+ output.println(" int memoryQueueItemID=0;");
+ ConflictGraph graph = null;
+ graph = mlpa.getConflictGraphResults().get(fsen);
if (graph != null) {
output.println(" {");
- output.println(" SESEcommon* parentCommon = &(___params___->common);");
- HashSet<SESELock> lockSet=mlpa.getConflictGraphLockMap().get(graph);
-
+ output
+ .println(" SESEcommon* parentCommon = &(___params___->common);");
+ HashSet<SESELock> lockSet = mlpa.getConflictGraphLockMap().get(
+ graph);
+
if (lockSet.size() > 0) {
- output.println(" numRelatedWaitingQueue=" + lockSet.size()
- + ";");
+ output.println(" numMemoryQueue=" + lockSet.size() + ";");
output
- .println(" parentCommon->numRelatedWaitingQueue=numRelatedWaitingQueue;");
+ .println(" parentCommon->numMemoryQueue=numMemoryQueue;");
output
- .println(" parentCommon->allocSiteArray=mlpCreateAllocSiteArray(numRelatedWaitingQueue);");
- int idx = 0;
- for (Iterator iterator = lockSet.iterator(); iterator.hasNext();) {
- SESELock seseLock = (SESELock) iterator.next();
- output.println(" parentCommon->allocSiteArray[" + idx
- + "].id=" + seseLock.getID() + ";");
- idx++;
- }
+ .println(" parentCommon->memoryQueueArray=mlpCreateMemoryQueueArray(numMemoryQueue);");
output.println();
}
output.println(" }");
}
+
// copy in-set into place, ready vars were already
// copied when the SESE was issued
Iterator<TempDescriptor> tempItr;
output.println(" "+dynVar+"_srcSESE = NULL;");
}
- // eom
+ // eom
// handling stall site
-
- ParentChildConflictsMap conflictsMap=mlpa.getConflictsResults().get(fn);
-
+ ParentChildConflictsMap conflictsMap = mlpa.getConflictsResults().get(fn);
if (conflictsMap != null) {
-
- Set<Long> allocSet = conflictsMap
- .getAllocationSiteIDSetofStallSite();
-
+ Set<Long> allocSet = conflictsMap.getAllocationSiteIDSetofStallSite();
if (allocSet.size() > 0) {
-
FlatNode enclosingFlatNode=null;
if( currentSESE.getIsCallerSESEplaceholder() && currentSESE.getParent()==null){
enclosingFlatNode=currentSESE.getfmEnclosing();
}else{
enclosingFlatNode=currentSESE;
- }
-
+ }
ConflictGraph graph=mlpa.getConflictGraphResults().get(enclosingFlatNode);
HashSet<SESELock> seseLockSet=mlpa.getConflictGraphLockMap().get(graph);
Set<WaitingElement> waitingElementSet=graph.getStallSiteWaitingElementSet(conflictsMap, seseLockSet);
-
+
if(waitingElementSet.size()>0){
- output.println(" /* stall on parent's stall sites */");
- output.println(" {");
+ output.println("// stall on parent's stall sites ");
+ output.println(" {");
+ output.println(" REntry* rentry;");
output.println(" pthread_mutex_lock( &(seseCaller->lock) );");
- output.println(" ConflictNode* node;");
- output.println(" struct Queue* list=NULL;");
- output.println(" WaitingElement* newElement=NULL;");
- output.println(" struct QueueItem* newQItem=NULL;");
- output.println(" waitingQueueItemID++;");
-// output.println(" psem_init( &(seseCaller->memoryStallSiteSem) );");
- output.println(" pthread_cond_init( &(seseCaller->stallDone), NULL );");
-// output.println(" psem_init( &(seseCaller->memoryStallSiteSem) );");
- output.println(" int qIdx;");
- output.println(" int takeCount=0;");
+
for (Iterator iterator = waitingElementSet.iterator(); iterator.hasNext();) {
WaitingElement waitingElement = (WaitingElement) iterator.next();
- output.println(" qIdx=getQueueIdx(seseCaller->allocSiteArray,numRelatedWaitingQueue,"
- + waitingElement.getWaitingID() + ");");
- output.println(" if(qIdx!=-1 && !isEmpty(seseCaller->allocSiteArray[qIdx].waitingQueue)){");
- output.println(" list=createQueue();");
- for (Iterator iterator2 = waitingElement.getAllocList().iterator(); iterator2.hasNext();) {
- Integer allocID = (Integer) iterator2 .next();
- output.println(" node=mlpCreateConflictNode( "+ allocID + " );");
- output.println(" addNewItem(list,node);");
- }
- output.println(" newElement=mlpCreateWaitingElement( "+ waitingElement.getStatus()
- + ", seseCaller, list, waitingQueueItemID );");
- output.println(" addNewItemBack(seseCaller->allocSiteArray[qIdx].waitingQueue,newElement);");
- output.println(" takeCount++;");
- output.println(" }");
+ output.println(" rentry=mlpCreateREntry("+ waitingElement.getStatus()+ ", seseCaller, ___locals___."+ waitingElement.getDynID() + ");");
+ output.println(" pthread_cond_init( &(rentry->stallDone), NULL );");
+ output.println(" rentry->queue=seseCaller->memoryQueueArray["+ waitingElement.getQueueID()+ "];");
+ output
+ .println(" if(ADDRENTRY(seseCaller->memoryQueueArray["+ waitingElement.getQueueID()
+ + "],rentry)==NOTREADY){");
+ output.println(" pthread_cond_wait( &(rentry->stallDone), &(seseCaller->lock) );");
+ output.println(" } ");
}
- output.println(" if( takeCount>0 ){");
-// output.println(" psem_take( &(seseCaller->memoryStallSiteSem) );");
- output.println(" pthread_cond_wait( &(seseCaller->stallDone), &(seseCaller->lock) );");
- output.println(" }");
-
output.println(" pthread_mutex_unlock( &(seseCaller->lock) );");
- output.println(" }");
+ output.println(" }");
}
-
}
- } // end of if (conflictsMap != null) {
+ }
+
}
}
// count up memory conflict dependencies,
// eom
- ConflictGraph graph=null;
- FlatSESEEnterNode parent=fsen.getParent();
- if(parent!=null){
- if(parent.isCallerSESEplaceholder){
- graph=mlpa.getConflictGraphResults().get(parent.getfmEnclosing());
- }else{
- graph=mlpa.getConflictGraphResults().get(parent);
- }
- }
- if (graph != null) {
-
- HashSet<SESELock> seseLockSet=mlpa.getConflictGraphLockMap().get(graph);
-
- output.println();
- output.println(" /*add waiting queue element*/");
- Set<WaitingElement> waitingQueueSet=graph.getWaitingElementSetBySESEID(fsen
- .getIdentifier(),seseLockSet);
- if (waitingQueueSet.size() > 0) {
- output.println(" {");
- output.println(" waitingQueueItemID++;");
- output.println(" ConflictNode* node;");
- output.println(" WaitingElement* newElement=NULL;");
- output.println(" struct Queue* list=NULL;");
- output.println(" struct QueueItem* newQItem=NULL;");
- output.println(" pthread_mutex_lock( &(parentCommon->lock) );");
- for (Iterator iterator = waitingQueueSet.iterator(); iterator
- .hasNext();) {
- WaitingElement waitingElement = (WaitingElement) iterator.next();
- output.println(" list=createQueue();");
- for (Iterator iterator2 = waitingElement.getAllocList().iterator(); iterator2
- .hasNext();) {
- Integer allocID = (Integer) iterator2
- .next();
- output.println(" node=mlpCreateConflictNode( "+allocID+" );");
- output.println(" addNewItem(list,node);");
- }
- output.println(" seseToIssue->common.waitingQueueItemID=waitingQueueItemID;");
- output.println(" newElement=mlpCreateWaitingElement( "+waitingElement.getStatus()+", seseToIssue, list, waitingQueueItemID );");
-
- output
- .println(" if(addWaitingQueueElement(parentCommon->allocSiteArray,numRelatedWaitingQueue,"
- + waitingElement.getWaitingID() + ",newElement)){");
- output.println(" ++(localCount);");
- output.println(" } ");
-
- output
- .println();
- }
- output.println(" pthread_mutex_unlock( &(parentCommon->lock) );");
- output.println(" }");
+ ConflictGraph graph = null;
+ FlatSESEEnterNode parent = fsen.getParent();
+ if (parent != null) {
+ if (parent.isCallerSESEplaceholder) {
+ graph = mlpa.getConflictGraphResults().get(parent.getfmEnclosing());
+ } else {
+ graph = mlpa.getConflictGraphResults().get(parent);
+ }
+ }
+ if (graph != null) {
+ HashSet<SESELock> seseLockSet = mlpa.getConflictGraphLockMap().get(
+ graph);
+ output.println();
+ output.println(" //add memory queue element");
+ Set<WaitingElement> waitingQueueSet = graph
+ .getWaitingElementSetBySESEID(fsen.getIdentifier(),
+ seseLockSet);
+ if (waitingQueueSet.size() > 0) {
+ output.println(" {");
+ output.println(" REntry* rentry=NULL;");
+ output.println(" seseToIssue->common.rentryIdx=0;");
+ output
+ .println(" pthread_mutex_lock( &(parentCommon->lock) );");
+ for (Iterator iterator = waitingQueueSet.iterator(); iterator
+ .hasNext();) {
+ WaitingElement waitingElement = (WaitingElement) iterator
+ .next();
+ output.println(" rentry=mlpCreateREntry("+ waitingElement.getStatus()+ ", seseToIssue, seseToIssue->"+ waitingElement.getDynID() + ");");
+ output.println(" rentry->queue=parentCommon->memoryQueueArray["+ waitingElement.getQueueID()+ "];");
+ output.println(" seseToIssue->common.rentryArray[seseToIssue->common.rentryIdx++]=rentry;");
+ output
+ .println(" if(ADDRENTRY(parentCommon->memoryQueueArray["
+ + waitingElement.getQueueID()
+ + "],rentry)==NOTREADY){");
+ output.println(" ++(localCount);");
+ output.println(" } ");
+ output.println();
}
-
- output.println();
+ output
+ .println(" pthread_mutex_unlock( &(parentCommon->lock) );");
+ output.println(" }");
}
-
- // eom
-// output.println(" pthread_mutex_init( &(seseToIssue->common.waitingQueueLock), NULL );");
- //
+ output.println();
+ }
if( fsen != mlpa.getMainSESE() ) {
// count up outstanding dependencies, static first, then dynamic
// clean up its lock element from waiting queue, and decrement dependency count for next SESE block
if( fsen != mlpa.getMainSESE() ) {
- output.println();
- output.println(" /* check memory dependency*/");
- output.println(" {");
- output.println(" pthread_mutex_lock( &(___params___->common.parent->lock) );");
-// output.println(" pthread_mutex_lock( &(___params___->common.parent->waitingQueueLock) );");
- output.println(" int idx;");
- output.println(" int giveCount=0;");
- output.println(" struct Queue* launchQueue=createQueue();");
- output.println(" struct QueueItem* nextQueueItem;");
- output.println(" for(idx = 0 ; idx < ___params___->common.parent->numRelatedWaitingQueue ; idx++){");
- output.println(" if(!isEmpty(___params___->common.parent->allocSiteArray[idx].waitingQueue)){");
- output.println(" struct QueueItem* qItem=getHead(___params___->common.parent->allocSiteArray[idx].waitingQueue);");
- output.println(" int removed=0;");
- output.println(" while(qItem!=NULL){");
- output.println(" WaitingElement* item=qItem->objectptr;");
- output.println(" SESEcommon* seseItem=(SESEcommon*)item->seseRec;");
- output.println(" if(seseItem->classID==___params___->common.classID && item->id==___params___->common.waitingQueueItemID){");
- output.println(" struct QueueItem* nItem=getNextQueueItem(qItem);");
- output.println(" removeItem(___params___->common.parent->allocSiteArray[idx].waitingQueue,qItem);");
- output.println(" removed=1;");
- output.println(" qItem=nItem;");
- output.println(" }else if(removed){");
- output.println(" qItem=NULL;");
- output.println(" }else{");
- output.println(" qItem=getNextQueueItem(qItem);");
- output.println(" }");
- output.println(" }");
- output.println(" if( !isEmpty(___params___->common.parent->allocSiteArray[idx].waitingQueue) ){");
-
- output.println(" struct QueueItem* nextQItem=getHead(___params___->common.parent->allocSiteArray[idx].waitingQueue);");
- output.println(" while(nextQItem!=NULL){");
- output.println(" WaitingElement* nextItem=nextQItem->objectptr;");
- output.println(" SESEcommon* seseNextItem=(SESEcommon*)nextItem->seseRec;");
- output.println(" if(nextItem->resolved==0){");
-
- output.println(" int isResolved=isRunnable(___params___->common.parent->allocSiteArray[idx].waitingQueue,nextQItem);");
- output.println(" if(seseNextItem->classID==___params___->common.parent->classID){"); // stall site
- output.println(" if(isResolved){");
- output.println(" struct QueueItem* stallItem=findItem(___params___->common.parent->allocSiteArray[idx].waitingQueue,nextItem);");
- output.println(" removeItem(___params___->common.parent->allocSiteArray[idx].waitingQueue,stallItem);");
- output.println(" giveCount++;");
- output.println(" }");
- output.println(" if(!isEmpty(___params___->common.parent->allocSiteArray[idx].waitingQueue)){");
- output.println(" nextQItem=getNextQueueItem(nextQItem);");
- output.println(" }else{");
- output.println(" nextQItem=NULL;");
- output.println(" }");
- output.println(" }else{");
- output.println(" if(isResolved){");
- //output.println(" struct QueueItem* currentItem=findItem(___params___->common.parent->allocSiteArray[idx].waitingQueue,nextItem);");
- //output.println(" nextQItem=getNextQueueItem(currentItem);");
- //output.println(" removeItem(___params___->common.parent->allocSiteArray[idx].waitingQueue,currentItem);");
- output.println(" nextItem->resolved=1;");
- output.println(" if( atomic_sub_and_test(1, &(seseNextItem->unresolvedDependencies)) ){");
- output.println(" addNewItem(launchQueue,(void*)seseNextItem);");
- output.println(" }");
- output.println(" }else{");
- output.println(" nextQItem=getNextQueueItem(nextQItem);");
- output.println(" }");
- output.println(" }");
-
- output.println(" }else{");
- output.println(" nextQItem=getNextQueueItem(nextQItem);");
- output.println(" }");
-
- output.println(" } "); // end of while(nextQItem!=NULL)
- output.println(" }");
- output.println(" }");
-// output.println(" }");
- output.println(" }");
- output.println(" pthread_mutex_unlock( &(___params___->common.parent->lock) );");
- output.println(" if(!isEmpty(launchQueue)){");
- output.println(" struct QueueItem* qItem=getHead(launchQueue);");
- output.println(" while(qItem!=NULL){");
- output.println(" workScheduleSubmit(qItem->objectptr);");
- output.println(" qItem=getNextQueueItem(qItem);");
- output.println(" }");
- output.println(" }");
- output.println(" if(giveCount>0){");
-// output.println(" psem_give(&(___params___->common.parent->memoryStallSiteSem));");
- output.println(" pthread_cond_signal(&(___params___->common.parent->stallDone));");
- output.println(" }");
- output.println(" }");
-
+ output.println();
+ output.println(" /* check memory dependency*/");
+ output.println(" {");
+ output
+ .println(" pthread_mutex_lock( &(___params___->common.parent->lock) );");
+ output.println(" int idx;");
+ output.println(" for(idx=0;idx<___params___->common.rentryIdx;idx++){");
+ output.println(" REntry* re=___params___->common.rentryArray[idx];");
+ output.println(" RETIRERENTRY(re->queue,re);");
+ output.println(" }");
+ output
+ .println(" pthread_mutex_unlock( &(___params___->common.parent->lock) );");
+ output.println(" }");
+
}
// if parent is stalling on you, let them know you're done
#include <assert.h>
#include "mem.h"
-#include "Queue.h"
#include "mlp_runtime.h"
#include "workschedule.h"
RUNFREE( seseRecord );
}
-AllocSite* mlpCreateAllocSiteArray(int numAllocSites){
+MemoryQueue** mlpCreateMemoryQueueArray(int numMemoryQueue){
int i;
- AllocSite* newAllocSite=(AllocSite*)RUNMALLOC( sizeof( AllocSite ) * numAllocSites );
- for(i=0; i<numAllocSites; i++){
- newAllocSite[i].waitingQueue=createQueue();
+ MemoryQueue** newMemoryQueue=(MemoryQueue**)RUNMALLOC( sizeof( MemoryQueue* ) * numMemoryQueue );
+ for(i=0; i<numMemoryQueue; i++){
+ newMemoryQueue[i]=createMemoryQueue();
}
- return newAllocSite;
+ return newMemoryQueue;
}
-ConflictNode* mlpCreateConflictNode(int id){
- ConflictNode* newConflictNode=(ConflictNode*)RUNMALLOC( sizeof( ConflictNode ) );
- newConflictNode->id=id;
- return newConflictNode;
+REntry* mlpCreateREntryArray(){
+ REntry* newREntryArray=(REntry*)RUNMALLOC(sizeof(REntry)*NUMRENTRY);
+ return newREntryArray;
}
-WaitingElement* mlpCreateWaitingElement(int status, void* seseToIssue, struct Queue* queue, int id){
- WaitingElement* newElement=(WaitingElement*)RUNMALLOC(sizeof(WaitingElement));
- newElement->status=status;
- newElement->seseRec=seseToIssue;
- newElement->list=queue;
- newElement->id=id;
- return newElement;
+REntry* mlpCreateREntry(int type, void* seseToIssue, void* dynID){
+ REntry* newREntry=(REntry*)RUNMALLOC(sizeof(REntry));
+ newREntry->type=type;
+ newREntry->seseRec=seseToIssue;
+ newREntry->dynID=dynID;
+ return newREntry;
}
-struct QueueItem* addWaitingQueueElement2(AllocSite* waitingQueueArray, int numWaitingQueue, int waitingID, WaitingElement* element){
+int isParent(REntry *r) {
+ if (r->type==PARENTREAD || r->type==PARENTWRITE) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
- int i;
- struct QueueItem* newItem=NULL;
- for(i=0;i<numWaitingQueue;i++){
- if(waitingQueueArray[i].id==waitingID){
- newItem=addNewItemBack(waitingQueueArray[i].waitingQueue,element);
- return newItem;
- //printf("add new item %d into waiting queue:%d\n",((SESEcommon*)seseRec)->classID,allocID);
- }
+int isParentCoarse(REntry *r){
+ if (r->type==PARENTCOARSE){
+ return TRUE;
+ }else{
+ return FALSE;
}
- return newItem;
-
}
-int addWaitingQueueElement(AllocSite* allocSiteArray, int numAllocSites, long allocID, WaitingElement* wElement){
+int isFineRead(REntry *r) {
+ if (r->type==READ || r->type==PARENTREAD) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
- int i;
- struct QueueItem* newItem=NULL;
- for(i=0;i<numAllocSites;i++){
- if(allocSiteArray[i].id==allocID){
-
- if(isRunnableNewElement(allocSiteArray[i].waitingQueue,wElement)){
- wElement->resolved=1;
- addNewItemBack(allocSiteArray[i].waitingQueue,wElement);
- return 0;
- }else{
- wElement->resolved=0;
- addNewItemBack(allocSiteArray[i].waitingQueue,wElement);
- return 1;
- }
-
- }
+int isFineWrite(REntry *r) {
+ if (r->type==WRITE || r->type==PARENTWRITE) {
+ return TRUE;
+ } else {
+ return FALSE;
}
- return 0;
}
-struct QueueItem* addWaitingQueueElement_backup(AllocSite* allocSiteArray, int numAllocSites, long allocID, void *seseRec){
+int isCoarse(REntry *r){
+ if(r->type==COARSE || r->type==PARENTCOARSE){
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
- int i;
- struct QueueItem* newItem=NULL;
- for(i=0;i<numAllocSites;i++){
- if(allocSiteArray[i].id==allocID){
- newItem=addNewItemBack(allocSiteArray[i].waitingQueue,seseRec);
- return newItem;
- //printf("add new item %d into waiting queue:%d\n",((SESEcommon*)seseRec)->classID,allocID);
- }
+int isSCC(REntry *r){
+ if(r->type==SCCITEM){
+ return TRUE;
+ } else {
+ return FALSE;
}
- return newItem;
}
-int getQueueIdx(AllocSite* allocSiteArray, int numAllocSites, long allocID){
+int isSingleItem(MemoryQueueItem *qItem){
+ if(qItem->type==SINGLEITEM){
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
- int i;
- for(i=0;i<numAllocSites;i++){
- if(allocSiteArray[i].id==allocID){
- return i;
- }
+int isHashtable(MemoryQueueItem *qItem){
+ if(qItem->type==HASHTABLE){
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+int isVector(MemoryQueueItem *qItem){
+ if(qItem->type==VECTOR){
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+int isReadBinItem(BinItem* b){
+ if(b->type==READBIN){
+ return TRUE;
+ }else{
+ return FALSE;
+ }
+}
+
+int isWriteBinItem(BinItem* b){
+ if(b->type==WRITEBIN){
+ return TRUE;
+ }else{
+ return FALSE;
}
- return -1;
}
-int isRunnableNewElement(struct Queue* waitingQueue, WaitingElement* wItem){
+int generateKey(unsigned int data){
+ return (data&H_MASK)>> 4;
+}
+
+Hashtable* createHashtable(){
+ int i=0;
+ Hashtable* newTable=(Hashtable*)RUNMALLOC(sizeof(Hashtable));
+ //newTable->array=(BinElement*)RUNMALLOC(sizeof(BinElement)*NUMBINS);
+ for(i=0;i<NUMBINS;i++){
+ newTable->array[i]=(BinElement*)RUNMALLOC(sizeof(BinElement));
+ newTable->array[i]->head=NULL;
+ newTable->array[i]->tail=NULL;
+ }
+ return newTable;
+}
+
+WriteBinItem* createWriteBinItem(){
+ WriteBinItem* binitem=(WriteBinItem*)RUNMALLOC(sizeof(WriteBinItem));
+ binitem->item.type=WRITEBIN;
+ return binitem;
+}
+
+ReadBinItem* createReadBinItem(){
+ ReadBinItem* binitem=(ReadBinItem*)RUNMALLOC(sizeof(ReadBinItem));
+ binitem->array=(REntry*)RUNMALLOC(sizeof(REntry*)*NUMREAD);
+ binitem->index=0;
+ binitem->item.type=READBIN;
+ return binitem;
+}
+
+Vector* createVector(){
+ Vector* vector=(Vector*)RUNMALLOC(sizeof(Vector));
+ vector->array=(REntry*)RUNMALLOC(sizeof(REntry*)*NUMITEMS);
+ vector->index=0;
+ return vector;
+}
- if(!isEmpty(waitingQueue)){
+SCC* createSCC(){
+ SCC* scc=(SCC*)RUNMALLOC(sizeof(SCC));
+ return scc;
+}
+
+MemoryQueue* createMemoryQueue(){
+ MemoryQueue* queue = (MemoryQueue*)RUNMALLOC(sizeof(MemoryQueue));
+
+ MemoryQueueItem* dummy=(MemoryQueueItem*)RUNMALLOC(sizeof(MemoryQueueItem));
+ dummy->type=3;
+ dummy->total=0;
+ dummy->status=READY;
+ queue->head = dummy;
+ queue->tail = dummy;
+ return queue;
+}
- struct QueueItem* current=getHead(waitingQueue);
- while(current!=NULL){
- if(isConflicted(current,wItem)){
- return 0;
- }
- current=getNextQueueItem(current);
+int ADDRENTRY(MemoryQueue * q, REntry * r) {
+ if (isFineRead(r) || isFineWrite(r)) {
+ return ADDTABLE(q, r);
+ } else if (isCoarse(r)) {
+ return ADDVECTOR(q, r);
+ } else if (isSCC(r)) {
+ return ADDSCC(q, r);
+ }
+}
+
+int ADDTABLE(MemoryQueue *q, REntry *r) {
+ if(!isHashtable(q->tail)) {
+ //Fast Case
+ MemoryQueueItem* tail=q->tail;
+ if (isParent(r) && tail->total==0 && q->tail==q->head) {
+ return READY;
+ }
+
+ //Add table
+ Hashtable* h=createHashtable();
+ tail->next=(MemoryQueueItem*)h;
+ //************NEED memory barrier here to ensure compiler does not cache Q.tail.status********
+ if (BARRIER() && tail->status==READY && tail->total==0 && q->tail==q->head) {
+ //previous Q item is finished
+ h->item.status=READY;
+ }
+ q->tail=(MemoryQueueItem*)h;
+ }
+
+ //at this point, have table
+ Hashtable* table=(Hashtable*)q->tail;
+ BinItem * val;
+ int key=generateKey((unsigned int)r->dynID);
+ do {
+ val=(BinItem*)0x1;
+ BinElement* bin=table->array[key];
+ val=(BinItem*)LOCKXCHG((unsigned int*)&(bin->head), (unsigned int)val);//note...talk to me about optimizations here.
+ } while(val==(BinItem*)0x1);
+ //at this point have locked bin
+ if (val==NULL) {
+ return EMPTYBINCASE(table, table->array[key], r);
+ } else {
+ if (isFineWrite(r)) {
+ WRITEBINCASE(table, r, val);
+ return NOTREADY;
+ } else if (isFineRead(r)) {
+ return READBINCASE(table, r, val);
}
}
- return 1;
}
-int isRunnable(struct Queue* waitingQueue, struct QueueItem* qItem){
+int EMPTYBINCASE(Hashtable *T, BinElement* be, REntry *r) {
+ int retval;
+ BinItem* b;
+ if (isFineWrite(r)) {
+ b=(BinItem*)createWriteBinItem();
+ ((WriteBinItem*)b)->val=r;//<-only different statement
+ } else if (isFineRead(r)) {
+ b=(BinItem*)createReadBinItem();
+ ReadBinItem* readbin=(ReadBinItem*)b;
+ readbin->array[readbin->index++]=*r;
+ }
+ b->total=1;
+
+ if (T->item.status==READY) {
+ //current entry is ready
+ b->status=READY;
+ retval=READY;
+ if (isParent(r)) {
+ be->head=NULL; // released lock
+ return retval;
+ }
+ } else {
+ b->status=NOTREADY;
+ retval=NOTREADY;
+ }
+
+ atomic_inc(&T->item.total);
+ r->hashtable=T;
+ r->binitem=b;
+ be->tail=b;
+ be->head=b;//released lock
+ return retval;
+}
- if(!isEmpty(waitingQueue)){
+int WRITEBINCASE(Hashtable *T, REntry *r, BinItem *val) {
+ //chain of bins exists => tail is valid
+ //if there is something in front of us, then we are not ready
- struct QueueItem* current=getHead(waitingQueue);
- while(current!=NULL){
- if(current!=qItem){
- if(isConflicted(current,(WaitingElement*)qItem->objectptr)){
- return 0;
- }
- }else{
- return 1;
- }
- current=getNextQueueItem(current);
+ int key=generateKey((unsigned int)r->dynID);
+ BinElement* be=T->array[key];
+
+ BinItem *bintail=be->tail;
+ WriteBinItem *b=createWriteBinItem();
+ b->val=r;
+ b->item.total=1;
+
+ atomic_inc(&T->item.total);
+
+ r->hashtable=T;
+ r->binitem=(BinItem*)b;
+
+ be->tail->next=(BinItem*)b;
+ be->tail=(BinItem*)b;
+ be->head=val;
+}
+
+READBINCASE(Hashtable *T, REntry *r, BinItem *val) {
+ int key=generateKey((unsigned int)r->dynID);
+ BinItem * bintail=T->array[key]->tail;
+ if (isReadBinItem(bintail)) {
+ return TAILREADCASE(T, r, val, bintail);
+ } else if (!isReadBinItem(bintail)) {
+ TAILWRITECASE(T, r, val, bintail);
+ return NOTREADY;
+ }
+}
+
+int TAILREADCASE(Hashtable *T, REntry *r, BinItem *val, BinItem *bintail) {
+ int key=generateKey((unsigned int)r->dynID);
+ ReadBinItem * readbintail=(ReadBinItem*)T->array[key]->tail;
+ int status, retval;
+ if (readbintail->item.status=READY) {
+ status=READY;
+ retval=READY;
+ if (isParent(r)) {
+ T->array[key]->head=val;//released lock
+ return READY;
}
+ } else {
+ status=NOTREADY;
+ retval=NOTREADY;
+ }
+
+ if (readbintail->index==NUMREAD) { // create new read group
+ ReadBinItem* rb=createReadBinItem();
+ rb->array[rb->index++]=*r;
+ rb->item.total=1;//safe only because item could not have started
+ rb->item.status=status;
+ T->array[key]->tail->next=(BinItem*)rb;
+ T->array[key]->tail=(BinItem*)rb;
+ r->binitem=(BinItem*)rb;
+ } else { // group into old tail
+ readbintail->array[readbintail->index++]=*r;
+ atomic_inc(&readbintail->item.total);
+ r->binitem=(BinItem*)readbintail;
}
- return 1;
+ atomic_inc(&T->item.total);
+ r->hashtable=T;
+ T->array[key]->head=val;//released lock
+ return retval;
}
-int isConflicted(struct QueueItem* prevItem, WaitingElement* element){
+TAILWRITECASE(Hashtable *T, REntry *r, BinItem *val, BinItem *bintail) {
+ int key=generateKey((unsigned int)r->dynID);
+ WriteBinItem* wb=createWriteBinItem();
+ wb->val=r;
+ wb->item.total=1;
+ wb->item.status=NOTREADY;
+ // rb->array[rb->index++]=*r;
+ //rb->item.total=1;//safe because item could not have started
+ //rb->item.status=NOTREADY;
+ atomic_inc(&T->item.total);
+ r->hashtable=T;
+ r->binitem=(BinItem*)wb;
+ T->array[key]->tail->next=(BinItem*)wb;
+ T->array[key]->tail=(BinItem*)wb;
+ T->array[key]->head=val;//released lock
+}
- WaitingElement* prevElement=prevItem->objectptr;
+ADDVECTOR(MemoryQueue *Q, REntry *r) {
+ if(!isVector(Q->tail)) {
+ //Fast Case
+ if (isParentCoarse(r) && Q->tail->total==0 && Q->tail==Q->head) {
+ return READY;
+ }
- if(prevElement->id!=element->id){
+ //added vector
+ Vector* V=createVector();
+ Q->tail->next=(MemoryQueueItem*)V;
+ //************NEED memory barrier here to ensure compiler does not cache Q.tail.status******
+ if (BARRIER() && Q->tail->status==READY&&Q->tail->total==0) {
+ //previous Q item is finished
+ V->item.status=READY;
+ }
+ Q->tail=(MemoryQueueItem*)V;
+ }
+ //at this point, have vector
+ Vector* V=(Vector*)Q->tail;
+ if (V->index==NUMITEMS) {
+ //vector is full
+ //added vector
+ V=createVector();
+ V->item.status=NOTREADY;
+ Q->tail->next=(MemoryQueueItem*)V;
+ //***NEED memory barrier here to ensure compiler does not cache Q.tail.status******
+ if (BARRIER() && Q->tail->status==READY) {
+ V->item.status=READY;
+ }
+ Q->tail=(MemoryQueueItem*)V;
+ }
- if(element->status==0){ // fine read
-
- if(prevElement->status==1 || prevElement->status==3){
-
- if(isOverlapped(prevElement->list,element->list)){
- return 1;
- }
-
- }else{
- return 0;
- }
-
- }else if(element->status==1){ // fine write
- if(isOverlapped(prevElement->list,element->list)){
- return 1;
- }
- }else if(element->status==2){// coarse read
-
- if(prevElement->status==1 || prevElement->status==3){
- if(isOverlapped(prevElement->list,element->list)){
- return 1;
- }
+ atomic_inc(&V->item.total);
+ //expose entry
+ int index=V->index;
+ V->array[index]=*r;
+ //*****NEED memory barrier here to ensure compiler does not reorder writes to V.array and V.index
+ BARRIER();
+ V->index++;
+ //*****NEED memory barrier here to ensure compiler does not cache V.status*********
+ if (BARRIER() && V->item.status==READY) {
+ void* flag=NULL;
+ LOCKXCHG((unsigned int*)&(V->array[index]), (unsigned int)flag);
+ if (flag!=NULL) {
+ if (isParent(r)) { //parent's retire immediately
+ atomic_dec(&V->item.total);
}
+ return READY;
+ } else {
+ return NOTREADY;//<- means that some other dispatcher got this one...so need to do accounting correctly
+ }
+ } else {
+ return NOTREADY;
+ }
+}
- }else if(element->status==3){// coarse write
- return 1;
+
+//SCC's don't come in parent variety
+ADDSCC(MemoryQueue *Q, REntry *r) {
+ //added SCC
+ SCC* S=createSCC();
+ S->item.total=1;
+ S->val=r;
+ Q->tail->next=(MemoryQueueItem*)S;
+ //*** NEED BARRIER HERE
+ if (BARRIER() && Q->tail->status==READY && Q->tail->total==0 && Q->tail==Q->head) {
+ //previous Q item is finished
+ S->item.status=READY;
+ Q->tail=(MemoryQueueItem*)S;
+ void* flag=NULL;
+ LOCKXCHG((int*)S->val, (int)flag);
+ if (flag!=NULL) {
+ return READY;
+ } else {
+ return NOTREADY;//<- means that some other dispatcher got this one...so need to do accounting correctly
}
+ } else {
+ Q->tail=(MemoryQueueItem*)S;
+ return NOTREADY;
+ }
+}
+
+void RETIRERENTRY(MemoryQueue* Q, REntry * r) {
+ if (isFineWrite(r)||isFineRead(r)) {
+ RETIREHASHTABLE(Q, r);
+ } else if (isCoarse(r)) {
+ RETIREVECTOR(Q, r);
+ } else if (isSCC(r)) {
+ RETIRESCC(Q, r);
}
+}
- return 0;
+RETIRESCC(MemoryQueue *Q, REntry *r) {
+ SCC* s=r->scc;
+ s->item.total=0;//don't need atomicdec
+ RESOLVECHAIN(Q);
}
-int isOverlapped(struct Queue* prevList, struct Queue* itemList){
- if(!isEmpty(prevList)){
- struct QueueItem* queueItemA=getHead(prevList);
-
- while(queueItemA!=NULL){
- ConflictNode* nodeA=queueItemA->objectptr;
+RETIREHASHTABLE(MemoryQueue *q, REntry *r) {
+ Hashtable *T=r->hashtable;
+ BinItem *b=r->binitem;
+ RETIREBIN(T,r,b);
+ atomic_dec(&T->item.total);
+ if (T->item.next!=NULL && T->item.total==0) {
+ RESOLVECHAIN(q);
+ }
+}
- if(!isEmpty(itemList)){
- struct QueueItem* queueItemB=getHead(itemList);
- while(queueItemB!=NULL){
- ConflictNode* nodeB=queueItemB->objectptr;
- if(nodeA->id==nodeB->id){
- return 1;
- }
- queueItemB=getNextQueueItem(queueItemB);
+RETIREBIN(Hashtable *T, REntry *r, BinItem *b) {
+ int key=generateKey((unsigned int)r->dynID);
+ if(isFineRead(r)) {
+ atomic_dec(&b->total);
+ }
+ if (isFineWrite(r) || (isFineRead(r) && b->next!=NULL && b->total==0)) {
+ // CHECK FIRST IF next is nonnull to guarantee that b.total cannot change
+ BinItem * val;
+ do {
+ val=(BinItem*)1;
+ val=(BinItem*)LOCKXCHG((unsigned int*)&(T->array[key]->head), (unsigned int)val);
+ } while(val==(BinItem*)1);
+ // at this point have locked bin
+ BinItem *ptr=val;
+ int haveread=FALSE;
+
+ int i;
+ while (ptr!=NULL) {
+ if (isReadBinItem(ptr)) {
+ ReadBinItem* rptr=(ReadBinItem*)ptr;
+ if (rptr->item.status==NOTREADY) {
+ for (i=0;i<rptr->index;i++) {
+ resolveDependencies(rptr->array[i]);
+ // XXXXX atomicdec(rptr->array[i].dependenciesCount);
+ if (isParent(&rptr->array[i])) {
+ //parents go immediately
+ atomic_dec(&rptr->item.total);
+ atomic_dec(&T->item.total);
+ }
+ }
+ }
+ rptr->item.status=READY;
+ if (rptr->item.next==NULL) {
+ break;
+ }
+ if (rptr->item.total!=0) {
+ haveread=TRUE;
+ } else if ((BinItem*)rptr==val) {
+ val=val->next;
+ }
+ } else if(isWriteBinItem(ptr)) {
+ if (haveread)
+ break;
+ if(ptr->status==NOTREADY){
+ resolveDependencies(((WriteBinItem*)ptr)->val);
+ ptr->status=READY;
+ if(isParent(((WriteBinItem*)ptr)->val)){
+ atomic_dec(&T->item.total);
+ val=val->next;
+ }else
+ break;
+ }else{ // write bin is already resolved
+ val=val->next;
}
- }
- queueItemA=getNextQueueItem(queueItemA);
+ /*
+ if(ptr->status==NOTREADY) {
+ ptr->status=READY;
+ resolveDependencies(((WriteBinItem*)ptr)->val);
+ if (isParent(((WriteBinItem*)ptr)->val)) {
+ atomic_dec(&T->item.total);
+ //val=val->next;
+ val=ptr->next;
+ } else
+ break;
+ }
+ */
+ }
+ ptr=ptr->next;
}
+ T->array[key]->head=val; // release lock
}
- return 0;
-
}
-int resolveWaitingQueue(struct Queue* waitingQueue,struct QueueItem* qItem){
- if(!isEmpty(waitingQueue)){
+RETIREVECTOR(MemoryQueue *Q, REntry *r) {
+ Vector* V=r->vector;
+ atomic_dec(&V->item.total);
+
+ if (V->item.next!=NULL && V->item.total==0) { //NOTE: ORDERING CRUCIAL HERE
+ RESOLVECHAIN(Q);
+ }
+}
- SESEcommon* qCommon=qItem->objectptr;
-
- struct QueueItem* current=getHead(waitingQueue);
- while(current!=NULL){
- if(current!=qItem){
- SESEcommon* currentCommon=current->objectptr;
- if(hasConflicts(currentCommon->classID,qCommon->connectedList)){
- return 0;
- }
- }else{
- return 1;
- }
- current=getNextQueueItem(current);
+RESOLVECHAIN(MemoryQueue *Q) {
+ while(TRUE) {
+ MemoryQueueItem* head=Q->head;
+ if (head->next==NULL||head->total!=0) {
+ //item is not finished
+ if (head->status!=READY) {
+ //need to update status
+ head->status=READY;
+ if (isHashtable(head)) {
+ RESOLVEHASHTABLE(Q, head);
+ } else if (isVector(head)) {
+ RESOLVEVECTOR(Q, head);
+ } else if (isSingleItem(head)) {
+ RESOLVESCC(head);
+ }
+ if (head->next==NULL)
+ break;
+ if (head->total!=0)
+ break;
+ } else
+ break;
}
+ MemoryQueueItem* nextitem=head->next;
+ CAS((int*)Q->head, (int)head, (int)nextitem);
+ //oldvalue not needed... if we fail we just repeat
}
- return 1;
}
-int hasConflicts(int classID, struct Queue* connectedList){
-
- if(!isEmpty(connectedList)){
- struct QueueItem* queueItem=getHead(connectedList);
-
- while(queueItem!=NULL){
- ConflictNode* node=queueItem->objectptr;
- if(node->id==classID){
- return 1;
- }
- queueItem=getNextQueueItem(queueItem);
+
+RESOLVEHASHTABLE(MemoryQueue *Q, Hashtable *T) {
+ int binidx;
+ for (binidx=0;binidx<NUMBINS;binidx++) {
+ BinElement* bin=T->array[binidx];
+ BinItem* val;
+ do {
+ val=(BinItem*)1;
+ LOCKXCHG((int*)bin->head, (int)val);
+ } while (val==(BinItem*)1);
+ //at this point have locked bin
+ int haveread=FALSE;
+ BinItem* ptr=val;
+ if(ptr!=NULL&&ptr->status==NOTREADY) {
+ do {
+ if (isWriteBinItem(ptr)) {
+ if (haveread)
+ break;
+ resolveDependencies(((WriteBinItem*)ptr)->val);
+ // XXXXX atomic_dec(ptr.val.dependenciesCount);
+ ptr->status=READY;
+ if (isParent(((WriteBinItem*)ptr)->val)) {
+ atomic_dec(&T->item.total);
+ val=val->next;
+ } else
+ break;
+ } else if (isReadBinItem(ptr)) {
+ int i;
+ ReadBinItem* rptr=(ReadBinItem*)ptr;
+ for(i=0;i<rptr->index;i++) {
+ resolveDependencies(rptr->array[i]);
+ // XXXXX atomicdec(ptr.array[i].dependenciesCount);
+ if (isParent(&rptr->array[i])) {
+ atomic_dec(&rptr->item.total);
+ atomic_dec(&T->item.total);
+ }
+ }
+ if (rptr->item.next==NULL||rptr->item.total!=0) {
+ haveread=TRUE;
+ } else if((BinItem*)rptr==val) {
+ val=val->next;
+ }
+ rptr->item.status=READY; {
+ }
+ ptr=ptr->next;
+ }
+ }while(ptr!=NULL);
}
+ bin->head=val; // released lock;
}
- return 0;
}
-void addNewConflictNode(ConflictNode* node, struct Queue* connectedList){
-
- if(!isEmpty(connectedList)){
- struct QueueItem* qItem=getHead(connectedList);
- while(qItem!=NULL){
- ConflictNode* qNode=qItem->objectptr;
- if(qNode->id==node->id){
- return;
+RESOLVEVECTOR(MemoryQueue *q, Vector *V) {
+ int i;
+ Vector* tmp=V;
+ //handle ready cases
+ while(TRUE) {
+ //enqueue everything
+ for (i=0;i<NUMITEMS;i++) {
+ void* val=NULL;
+ LOCKXCHG((int*)&tmp->array[i], (int)val);
+ if (val!=NULL) {
+ // XXXXX atomicdec(val.dependenciesCount);
+ if (isParent(val)) {
+ atomic_dec(&tmp->item.total);
+ }
}
- qItem=getNextQueueItem(qItem);
+ }
+ if (tmp->item.next!=NULL&&isVector(tmp->item.next)) {
+ tmp=(Vector*)tmp->item.next;
+ } else {
+ break;
}
}
-
- addNewItem(connectedList,node);
-
}
-int contains(struct Queue* queue, struct QueueItem* qItem){
-
- if(!isEmpty(queue)){
- struct QueueItem* nextQItem=getHead(queue);
- while(nextQItem!=NULL){
- if((nextQItem->objectptr)==qItem){
- return 1;
- }
- nextQItem=getNextQueueItem(nextQItem);
- }
+RESOLVESCC(SCC *S) {
+ //precondition: SCC's state is READY
+ void* flag=NULL;
+ LOCKXCHG((int*)S->val, (int)flag);
+ if (flag!=NULL) {
+ // XXXXX atomicdec(flag.dependenciesCount);
}
+}
- return 0;
+resolveDependencies(REntry* rentry){
+ SESEcommon* seseCommon=(SESEcommon*)rentry->seseRec;
+ if(rentry->type==0 || rentry->type==1){
+ if( atomic_sub_and_test(1, &(seseCommon->unresolvedDependencies)) ){
+ workScheduleSubmit(seseCommon);
+ }
+ }else if(rentry->type==2 || rentry->type==3){
+ pthread_cond_signal(&(rentry->stallDone));
+ }
}