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 #include "classdefs.h"
19
20
21
22 #ifndef FALSE
23 #define FALSE 0
24 #endif
25
26 #ifndef TRUE
27 #define TRUE 1
28 #endif
29
30 #define NUMBINS 128
31 #define NUMREAD 64
32 #define NUMITEMS 64
33 #define NUMRENTRY 256
34
35 #define READY 1
36 #define NOTREADY 0
37
38 #define READ 0
39 #define WRITE 1
40 #define PARENTREAD 2
41 #define PARENTWRITE 3
42 #define COARSE 4
43 #define PARENTCOARSE 5
44 #define SCCITEM 6
45
46 #define HASHTABLE 0
47 #define VECTOR 1
48 #define SINGLEITEM 2
49
50 #define READBIN 0
51 #define WRITEBIN 1
52
53 #define H_MASK (NUMBINS)-1
54
55 #ifndef FALSE
56 #define FALSE 0
57 #endif
58
59 #ifndef TRUE
60 #define TRUE 1
61 #endif
62
63
64 // these are useful for interpreting an INTPTR to an
65 // Object at runtime to retrieve the object's type
66 // or object id (OID)
67 #define OBJPTRPTR_2_OBJTYPE(opp) ((struct ___Object___*)*(opp))->type
68 #define OBJPTRPTR_2_OBJOID(opp) ((struct ___Object___*)*(opp))->oid
69
70
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 {
79   int numItems;
80   struct ForwardingListElement_t* nextElement;
81   INTPTR items[FLIST_ITEMS_PER_ELEMENT];
82 } ForwardingListElement;
83
84 struct MemPool_t;
85
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 {
91
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!
96   int classID;
97   volatile int unresolvedDependencies;
98
99   // a parent waits on this semaphore when stalling on
100   // this child, the child gives it at its SESE exit
101   psemaphore* parentsStallSem;
102
103
104   // NOTE: first element is embedded in the task
105   // record, so don't free it!
106   //ForwardingListElement forwardList;
107   struct Queue forwardList;
108
109   volatile int doneExecuting;
110   volatile int numRunningChildren;
111
112   struct SESEcommon_t*   parent;
113
114   int numMemoryQueue;
115   int rentryIdx;
116   int unresolvedRentryIdx;
117   volatile int refCount;
118   int numDependentSESErecords;
119   int offsetToDepSESErecords;
120   struct MemPool_t *     taskRecordMemPool;
121
122   struct MemoryQueue_t** memoryQueueArray;
123   struct REntry_t* rentryArray[NUMRENTRY];
124   struct REntry_t* unresolvedRentryArray[NUMRENTRY];
125
126 #ifdef RCR
127   struct Hashtable_rcr ** allHashStructures;
128   int offsetToParamRecords;
129   volatile int rcrstatus;
130   volatile int retired;
131 #endif
132
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;
137 } SESEcommon;
138
139 // a thread-local var refers to the currently
140 // running task
141 extern __thread SESEcommon* runningSESE;
142 extern __thread int childSESE;
143
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;
148
149
150
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
154   int type;
155 #ifdef RCR
156   int count;
157 #else
158   int isBufMode;
159 #endif
160   struct MemoryQueueItem_t *qitem;
161   struct BinItem_t* binitem;
162   struct MemoryQueue_t* queue;
163   SESEcommon* seseRec;
164   INTPTR* pointer;
165 #ifdef RCR
166   INTPTR mask;
167   int index;
168 #else
169   psemaphore * parentStallSem;
170   int tag;
171 #endif
172 } REntry;
173
174 #ifdef RCR
175 #define RCRSIZE 32
176 #define RUNBIAS 1000000
177
178 struct rcrRecord {
179   int count;
180   int index;
181   int flag;
182   int array[RCRSIZE];
183   void * ptrarray[RCRSIZE];
184   struct rcrRecord *next;
185 };
186
187 typedef struct SESEstall_t {
188   SESEcommon common;
189   int size;
190   void * next;
191   struct ___Object___* ___obj___;
192   struct rcrRecord rcrRecords[1];
193   int tag;
194 } SESEstall;
195 #endif
196
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;
202
203 } MemoryQueueItem;
204
205 typedef struct MemoryQueue_t {
206   MemoryQueueItem * head;
207   MemoryQueueItem * tail;
208   REntry * binbuf[NUMBINS];
209   REntry * buf[NUMRENTRY];
210   int bufcount;
211 #ifndef OOO_DISABLE_TASKMEMPOOL
212   MemPool * rentrypool;
213 #endif
214 } MemoryQueue;
215
216 typedef struct BinItem_t {
217   int total;
218   int status;       //NOTREADY, READY
219   int type;         //READBIN:0, WRITEBIN:1
220   struct BinItem_t * next;
221 } BinItem;
222
223 typedef struct Hashtable_t {
224   MemoryQueueItem item;
225   struct BinElement_t* array[NUMBINS];
226   struct Queue*   unresolvedQueue;
227 } Hashtable;
228
229 typedef struct BinElement_t {
230   BinItem * head;
231   BinItem * tail;
232 } BinElement;
233
234 typedef struct WriteBinItem_t {
235   BinItem item;
236   REntry * val;
237 } WriteBinItem;
238
239 typedef struct ReadBinItem_t {
240   BinItem item;
241   REntry * array[NUMREAD];
242   int index;
243 } ReadBinItem;
244
245 typedef struct Vector_t {
246   MemoryQueueItem item;
247   REntry * array[NUMITEMS];
248   int index;
249 } Vector;
250
251 typedef struct SCC_t {
252   MemoryQueueItem item;
253   REntry * val;
254 } SCC;
255
256 int ADDRENTRY(MemoryQueue* q, REntry * r);
257 void RETIRERENTRY(MemoryQueue* Q, REntry * r);
258
259
260
261
262 static inline void ADD_FORWARD_ITEM(ForwardingListElement* e,
263                                     SESEcommon*            s) {
264   //atomic_inc( &(s->refCount) );
265 }
266
267 // simple mechanical allocation and
268 // deallocation of SESE records
269 void* mlpAllocSESErecord(int size);
270 void  mlpFreeSESErecord(SESEcommon* seseRecord);
271
272 MemoryQueue** mlpCreateMemoryQueueArray(int numMemoryQueue);
273 REntry* mlpCreateFineREntry(MemoryQueue *q, int type, SESEcommon* seseToIssue, void* dynID);
274 #ifdef RCR
275 REntry* mlpCreateREntry(MemoryQueue *q, int type, SESEcommon* seseToIssue, INTPTR mask);
276 #else
277 REntry* mlpCreateREntry(MemoryQueue *q, int type, SESEcommon* seseToIssue);
278 #endif
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);
291
292 #ifndef RCR
293 int RESOLVEBUF(MemoryQueue * q, SESEcommon *seseCommon);
294 void resolvePointer(REntry* rentry);
295 #endif
296
297 static inline void ADD_REFERENCE_TO(SESEcommon* seseRec) {
298   atomic_inc(&(seseRec->refCount) );
299 }
300
301 static inline int RELEASE_REFERENCE_TO(SESEcommon* seseRec) {
302   if( atomic_sub_and_test(1, &(seseRec->refCount) ) ) {
303     poolfreeinto(seseRec->parent->taskRecordMemPool, seseRec);
304     return 1;
305   }
306   return 0;
307 }
308
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);
312     return 1;
313   }
314   return 0;
315 }
316
317 #define CHECK_RECORD(x) ;
318
319
320 ////////////////////////////////////////////////
321 //
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
327 //
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__);
330
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__); }
332
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); } \
337 }
338
339
340
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);
346
347
348 #endif /* __MLP_RUNTIME__ */