I misunderstood the REntry pointer, its a pointer to an object pointer and it SHOULD...
[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   struct Hashtable_t* hashtable;
151   struct BinItem_t* binitem;
152   struct Vector_t* vector;
153   struct SCC_t* scc;
154   struct MemoryQueue_t* queue;
155   psemaphore * parentStallSem;
156   int tag;
157   SESEcommon* seseRec;
158   INTPTR* pointer;
159   int isBufMode;
160 } REntry;
161
162 #ifdef RCR
163 #define RCRSIZE 32
164 #define RUNBIAS 1000000
165
166 struct rcrRecord {
167   int count;
168   int index;
169   int flag;
170   int array[RCRSIZE];
171   void * ptrarray[RCRSIZE];
172   struct rcrRecord *next;
173 };
174
175 typedef struct SESEstall_t { 
176   SESEcommon common;
177   int size;
178   void * next;
179   struct ___Object___* ___obj___;
180   struct rcrRecord rcrRecords[1];
181   int tag;
182 } SESEstall;
183 #endif
184
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;
190   
191 } MemoryQueueItem;
192
193 typedef struct MemoryQueue_t {
194   MemoryQueueItem * head;
195   MemoryQueueItem * tail;  
196   REntry * binbuf[NUMBINS];
197   REntry * buf[NUMRENTRY];
198   int bufcount;
199 #ifndef OOO_DISABLE_TASKMEMPOOL
200   MemPool * rentrypool;
201 #endif
202 } MemoryQueue;
203
204 typedef struct BinItem_t {
205   int total;
206   int status;       //NOTREADY, READY
207   int type;         //READBIN:0, WRITEBIN:1
208   struct BinItem_t * next;
209 } BinItem;
210
211 typedef struct Hashtable_t {
212   MemoryQueueItem item;
213   struct BinElement_t* array[NUMBINS];
214   struct Queue*   unresolvedQueue;
215 } Hashtable;
216
217 typedef struct BinElement_t {
218   BinItem * head;
219   BinItem * tail;
220 } BinElement;
221
222 typedef struct WriteBinItem_t {
223   BinItem item;
224   REntry * val;
225 } WriteBinItem;
226
227 typedef struct ReadBinItem_t {
228   BinItem item;
229   REntry * array[NUMREAD];
230   int index;
231 } ReadBinItem;
232
233 typedef struct Vector_t {
234   MemoryQueueItem item;
235   REntry * array[NUMITEMS];
236   int index;
237 } Vector;
238
239 typedef struct SCC_t {
240   MemoryQueueItem item;
241   REntry * val;
242 } SCC;
243
244 int ADDRENTRY(MemoryQueue* q, REntry * r);
245 void RETIRERENTRY(MemoryQueue* Q, REntry * r);
246
247
248
249
250 static inline void ADD_FORWARD_ITEM( ForwardingListElement* e,
251                                      SESEcommon*            s ) {
252   //atomic_inc( &(s->refCount) );
253 }
254
255
256
257
258 // simple mechanical allocation and 
259 // deallocation of SESE records
260 void* mlpAllocSESErecord( int size );
261 void  mlpFreeSESErecord( SESEcommon* seseRecord );
262
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);
268
269
270
271
272 static inline void ADD_REFERENCE_TO( SESEcommon* seseRec ) {
273   atomic_inc( &(seseRec->refCount) );
274 }
275
276 static inline int RELEASE_REFERENCE_TO( SESEcommon* seseRec ) {
277   if( atomic_sub_and_test( 1, &(seseRec->refCount) ) ) {
278     poolfreeinto( seseRec->parent->taskRecordMemPool, seseRec );
279     return 1;
280   }
281   return 0;
282 }
283
284 #define CHECK_RECORD(x) ;
285
286
287 ////////////////////////////////////////////////
288 // 
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
294 //
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__);
297
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__);}
299
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; \
306 }
307
308
309
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 );
315   
316
317 #endif /* __MLP_RUNTIME__ */