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