#define __MLP_RUNTIME__
+#include <stdlib.h>
+#include <stdio.h>
+
+
#include <pthread.h>
+#include "runtime.h"
+#include "mem.h"
#include "Queue.h"
#include "psemaphore.h"
#include "mlp_lock.h"
#include "memPool.h"
+
+
#ifndef FALSE
#define FALSE 0
#endif
// these are useful for interpreting an INTPTR to an
// Object at runtime to retrieve the object's type
// or object id (OID), 64-bit safe
-#define OBJPTRPTR_2_OBJTYPE( opp ) ((int*)(opp))[0]
-#define OBJPTRPTR_2_OBJOID( opp ) ((int*)(opp))[1]
-
-
+#define OBJPTRPTR_2_OBJTYPE( opp ) ((int*)*(opp))[0]
+#define OBJPTRPTR_2_OBJOID( opp ) ((int*)*(opp))[1]
// forwarding list elements is a linked
// structure of arrays, should help task
INTPTR items[FLIST_ITEMS_PER_ELEMENT];
} ForwardingListElement;
-
+struct MemPool_t;
// these fields are common to any SESE, and casting the
// generated SESE record to this can be used, because
// IMPORTANT: the class ID must be the first field of
// the task record so task dispatch works correctly!
int classID;
-
+ volatile int unresolvedDependencies;
// a parent waits on this semaphore when stalling on
// this child, the child gives it at its SESE exit
psemaphore* parentsStallSem;
- // the lock guards the following data SESE's
- // use to coordinate with one another
- pthread_mutex_t lock;
-
// NOTE: first element is embedded in the task
// record, so don't free it!
//ForwardingListElement forwardList;
- struct Queue* forwardList;
+ struct Queue forwardList;
- volatile int unresolvedDependencies;
-
- pthread_cond_t doneCond;
volatile int doneExecuting;
-
- pthread_cond_t runningChildrenCond;
- int numRunningChildren;
+ volatile int numRunningChildren;
struct SESEcommon_t* parent;
int numMemoryQueue;
int rentryIdx;
int unresolvedRentryIdx;
+ volatile int refCount;
+ int numDependentSESErecords;
+ int offsetToDepSESErecords;
+ struct MemPool_t * taskRecordMemPool;
+
struct MemoryQueue_t** memoryQueueArray;
struct REntry_t* rentryArray[NUMRENTRY];
struct REntry_t* unresolvedRentryArray[NUMRENTRY];
- int numDependentSESErecords;
- int offsetToDepSESErecords;
#ifdef RCR
int offsetToParamRecords;
volatile int rcrstatus;
volatile int retired;
#endif
- // for determining when task records can be returned
- // to the parent record's memory pool
- MemPool* taskRecordMemPool;
- volatile int refCount;
+ // the lock guards the following data SESE's
+ // use to coordinate with one another
+ pthread_mutex_t lock;
+ pthread_cond_t runningChildrenCond;
} SESEcommon;
// a thread-local var refers to the currently
// running task
extern __thread SESEcommon* runningSESE;
+extern __thread int childSESE;
// there only needs to be one stall semaphore
// per thread, just give a reference to it to
// fine read:0, fine write:1, parent read:2,
// parent write:3 coarse: 4, parent coarse:5, scc: 6
int type;
- struct Hashtable_t* hashtable;
+ int tag;
+ MemoryQueueItem *qitem;
struct BinItem_t* binitem;
- struct Vector_t* vector;
- struct SCC_t* scc;
struct MemoryQueue_t* queue;
- psemaphore parentStallSem;
- int tag;
SESEcommon* seseRec;
INTPTR* pointer;
+ psemaphore * parentStallSem;
+#ifdef RCR
+ INTPTR mask;
+#endif
int isBufMode;
} REntry;
int type; // hashtable:0, vector:1, singleitem:2
int total; //total non-retired
int status; //NOTREADY, READY
- struct MemoryQueueItem_t *next;
+ struct MemoryQueueItem_t *next;
+
} MemoryQueueItem;
typedef struct MemoryQueue_t {
REntry * binbuf[NUMBINS];
REntry * buf[NUMRENTRY];
int bufcount;
+#ifndef OOO_DISABLE_TASKMEMPOOL
+ MemPool * rentrypool;
+#endif
} MemoryQueue;
typedef struct BinItem_t {
//atomic_inc( &(s->refCount) );
}
-
-
-
// simple mechanical allocation and
// deallocation of SESE records
void* mlpAllocSESErecord( int size );
void mlpFreeSESErecord( SESEcommon* seseRecord );
MemoryQueue** mlpCreateMemoryQueueArray(int numMemoryQueue);
-REntry* mlpCreateFineREntry(int type, SESEcommon* seseToIssue, void* dynID);
-REntry* mlpCreateREntry (int type, SESEcommon* seseToIssue);
+REntry* mlpCreateFineREntry(MemoryQueue *q, int type, SESEcommon* seseToIssue, void* dynID);
+#ifdef RCR
+REntry* mlpCreateREntry(MemoryQueue *q, int type, SESEcommon* seseToIssue, INTPTR mask);
+#else
+REntry* mlpCreateREntry(MemoryQueue *q, int type, SESEcommon* seseToIssue);
+#endif
MemoryQueue* createMemoryQueue();
void rehashMemoryQueue(SESEcommon* seseParent);
-
static inline void ADD_REFERENCE_TO( SESEcommon* seseRec ) {
atomic_inc( &(seseRec->refCount) );
}
-static inline void RELEASE_REFERENCE_TO( SESEcommon* seseRec ) {
+static inline int RELEASE_REFERENCE_TO( SESEcommon* seseRec ) {
if( atomic_sub_and_test( 1, &(seseRec->refCount) ) ) {
poolfreeinto( seseRec->parent->taskRecordMemPool, seseRec );
+ return 1;
}
+ return 0;
+}
+
+#define CHECK_RECORD(x) ;
+
+
+////////////////////////////////////////////////
+//
+// Some available debug versions of the above
+// pool allocation-related helpers. The lower
+// 'x' appended to names means they are not hooked
+// up, but check em in so we can switch names and
+// use them for debugging
+//
+////////////////////////////////////////////////
+#define ADD_REFERENCE_TOx(x) atomic_inc( &((x)->refCount) ); printf("0x%x ADD 0x%x on %d\n",(INTPTR)runningSESE,(INTPTR)(x),__LINE__);
+
+#define RELEASE_REFERENCE_TOx(x) if (atomic_sub_and_test(1, &((x)->refCount))) {poolfreeinto(x->parent->taskRecordMemPool, x);printf("0x%x REL 0x%x on %d\n",(INTPTR)runningSESE,(INTPTR)(x),__LINE__);}
+
+#define CHECK_RECORDx(x) { \
+ if( ((SESEcommon*)(x))->refCount != 0 ) { \
+ printf( "Acquired 0x%x from poolalloc, with refCount=%d\n", (INTPTR)(x), ((SESEcommon*)(x))->refCount ); } \
+ if( ((SESEcommon*)(x))->fresh != 1 ) { \
+ printf("0x%x reclaimed 0x%x on %d\n",(INTPTR)runningSESE,(INTPTR)(x),__LINE__); } \
+ ((SESEcommon*)(x))->fresh = 0; \
}
+
+// this is for using a memPool to allocate task records,
+// pass this into the poolcreate so it will run your
+// custom init code ONLY for fresh records, reused records
+// can be returned as is
+void freshTaskRecordInitializer( void* seseRecord );
+
+
#endif /* __MLP_RUNTIME__ */