changes...handle races between coarse and fine grained conflict resolution
[IRC.git] / Robust / src / Runtime / mlp_runtime.h
1 #ifndef __MLP_RUNTIME__
2 #define __MLP_RUNTIME__
3
4
5 #include <pthread.h>
6 #include "Queue.h"
7 #include "psemaphore.h"
8 #include "mlp_lock.h"
9 #include "memPool.h"
10
11 #ifndef FALSE
12 #define FALSE 0
13 #endif
14
15 #ifndef TRUE
16 #define TRUE 1
17 #endif
18
19 #define NUMBINS 128
20 #define NUMREAD 64
21 #define NUMITEMS 64
22 #define NUMRENTRY 256
23
24 #define READY 1
25 #define NOTREADY 0
26
27 #define READ 0
28 #define WRITE 1
29 #define PARENTREAD 2
30 #define PARENTWRITE 3
31 #define COARSE 4
32 #define PARENTCOARSE 5
33 #define SCCITEM 6
34
35 #define HASHTABLE 0
36 #define VECTOR 1
37 #define SINGLEITEM 2
38
39 #define READBIN 0
40 #define WRITEBIN 1
41
42 #define H_MASK (NUMBINS)-1
43
44 #ifndef FALSE
45 #define FALSE 0
46 #endif
47
48 #ifndef TRUE
49 #define TRUE 1
50 #endif
51
52
53 // these are useful for interpreting an INTPTR to an
54 // Object at runtime to retrieve the object's type
55 // or object id (OID), 64-bit safe
56 #define OBJPTRPTR_2_OBJTYPE( opp ) ((int*)(*(opp)))[0]
57 #define OBJPTRPTR_2_OBJOID(  opp ) ((int*)(*(opp)))[1]
58
59
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
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
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   // the lock guards the following data SESE's
95   // use to coordinate with one another
96   pthread_mutex_t lock;
97
98   // NOTE: first element is embedded in the task
99   // record, so don't free it!
100   //ForwardingListElement forwardList;
101   struct Queue* forwardList;
102
103   volatile int    unresolvedDependencies;
104
105   pthread_cond_t  doneCond;
106   volatile int             doneExecuting;
107
108   pthread_cond_t  runningChildrenCond;
109   int             numRunningChildren;
110
111   struct SESEcommon_t*   parent;
112   
113   int numMemoryQueue;
114   int rentryIdx;
115   int unresolvedRentryIdx;
116   struct MemoryQueue_t** memoryQueueArray;
117   struct REntry_t* rentryArray[NUMRENTRY];
118   struct REntry_t* unresolvedRentryArray[NUMRENTRY];
119
120   int numDependentSESErecords;
121   int offsetToDepSESErecords;
122 #ifdef RCR
123   int offsetToParamRecords;
124   volatile int rcrstatus;
125   volatile int retired;
126 #endif
127
128   // for determining when task records can be returned
129   // to the parent record's memory pool
130   MemPool*     taskRecordMemPool;
131   volatile int refCount;
132 } SESEcommon;
133
134 // a thread-local var refers to the currently
135 // running task
136 extern __thread SESEcommon* runningSESE;
137
138 // there only needs to be one stall semaphore
139 // per thread, just give a reference to it to
140 // the task you are about to block on
141 extern __thread psemaphore runningSESEstallSem;
142
143
144
145 typedef struct REntry_t{
146   // fine read:0, fine write:1, parent read:2, 
147   // parent write:3 coarse: 4, parent coarse:5, scc: 6
148   int type;
149   struct Hashtable_t* hashtable;
150   struct BinItem_t* binitem;
151   struct Vector_t* vector;
152   struct SCC_t* scc;
153   struct MemoryQueue_t* queue;
154   psemaphore parentStallSem;
155   int tag;
156   SESEcommon* seseRec;
157   INTPTR* pointer;
158   int isBufMode;
159 } REntry;
160
161 typedef struct MemoryQueueItem_t {
162   int type; // hashtable:0, vector:1, singleitem:2
163   int total;        //total non-retired
164   int status;       //NOTREADY, READY
165   struct MemoryQueueItem_t *next; 
166 } MemoryQueueItem;
167
168 typedef struct MemoryQueue_t {
169   MemoryQueueItem * head;
170   MemoryQueueItem * tail;  
171   REntry * binbuf[NUMBINS];
172   REntry * buf[NUMRENTRY];
173   int bufcount;
174 } MemoryQueue;
175
176 typedef struct BinItem_t {
177   int total;
178   int status;       //NOTREADY, READY
179   int type;         //READBIN:0, WRITEBIN:1
180   struct BinItem_t * next;
181 } BinItem;
182
183 typedef struct Hashtable_t {
184   MemoryQueueItem item;
185   struct BinElement_t* array[NUMBINS];
186   struct Queue*   unresolvedQueue;
187 } Hashtable;
188
189 typedef struct BinElement_t {
190   BinItem * head;
191   BinItem * tail;
192 } BinElement;
193
194 typedef struct WriteBinItem_t {
195   BinItem item;
196   REntry * val;
197 } WriteBinItem;
198
199 typedef struct ReadBinItem_t {
200   BinItem item;
201   REntry * array[NUMREAD];
202   int index;
203 } ReadBinItem;
204
205 typedef struct Vector_t {
206   MemoryQueueItem item;
207   REntry * array[NUMITEMS];
208   int index;
209 } Vector;
210
211 typedef struct SCC_t {
212   MemoryQueueItem item;
213   REntry * val;
214 } SCC;
215
216 int ADDRENTRY(MemoryQueue* q, REntry * r);
217 void RETIRERENTRY(MemoryQueue* Q, REntry * r);
218
219
220
221
222 static inline void ADD_FORWARD_ITEM( ForwardingListElement* e,
223                                      SESEcommon*            s ) {
224   //atomic_inc( &(s->refCount) );
225 }
226
227
228
229
230 // simple mechanical allocation and 
231 // deallocation of SESE records
232 void* mlpAllocSESErecord( int size );
233 void  mlpFreeSESErecord( SESEcommon* seseRecord );
234
235 MemoryQueue** mlpCreateMemoryQueueArray(int numMemoryQueue);
236 REntry* mlpCreateFineREntry(int type, SESEcommon* seseToIssue, void* dynID);
237 REntry* mlpCreateREntry    (int type, SESEcommon* seseToIssue);
238 MemoryQueue* createMemoryQueue();
239 void rehashMemoryQueue(SESEcommon* seseParent);
240
241
242 static inline void ADD_REFERENCE_TO( SESEcommon* seseRec ) {
243   atomic_inc( &(seseRec->refCount) );
244 }
245
246 static inline void RELEASE_REFERENCE_TO( SESEcommon* seseRec ) {
247   if( atomic_sub_and_test( 1, &(seseRec->refCount) ) ) {
248     poolfreeinto( seseRec->parent->taskRecordMemPool, seseRec );
249   }
250 }
251
252
253 #endif /* __MLP_RUNTIME__ */