1 #ifndef __MLP_RUNTIME__
2 #define __MLP_RUNTIME__
13 #include "psemaphore.h"
40 #define PARENTCOARSE 5
50 #define H_MASK (NUMBINS)-1
61 // these are useful for interpreting an INTPTR to an
62 // Object at runtime to retrieve the object's type
63 // or object id (OID), 64-bit safe
64 #define OBJPTRPTR_2_OBJTYPE( opp ) ((int*)*(opp))[0]
65 #define OBJPTRPTR_2_OBJOID( opp ) ((int*)*(opp))[1]
67 // forwarding list elements is a linked
68 // structure of arrays, should help task
69 // dispatch because the first element is
70 // an embedded member of the task record,
71 // only have to do memory allocation if
72 // a lot of items are on the list
73 #define FLIST_ITEMS_PER_ELEMENT 30
74 typedef struct ForwardingListElement_t {
76 struct ForwardingListElement_t* nextElement;
77 INTPTR items[FLIST_ITEMS_PER_ELEMENT];
78 } ForwardingListElement;
82 // these fields are common to any SESE, and casting the
83 // generated SESE record to this can be used, because
84 // the common structure is always the first item in a
85 // customized SESE record
86 typedef struct SESEcommon_t {
88 // the identifier for the class of sese's that
89 // are instances of one particular static code block
90 // IMPORTANT: the class ID must be the first field of
91 // the task record so task dispatch works correctly!
93 volatile int unresolvedDependencies;
95 // a parent waits on this semaphore when stalling on
96 // this child, the child gives it at its SESE exit
97 psemaphore* parentsStallSem;
100 // NOTE: first element is embedded in the task
101 // record, so don't free it!
102 //ForwardingListElement forwardList;
103 struct Queue forwardList;
105 volatile int doneExecuting;
106 volatile int numRunningChildren;
108 struct SESEcommon_t* parent;
112 int unresolvedRentryIdx;
113 volatile int refCount;
114 int numDependentSESErecords;
115 int offsetToDepSESErecords;
116 struct MemPool_t * taskRecordMemPool;
118 struct MemoryQueue_t** memoryQueueArray;
119 struct REntry_t* rentryArray[NUMRENTRY];
120 struct REntry_t* unresolvedRentryArray[NUMRENTRY];
123 int offsetToParamRecords;
124 volatile int rcrstatus;
125 volatile int retired;
128 // the lock guards the following data SESE's
129 // use to coordinate with one another
130 pthread_mutex_t lock;
131 pthread_cond_t runningChildrenCond;
134 // a thread-local var refers to the currently
136 extern __thread SESEcommon* runningSESE;
137 extern __thread int childSESE;
139 // there only needs to be one stall semaphore
140 // per thread, just give a reference to it to
141 // the task you are about to block on
142 extern __thread psemaphore runningSESEstallSem;
146 typedef struct REntry_t{
147 // fine read:0, fine write:1, parent read:2,
148 // parent write:3 coarse: 4, parent coarse:5, scc: 6
150 struct Hashtable_t* hashtable;
151 struct BinItem_t* binitem;
152 struct Vector_t* vector;
154 struct MemoryQueue_t* queue;
155 psemaphore * parentStallSem;
164 #define RUNBIAS 1000000
171 void * ptrarray[RCRSIZE];
172 struct rcrRecord *next;
175 typedef struct SESEstall_t {
179 struct ___Object___* ___obj___;
180 struct rcrRecord rcrRecords[1];
185 typedef struct MemoryQueueItem_t {
186 int type; // hashtable:0, vector:1, singleitem:2
187 int total; //total non-retired
188 int status; //NOTREADY, READY
189 struct MemoryQueueItem_t *next;
193 typedef struct MemoryQueue_t {
194 MemoryQueueItem * head;
195 MemoryQueueItem * tail;
196 REntry * binbuf[NUMBINS];
197 REntry * buf[NUMRENTRY];
199 #ifndef OOO_DISABLE_TASKMEMPOOL
200 MemPool * rentrypool;
204 typedef struct BinItem_t {
206 int status; //NOTREADY, READY
207 int type; //READBIN:0, WRITEBIN:1
208 struct BinItem_t * next;
211 typedef struct Hashtable_t {
212 MemoryQueueItem item;
213 struct BinElement_t* array[NUMBINS];
214 struct Queue* unresolvedQueue;
217 typedef struct BinElement_t {
222 typedef struct WriteBinItem_t {
227 typedef struct ReadBinItem_t {
229 REntry * array[NUMREAD];
233 typedef struct Vector_t {
234 MemoryQueueItem item;
235 REntry * array[NUMITEMS];
239 typedef struct SCC_t {
240 MemoryQueueItem item;
244 int ADDRENTRY(MemoryQueue* q, REntry * r);
245 void RETIRERENTRY(MemoryQueue* Q, REntry * r);
250 static inline void ADD_FORWARD_ITEM( ForwardingListElement* e,
252 //atomic_inc( &(s->refCount) );
258 // simple mechanical allocation and
259 // deallocation of SESE records
260 void* mlpAllocSESErecord( int size );
261 void mlpFreeSESErecord( SESEcommon* seseRecord );
263 MemoryQueue** mlpCreateMemoryQueueArray(int numMemoryQueue);
264 REntry* mlpCreateFineREntry(MemoryQueue *q, int type, SESEcommon* seseToIssue, void* dynID);
265 REntry* mlpCreateREntry(MemoryQueue *q, int type, SESEcommon* seseToIssue);
266 MemoryQueue* createMemoryQueue();
267 void rehashMemoryQueue(SESEcommon* seseParent);
272 static inline void ADD_REFERENCE_TO( SESEcommon* seseRec ) {
273 atomic_inc( &(seseRec->refCount) );
276 static inline int RELEASE_REFERENCE_TO( SESEcommon* seseRec ) {
277 if( atomic_sub_and_test( 1, &(seseRec->refCount) ) ) {
278 poolfreeinto( seseRec->parent->taskRecordMemPool, seseRec );
284 #define CHECK_RECORD(x) ;
287 ////////////////////////////////////////////////
289 // Some available debug versions of the above
290 // pool allocation-related helpers. The lower
291 // 'x' appended to names means they are not hooked
292 // up, but check em in so we can switch names and
293 // use them for debugging
295 ////////////////////////////////////////////////
296 #define ADD_REFERENCE_TOx(x) atomic_inc( &((x)->refCount) ); printf("0x%x ADD 0x%x on %d\n",(INTPTR)runningSESE,(INTPTR)(x),__LINE__);
298 #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__);}
300 #define CHECK_RECORDx(x) { \
301 if( ((SESEcommon*)(x))->refCount != 0 ) { \
302 printf( "Acquired 0x%x from poolalloc, with refCount=%d\n", (INTPTR)(x), ((SESEcommon*)(x))->refCount ); } \
303 if( ((SESEcommon*)(x))->fresh != 1 ) { \
304 printf("0x%x reclaimed 0x%x on %d\n",(INTPTR)runningSESE,(INTPTR)(x),__LINE__); } \
305 ((SESEcommon*)(x))->fresh = 0; \
310 // this is for using a memPool to allocate task records,
311 // pass this into the poolcreate so it will run your
312 // custom init code ONLY for fresh records, reused records
313 // can be returned as is
314 void freshTaskRecordInitializer( void* seseRecord );
317 #endif /* __MLP_RUNTIME__ */