changes
[IRC.git] / Robust / src / Runtime / mlp_runtime.h
1 #ifndef __MLP_RUNTIME__
2 #define __MLP_RUNTIME__
3
4
5 #include <stdlib.h>
6 #include <stdio.h>
7
8
9 #include <pthread.h>
10 #include "runtime.h"
11 #include "mem.h"
12 #include "Queue.h"
13 #include "psemaphore.h"
14 #include "mlp_lock.h"
15 #include "memPool.h"
16
17
18
19 #ifndef FALSE
20 #define FALSE 0
21 #endif
22
23 #ifndef TRUE
24 #define TRUE 1
25 #endif
26
27 #define NUMBINS 128
28 #define NUMREAD 64
29 #define NUMITEMS 64
30 #define NUMRENTRY 256
31
32 #define READY 1
33 #define NOTREADY 0
34
35 #define READ 0
36 #define WRITE 1
37 #define PARENTREAD 2
38 #define PARENTWRITE 3
39 #define COARSE 4
40 #define PARENTCOARSE 5
41 #define SCCITEM 6
42
43 #define HASHTABLE 0
44 #define VECTOR 1
45 #define SINGLEITEM 2
46
47 #define READBIN 0
48 #define WRITEBIN 1
49
50 #define H_MASK (NUMBINS)-1
51
52 #ifndef FALSE
53 #define FALSE 0
54 #endif
55
56 #ifndef TRUE
57 #define TRUE 1
58 #endif
59
60
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]
66
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 {
75   int                             numItems;
76   struct ForwardingListElement_t* nextElement;
77   INTPTR                          items[FLIST_ITEMS_PER_ELEMENT];
78 } ForwardingListElement;
79
80 struct MemPool_t;
81
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 {  
87
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!
92   int classID;
93   volatile int    unresolvedDependencies;
94
95   // a parent waits on this semaphore when stalling on
96   // this child, the child gives it at its SESE exit
97   psemaphore* parentsStallSem;
98
99   
100   // NOTE: first element is embedded in the task
101   // record, so don't free it!
102   //ForwardingListElement forwardList;
103   struct Queue forwardList;
104
105   volatile int             doneExecuting;
106   volatile int             numRunningChildren;
107
108   struct SESEcommon_t*   parent;
109   
110   int numMemoryQueue;
111   int rentryIdx;
112   int unresolvedRentryIdx;
113   volatile int refCount;
114   int numDependentSESErecords;
115   int offsetToDepSESErecords;
116   struct MemPool_t *     taskRecordMemPool;
117
118   struct MemoryQueue_t** memoryQueueArray;
119   struct REntry_t* rentryArray[NUMRENTRY];
120   struct REntry_t* unresolvedRentryArray[NUMRENTRY];
121
122 #ifdef RCR
123   struct Hashtable_rcr ** allHashStructures;
124   int offsetToParamRecords;
125   volatile int rcrstatus;
126   volatile int retired;
127 #endif
128
129   // the lock guards the following data SESE's
130   // use to coordinate with one another
131   pthread_mutex_t lock;
132   pthread_cond_t  runningChildrenCond;
133 } SESEcommon;
134
135 // a thread-local var refers to the currently
136 // running task
137 extern __thread SESEcommon* runningSESE;
138 extern __thread int childSESE;
139
140 // there only needs to be one stall semaphore
141 // per thread, just give a reference to it to
142 // the task you are about to block on
143 extern __thread psemaphore runningSESEstallSem;
144
145
146
147 typedef struct REntry_t{
148   // fine read:0, fine write:1, parent read:2, 
149   // parent write:3 coarse: 4, parent coarse:5, scc: 6
150   int type;
151 #ifdef RCR
152   int count;
153 #else
154   int isBufMode;
155 #endif
156   struct MemoryQueueItem_t *qitem;
157   struct BinItem_t* binitem;
158   struct MemoryQueue_t* queue;
159   SESEcommon* seseRec;
160   INTPTR* pointer;
161 #ifdef RCR
162   INTPTR mask;
163   int index;
164 #else
165   psemaphore * parentStallSem;
166   int tag;
167 #endif
168 } REntry;
169
170 #ifdef RCR
171 #define RCRSIZE 32
172 #define RUNBIAS 1000000
173
174 struct rcrRecord {
175   int count;
176   int index;
177   int flag;
178   int array[RCRSIZE];
179   void * ptrarray[RCRSIZE];
180   struct rcrRecord *next;
181 };
182
183 typedef struct SESEstall_t { 
184   SESEcommon common;
185   int size;
186   void * next;
187   struct ___Object___* ___obj___;
188   struct rcrRecord rcrRecords[1];
189   int tag;
190 } SESEstall;
191 #endif
192
193 typedef struct MemoryQueueItem_t {
194   int type; // hashtable:0, vector:1, singleitem:2
195   int total;        //total non-retired
196   int status;       //NOTREADY, READY
197   struct MemoryQueueItem_t *next;
198   
199 } MemoryQueueItem;
200
201 typedef struct MemoryQueue_t {
202   MemoryQueueItem * head;
203   MemoryQueueItem * tail;  
204   REntry * binbuf[NUMBINS];
205   REntry * buf[NUMRENTRY];
206   int bufcount;
207 #ifndef OOO_DISABLE_TASKMEMPOOL
208   MemPool * rentrypool;
209 #endif
210 } MemoryQueue;
211
212 typedef struct BinItem_t {
213   int total;
214   int status;       //NOTREADY, READY
215   int type;         //READBIN:0, WRITEBIN:1
216   struct BinItem_t * next;
217 } BinItem;
218
219 typedef struct Hashtable_t {
220   MemoryQueueItem item;
221   struct BinElement_t* array[NUMBINS];
222   struct Queue*   unresolvedQueue;
223 } Hashtable;
224
225 typedef struct BinElement_t {
226   BinItem * head;
227   BinItem * tail;
228 } BinElement;
229
230 typedef struct WriteBinItem_t {
231   BinItem item;
232   REntry * val;
233 } WriteBinItem;
234
235 typedef struct ReadBinItem_t {
236   BinItem item;
237   REntry * array[NUMREAD];
238   int index;
239 } ReadBinItem;
240
241 typedef struct Vector_t {
242   MemoryQueueItem item;
243   REntry * array[NUMITEMS];
244   int index;
245 } Vector;
246
247 typedef struct SCC_t {
248   MemoryQueueItem item;
249   REntry * val;
250 } SCC;
251
252 int ADDRENTRY(MemoryQueue* q, REntry * r);
253 void RETIRERENTRY(MemoryQueue* Q, REntry * r);
254
255
256
257
258 static inline void ADD_FORWARD_ITEM( ForwardingListElement* e,
259                                      SESEcommon*            s ) {
260   //atomic_inc( &(s->refCount) );
261 }
262
263 // simple mechanical allocation and 
264 // deallocation of SESE records
265 void* mlpAllocSESErecord( int size );
266 void  mlpFreeSESErecord( SESEcommon* seseRecord );
267
268 MemoryQueue** mlpCreateMemoryQueueArray(int numMemoryQueue);
269 REntry* mlpCreateFineREntry(MemoryQueue *q, int type, SESEcommon* seseToIssue, void* dynID);
270 #ifdef RCR
271 REntry* mlpCreateREntry(MemoryQueue *q, int type, SESEcommon* seseToIssue, INTPTR mask);
272 #else
273 REntry* mlpCreateREntry(MemoryQueue *q, int type, SESEcommon* seseToIssue);
274 #endif
275 MemoryQueue* createMemoryQueue();
276 void rehashMemoryQueue(SESEcommon* seseParent);
277 void TAILWRITECASE(Hashtable *T, REntry *r, BinItem *val, BinItem *bintail, int key, int inc);
278 void RETIRESCC(MemoryQueue *Q, REntry *r);
279 void RETIREHASHTABLE(MemoryQueue *q, REntry *r);
280 void RETIREBIN(Hashtable *T, REntry *r, BinItem *b);
281 void RETIREVECTOR(MemoryQueue *Q, REntry *r);
282 void RESOLVECHAIN(MemoryQueue *Q);
283 void RESOLVEHASHTABLE(MemoryQueue *Q, Hashtable *T);
284 void RESOLVEVECTOR(MemoryQueue *q, Vector *V);
285 void RESOLVESCC(SCC *S);
286 void resolveDependencies(REntry* rentry);
287
288 #ifndef RCR
289 int RESOLVEBUF(MemoryQueue * q, SESEcommon *seseCommon);
290 void resolvePointer(REntry* rentry);
291 #endif
292
293 static inline void ADD_REFERENCE_TO( SESEcommon* seseRec ) {
294   atomic_inc( &(seseRec->refCount) );
295 }
296
297 static inline int RELEASE_REFERENCE_TO( SESEcommon* seseRec ) {
298   if( atomic_sub_and_test( 1, &(seseRec->refCount) ) ) {
299     poolfreeinto( seseRec->parent->taskRecordMemPool, seseRec );
300     return 1;
301   }
302   return 0;
303 }
304
305 static inline int RELEASE_REFERENCES_TO( SESEcommon* seseRec, int refCount) {
306   if( atomic_sub_and_test( refCount, &(seseRec->refCount) ) ) {
307     poolfreeinto( seseRec->parent->taskRecordMemPool, seseRec );
308     return 1;
309   }
310   return 0;
311 }
312
313 #define CHECK_RECORD(x) ;
314
315
316 ////////////////////////////////////////////////
317 // 
318 //  Some available debug versions of the above
319 //  pool allocation-related helpers.  The lower
320 //  'x' appended to names means they are not hooked
321 //  up, but check em in so we can switch names and
322 //  use them for debugging
323 //
324 ////////////////////////////////////////////////
325 #define ADD_REFERENCE_TOx(x) atomic_inc( &((x)->refCount) ); printf("0x%x ADD 0x%x on %d\n",(INTPTR)runningSESE,(INTPTR)(x),__LINE__);
326
327 #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__);}
328
329 #define CHECK_RECORDx(x) {                                              \
330     if( ((SESEcommon*)(x))->refCount < 0 ||                             \
331         ((SESEcommon*)(x))->refCount < 0 ) {                            \
332       printf( "Acquired 0x%x from poolalloc, with refCount=%d\n", (INTPTR)(x), ((SESEcommon*)(x))->refCount ); } \
333   }
334
335
336
337 // this is for using a memPool to allocate task records,
338 // pass this into the poolcreate so it will run your
339 // custom init code ONLY for fresh records, reused records
340 // can be returned as is
341 void freshTaskRecordInitializer( void* seseRecord );
342   
343
344 #endif /* __MLP_RUNTIME__ */