#include <pthread.h>
#include "Queue.h"
+#include "psemaphore.h"
+#include "mlp_lock.h"
+#include "memPool.h"
+#ifndef FALSE
+#define FALSE 0
+#endif
-// a forward delcaration for SESEvar
-struct SESErecord_t;
+#ifndef TRUE
+#define TRUE 1
+#endif
+#define NUMBINS 64
+#define NUMREAD 64
+#define NUMITEMS 64
+#define NUMRENTRY 256
-typedef struct SESEvar_t {
- //unsigned char mode;
-
- // the value when it is known will be placed
- // in this location, which can be accessed
- // as a variety of types
- union {
- char sesetype_byte;
- int sesetype_boolean;
- short sesetype_short;
- int sesetype_int;
- long long sesetype_long;
- short sesetype_char;
- float sesetype_float;
- double sesetype_double;
- void* sesetype_object;
- };
-
- // a statically or dynamically known SESE
- // to gather the variable's value from
- // if source==NULL it indicates the root
- // SESE, which has no record, just normal
- // temp names
- //struct SESErecord_t* source;
- //unsigned int index;
-} SESEvar;
+#define READY 1
+#define NOTREADY 0
+#define READ 0
+#define WRITE 1
+#define PARENTREAD 2
+#define PARENTWRITE 3
+#define COARSE 4
+#define PARENTCOARSE 5
+#define SCCITEM 6
-typedef struct SESErecord_t {
- // the identifier for the class of sese's that
- // are instances of one particular static code block
- int classID;
+#define HASHTABLE 0
+#define VECTOR 1
+#define SINGLEITEM 2
- // not globally unqiue, but each parent ensures that
- // its children have unique identifiers, including to
- // the parent itself
- int instanceID;
+#define READBIN 0
+#define WRITEBIN 1
- // used to give out IDs to children
- int childInstanceIDs;
+#define H_MASK (NUMBINS<<4)-1
- // pointers to SESEs directly above or below
- // in the heirarchy
- struct SESErecord_t* parent;
- struct Queue* childrenList;
+#ifndef FALSE
+#define FALSE 0
+#endif
- // for state of vars after issue
- SESEvar* vars;
-
- // when this sese is ready to be invoked,
- // allocate and fill in this structure, and
- // the primitives will be passed out of the
- // above var array at the call site
- void* paramStruct;
+#ifndef TRUE
+#define TRUE 1
+#endif
- pthread_cond_t* startCondVar;
- pthread_mutex_t* startCondVarLock;
+#define OBJPTRPTR_2_OBJTYPE( opp ) ((int*)(*(opp)))[0]
+#define OBJPTRPTR_2_OBJOID( opp ) ((int*)(*(opp)))[1]
- // use a list of SESErecords and a lock to let
- // consumers tell this SESE who wants values
- // forwarded to it
- pthread_mutex_t* forwardListLock;
- struct Queue* forwardList;
- int doneExecuting;
-} SESErecord;
+// these fields are common to any SESE, and casting the
+// generated SESE record to this can be used, because
+// the common structure is always the first item in a
+// customized SESE record
+typedef struct SESEcommon_t {
-typedef struct invokeSESEargs_t {
+ // 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;
- SESErecord* invokee;
- SESErecord* parent;
-} invokeSESEargs;
+ // a parent waits on this semaphore when stalling on
+ // this child, the child gives it at its SESE exit
+ psemaphore stallSem;
-// simple mechanical allocation and deallocation
-// of SESE records
-SESErecord* mlpCreateSESErecord( int classID,
- int instanceID,
- SESErecord* parent,
- int numVars,
- void* paramStruct
- );
-
-void mlpDestroySESErecord( SESErecord* sese );
-
-
-// main library functions
-void mlpInit();
-
-SESErecord* mlpGetCurrent();
-SESErecord* mlpSchedule();
-
-void mlpIssue ( SESErecord* sese );
-void mlpStall ( SESErecord* sese );
-void mlpNotifyExit( SESErecord* sese );
-
-
-extern SESErecord* rootsese;
+
+ // the lock guards the following data SESE's
+ // use to coordinate with one another
+ pthread_mutex_t lock;
+
+ struct Queue* forwardList;
+ volatile int unresolvedDependencies;
+
+ pthread_cond_t doneCond;
+ int doneExecuting;
+
+ pthread_cond_t runningChildrenCond;
+ int numRunningChildren;
+
+ struct SESEcommon_t* parent;
+
+ psemaphore parentStallSem;
+ pthread_cond_t stallDone;
+
+ int numMemoryQueue;
+ int rentryIdx;
+ int unresolvedRentryIdx;
+ struct MemoryQueue_t** memoryQueueArray;
+ struct REntry_t* rentryArray[NUMRENTRY];
+ struct REntry_t* unresolvedRentryArray[NUMRENTRY];
+
+ 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 var refers to the currently
+// running task
+extern __thread SESEcommon* runningSESE;
+
+
+
+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;
+ struct BinItem_t* binitem;
+ struct Vector_t* vector;
+ struct SCC_t* scc;
+ struct MemoryQueue_t* queue;
+ psemaphore parentStallSem;
+ SESEcommon* seseRec;
+ INTPTR* pointer;
+ int isBufMode;
+} REntry;
+
+typedef struct MemoryQueueItem_t {
+ int type; // hashtable:0, vector:1, singleitem:2
+ int total; //total non-retired
+ int status; //NOTREADY, READY
+ struct MemoryQueueItem_t *next;
+} MemoryQueueItem;
+
+typedef struct MemoryQueue_t {
+ MemoryQueueItem * head;
+ MemoryQueueItem * tail;
+ REntry * binbuf[NUMBINS];
+ REntry * buf[NUMRENTRY];
+ int bufcount;
+} MemoryQueue;
+
+typedef struct BinItem_t {
+ int total;
+ int status; //NOTREADY, READY
+ int type; //READBIN:0, WRITEBIN:1
+ struct BinItem_t * next;
+} BinItem;
+
+typedef struct Hashtable_t {
+ MemoryQueueItem item;
+ struct BinElement_t* array[NUMBINS];
+ struct Queue* unresolvedQueue;
+} Hashtable;
+
+typedef struct BinElement_t {
+ BinItem * head;
+ BinItem * tail;
+} BinElement;
+
+typedef struct WriteBinItem_t {
+ BinItem item;
+ REntry * val;
+} WriteBinItem;
+
+typedef struct ReadBinItem_t {
+ BinItem item;
+ REntry * array[NUMREAD];
+ int index;
+} ReadBinItem;
+
+typedef struct Vector_t {
+ MemoryQueueItem item;
+ REntry * array[NUMITEMS];
+ int index;
+} Vector;
+
+typedef struct SCC_t {
+ MemoryQueueItem item;
+ REntry * val;
+} SCC;
+
+int ADDRENTRY(MemoryQueue* q, REntry * r);
+void RETIRERENTRY(MemoryQueue* Q, REntry * r);
+
+
+
+// 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);
+MemoryQueue* createMemoryQueue();
+void rehashMemoryQueue(SESEcommon* seseParent);
+
+
+static inline void ADD_REFERENCE_TO( SESEcommon* seseRec ) {
+#ifndef OOO_DISABLE_TASKMEMPOOL
+ atomic_inc( &(seseRec->refCount) );
+#endif
+}
+
+static inline void RELEASE_REFERENCE_TO( SESEcommon* seseRec ) {
+#ifndef OOO_DISABLE_TASKMEMPOOL
+ if( atomic_sub_and_test( 1, &(seseRec->refCount) ) ) {
+ poolfreeinto( seseRec->parent->taskRecordMemPool, seseRec );
+ }
+#endif
+}
#endif /* __MLP_RUNTIME__ */