System.out.println("size="+lockSet.size());
if (lockSet.size() > 0) {
output.println(" numMemoryQueue=" + lockSet.size() + ";");
- output
- .println(" seseCaller->numMemoryQueue=numMemoryQueue;");
- output
- .println(" seseCaller->memoryQueueArray=mlpCreateMemoryQueueArray(numMemoryQueue);");
+ output.println(" runningSESE->numMemoryQueue=numMemoryQueue;");
+ output.println(" runningSESE->memoryQueueArray=mlpCreateMemoryQueueArray(numMemoryQueue);");
output.println();
}
}
System.out.println("size="+lockSet.size());
if (lockSet.size() > 0) {
output.println(" numMemoryQueue=" + lockSet.size() + ";");
- output
- .println(" seseCaller->numMemoryQueue=numMemoryQueue;");
- output
- .println(" seseCaller->memoryQueueArray=mlpCreateMemoryQueueArray(numMemoryQueue);");
+ output.println(" runningSESE->numMemoryQueue=numMemoryQueue;");
+ output.println(" runningSESE->memoryQueueArray=mlpCreateMemoryQueueArray(numMemoryQueue);");
output.println();
}
}
output.print(fsen.getSESErecordName()+"* "+paramsprefix);
output.println("){\n");
+
TempObject objecttemp=(TempObject) tempstable.get(md);
if ((GENERATEPRECISEGC) || (this.state.MULTICOREGC)) {
output.println(" "+type+" "+temp+";");
}
}
+
+
+ // initialize thread-local var to a the task's record, which is fused
+ // with the param list
+ output.println(" ");
+ output.println(" /* code of this task's body should use this to access the running task record */");
+ output.println(" runningSESE = &(___params___->common);");
+ output.println(" ");
// setup memory queue
// eom
Analysis.OoOJava.ConflictGraph graph = oooa.getConflictGraph(fsen);
if (graph != null && graph.hasConflictEdge()) {
output.println(" {");
- output
- .println(" SESEcommon* parentCommon = &(___params___->common);");
Set<Analysis.OoOJava.SESELock> lockSet = oooa.getLockMappings(graph);
System.out.println("#lockSet="+lockSet);
if (lockSet.size() > 0) {
output.println(" numMemoryQueue=" + lockSet.size() + ";");
- output
- .println(" parentCommon->numMemoryQueue=numMemoryQueue;");
- output
- .println(" parentCommon->memoryQueueArray=mlpCreateMemoryQueueArray(numMemoryQueue);");
+ output.println(" runningSESE->numMemoryQueue=numMemoryQueue;");
+ output.println(" runningSESE->memoryQueueArray=mlpCreateMemoryQueueArray(numMemoryQueue);");
output.println();
}
output.println(" }");
graph = mlpa.getConflictGraphResults().get(fsen);
if (graph != null && graph.hasConflictEdge()) {
output.println(" {");
- output
- .println(" SESEcommon* parentCommon = &(___params___->common);");
HashSet<SESELock> lockSet = mlpa.getConflictGraphLockMap().get(
graph);
System.out.println("#lockSet="+lockSet);
if (lockSet.size() > 0) {
output.println(" numMemoryQueue=" + lockSet.size() + "; ");
- output
- .println(" parentCommon->numMemoryQueue=numMemoryQueue;");
- output
- .println(" parentCommon->memoryQueueArray=mlpCreateMemoryQueueArray(numMemoryQueue);");
+ output.println(" runningSESE->numMemoryQueue=numMemoryQueue;");
+ output.println(" runningSESE->memoryQueueArray=mlpCreateMemoryQueueArray(numMemoryQueue);");
output.println();
}
output.println(" }");
}
+ // set up a task's mem pool to recycle the allocation of children tasks
+ // TODO: optimize by skipping this initialization when the current task
+ // is known to have no children (non-trivial, no children in body and
+ // no possibilty of issuing child within method calls)
+ output.println(" {");
+ output.println(" runningSESE->taskRecordMemPool = poolcreate( "+
+ maxTaskRecSizeStr+" );");
+ output.println(" }");
+
+
// copy in-set into place, ready vars were already
// copied when the SESE was issued
Iterator<TempDescriptor> tempItr;
VariableSourceToken vst = fsen.getStaticInVarSrc( temp );
SESEandAgePair srcPair = new SESEandAgePair( vst.getSESE(), vst.getAge() );
- // can't grab something from this source until it is done
- output.println(" {");
- /*
- If we are running, everything is done. This check is redundant.
-
- output.println(" SESEcommon* com = (SESEcommon*)"+paramsprefix+"->"+srcPair+";" );
- output.println(" pthread_mutex_lock( &(com->lock) );");
- output.println(" while( com->doneExecuting == FALSE ) {");
- output.println(" pthread_cond_wait( &(com->doneCond), &(com->lock) );");
- output.println(" }");
- output.println(" pthread_mutex_unlock( &(com->lock) );");
- */
output.println(" "+generateTemp( fsen.getfmBogus(), temp, null )+
" = "+paramsprefix+"->"+srcPair+"->"+vst.getAddrVar()+";");
-
- output.println(" }");
+ //output.println(" if( atomic_sub_and_test( 1, &src->refCount ) ) {");
+ //output.println(" poolfree( src->parent->taskRecordMemPool, src );");
+ //output.println(" }");
}
// dynamic vars come from an SESE and src
// go grab it from the SESE source
output.println(" if( "+paramsprefix+"->"+temp+"_srcSESE != NULL ) {");
- // gotta wait until the source is done
- output.println(" SESEcommon* com = (SESEcommon*)"+paramsprefix+"->"+temp+"_srcSESE;" );
- /*
- If we are running, everything is done!
- output.println(" pthread_mutex_lock( &(com->lock) );");
- output.println(" while( com->doneExecuting == FALSE ) {");
- output.println(" pthread_cond_wait( &(com->doneCond), &(com->lock) );");
- output.println(" }");
- output.println(" pthread_mutex_unlock( &(com->lock) );");
- */
-
String typeStr;
if( type.isNull() ) {
typeStr = "void*";
" = *(("+typeStr+"*) ("+
paramsprefix+"->"+temp+"_srcSESE + "+
paramsprefix+"->"+temp+"_srcOffset));");
+
+ //output.println(" if( atomic_sub_and_test( 1, &src->refCount ) ) {");
+ //output.println(" poolfree( src->parent->taskRecordMemPool, src );");
+ //output.println(" }");
- // or if the source was our parent, its in the record to grab
+
+ // or if the source was our parent, its in our record to grab
output.println(" } else {");
output.println(" "+generateTemp( fsen.getfmBogus(), temp, null )+
" = "+paramsprefix+"->"+temp+";");
// }
}
- // initialize thread-local var to a non-zero, invalid address
- output.println(" seseCaller = (SESEcommon*) 0x2;");
-
if( state.COREPROF ) {
output.println(" CP_LOGEVENT( CP_EVENTID_TASKEXECUTE, CP_EVENTTYPE_BEGIN );");
}
}
if( waitingElement.getStatus() >= ConflictNode.COARSE ){
- output.println(" rentry=mlpCreateREntry("+ waitingElement.getStatus()+ ", seseCaller);");
+ output.println(" rentry=mlpCreateREntry("+ waitingElement.getStatus()+ ", runningSESE);");
}else{
- output.println(" rentry=mlpCreateFineREntry("+ waitingElement.getStatus()+ ", seseCaller, (void*)&" +generateTemp(fm,waitingElement.getTempDesc(),lb)+ ");");
+ output.println(" rentry=mlpCreateFineREntry("+ waitingElement.getStatus()+ ", runningSESE, (void*)&" +generateTemp(fm,waitingElement.getTempDesc(),lb)+ ");");
}
output.println(" psem_init( &(rentry->parentStallSem) );");
- output.println(" rentry->queue=seseCaller->memoryQueueArray["+ waitingElement.getQueueID()+ "];");
- output.println(" if(ADDRENTRY(seseCaller->memoryQueueArray["+ waitingElement.getQueueID()
+ output.println(" rentry->queue=runningSESE->memoryQueueArray["+ waitingElement.getQueueID()+ "];");
+ output.println(" if(ADDRENTRY(runningSESE->memoryQueueArray["+ waitingElement.getQueueID()
+ "],rentry)==NOTREADY){");
if( state.COREPROF ) {
//output.println(" CP_LOGEVENT( CP_EVENTID_TASKSTALLMEM, CP_EVENTTYPE_BEGIN );");
if( waitingElement.getStatus() >= ConflictNode.COARSE ){
// HERE! a parent might conflict with a child
- output.println(" rentry=mlpCreateREntry("+ waitingElement.getStatus()+ ", seseCaller);");
+ output.println(" rentry=mlpCreateREntry("+ waitingElement.getStatus()+ ", runningSESE);");
}else{
- output.println(" rentry=mlpCreateFineREntry("+ waitingElement.getStatus()+ ", seseCaller, (void*)&___locals___."+ waitingElement.getDynID() + ");");
- // output.println(" rentry=mlpCreateFineREntry("+ waitingElement.getStatus()+ ", seseCaller, ___locals___."+ waitingElement.getDynID() + "->oid);");
+ output.println(" rentry=mlpCreateFineREntry("+ waitingElement.getStatus()+ ", runningSESE, (void*)&___locals___."+ waitingElement.getDynID() + ");");
}
output.println(" psem_init( &(rentry->parentStallSem) );");
- output.println(" rentry->queue=seseCaller->memoryQueueArray["+ waitingElement.getQueueID()+ "];");
+ output.println(" rentry->queue=runningSESE->memoryQueueArray["+ waitingElement.getQueueID()+ "];");
output
- .println(" if(ADDRENTRY(seseCaller->memoryQueueArray["+ waitingElement.getQueueID()
+ .println(" if(ADDRENTRY(runningSESE->memoryQueueArray["+ waitingElement.getQueueID()
+ "],rentry)==NOTREADY){");
if( state.COREPROF ) {
//output.println(" CP_LOGEVENT( CP_EVENTID_TASKSTALLMEM, CP_EVENTTYPE_BEGIN );");
output.println(" SESEcommon* parentCommon = &("+paramsprefix+"->common);");
} else {
//output.println(" SESEcommon* parentCommon = (SESEcommon*) peekItem( seseCallStack );");
- output.println(" SESEcommon* parentCommon = seseCaller;");
+ output.println(" SESEcommon* parentCommon = runningSESE;");
}
}
fsen.getSESErecordName()+"*) mlpAllocSESErecord( sizeof( "+
fsen.getSESErecordName()+" ) );");
+ /*
+ if( (state.MLP && fsen != mlpa.getMainSESE()) ||
+ (state.OOOJAVA && fsen != oooa.getMainSESE())
+ ) {
+ output.println(" "+
+ fsen.getSESErecordName()+"* seseToIssue = ("+
+ fsen.getSESErecordName()+"*) poolalloc( runningSESE->taskRecordMemPool );");
+ } else {
+ output.println(" "+
+ fsen.getSESErecordName()+"* seseToIssue = ("+
+ fsen.getSESErecordName()+"*) mlpAllocSESErecord( sizeof( "+
+ fsen.getSESErecordName()+" ) );");
+ }
+ */
+
// set up the SESE in-set and out-set objects, which look
// like a garbage list
output.println(" struct garbagelist * gl= (struct garbagelist *)&(((SESEcommon*)(seseToIssue))[1]);");
);
}
-
- // and keep the thread-local sese stack up to date (jjenista--this still relevant??)
- //output.println(" addNewItem( seseCallStack, (void*) seseToIssue);");
-
// fill in common data
output.println(" int localCount=0;");
output.println(" seseToIssue->common.classID = "+fsen.getIdentifier()+";");
output.println(" pthread_cond_init( &(seseToIssue->common.runningChildrenCond), NULL );");
output.println(" seseToIssue->common.numRunningChildren = 0;");
output.println(" seseToIssue->common.parent = parentCommon;");
+ output.println(" seseToIssue->common.refCount = 1;");
// all READY in-vars should be copied now and be done with it
Iterator<TempDescriptor> tempItr = fsen.getReadyInVarSet().iterator();
output.println(" }");
output.println(" if( !src->doneExecuting ) {");
output.println(" addNewItem( src->forwardList, seseToIssue );");
-// output.println(" ++(seseToIssue->common.unresolvedDependencies);");
+ output.println(" src->refCount++;");
output.println(" ++(localCount);");
output.println(" }");
output.println(" pthread_mutex_unlock( &(src->lock) );");
output.println(" seseToIssue != peekItem( src->forwardList ) ) {");
output.println(" if( !src->doneExecuting ) {");
output.println(" addNewItem( src->forwardList, seseToIssue );");
-// output.println(" ++(seseToIssue->common.unresolvedDependencies);");
+ output.println(" src->refCount++;");
output.println(" ++(localCount);");
output.println(" }");
output.println(" }");
output.println(" }");
output.println(" }");
- // this is a thread-only variable that can be handled when critical sese-to-sese
- // data has been taken care of--set sese pointer to remember self over method
- // calls to a non-zero, invalid address
- output.println(" seseCaller = (SESEcommon*) 0x1;");
+ // only do this pool free if this is not the Main sese (which has no parent
+ // and therefore no pool to free into)
+ if( (state.MLP && fsen != mlpa.getMainSESE()) ||
+ (state.OOOJAVA && fsen != oooa.getMainSESE())
+ ) {
+ //output.println(" if( atomic_sub_and_test( 1, &runningSESE->refCount ) ) {");
+ //output.println(" poolfree( runningSESE->parent->taskRecordMemPool, runningSESE );");
+ //output.println(" }");
+ }
+
+ // as this thread is wrapping up the task, make sure the thread-local var
+ // for the currently running task record references an invalid task
+ output.println(" runningSESE = (SESEcommon*) 0x1;");
if( state.COREPROF ) {
output.println(" CP_LOGEVENT( CP_EVENTID_TASKRETIRE, CP_EVENTTYPE_END );");
private void generateFlatCall(FlatMethod fm, LocalityBinding lb, FlatCall fc, PrintWriter output) {
+ /*
if( (state.MLP && !nonSESEpass) ||
(state.OOOJAVA && !nonSESEpass)
) {
- output.println(" seseCaller = (SESEcommon*)"+paramsprefix+";");
+ output.println(" runningSESE = (SESEcommon*)"+paramsprefix+";");
}
+ */
MethodDescriptor md=fc.getMethod();
ParamsObject objectparams=(ParamsObject)paramstable.get(lb!=null ? locality.getBinding(lb, fc) : md);
#include "methodheaders.h"
-
-/*
-__thread struct Queue* seseCallStack;
-__thread pthread_once_t mlpOnceObj = PTHREAD_ONCE_INIT;
-void mlpInitOncePerThread() {
- seseCallStack = createQueue();
-}
-*/
-__thread SESEcommon_p seseCaller;
+__thread SESEcommon* runningSESE;
void* mlpAllocSESErecord( int size ) {
newREntry->type=type;
newREntry->seseRec=seseToIssue;
newREntry->pointer=dynID;
- if((*newREntry->pointer)!=0){// make sure it is not unresolved address.
- struct ___Object___ * obj=(struct ___Object___*)((unsigned INTPTR)*newREntry->pointer);
- newREntry->oid=obj->oid;
- }
return newREntry;
}
//at this point, have table
Hashtable* table=(Hashtable*)q->tail;
r->hashtable=table; // set rentry's hashtable
- if((*(r->pointer)==0 || (*(r->pointer)!=0 && BARRIER() && table->unresolvedQueue!=NULL))){
+ if( *(r->pointer)==0 ||
+ ( *(r->pointer)!=0 &&
+ BARRIER() &&
+ table->unresolvedQueue!=NULL
+ )
+ ){
struct Queue* val;
// grab lock on the queue
do {
return NOTREADY;
}
BinItem * val;
- //int key=generateKey((unsigned int)(unsigned INTPTR)*(r->pointer));
- int key=generateKey(r->oid);
+
+ // leave this--its a helpful test when things are going bonkers
+ //if( OBJPTRPTR_2_OBJOID( r->pointer ) == 0 ) {
+ // // we started numbering object ID's at 1, if we try to
+ // // hash a zero oid, something BAD is about to happen!
+ // printf( "Tried to insert invalid object type=%d into mem Q hashtable!\n",
+ // OBJPTRPTR_2_OBJTYPE( r->pointer ) );
+ // exit( -1 );
+ //}
+ int key=generateKey( OBJPTRPTR_2_OBJOID( r->pointer ) );
do {
val=(BinItem*)0x1;
BinElement* bin=table->array[key];
int ADDTABLEITEM(Hashtable* table, REntry* r, int inc){
BinItem * val;
- // int key=generateKey((unsigned int)(unsigned INTPTR)*(r->pointer));
- int key=generateKey(r->oid);
+ int key=generateKey( OBJPTRPTR_2_OBJOID( r->pointer ) );
do {
val=(BinItem*)0x1;
BinElement* bin=table->array[key];
readbintail->array[readbintail->index++]=r;
atomic_inc(&readbintail->item.total);
r->binitem=(BinItem*)readbintail;
- //printf("grouping with %d\n",readbintail->index);
}
if(inc){
atomic_inc(&T->item.total);
}
RETIREBIN(Hashtable *T, REntry *r, BinItem *b) {
- // int key=generateKey((unsigned int)(unsigned INTPTR)*(r->pointer));
- int key=generateKey(r->oid);
+ int key=generateKey( OBJPTRPTR_2_OBJOID( r->pointer ) );
if(isFineRead(r)) {
atomic_dec(&b->total);
}
for(i=0; i<q->bufcount;i++){
REntry *r=q->buf[i];
if(r->type==WRITE){
- int key=generateKey(r->oid);
+ int key=generateKey( OBJPTRPTR_2_OBJOID( r->pointer ) );
if(q->binbuf[key]==NULL){
// for multiple writes, add only the first write that hashes to the same bin
q->binbuf[key]=r;
for(i=0; i<q->bufcount;i++){
REntry *r=q->buf[i];
if(r!=NULL && r->type==READ){
- int key=generateKey(r->oid);
+ int key=generateKey( OBJPTRPTR_2_OBJOID( r->pointer ) );
if(q->binbuf[key]==NULL){
// read item that hashes to the bin which doen't contain any write
seseCommon->rentryArray[seseCommon->rentryIdx++]=r;
for(i=0; i<q->bufcount;i++){
REntry *r=q->buf[i];
if(r->type==WRITE){
- int key=generateKey(r->oid);
+ int key=generateKey( OBJPTRPTR_2_OBJOID( r->pointer ) );
if(q->binbuf[key]==NULL){
// for multiple writes, add only the first write that hashes to the same bin
q->binbuf[key]=r;
for(i=0; i<q->bufcount;i++){
REntry *r=q->buf[i];
if(r!=NULL && r->type==READ){
- int key=generateKey(r->oid);
+ int key=generateKey( OBJPTRPTR_2_OBJOID( r->pointer ) );
if(q->binbuf[key]==NULL){
// read item that hashes to the bin which doen't contain any write
seseCommon->rentryArray[seseCommon->rentryIdx++]=r;
break;
}
removeItem(val,head);
- //now, address is resolved. update OID field.
- struct ___Object___ * obj=(struct ___Object___*)((unsigned INTPTR)*rentry->pointer);
- rentry->oid=obj->oid;
+
+ //now, address is resolved
//check if rentry is buffer mode
if(rentry->isBufMode==TRUE){
}
}
-void rehashMemoryQueue(SESEcommon_p seseParent){
+void rehashMemoryQueue(SESEcommon* seseParent){
#if 0
// update memory queue
int i,binidx;
#include "Queue.h"
#include "psemaphore.h"
#include "mlp_lock.h"
+#include "memPool.h"
#ifndef FALSE
#define FALSE 0
#define TRUE 1
#endif
+
+#define OBJPTRPTR_2_OBJTYPE( opp ) ((int*)(*(opp)))[0]
+#define OBJPTRPTR_2_OBJOID( opp ) ((int*)(*(opp)))[1]
+
+
typedef struct REntry_t{
int type; // fine read:0, fine write:1, parent read:2, parent write:3 coarse: 4, parent coarse:5, scc: 6
struct Hashtable_t* hashtable;
psemaphore parentStallSem;
void* seseRec;
INTPTR* pointer;
- int oid;
int isBufMode;
} REntry;
void RETIRERENTRY(MemoryQueue* Q, REntry * r);
-// forward declaration of pointer type
-typedef struct SESEcommon_t* SESEcommon_p;
// these fields are common to any SESE, and casting the
// generated SESE record to this can be used, because
// the identifier for the class of sese's that
// are instances of one particular static code block
+ // IMPORTANT: the class ID must be the first field of
+ // the task record so task dispatch works correctly!
int classID;
// a parent waits on this semaphore when stalling on
pthread_mutex_t lock;
struct Queue* forwardList;
- volatile int unresolvedDependencies;
+ volatile int unresolvedDependencies;
pthread_cond_t doneCond;
int doneExecuting;
pthread_cond_t runningChildrenCond;
int numRunningChildren;
- SESEcommon_p parent;
+ struct SESEcommon_t* parent;
psemaphore parentStallSem;
pthread_cond_t stallDone;
int numDependentSESErecords;
int offsetToDepSESErecords;
+ // for determining when task records can be returned
+ // to the parent record's memory pool
+ MemPool* taskRecordMemPool;
+ volatile int refCount;
+
} SESEcommon;
-// a thread-local stack of SESEs and function to
-// ensure it is initialized once per thread
-/*
-extern __thread struct Queue* seseCallStack;
-extern __thread pthread_once_t mlpOnceObj;
-void mlpInitOncePerThread();
-*/
-extern __thread SESEcommon_p seseCaller;
+
+// a thread-local var refers to the currently
+// running task
+extern __thread SESEcommon* runningSESE;
// simple mechanical allocation and
REntry* mlpCreateFineREntry(int type, void* seseToIssue, void* dynID);
REntry* mlpCreateREntry(int type, void* seseToIssue);
MemoryQueue* createMemoryQueue();
-void rehashMemoryQueue(SESEcommon_p seseParent);
+void rehashMemoryQueue(SESEcommon* seseParent);
#endif /* __MLP_RUNTIME__ */