changes
[IRC.git] / Robust / src / Runtime / mlp_runtime.h
index 859a430bffdf8f5141ab58243ac34b2a08a00ff0..ec0715b600ff355517bc22ba41d6b571c55b3fc9 100644 (file)
@@ -2,10 +2,52 @@
 #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
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#define NUMBINS 128
+#define NUMREAD 64
+#define NUMITEMS 64
+#define NUMRENTRY 256
+
+#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
+
+#define HASHTABLE 0
+#define VECTOR 1
+#define SINGLEITEM 2
 
+#define READBIN 0
+#define WRITEBIN 1
+
+#define H_MASK (NUMBINS)-1
 
 #ifndef FALSE
 #define FALSE 0
 #define TRUE 1
 #endif
 
-// forward declaration of pointer type
-typedef struct SESEcommon_t* SESEcommon_p;
+
+// 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]
+
+// forwarding list elements is a linked
+// structure of arrays, should help task
+// dispatch because the first element is
+// an embedded member of the task record,
+// only have to do memory allocation if
+// a lot of items are on the list
+#define FLIST_ITEMS_PER_ELEMENT 30
+typedef struct ForwardingListElement_t {
+  int                             numItems;
+  struct ForwardingListElement_t* nextElement;
+  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
@@ -26,35 +87,230 @@ typedef struct SESEcommon_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;
+  volatile int    unresolvedDependencies;
 
   // a parent waits on this semaphore when stalling on
   // this child, the child gives it at its SESE exit
-  psemaphore stallSem;
+  psemaphore* parentsStallSem;
 
   
+  // NOTE: first element is embedded in the task
+  // record, so don't free it!
+  //ForwardingListElement forwardList;
+  struct Queue forwardList;
+
+  volatile int             doneExecuting;
+  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];
+
+#ifdef RCR
+  int offsetToParamRecords;
+  volatile int rcrstatus;
+  volatile int retired;
+#endif
+
   // the lock guards the following data SESE's
   // use to coordinate with one another
   pthread_mutex_t lock;
+  pthread_cond_t  runningChildrenCond;
+} SESEcommon;
 
-  struct Queue*   forwardList;
-  int             unresolvedDependencies;
+// a thread-local var refers to the currently
+// running task
+extern __thread SESEcommon* runningSESE;
+extern __thread int childSESE;
 
-  pthread_cond_t  doneCond;
-  int             doneExecuting;
+// there only needs to be one stall semaphore
+// per thread, just give a reference to it to
+// the task you are about to block on
+extern __thread psemaphore runningSESEstallSem;
 
-  pthread_cond_t  runningChildrenCond;
-  int             numRunningChildren;
 
-  SESEcommon_p    parent;
 
-} SESEcommon;
+typedef struct REntry_t{
+  // fine read:0, fine write:1, parent read:2, 
+  // parent write:3 coarse: 4, parent coarse:5, scc: 6
+  int type;
+  int tag;
+  MemoryQueueItem *qitem;
+  struct BinItem_t* binitem;
+  struct MemoryQueue_t* queue;
+  SESEcommon* seseRec;
+  INTPTR* pointer;
+  psemaphore * parentStallSem;
+#ifdef RCR
+  INTPTR mask;
+#endif
+  int isBufMode;
+} REntry;
 
+#ifdef RCR
+#define RCRSIZE 32
+#define RUNBIAS 1000000
+
+struct rcrRecord {
+  int count;
+  int index;
+  int flag;
+  int array[RCRSIZE];
+  void * ptrarray[RCRSIZE];
+  struct rcrRecord *next;
+};
+
+typedef struct SESEstall_t { 
+  SESEcommon common;
+  int size;
+  void * next;
+  struct ___Object___* ___obj___;
+  struct rcrRecord rcrRecords[1];
+  int tag;
+} SESEstall;
+#endif
+
+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;
+#ifndef OOO_DISABLE_TASKMEMPOOL
+  MemPool * rentrypool;
+#endif
+} 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);
+
+
+
+
+static inline void ADD_FORWARD_ITEM( ForwardingListElement* e,
+                                     SESEcommon*            s ) {
+  //atomic_inc( &(s->refCount) );
+}
 
 // simple mechanical allocation and 
 // deallocation of SESE records
-void* mlpCreateSESErecord( int size );
-void  mlpDestroySESErecord( void* seseRecord );
+void* mlpAllocSESErecord( int size );
+void  mlpFreeSESErecord( SESEcommon* seseRecord );
+
+MemoryQueue** mlpCreateMemoryQueueArray(int numMemoryQueue);
+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 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__ */