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   int offsetToParamRecords;
124   volatile int rcrstatus;
125   volatile int retired;
126 #endif
127
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;
132 } SESEcommon;
133
134 // a thread-local var refers to the currently
135 // running task
136 extern __thread SESEcommon* runningSESE;
137 extern __thread int childSESE;
138
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;
143
144
145
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
149   int type;
150   int tag;
151   MemoryQueueItem *qitem;
152   struct BinItem_t* binitem;
153   struct MemoryQueue_t* queue;
154   SESEcommon* seseRec;
155   INTPTR* pointer;
156   psemaphore * parentStallSem;
157 #ifdef RCR
158   INTPTR mask;
159 #endif
160   int isBufMode;
161 } REntry;
162
163 #ifdef RCR
164 #define RCRSIZE 32
165 #define RUNBIAS 1000000
166
167 struct rcrRecord {
168   int count;
169   int index;
170   int flag;
171   int array[RCRSIZE];
172   void * ptrarray[RCRSIZE];
173   struct rcrRecord *next;
174 };
175
176 typedef struct SESEstall_t { 
177   SESEcommon common;
178   int size;
179   void * next;
180   struct ___Object___* ___obj___;
181   struct rcrRecord rcrRecords[1];
182   int tag;
183 } SESEstall;
184 #endif
185
186 typedef struct MemoryQueueItem_t {
187   int type; // hashtable:0, vector:1, singleitem:2
188   int total;        //total non-retired
189   int status;       //NOTREADY, READY
190   struct MemoryQueueItem_t *next;
191   
192 } MemoryQueueItem;
193
194 typedef struct MemoryQueue_t {
195   MemoryQueueItem * head;
196   MemoryQueueItem * tail;  
197   REntry * binbuf[NUMBINS];
198   REntry * buf[NUMRENTRY];
199   int bufcount;
200 #ifndef OOO_DISABLE_TASKMEMPOOL
201   MemPool * rentrypool;
202 #endif
203 } MemoryQueue;
204
205 typedef struct BinItem_t {
206   int total;
207   int status;       //NOTREADY, READY
208   int type;         //READBIN:0, WRITEBIN:1
209   struct BinItem_t * next;
210 } BinItem;
211
212 typedef struct Hashtable_t {
213   MemoryQueueItem item;
214   struct BinElement_t* array[NUMBINS];
215   struct Queue*   unresolvedQueue;
216 } Hashtable;
217
218 typedef struct BinElement_t {
219   BinItem * head;
220   BinItem * tail;
221 } BinElement;
222
223 typedef struct WriteBinItem_t {
224   BinItem item;
225   REntry * val;
226 } WriteBinItem;
227
228 typedef struct ReadBinItem_t {
229   BinItem item;
230   REntry * array[NUMREAD];
231   int index;
232 } ReadBinItem;
233
234 typedef struct Vector_t {
235   MemoryQueueItem item;
236   REntry * array[NUMITEMS];
237   int index;
238 } Vector;
239
240 typedef struct SCC_t {
241   MemoryQueueItem item;
242   REntry * val;
243 } SCC;
244
245 int ADDRENTRY(MemoryQueue* q, REntry * r);
246 void RETIRERENTRY(MemoryQueue* Q, REntry * r);
247
248
249
250
251 static inline void ADD_FORWARD_ITEM( ForwardingListElement* e,
252                                      SESEcommon*            s ) {
253   //atomic_inc( &(s->refCount) );
254 }
255
256 // simple mechanical allocation and 
257 // deallocation of SESE records
258 void* mlpAllocSESErecord( int size );
259 void  mlpFreeSESErecord( SESEcommon* seseRecord );
260
261 MemoryQueue** mlpCreateMemoryQueueArray(int numMemoryQueue);
262 REntry* mlpCreateFineREntry(MemoryQueue *q, int type, SESEcommon* seseToIssue, void* dynID);
263 #ifdef RCR
264 REntry* mlpCreateREntry(MemoryQueue *q, int type, SESEcommon* seseToIssue, INTPTR mask);
265 #else
266 REntry* mlpCreateREntry(MemoryQueue *q, int type, SESEcommon* seseToIssue);
267 #endif
268 MemoryQueue* createMemoryQueue();
269 void rehashMemoryQueue(SESEcommon* seseParent);
270
271 static inline void ADD_REFERENCE_TO( SESEcommon* seseRec ) {
272   atomic_inc( &(seseRec->refCount) );
273 }
274
275 static inline int RELEASE_REFERENCE_TO( SESEcommon* seseRec ) {
276   if( atomic_sub_and_test( 1, &(seseRec->refCount) ) ) {
277     poolfreeinto( seseRec->parent->taskRecordMemPool, seseRec );
278     return 1;
279   }
280   return 0;
281 }
282
283 #define CHECK_RECORD(x) ;
284
285
286 ////////////////////////////////////////////////
287 // 
288 //  Some available debug versions of the above
289 //  pool allocation-related helpers.  The lower
290 //  'x' appended to names means they are not hooked
291 //  up, but check em in so we can switch names and
292 //  use them for debugging
293 //
294 ////////////////////////////////////////////////
295 #define ADD_REFERENCE_TOx(x) atomic_inc( &((x)->refCount) ); printf("0x%x ADD 0x%x on %d\n",(INTPTR)runningSESE,(INTPTR)(x),__LINE__);
296
297 #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__);}
298
299 #define CHECK_RECORDx(x) { \
300   if( ((SESEcommon*)(x))->refCount != 0 ) {                             \
301     printf( "Acquired 0x%x from poolalloc, with refCount=%d\n", (INTPTR)(x), ((SESEcommon*)(x))->refCount ); } \
302   if( ((SESEcommon*)(x))->fresh != 1 ) {                              \
303     printf("0x%x reclaimed 0x%x on %d\n",(INTPTR)runningSESE,(INTPTR)(x),__LINE__); } \
304   ((SESEcommon*)(x))->fresh = 0; \
305 }
306
307
308
309 // this is for using a memPool to allocate task records,
310 // pass this into the poolcreate so it will run your
311 // custom init code ONLY for fresh records, reused records
312 // can be returned as is
313 void freshTaskRecordInitializer( void* seseRecord );
314   
315
316 #endif /* __MLP_RUNTIME__ */