[project @ 2000-01-13 14:33:57 by hwloidl]
[ghc-hetmet.git] / ghc / includes / GranSim.h
1 /*
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 $
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 #ifndef GRANSIM_H
15 #define GRANSIM_H
16
17 #if !defined(GRAN)
18
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 */
26
27 #endif
28
29 #if defined(GRAN)  /* whole file */
30
31 extern StgTSO *CurrentTSOs[];
32
33 //@node Headers for GranSim specific objects, , ,
34 //@section Headers for GranSim specific objects
35
36 //@menu
37 //* Includes::                  
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 Includes, Externs and prototypes, Headers for GranSim specific objects, Headers for GranSim specific objects
48 //@subsection Includes
49
50 /*
51 #include "Closures.h"
52 #include "TSO.h"
53 #include "Rts.h"
54 */
55
56 //@node Externs and prototypes, Run and blocking queues, Includes, Headers for GranSim specific objects
57 //@subsection Externs and prototypes
58
59 /* Global constants */
60 extern char *gran_event_names[];
61 extern char *proc_status_names[];
62 extern char *event_names[];
63
64 /* Vars checked from within STG land */
65 extern rtsBool  NeedToReSchedule, IgnoreEvents, IgnoreYields; 
66
67 extern rtsTime  TimeOfNextEvent, TimeOfLastEvent, EndOfTimeSlice;
68
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;
71
72 extern nat SparksAvail;     /* How many sparks are available */
73 extern nat SurplusThreads;  /* How many excess threads are there */
74 extern nat sparksIgnored, sparksCreated;
75
76 //@node Run and blocking queues, Spark queues, Externs and prototypes, Headers for GranSim specific objects
77 //@subsection Run and blocking queues
78
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[];
83
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]
91
92 //@node Spark queues, Processor related stuff, Run and blocking queues, Headers for GranSim specific objects
93 //@subsection Spark queues
94
95 /*
96 In GranSim we use a double linked list to represent spark queues.
97
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.
102 */
103
104 /* Sparks and spark queues */
105 typedef struct rtsSpark_
106 {
107   StgClosure    *node;
108   StgInt         name, global;
109   StgInt         gran_info;      /* for granularity improvement mechanisms */
110   PEs            creator;        /* PE that created this spark (unused) */
111   struct rtsSpark_  *prev, *next;
112 } rtsSpark;
113 typedef rtsSpark *rtsSparkQ;
114
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[];
119
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);
126
127 //@node Processor related stuff, GranSim costs, Spark queues, Headers for GranSim specific objects
128 //@subsection Processor related stuff
129
130 extern PEs CurrentProc;
131 extern rtsTime CurrentTime[];  
132
133 /* Maximum number of PEs that can be simulated */
134 #define MAX_PROC             32 /* (BITS_IN(StgWord))  */ // ToDo: fix this!!
135 //#if MAX_PROC==16 
136 //#else 
137 //#error MAX_PROC should be 32 on this architecture 
138 //#endif 
139
140 #define CurrentTSO           CurrentTSOs[CurrentProc]
141
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 */ 
147
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)
153 #define Nowhere               (0l)
154 #define Now                   CurrentTime[CurrentProc]
155
156 #define IS_LOCAL_TO(ga,proc)  ((1l << (PEs) proc) & ga)
157
158 #define GRAN_TIME_SLICE       1000        /* max time between 2 ReSchedules */
159
160 //@node GranSim costs, STG called GranSim functions, Processor related stuff, Headers for GranSim specific objects
161 //@subsection GranSim costs
162
163 /* Default constants for communication (see RtsFlags on how to change them) */
164
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)
171
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 */
175
176 /* How much to increase GrAnSims internal packet size if an overflow 
177    occurs.
178    NB: This is a GrAnSim internal variable and is independent of the
179    simulated packet buffer size.
180 */
181
182 #define GRANSIM_DEFAULT_PACK_BUFFER_SIZE     400
183 #define REALLOC_SZ                           200
184
185 /* extern W_ gran_mpacktime, gran_mtidytime, gran_munpacktime; */
186
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)
193
194 /* Instruction Cost model (SPARC, including cache misses) */
195 #define ARITH_COST                 1
196 #define BRANCH_COST                2
197 #define LOAD_COST                  4
198 #define STORE_COST                 4
199 #define FLOAT_COST                 1 /* ? */
200
201 #define HEAPALLOC_COST             11
202
203 #define PRI_SPARK_OVERHEAD    5
204 #define PRI_SCHED_OVERHEAD    5
205
206 //@node STG called GranSim functions, STG-called routines, GranSim costs, Headers for GranSim specific objects
207 //@subsection STG called GranSim functions
208
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);
218
219
220 //@node STG-called routines,  , STG called GranSim functions, Headers for GranSim specific objects
221 //@subsection STG-called routines
222
223 /* Wrapped version of calls to GranSim-specific STG routines */
224
225 /*
226 #define DO_PERFORM_RESCHEDULE(liveness, always_reenter_node) PerformReschedule_wrapper(liveness, always_reenter_node)
227 */
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)
232
233 /* 
234    ToDo: Clean up this mess of GRAN macros!!! -- HWL
235 */
236 // DO_GRAN_FETCH((StgClosure*)R1.p);
237 #define GRAN_FETCH()            /* nothing */
238
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
243
244 /*
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
255           
256         replace gran_yield_? with gran_block_? (they really block the current
257         thread)
258 */
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);       \
263           } else {                         \
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); \
269                 } \
270             /* GRAN_YIELD(ptrs)  */             \
271           }
272
273
274 //                                                   YIELD(liveness,reenter)
275
276 // GRAN_YIELD(liveness_mask); 
277
278 // GRAN_FETCH_AND_RESCHEDULE(liveness_mask,reenter)
279
280 #define THREAD_CONTEXT_SWITCH(liveness_mask,reenter)    \
281         do { \
282         if (context_switch /* OR_INTERVAL_EXPIRED */) { \
283           GRAN_RESCHEDULE(liveness_mask,reenter); \
284         } }while(0)
285
286 #define GRAN_EXEC(arith,branch,load,store,floats)       \
287         { \
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;                      \
295         }
296
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
301 */
302
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); \
309                                 }
310
311 #define GRAN_YIELD(ptrs)                                   \
312         {                                                   \
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);   \
319           }                                                    \
320         }
321
322 #define ADD_TO_SPARK_QUEUE(spark)             \
323    STGCALL1(add_to_spark_queue,spark) \
324
325 #endif /* GRAN */
326
327 #endif /* GRANSIM_H */