1 #ifndef __MLP_RUNTIME__
2 #define __MLP_RUNTIME__
13 #include "psemaphore.h"
18 #include "classdefs.h"
43 #define PARENTCOARSE 5
53 #define H_MASK (NUMBINS)-1
64 // these are useful for interpreting an INTPTR to an
65 // Object at runtime to retrieve the object's type
67 #define OBJPTRPTR_2_OBJTYPE(opp) ((struct ___Object___*)*(opp))->type
68 #define OBJPTRPTR_2_OBJOID(opp) ((struct ___Object___*)*(opp))->oid
71 // forwarding list elements is a linked
72 // structure of arrays, should help task
73 // dispatch because the first element is
74 // an embedded member of the task record,
75 // only have to do memory allocation if
76 // a lot of items are on the list
77 #define FLIST_ITEMS_PER_ELEMENT 30
78 typedef struct ForwardingListElement_t {
80 struct ForwardingListElement_t* nextElement;
81 INTPTR items[FLIST_ITEMS_PER_ELEMENT];
82 } ForwardingListElement;
86 // these fields are common to any SESE, and casting the
87 // generated SESE record to this can be used, because
88 // the common structure is always the first item in a
89 // customized SESE record
90 typedef struct SESEcommon_t {
92 // the identifier for the class of sese's that
93 // are instances of one particular static code block
94 // IMPORTANT: the class ID must be the first field of
95 // the task record so task dispatch works correctly!
97 volatile int unresolvedDependencies;
99 // a parent waits on this semaphore when stalling on
100 // this child, the child gives it at its SESE exit
101 psemaphore* parentsStallSem;
104 // NOTE: first element is embedded in the task
105 // record, so don't free it!
106 //ForwardingListElement forwardList;
107 struct Queue forwardList;
109 volatile int doneExecuting;
110 volatile int numRunningChildren;
112 struct SESEcommon_t* parent;
116 int unresolvedRentryIdx;
117 volatile int refCount;
118 int numDependentSESErecords;
119 int offsetToDepSESErecords;
120 struct MemPool_t * taskRecordMemPool;
122 struct MemoryQueue_t** memoryQueueArray;
123 struct REntry_t* rentryArray[NUMRENTRY];
124 struct REntry_t* unresolvedRentryArray[NUMRENTRY];
127 struct Hashtable_rcr ** allHashStructures;
128 int offsetToParamRecords;
129 volatile int rcrstatus;
130 volatile int retired;
133 // the lock guards the following data SESE's
134 // use to coordinate with one another
135 pthread_mutex_t lock;
136 pthread_cond_t runningChildrenCond;
139 // a thread-local var refers to the currently
141 extern __thread SESEcommon* runningSESE;
142 extern __thread int childSESE;
144 // there only needs to be one stall semaphore
145 // per thread, just give a reference to it to
146 // the task you are about to block on
147 extern __thread psemaphore runningSESEstallSem;
151 typedef struct REntry_t {
152 // fine read:0, fine write:1, parent read:2,
153 // parent write:3 coarse: 4, parent coarse:5, scc: 6
160 struct MemoryQueueItem_t *qitem;
161 struct BinItem_t* binitem;
162 struct MemoryQueue_t* queue;
169 psemaphore * parentStallSem;
176 #define RUNBIAS 1000000
183 void * ptrarray[RCRSIZE];
184 struct rcrRecord *next;
187 typedef struct SESEstall_t {
191 struct ___Object___* ___obj___;
192 struct rcrRecord rcrRecords[1];
197 typedef struct MemoryQueueItem_t {
198 int type; // hashtable:0, vector:1, singleitem:2
199 int total; //total non-retired
200 int status; //NOTREADY, READY
201 struct MemoryQueueItem_t *next;
205 typedef struct MemoryQueue_t {
206 MemoryQueueItem * head;
207 MemoryQueueItem * tail;
208 REntry * binbuf[NUMBINS];
209 REntry * buf[NUMRENTRY];
211 #ifndef OOO_DISABLE_TASKMEMPOOL
212 MemPool * rentrypool;
216 typedef struct BinItem_t {
218 int status; //NOTREADY, READY
219 int type; //READBIN:0, WRITEBIN:1
220 struct BinItem_t * next;
223 typedef struct Hashtable_t {
224 MemoryQueueItem item;
225 struct BinElement_t* array[NUMBINS];
226 struct Queue* unresolvedQueue;
229 typedef struct BinElement_t {
234 typedef struct WriteBinItem_t {
239 typedef struct ReadBinItem_t {
241 REntry * array[NUMREAD];
245 typedef struct Vector_t {
246 MemoryQueueItem item;
247 REntry * array[NUMITEMS];
251 typedef struct SCC_t {
252 MemoryQueueItem item;
256 int ADDRENTRY(MemoryQueue* q, REntry * r);
257 void RETIRERENTRY(MemoryQueue* Q, REntry * r);
262 static inline void ADD_FORWARD_ITEM(ForwardingListElement* e,
264 //atomic_inc( &(s->refCount) );
267 // simple mechanical allocation and
268 // deallocation of SESE records
269 void* mlpAllocSESErecord(int size);
270 void mlpFreeSESErecord(SESEcommon* seseRecord);
272 MemoryQueue** mlpCreateMemoryQueueArray(int numMemoryQueue);
273 REntry* mlpCreateFineREntry(MemoryQueue *q, int type, SESEcommon* seseToIssue, void* dynID);
275 REntry* mlpCreateREntry(MemoryQueue *q, int type, SESEcommon* seseToIssue, INTPTR mask);
277 REntry* mlpCreateREntry(MemoryQueue *q, int type, SESEcommon* seseToIssue);
279 MemoryQueue* createMemoryQueue();
280 void rehashMemoryQueue(SESEcommon* seseParent);
281 void TAILWRITECASE(Hashtable *T, REntry *r, BinItem *val, BinItem *bintail, int key, int inc);
282 void RETIRESCC(MemoryQueue *Q, REntry *r);
283 void RETIREHASHTABLE(MemoryQueue *q, REntry *r);
284 void RETIREBIN(Hashtable *T, REntry *r, BinItem *b);
285 void RETIREVECTOR(MemoryQueue *Q, REntry *r);
286 void RESOLVECHAIN(MemoryQueue *Q);
287 void RESOLVEHASHTABLE(MemoryQueue *Q, Hashtable *T);
288 void RESOLVEVECTOR(MemoryQueue *q, Vector *V);
289 void RESOLVESCC(MemoryQueue *q, SCC *S);
290 void resolveDependencies(REntry* rentry);
293 int RESOLVEBUF(MemoryQueue * q, SESEcommon *seseCommon);
294 void resolvePointer(REntry* rentry);
297 static inline void ADD_REFERENCE_TO(SESEcommon* seseRec) {
298 atomic_inc(&(seseRec->refCount) );
301 static inline int RELEASE_REFERENCE_TO(SESEcommon* seseRec) {
302 if( atomic_sub_and_test(1, &(seseRec->refCount) ) ) {
303 poolfreeinto(seseRec->parent->taskRecordMemPool, seseRec);
309 static inline int RELEASE_REFERENCES_TO(SESEcommon* seseRec, int refCount) {
310 if( atomic_sub_and_test(refCount, &(seseRec->refCount) ) ) {
311 poolfreeinto(seseRec->parent->taskRecordMemPool, seseRec);
317 #define CHECK_RECORD(x) ;
320 ////////////////////////////////////////////////
322 // Some available debug versions of the above
323 // pool allocation-related helpers. The lower
324 // 'x' appended to names means they are not hooked
325 // up, but check em in so we can switch names and
326 // use them for debugging
328 ////////////////////////////////////////////////
329 #define ADD_REFERENCE_TOx(x) atomic_inc(&((x)->refCount) ); printf("0x%x ADD 0x%x on %d\n",(INTPTR)runningSESE,(INTPTR)(x),__LINE__);
331 #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__); }
333 #define CHECK_RECORDx(x) { \
334 if( ((SESEcommon*)(x))->refCount < 0 || \
335 ((SESEcommon*)(x))->refCount < 0 ) { \
336 printf("Acquired 0x%x from poolalloc, with refCount=%d\n", (INTPTR)(x), ((SESEcommon*)(x))->refCount); } \
341 // this is for using a memPool to allocate task records,
342 // pass this into the poolcreate so it will run your
343 // custom init code ONLY for fresh records, reused records
344 // can be returned as is
345 void freshTaskRecordInitializer(void* seseRecord);
348 #endif /* __MLP_RUNTIME__ */