[project @ 2003-08-01 15:38:41 by panne]
[ghc-hetmet.git] / ghc / includes / GranSim.h
1 /*
2   Time-stamp: <Fri Mar 24 2000 23:55:42 Stardate: [-30]4554.98 hwloidl>
3   $Id: GranSim.h,v 1.3 2000/03/31 03:09:35 hwloidl Exp $
4   
5   Headers for GranSim specific objects.
6   
7   Note that in GranSim we have one run-queue and blocking-queue for each
8   processor. Therefore, this header file redefines variables like
9   run_queue_hd to be relative to CurrentProc. The main arrays of runnable
10   and blocking queues are defined in Schedule.c.  The important STG-called
11   GranSim macros (e.g. for fetching nodes) are at the end of this
12   file. Usually they are just wrappers to proper C functions in GranSim.c.  
13 */
14
15 #ifndef GRANSIM_H
16 #define GRANSIM_H
17
18 #if !defined(GRAN)
19
20 /* Dummy definitions for basic GranSim macros called from STG land */
21 #define DO_GRAN_ALLOCATE(n)                               /* nothing */
22 #define DO_GRAN_UNALLOCATE(n)                             /* nothing */
23 #define DO_GRAN_FETCH(node)                               /* nothing */
24 #define DO_GRAN_EXEC(arith,branch,load,store,floats)      /* nothing */
25 #define GRAN_FETCH_AND_RESCHEDULE(liveness_mask,reenter)  /* nothing */
26 #define GRAN_RESCHEDULE(liveness_mask,reenter)            /* nothing */
27
28 #endif
29
30 #if defined(GRAN)  /* whole file */
31
32 extern StgTSO *CurrentTSO;
33
34 //@node Headers for GranSim specific objects, , ,
35 //@section Headers for GranSim specific objects
36
37 //@menu
38 //* Externs and prototypes::    
39 //* Run and blocking queues::   
40 //* Spark queues::              
41 //* Processor related stuff::   
42 //* GranSim costs::             
43 //* STG called GranSim functions::  
44 //* STG-called routines::       
45 //@end menu
46
47 //@node Externs and prototypes, Run and blocking queues, Includes, Headers for GranSim specific objects
48 //@subsection Externs and prototypes
49
50 /* Global constants */
51 extern char *gran_event_names[];
52 extern char *proc_status_names[];
53 extern char *event_names[];
54
55 /* Vars checked from within STG land */
56 extern rtsBool  NeedToReSchedule, IgnoreEvents, IgnoreYields; 
57
58 extern rtsTime  TimeOfNextEvent, TimeOfLastEvent, EndOfTimeSlice;
59
60 /* costs for basic operations (copied from RTS flags) */
61 extern nat gran_arith_cost, gran_branch_cost, gran_load_cost, gran_store_cost, gran_float_cost;
62
63 extern nat SparksAvail;     /* How many sparks are available */
64 extern nat SurplusThreads;  /* How many excess threads are there */
65 extern nat sparksIgnored, sparksCreated;
66
67 //@node Run and blocking queues, Spark queues, Externs and prototypes, Headers for GranSim specific objects
68 //@subsection Run and blocking queues
69
70 /* declared in Schedule.c */
71 extern StgTSO *run_queue_hds[], *run_queue_tls[];
72 extern StgTSO *blocked_queue_hds[], *blocked_queue_tls[];
73 extern StgTSO *ccalling_threadss[];
74
75 #define run_queue_hd         run_queue_hds[CurrentProc]
76 #define run_queue_tl         run_queue_tls[CurrentProc]
77 #define blocked_queue_hd     blocked_queue_hds[CurrentProc]
78 #define blocked_queue_tl     blocked_queue_tls[CurrentProc]
79 #define pending_sparks_hd    pending_sparks_hds[CurrentProc]
80 #define pending_sparks_tl    pending_sparks_tls[CurrentProc]
81 #define ccalling_threads     ccalling_threadss[CurrentProc]
82
83 //@node Spark queues, Processor related stuff, Run and blocking queues, Headers for GranSim specific objects
84 //@subsection Spark queues
85
86 /*
87   In GranSim we use a double linked list to represent spark queues.
88   
89   This is more flexible, but slower, than the array of pointers
90   representation used in GUM. We use the flexibility to define new fields in
91   the rtsSpark structure, representing e.g. granularity info (see HWL's PhD
92   thesis), or info about the parent of a spark.
93 */
94
95 /* Sparks and spark queues */
96 typedef struct rtsSpark_
97 {
98   StgClosure    *node;
99   nat            name, global;
100   nat            gran_info;      /* for granularity improvement mechanisms */
101   PEs            creator;        /* PE that created this spark (unused) */
102   struct rtsSpark_  *prev, *next;
103 } rtsSpark;
104 typedef rtsSpark *rtsSparkQ;
105
106 /* The spark queues, proper */
107 /* In GranSim this is a globally visible array of spark queues */
108 extern rtsSparkQ pending_sparks_hds[];
109 extern rtsSparkQ pending_sparks_tls[];
110
111 /* Prototypes of those spark routines visible to compiler generated .hc */
112 /* Routines only used inside the RTS are defined in rts/parallel GranSimRts.h */
113 rtsSpark    *newSpark(StgClosure *node, 
114                       nat name, nat gran_info, nat size_info, 
115                       nat par_info, nat local);
116 // void         add_to_spark_queue(rtsSpark *spark);
117
118 //@node Processor related stuff, GranSim costs, Spark queues, Headers for GranSim specific objects
119 //@subsection Processor related stuff
120
121 extern PEs CurrentProc;
122 extern rtsTime CurrentTime[];  
123
124 /* Maximum number of PEs that can be simulated */
125 #define MAX_PROC             32 /* (BITS_IN(StgWord))  */ // ToDo: fix this!!
126 //#if MAX_PROC==16 
127 //#else 
128 //#error MAX_PROC should be 32 on this architecture 
129 //#endif 
130
131 // #define CurrentTSO           CurrentTSOs[CurrentProc]
132
133 /* Processor numbers to bitmasks and vice-versa */
134 #define MainProc             0           /* Id of main processor */
135 #define NO_PRI               0           /* dummy priority */
136 #define MAX_PRI              10000       /* max possible priority */
137 #define MAIN_PRI             MAX_PRI     /* priority of main thread */ 
138
139 /* GrAnSim uses IdleProcs as bitmask to indicate which procs are idle */
140 #define PE_NUMBER(n)          (1l << (long)n)
141 #define ThisPE                PE_NUMBER(CurrentProc)
142 #define MainPE                PE_NUMBER(MainProc)
143 #define Everywhere            (~0l)
144 #define Nowhere               (0l)
145 #define Now                   CurrentTime[CurrentProc]
146
147 #define IS_LOCAL_TO(ga,proc)  ((1l << (PEs) proc) & ga)
148
149 #define GRAN_TIME_SLICE       1000        /* max time between 2 ReSchedules */
150
151 //@node GranSim costs, STG called GranSim functions, Processor related stuff, Headers for GranSim specific objects
152 //@subsection GranSim costs
153
154 /* Default constants for communication (see RtsFlags on how to change them) */
155
156 #define LATENCY                    1000 /* Latency for single packet */
157 #define ADDITIONAL_LATENCY          100 /* Latency for additional packets */
158 #define BASICBLOCKTIME               10
159 #define FETCHTIME               (LATENCY*2+MSGUNPACKTIME)
160 #define LOCALUNBLOCKTIME             10
161 #define GLOBALUNBLOCKTIME       (LATENCY+MSGUNPACKTIME)
162
163 #define MSGPACKTIME                  0  /* Cost of creating a packet */
164 #define MSGUNPACKTIME                0  /* Cost of receiving a packet */
165 #define MSGTIDYTIME                  0  /* Cost of cleaning up after send */
166
167 /* How much to increase GrAnSims internal packet size if an overflow 
168    occurs.
169    NB: This is a GrAnSim internal variable and is independent of the
170    simulated packet buffer size.
171 */
172
173 #define GRANSIM_DEFAULT_PACK_BUFFER_SIZE     400
174 #define REALLOC_SZ                           200
175
176 /* extern W_ gran_mpacktime, gran_mtidytime, gran_munpacktime; */
177
178 /* Thread cost model */
179 #define THREADCREATETIME           (25+THREADSCHEDULETIME)
180 #define THREADQUEUETIME             12  /* Cost of adding a thread to the running/runnable queue */
181 #define THREADDESCHEDULETIME        75  /* Cost of descheduling a thread */
182 #define THREADSCHEDULETIME          75  /* Cost of scheduling a thread */
183 #define THREADCONTEXTSWITCHTIME     (THREADDESCHEDULETIME+THREADSCHEDULETIME)
184
185 /* Instruction Cost model (SPARC, including cache misses) */
186 #define ARITH_COST                 1
187 #define BRANCH_COST                2
188 #define LOAD_COST                  4
189 #define STORE_COST                 4
190 #define FLOAT_COST                 1 /* ? */
191
192 #define HEAPALLOC_COST             11
193
194 #define PRI_SPARK_OVERHEAD    5
195 #define PRI_SCHED_OVERHEAD    5
196
197 //@node STG called GranSim functions, STG-called routines, GranSim costs, Headers for GranSim specific objects
198 //@subsection STG called GranSim functions
199
200 /* STG called GranSim functions */
201 void GranSimAllocate(StgInt n);
202 void GranSimUnallocate(StgInt n);
203 void GranSimExec(StgWord ariths, StgWord branches, StgWord loads, StgWord stores, StgWord floats);
204 StgInt GranSimFetch(StgClosure *node);
205 void GranSimSpark(StgInt local, StgClosure *node);
206 void GranSimSparkAt(rtsSpark *spark, StgClosure *where,StgInt identifier);
207 void GranSimSparkAtAbs(rtsSpark *spark, PEs proc, StgInt identifier);
208 void GranSimBlock(StgTSO *tso, PEs proc, StgClosure *node);
209
210
211 //@node STG-called routines,  , STG called GranSim functions, Headers for GranSim specific objects
212 //@subsection STG-called routines
213
214 /* Wrapped version of calls to GranSim-specific STG routines */
215
216 /*
217 #define DO_PERFORM_RESCHEDULE(liveness, always_reenter_node) PerformReschedule_wrapper(liveness, always_reenter_node)
218 */
219 #define DO_GRAN_ALLOCATE(n)     STGCALL1(GranSimAllocate, n)
220 #define DO_GRAN_UNALLOCATE(n)   STGCALL1(GranSimUnallocate, n)
221 #define DO_GRAN_FETCH(node)     STGCALL1(GranSimFetch, node)
222 #define DO_GRAN_EXEC(arith,branch,load,store,floats) GranSimExec(arith,branch,load,store,floats)
223
224 /* 
225    ToDo: Clean up this mess of GRAN macros!!! -- HWL
226 */
227 // DO_GRAN_FETCH((StgClosure*)R1.p);
228 #define GRAN_FETCH()            /* nothing */
229
230 #define GRAN_FETCH_AND_RESCHEDULE(liveness,reenter)     \
231           DO_GRAN_FETCH((StgClosure*)R1.p);                             \
232           DO_GRAN_YIELD(liveness,ENTRY_CODE((D_)(*R1.p))); 
233 // RESTORE_EVERYTHING is done implicitly before entering threaded world agian
234
235 /*
236   This is the only macro currently enabled;
237   It should check whether it is time for the current thread to yield
238   (e.g. if there is a more recent event in the queue) and it should check
239   whether node is local, via a call to GranSimFetch.
240   ToDo: split this in 2 routines:
241          - GRAN_YIELD (as it is below)
242          - GRAN_FETCH (the rest of this macro)
243         emit only these 2 macros based on node's liveness
244           node alive: emit both macros
245           node not alive: do only a GRAN_YIELD
246           
247         replace gran_yield_? with gran_block_? (they really block the current
248         thread)
249 */
250 #define GRAN_RESCHEDULE(liveness,ptrs)  \
251           if (RET_STGCALL1(StgInt, GranSimFetch, (StgClosure*)R1.p)) {\
252             EXTFUN_RTS(gran_block_##ptrs); \
253             JMP_(gran_block_##ptrs);       \
254           } else {                         \
255             if (TimeOfLastEvent < CurrentTime[CurrentProc] && \
256                 HEAP_ALLOCED((StgClosure *)R1.p) && \
257                 LOOKS_LIKE_GHC_INFO(get_itbl((StgClosure *)R1.p))) { \
258                                   EXTFUN_RTS(gran_yield_##ptrs); \
259                                   JMP_(gran_yield_##ptrs); \
260                 } \
261             /* GRAN_YIELD(ptrs)  */             \
262           }
263
264
265 //                                                   YIELD(liveness,reenter)
266
267 // GRAN_YIELD(liveness_mask); 
268
269 // GRAN_FETCH_AND_RESCHEDULE(liveness_mask,reenter)
270
271 #define THREAD_CONTEXT_SWITCH(liveness_mask,reenter)    \
272         do { \
273         if (context_switch /* OR_INTERVAL_EXPIRED */) { \
274           GRAN_RESCHEDULE(liveness_mask,reenter); \
275         } }while(0)
276
277 #define GRAN_EXEC(arith,branch,load,store,floats)       \
278         { \
279           W_ cost = gran_arith_cost*arith +   \
280                     gran_branch_cost*branch + \
281                     gran_load_cost*load +   \
282                     gran_store_cost*store +   \
283                     gran_float_cost*floats;   \
284           CurrentTSO->gran.exectime += cost;                      \
285           CurrentTime[CurrentProc] += cost;                      \
286         }
287
288 /* In GranSim we first check whether there is an event to handle; only if
289    this is the case (or the time slice is over in case of fair scheduling)
290    we do a yield, which is very similar to that in the concurrent world 
291    ToDo: check whether gran_yield_? can be merged with other yielding codes
292 */
293
294 #define DO_GRAN_YIELD(ptrs)     if (!IgnoreYields && \
295                                     TimeOfLastEvent < CurrentTime[CurrentProc] && \
296                                     HEAP_ALLOCED((StgClosure *)R1.p) && \
297                                     LOOKS_LIKE_GHC_INFO(get_itbl((StgClosure *)R1.p))) { \
298                                   EXTFUN_RTS(gran_yield_##ptrs); \
299                                   JMP_(gran_yield_##ptrs); \
300                                 }
301
302 #define GRAN_YIELD(ptrs)                                   \
303         {                                                   \
304           extern  nat context_switch;                          \
305           if ( (CurrentTime[CurrentProc]>=EndOfTimeSlice) ||   \
306                ((CurrentTime[CurrentProc]>=TimeOfNextEvent) && \
307                 (TimeOfNextEvent!=0) && !IgnoreEvents )) {     \
308             /* context_switch = 1; */                          \
309             DO_GRAN_YIELD(ptrs);   \
310           }                                                    \
311         }
312
313 #define ADD_TO_SPARK_QUEUE(spark)             \
314    STGCALL1(add_to_spark_queue,spark) \
315
316 #endif /* GRAN */
317
318 #endif /* GRANSIM_H */