add feature to memPool for detecting misuse of records by clients, also added a funct...
[IRC.git] / Robust / src / Runtime / mlp_runtime.h
1 #ifndef __MLP_RUNTIME__
2 #define __MLP_RUNTIME__
3
4
5 #include <pthread.h>
6 #include "runtime.h"
7 #include "mem.h"
8 #include "Queue.h"
9 #include "psemaphore.h"
10 #include "mlp_lock.h"
11 #include "memPool.h"
12
13 #ifndef FALSE
14 #define FALSE 0
15 #endif
16
17 #ifndef TRUE
18 #define TRUE 1
19 #endif
20
21 #define NUMBINS 128
22 #define NUMREAD 64
23 #define NUMITEMS 64
24 #define NUMRENTRY 256
25
26 #define READY 1
27 #define NOTREADY 0
28
29 #define READ 0
30 #define WRITE 1
31 #define PARENTREAD 2
32 #define PARENTWRITE 3
33 #define COARSE 4
34 #define PARENTCOARSE 5
35 #define SCCITEM 6
36
37 #define HASHTABLE 0
38 #define VECTOR 1
39 #define SINGLEITEM 2
40
41 #define READBIN 0
42 #define WRITEBIN 1
43
44 #define H_MASK (NUMBINS)-1
45
46 #ifndef FALSE
47 #define FALSE 0
48 #endif
49
50 #ifndef TRUE
51 #define TRUE 1
52 #endif
53
54
55 // these are useful for interpreting an INTPTR to an
56 // Object at runtime to retrieve the object's type
57 // or object id (OID), 64-bit safe
58 #define OBJPTRPTR_2_OBJTYPE( opp ) ((int*)(opp))[0]
59 #define OBJPTRPTR_2_OBJOID(  opp ) ((int*)(opp))[1]
60
61 // forwarding list elements is a linked
62 // structure of arrays, should help task
63 // dispatch because the first element is
64 // an embedded member of the task record,
65 // only have to do memory allocation if
66 // a lot of items are on the list
67 #define FLIST_ITEMS_PER_ELEMENT 30
68 typedef struct ForwardingListElement_t {
69   int                             numItems;
70   struct ForwardingListElement_t* nextElement;
71   INTPTR                          items[FLIST_ITEMS_PER_ELEMENT];
72 } ForwardingListElement;
73
74 struct MemPool_t;
75
76 // these fields are common to any SESE, and casting the
77 // generated SESE record to this can be used, because
78 // the common structure is always the first item in a
79 // customized SESE record
80 typedef struct SESEcommon_t {  
81
82   // the identifier for the class of sese's that
83   // are instances of one particular static code block
84   // IMPORTANT: the class ID must be the first field of
85   // the task record so task dispatch works correctly!
86   int classID;
87   volatile int    unresolvedDependencies;
88
89   // a parent waits on this semaphore when stalling on
90   // this child, the child gives it at its SESE exit
91   psemaphore* parentsStallSem;
92
93   
94   // NOTE: first element is embedded in the task
95   // record, so don't free it!
96   //ForwardingListElement forwardList;
97   struct Queue forwardList;
98
99   volatile int             doneExecuting;
100   volatile int             numRunningChildren;
101
102   struct SESEcommon_t*   parent;
103   
104   int numMemoryQueue;
105   int rentryIdx;
106   int unresolvedRentryIdx;
107   volatile int refCount;
108   int numDependentSESErecords;
109   int offsetToDepSESErecords;
110   struct MemPool_t *     taskRecordMemPool;
111
112   struct MemoryQueue_t** memoryQueueArray;
113   struct REntry_t* rentryArray[NUMRENTRY];
114   struct REntry_t* unresolvedRentryArray[NUMRENTRY];
115
116
117 #ifdef RCR
118   int offsetToParamRecords;
119   volatile int rcrstatus;
120   volatile int retired;
121 #endif
122
123   // the lock guards the following data SESE's
124   // use to coordinate with one another
125   pthread_mutex_t lock;
126   pthread_cond_t  runningChildrenCond;
127 } SESEcommon;
128
129 // a thread-local var refers to the currently
130 // running task
131 extern __thread SESEcommon* runningSESE;
132 extern __thread int childSESE;
133
134 // there only needs to be one stall semaphore
135 // per thread, just give a reference to it to
136 // the task you are about to block on
137 extern __thread psemaphore runningSESEstallSem;
138
139
140
141 typedef struct REntry_t{
142   // fine read:0, fine write:1, parent read:2, 
143   // parent write:3 coarse: 4, parent coarse:5, scc: 6
144   int type;
145   struct Hashtable_t* hashtable;
146   struct BinItem_t* binitem;
147   struct Vector_t* vector;
148   struct SCC_t* scc;
149   struct MemoryQueue_t* queue;
150   psemaphore * parentStallSem;
151   int tag;
152   SESEcommon* seseRec;
153   INTPTR* pointer;
154   int isBufMode;
155 } REntry;
156
157 #ifdef RCR
158 #define RCRSIZE 32
159 #define RUNBIAS 1000000
160
161 struct rcrRecord {
162   int count;
163   int index;
164   int flag;
165   int array[RCRSIZE];
166   void * ptrarray[RCRSIZE];
167   struct rcrRecord *next;
168 };
169
170 typedef struct SESEstall_t { 
171   SESEcommon common;
172   int size;
173   void * next;
174   struct ___Object___* ___obj___;
175   struct rcrRecord rcrRecords[1];
176   int tag;
177 } SESEstall;
178 #endif
179
180 typedef struct MemoryQueueItem_t {
181   int type; // hashtable:0, vector:1, singleitem:2
182   int total;        //total non-retired
183   int status;       //NOTREADY, READY
184   struct MemoryQueueItem_t *next;
185   
186 } MemoryQueueItem;
187
188 typedef struct MemoryQueue_t {
189   MemoryQueueItem * head;
190   MemoryQueueItem * tail;  
191   REntry * binbuf[NUMBINS];
192   REntry * buf[NUMRENTRY];
193   int bufcount;
194 #ifndef OOO_DISABLE_TASKMEMPOOL
195   MemPool * rentrypool;
196 #endif
197 } MemoryQueue;
198
199 typedef struct BinItem_t {
200   int total;
201   int status;       //NOTREADY, READY
202   int type;         //READBIN:0, WRITEBIN:1
203   struct BinItem_t * next;
204 } BinItem;
205
206 typedef struct Hashtable_t {
207   MemoryQueueItem item;
208   struct BinElement_t* array[NUMBINS];
209   struct Queue*   unresolvedQueue;
210 } Hashtable;
211
212 typedef struct BinElement_t {
213   BinItem * head;
214   BinItem * tail;
215 } BinElement;
216
217 typedef struct WriteBinItem_t {
218   BinItem item;
219   REntry * val;
220 } WriteBinItem;
221
222 typedef struct ReadBinItem_t {
223   BinItem item;
224   REntry * array[NUMREAD];
225   int index;
226 } ReadBinItem;
227
228 typedef struct Vector_t {
229   MemoryQueueItem item;
230   REntry * array[NUMITEMS];
231   int index;
232 } Vector;
233
234 typedef struct SCC_t {
235   MemoryQueueItem item;
236   REntry * val;
237 } SCC;
238
239 int ADDRENTRY(MemoryQueue* q, REntry * r);
240 void RETIRERENTRY(MemoryQueue* Q, REntry * r);
241
242
243
244
245 static inline void ADD_FORWARD_ITEM( ForwardingListElement* e,
246                                      SESEcommon*            s ) {
247   //atomic_inc( &(s->refCount) );
248 }
249
250
251
252
253 // simple mechanical allocation and 
254 // deallocation of SESE records
255 void* mlpAllocSESErecord( int size );
256 void  mlpFreeSESErecord( SESEcommon* seseRecord );
257
258 MemoryQueue** mlpCreateMemoryQueueArray(int numMemoryQueue);
259 REntry* mlpCreateFineREntry(MemoryQueue *q, int type, SESEcommon* seseToIssue, void* dynID);
260 REntry* mlpCreateREntry(MemoryQueue *q, int type, SESEcommon* seseToIssue);
261 MemoryQueue* createMemoryQueue();
262 void rehashMemoryQueue(SESEcommon* seseParent);
263
264
265 static inline void ADD_REFERENCE_TO( SESEcommon* seseRec ) {
266   atomic_inc( &(seseRec->refCount) );
267 }
268
269 static inline void RELEASE_REFERENCE_TO( SESEcommon* seseRec ) {
270   if( atomic_sub_and_test( 1, &(seseRec->refCount) ) ) {
271     poolfreeinto( seseRec->parent->taskRecordMemPool, seseRec );
272   }
273 }
274
275
276 // this is for using a memPool to allocate task records,
277 // pass this into the poolcreate so it will run your
278 // custom init code ONLY for fresh records, reused records
279 // can be returned as is
280 void freshTaskRecordInitializer( void* seseRecord );
281   
282
283 #endif /* __MLP_RUNTIME__ */