[project @ 2004-02-12 02:04:59 by mthomas]
[ghc-hetmet.git] / ghc / rts / RtsFlags.c
1 /* -----------------------------------------------------------------------------
2  * $Id: RtsFlags.c,v 1.72 2003/11/12 17:49:09 sof Exp $
3  *
4  * (c) The AQUA Project, Glasgow University, 1994-1997
5  * (c) The GHC Team, 1998-1999
6  *
7  * Functions for parsing the argument list.
8  *
9  * ---------------------------------------------------------------------------*/
10
11 //@menu
12 //* Includes::                  
13 //* Constants::                 
14 //* Static function decls::     
15 //* Command-line option parsing routines::  
16 //* GranSim specific options::  
17 //* Aux fcts::                  
18 //@end menu
19 //*/
20
21 //@node Includes, Constants
22 //@subsection Includes
23
24 #include "PosixSource.h"
25 #include "Rts.h"
26 #include "RtsFlags.h"
27 #include "RtsUtils.h"
28 #include "BlockAlloc.h"
29 #include "Timer.h"              /* CS_MIN_MILLISECS */
30 #include "Profiling.h"
31
32 #ifdef HAVE_CTYPE_H
33 #include <ctype.h>
34 #endif
35
36 #include <stdlib.h>
37 #include <string.h>
38
39 extern struct RTS_FLAGS RtsFlags;
40
41 /*
42  * Split argument lists
43  */
44 int     prog_argc = 0;    /* an "int" so as to match normal "argc" */
45 char  **prog_argv = NULL;
46 char   *prog_name = NULL; /* 'basename' of prog_argv[0] */
47 int     rts_argc = 0;  /* ditto */
48 char   *rts_argv[MAX_RTS_ARGS];
49
50 //@node Constants, Static function decls, Includes
51 //@subsection Constants
52
53 /*
54  * constants, used later 
55  */
56 #define RTS 1
57 #define PGM 0
58
59 #if defined(GRAN)
60
61 static char *gran_debug_opts_strs[] = {
62   "DEBUG (-bDe, -bD1): event_trace; printing event trace.\n",
63   "DEBUG (-bDE, -bD2): event_stats; printing event statistics.\n",
64   "DEBUG (-bDb, -bD4): bq; check blocking queues\n",
65   "DEBUG (-bDG, -bD8): pack; routines for (un-)packing graph structures.\n",
66   "DEBUG (-bDq, -bD16): checkSparkQ; check consistency of the spark queues.\n",
67   "DEBUG (-bDf, -bD32): thunkStealing; print forwarding of fetches.\n",
68   "DEBUG (-bDr, -bD64): randomSteal; stealing sparks/threads from random PEs.\n",
69   "DEBUG (-bDF, -bD128): findWork; searching spark-pools (local & remote), thread queues for work.\n",
70   "DEBUG (-bDu, -bD256): unused; currently unused flag.\n",
71   "DEBUG (-bDS, -bD512): pri; priority sparking or scheduling.\n",
72   "DEBUG (-bD:, -bD1024): checkLight; check GranSim-Light setup.\n",
73   "DEBUG (-bDo, -bD2048): sortedQ; check whether spark/thread queues are sorted.\n",
74   "DEBUG (-bDz, -bD4096): blockOnFetch; check for blocked on fetch.\n",
75   "DEBUG (-bDP, -bD8192): packBuffer; routines handling pack buffer (GranSim internal!).\n",
76   "DEBUG (-bDt, -bD16384): blockOnFetch_sanity; check for TSO asleep on fetch.\n",
77 };
78
79 /* one character codes for the available debug options */
80 static char gran_debug_opts_flags[] = {
81   'e', 'E', 'b', 'G', 'q', 'f', 'r', 'F', 'u', 'S', ':', 'o', 'z', 'P', 't'
82 };
83
84 #elif defined(PAR)
85
86 static char *par_debug_opts_strs[] = {
87   "DEBUG (-qDv, -qD1): verbose; be generally verbose with parallel related stuff.\n",
88   "DEBUG (-qDq, -qD2): bq; print blocking queues.\n",
89   "DEBUG (-qDs, -qD4): schedule; scheduling of parallel threads.\n",
90   "DEBUG (-qDe, -qD8): free; free messages.\n",
91   "DEBUG (-qDr, -qD16): resume; resume messages.\n",
92   "DEBUG (-qDw, -qD32): weight; print weights and distrib GC stuff.\n",
93   "DEBUG (-qDF, -qD64): fetch; fetch messages.\n",
94   // "DEBUG (-qDa, -qD128): ack; ack messages.\n",
95   "DEBUG (-qDf, -qD128): fish; fish messages.\n",
96   //"DEBUG (-qDo, -qD512): forward; forwarding messages to other PEs.\n",
97   "DEBUG (-qDl, -qD256): tables; print internal LAGA etc tables.\n",
98   "DEBUG (-qDo, -qD512): packet; packets and graph structures when packing.\n",
99   "DEBUG (-qDp, -qD1024): pack; packing and unpacking graphs.\n",
100   "DEBUG (-qDz, -qD2048): paranoia; ridiculously detailed output (excellent for filling a partition).\n"
101 };
102
103 /* one character codes for the available debug options */
104 static char par_debug_opts_flags[] = {
105   'v', 'q', 's', 'e', 'r', 'w', 'F', 'f', 'l', 'o', 'p', 'z'
106 };
107
108 #endif /* PAR */
109
110 //@node Static function decls, Command-line option parsing routines, Constants
111 //@subsection Static function decls
112
113 /* -----------------------------------------------------------------------------
114    Static function decls
115    -------------------------------------------------------------------------- */
116
117 static FILE *           /* return NULL on error */
118 open_stats_file (
119     I_ arg,
120     int argc, char *argv[],
121     int rts_argc, char *rts_argv[],
122     const char *FILENAME_FMT);
123
124 static I_ decode(const char *s);
125 static void bad_option(const char *s);
126
127 #if defined(GRAN)
128 static void enable_GranSimLight(void);
129 static void process_gran_option(int arg, int *rts_argc, char *rts_argv[], rtsBool *error);
130 static void set_GranSim_debug_options(nat n);
131 static void help_GranSim_debug_options(nat n);
132 #elif defined(PAR)
133 static void process_par_option(int arg, int *rts_argc, char *rts_argv[], rtsBool *error);
134 static void set_par_debug_options(nat n);
135 static void help_par_debug_options(nat n);
136 #endif
137
138 //@node Command-line option parsing routines, GranSim specific options, Static function decls
139 //@subsection Command-line option parsing routines
140
141 /* -----------------------------------------------------------------------------
142  * Command-line option parsing routines.
143  * ---------------------------------------------------------------------------*/
144
145 void initRtsFlagsDefaults(void)
146 {
147     RtsFlags.GcFlags.statsFile          = NULL;
148     RtsFlags.GcFlags.giveStats          = NO_GC_STATS;
149
150     RtsFlags.GcFlags.maxStkSize         = (1024 * 1024) / sizeof(W_);
151     RtsFlags.GcFlags.initialStkSize     = 1024 / sizeof(W_);
152
153     RtsFlags.GcFlags.minAllocAreaSize   = (256 * 1024)        / BLOCK_SIZE;
154     RtsFlags.GcFlags.minOldGenSize      = (1024 * 1024)       / BLOCK_SIZE;
155     RtsFlags.GcFlags.maxHeapSize        = 0;    /* off by default */
156     RtsFlags.GcFlags.heapSizeSuggestion = 0;    /* none */
157     RtsFlags.GcFlags.pcFreeHeap         = 3;    /* 3% */
158     RtsFlags.GcFlags.oldGenFactor       = 2;
159 #if defined(PAR)
160     /* A hack currently needed for GUM -- HWL */
161     RtsFlags.GcFlags.generations        = 1;
162     RtsFlags.GcFlags.steps              = 2;
163     RtsFlags.GcFlags.squeezeUpdFrames   = rtsFalse;
164 #else
165     RtsFlags.GcFlags.generations        = 2;
166     RtsFlags.GcFlags.steps              = 2;
167     RtsFlags.GcFlags.squeezeUpdFrames   = rtsTrue;
168 #endif
169     RtsFlags.GcFlags.compact            = rtsFalse;
170     RtsFlags.GcFlags.compactThreshold   = 30.0;
171 #ifdef RTS_GTK_FRONTPANEL
172     RtsFlags.GcFlags.frontpanel         = rtsFalse;
173 #endif
174
175 #ifdef DEBUG
176     RtsFlags.DebugFlags.scheduler       = rtsFalse;
177     RtsFlags.DebugFlags.interpreter     = rtsFalse;
178     RtsFlags.DebugFlags.codegen         = rtsFalse;
179     RtsFlags.DebugFlags.weak            = rtsFalse;
180     RtsFlags.DebugFlags.gccafs          = rtsFalse;
181     RtsFlags.DebugFlags.gc              = rtsFalse;
182     RtsFlags.DebugFlags.block_alloc     = rtsFalse;
183     RtsFlags.DebugFlags.sanity          = rtsFalse;
184     RtsFlags.DebugFlags.stable          = rtsFalse;
185     RtsFlags.DebugFlags.prof            = rtsFalse;
186     RtsFlags.DebugFlags.gran            = rtsFalse;
187     RtsFlags.DebugFlags.par             = rtsFalse;
188     RtsFlags.DebugFlags.linker          = rtsFalse;
189 #endif
190
191 #if defined(PROFILING) || defined(PAR)
192     RtsFlags.CcFlags.doCostCentres      = 0;
193 #endif /* PROFILING or PAR */
194
195 #ifdef PROFILING
196     RtsFlags.ProfFlags.doHeapProfile      = rtsFalse;
197     RtsFlags.ProfFlags.profileInterval    = 100;
198     RtsFlags.ProfFlags.includeTSOs        = rtsFalse;
199     RtsFlags.ProfFlags.showCCSOnException = rtsFalse;
200     RtsFlags.ProfFlags.maxRetainerSetSize = 8;
201     RtsFlags.ProfFlags.modSelector        = NULL;
202     RtsFlags.ProfFlags.descrSelector      = NULL;
203     RtsFlags.ProfFlags.typeSelector       = NULL;
204     RtsFlags.ProfFlags.ccSelector         = NULL;
205     RtsFlags.ProfFlags.ccsSelector        = NULL;
206     RtsFlags.ProfFlags.retainerSelector   = NULL;
207     RtsFlags.ProfFlags.bioSelector        = NULL;
208
209 #elif defined(DEBUG)
210     RtsFlags.ProfFlags.doHeapProfile      = rtsFalse;
211 #endif
212
213     RtsFlags.ConcFlags.ctxtSwitchTime   = CS_MIN_MILLISECS;  /* In milliseconds */
214
215 #ifdef SMP
216     RtsFlags.ParFlags.nNodes            = 1;
217 #endif
218
219 #ifdef PAR
220     RtsFlags.ParFlags.ParStats.Full       = rtsFalse;
221     RtsFlags.ParFlags.ParStats.Suppressed = rtsFalse;
222     RtsFlags.ParFlags.ParStats.Binary     = rtsFalse;
223     RtsFlags.ParFlags.ParStats.Sparks     = rtsFalse;
224     RtsFlags.ParFlags.ParStats.Heap       = rtsFalse;
225     RtsFlags.ParFlags.ParStats.NewLogfile = rtsFalse;
226     RtsFlags.ParFlags.ParStats.Global     = rtsFalse;
227
228     RtsFlags.ParFlags.outputDisabled    = rtsFalse;
229 #ifdef DIST
230     RtsFlags.ParFlags.doFairScheduling  = rtsTrue;  /* fair sched by def */
231 #else
232     RtsFlags.ParFlags.doFairScheduling  = rtsFalse;  /* unfair sched by def */
233 #endif
234     RtsFlags.ParFlags.packBufferSize    = 1024;
235     RtsFlags.ParFlags.thunksToPack      = 1; /* 0 ... infinity; */
236     RtsFlags.ParFlags.globalising       = 1; /* 0 ... everything */
237     RtsFlags.ParFlags.maxThreads        = 1024;
238     RtsFlags.ParFlags.maxFishes        = MAX_FISHES;
239     RtsFlags.ParFlags.fishDelay         = FISH_DELAY;
240 #endif
241
242 #if defined(PAR) || defined(SMP)
243     RtsFlags.ParFlags.maxLocalSparks    = 4096;
244 #endif /* PAR || SMP */
245
246 #if defined(GRAN)
247     /* ToDo: check defaults for GranSim and GUM */
248     RtsFlags.GcFlags.maxStkSize         = (1024 * 1024) / sizeof(W_);
249     RtsFlags.GcFlags.initialStkSize     = 1024 / sizeof(W_);
250
251     RtsFlags.GranFlags.maxThreads       = 65536; // refers to mandatory threads
252     RtsFlags.GranFlags.GranSimStats.Full        = rtsFalse;
253     RtsFlags.GranFlags.GranSimStats.Suppressed  = rtsFalse;
254     RtsFlags.GranFlags.GranSimStats.Binary      = rtsFalse;
255     RtsFlags.GranFlags.GranSimStats.Sparks      = rtsFalse;
256     RtsFlags.GranFlags.GranSimStats.Heap        = rtsFalse;
257     RtsFlags.GranFlags.GranSimStats.NewLogfile  = rtsFalse;
258     RtsFlags.GranFlags.GranSimStats.Global      = rtsFalse;
259
260     RtsFlags.GranFlags.packBufferSize   = 1024;
261     RtsFlags.GranFlags.packBufferSize_internal = GRANSIM_DEFAULT_PACK_BUFFER_SIZE;
262
263     RtsFlags.GranFlags.proc         = MAX_PROC;
264     RtsFlags.GranFlags.Fishing      = rtsFalse;
265     RtsFlags.GranFlags.maxFishes   = MAX_FISHES;
266     RtsFlags.GranFlags.time_slice   = GRAN_TIME_SLICE;
267     RtsFlags.GranFlags.Light        = rtsFalse;
268
269     RtsFlags.GranFlags.Costs.latency =             LATENCY;          
270     RtsFlags.GranFlags.Costs.additional_latency =  ADDITIONAL_LATENCY; 
271     RtsFlags.GranFlags.Costs.fetchtime =           FETCHTIME; 
272     RtsFlags.GranFlags.Costs.lunblocktime =        LOCALUNBLOCKTIME; 
273     RtsFlags.GranFlags.Costs.gunblocktime =        GLOBALUNBLOCKTIME;
274     RtsFlags.GranFlags.Costs.mpacktime =           MSGPACKTIME;      
275     RtsFlags.GranFlags.Costs.munpacktime =         MSGUNPACKTIME;
276     RtsFlags.GranFlags.Costs.mtidytime =           MSGTIDYTIME;
277
278     RtsFlags.GranFlags.Costs.threadcreatetime =         THREADCREATETIME;
279     RtsFlags.GranFlags.Costs.threadqueuetime =          THREADQUEUETIME;
280     RtsFlags.GranFlags.Costs.threaddescheduletime =     THREADDESCHEDULETIME;
281     RtsFlags.GranFlags.Costs.threadscheduletime =       THREADSCHEDULETIME;
282     RtsFlags.GranFlags.Costs.threadcontextswitchtime =  THREADCONTEXTSWITCHTIME;
283
284     RtsFlags.GranFlags.Costs.arith_cost =         ARITH_COST;       
285     RtsFlags.GranFlags.Costs.branch_cost =        BRANCH_COST; 
286     RtsFlags.GranFlags.Costs.load_cost =          LOAD_COST;        
287     RtsFlags.GranFlags.Costs.store_cost =         STORE_COST; 
288     RtsFlags.GranFlags.Costs.float_cost =         FLOAT_COST;       
289
290     RtsFlags.GranFlags.Costs.heapalloc_cost =     HEAPALLOC_COST;
291
292     RtsFlags.GranFlags.Costs.pri_spark_overhead = PRI_SPARK_OVERHEAD;        
293     RtsFlags.GranFlags.Costs.pri_sched_overhead = PRI_SCHED_OVERHEAD;        
294
295     RtsFlags.GranFlags.DoFairSchedule           = rtsFalse;             
296     RtsFlags.GranFlags.DoAsyncFetch             = rtsFalse;        
297     RtsFlags.GranFlags.DoStealThreadsFirst      = rtsFalse;        
298     RtsFlags.GranFlags.DoAlwaysCreateThreads    = rtsFalse;      
299     RtsFlags.GranFlags.DoBulkFetching           = rtsFalse;             
300     RtsFlags.GranFlags.DoThreadMigration        = rtsFalse;          
301     RtsFlags.GranFlags.FetchStrategy            = 2;                     
302     RtsFlags.GranFlags.PreferSparksOfLocalNodes = rtsFalse;   
303     RtsFlags.GranFlags.DoPrioritySparking       = rtsFalse;         
304     RtsFlags.GranFlags.DoPriorityScheduling     = rtsFalse;       
305     RtsFlags.GranFlags.SparkPriority            = 0;
306     RtsFlags.GranFlags.SparkPriority2           = 0; 
307     RtsFlags.GranFlags.RandomPriorities         = rtsFalse;           
308     RtsFlags.GranFlags.InversePriorities        = rtsFalse;          
309     RtsFlags.GranFlags.IgnorePriorities         = rtsFalse;           
310     RtsFlags.GranFlags.ThunksToPack             = 0;                      
311     RtsFlags.GranFlags.RandomSteal              = rtsTrue;
312 #endif
313
314 #ifdef TICKY_TICKY
315     RtsFlags.TickyFlags.showTickyStats   = rtsFalse;
316     RtsFlags.TickyFlags.tickyFile        = NULL;
317 #endif
318 }
319
320 static const char *
321 usage_text[] = {
322 "",
323 "Usage: <prog> <args> [+RTS <rtsopts> | -RTS <args>] ... --RTS <args>",
324 "",
325 "   +RTS    Indicates run time system options follow",
326 "   -RTS    Indicates program arguments follow",
327 "  --RTS    Indicates that ALL subsequent arguments will be given to the",
328 "           program (including any of these RTS flags)",
329 "",
330 "The following run time system options are available:",
331 "",
332 "  -?       Prints this message and exits; the program is not executed",
333 "",
334 "  -K<size> Sets the maximum stack size (default 1M)  Egs: -K32k   -K512k",
335 "  -k<size> Sets the initial thread stack size (default 1k)  Egs: -k4k   -k2m",
336 "",
337 "  -A<size> Sets the minimum allocation area size (default 256k) Egs: -A1m -A10k",
338 "  -M<size> Sets the maximum heap size (default unlimited)  Egs: -M256k -M1G",
339 "  -H<size> Sets the minimum heap size (default 0M)   Egs: -H24m  -H1G",
340 "  -m<n>    Minimum % of heap which must be available (default 3%)",
341 "  -G<n>    Number of generations (default: 2)",
342 "  -T<n>    Number of steps in younger generations (default: 2)",
343 "  -c<n>    Auto-enable compaction of the oldest generation when live data is",
344 "           at least <n>% of the maximum heap size set with -M (default: 30%)",
345 "  -c       Enable compaction for all major collections",
346 "",
347 "  -t<file> One-line GC statistics  (default file: <program>.stat)",
348 "  -s<file> Summary  GC statistics  (with -Sstderr going to stderr)",
349 "  -S<file> Detailed GC statistics",
350 #ifdef RTS_GTK_FRONTPANEL
351 "  -f       Display front panel (requires X11 & GTK+)",
352 #endif
353 "",
354 "",
355 "  -Z       Don't squeeze out update frames on stack overflow",
356 "  -B       Sound the bell at the start of each garbage collection",
357 #if defined(PROFILING) || defined(PAR)
358 "",
359 "  -px      Time/allocation profile (XML)  (output file <program>.prof)",
360 "  -p       Time/allocation profile        (output file <program>.prof)",
361 "  -P       More detailed Time/Allocation profile",
362 "  -Pa      Give information about *all* cost centres",
363
364 # if defined(PROFILING)
365 "",
366 "  -hx            Heap residency profile (XML)   (output file <program>.prof)",
367 "  -h<break-down> Heap residency profile (hp2ps) (output file <program>.hp)",
368 "     break-down: c = cost centre stack (default)",
369 "                 m = module",
370 "                 d = closure description",
371 "                 y = type description",
372 "                 r = retainer",
373 "                 b = biography (LAG,DRAG,VOID,USE)",
374 "  A subset of closures may be selected thusly:",
375 "    -hc<cc>,...  specific cost centre(s) (top of stack only)",
376 "    -hC<cc>,...  specific cost centre(s) (anywhere in stack)",
377 "    -hm<mod>...  all cost centres from the specified modules(s)",
378 "    -hd<des>,... closures with specified closure descriptions",
379 "    -hy<typ>...  closures with specified type descriptions",
380 "    -hr<cc>...   closures with specified retainers",
381 "    -hb<bio>...  closures with specified biographies (lag,drag,void,use)",
382 "",
383 "  -R<size>       Set the maximum retainer set size (default: 8)",
384 "",
385 "  -i<sec>        Time between heap samples (seconds, default: 0.1)",
386 "",
387 "  -xt            Include threads (TSOs) in a heap profile",
388 "",
389 "  -xc      Show current cost centre stack on raising an exception",
390 # endif
391 #endif /* PROFILING or PAR */
392 #if !defined(PROFILING) && defined(DEBUG)
393 "",
394 "  -h<break-down> Debugging Heap residency profile",
395 "                 (output file <program>.hp)",
396 "     break-down: L = closure label (default)",
397 "                 T = closure type (constructor, thunk etc.)",
398 #endif
399 "",
400 #if defined(TICKY_TICKY)
401 "  -r<file>  Produce reduction profiling statistics (with -rstderr for stderr)",
402 "",
403 #endif
404 #if defined(PAR)
405 "  -N<n>     Use <n> PVMish processors in parallel (default: 2)",
406 /* NB: the -N<n> is implemented by the driver!! */
407 #endif
408 "  -C<secs>  Context-switch interval in seconds",
409 "                (0 or no argument means switch as often as possible)",
410 "                the default is .02 sec; resolution is .02 sec",
411 "",
412 #if defined(DEBUG)
413 "  -Ds  DEBUG: scheduler",
414 "  -Di  DEBUG: interpreter",
415 "  -Dc  DEBUG: codegen",
416 "  -Dw  DEBUG: weak",
417 "  -DG  DEBUG: gccafs",
418 "  -Dg  DEBUG: gc",
419 "  -Db  DEBUG: block",
420 "  -DS  DEBUG: sanity",
421 "  -Dt  DEBUG: stable",
422 "  -Dp  DEBUG: prof",
423 "  -Dr  DEBUG: gran",
424 "  -DP  DEBUG: par",
425 "  -Dl  DEBUG: linker",
426 "",
427 #endif // DEBUG
428 #if defined(SMP)
429 "  -N<n>     Use <n> OS threads (default: 1)",
430 #endif
431 #if defined(SMP) || defined(PAR)
432 "  -e<size>  Size of spark pools (default 100)",
433 #endif
434 #if defined(PAR)
435 "  -t<num>   Set maximum number of advisory threads per PE (default 32)",
436 "  -qP       Enable activity profile (output files in ~/<program>*.gr)",
437 "  -qQ<size> Set pack-buffer size (default: 1024)",
438 "  -qd       Turn on PVM-ish debugging",
439 "  -qO       Disable output for performance measurement",
440 #endif
441 #if defined(SMP) || defined(PAR)
442 "  -e<n>     Maximum number of outstanding local sparks (default: 4096)",
443 #endif
444 #if defined(PAR)
445 "  -d        Turn on PVM-ish debugging",
446 "  -O        Disable output for performance measurement",
447 #endif /* PAR */
448 #if defined(GRAN)  /* ToDo: fill in decent Docu here */
449 "  -b...     All GranSim options start with -b; see GranSim User's Guide for details",
450 #endif
451 "",
452 "RTS options may also be specified using the GHCRTS environment variable.",
453 "",
454 "Other RTS options may be available for programs compiled a different way.",
455 "The GHC User's Guide has full details.",
456 "",
457 0
458 };
459
460 STATIC_INLINE rtsBool
461 strequal(const char *a, const char * b)
462 {
463     return(strcmp(a, b) == 0);
464 }
465
466 static void
467 splitRtsFlags(char *s, int *rts_argc, char *rts_argv[])
468 {
469     char *c1, *c2;
470
471     c1 = s;
472     do {
473         while (isspace(*c1)) { c1++; };
474         c2 = c1;
475         while (!isspace(*c2) && *c2 != '\0') { c2++; };
476         
477         if (c1 == c2) { break; }
478         
479         if (*rts_argc < MAX_RTS_ARGS-1) {
480             s = stgMallocBytes(c2-c1+1, "RtsFlags.c:splitRtsFlags()");
481             strncpy(s, c1, c2-c1);
482             s[c2-c1] = '\0';
483             rts_argv[(*rts_argc)++] = s;
484         } else {
485             barf("too many RTS arguments (max %d)", MAX_RTS_ARGS-1);
486         }
487         
488         c1 = c2;
489     } while (*c1 != '\0');
490 }
491     
492 void
493 setupRtsFlags(int *argc, char *argv[], int *rts_argc, char *rts_argv[])
494 {
495     rtsBool error = rtsFalse;
496     I_ mode;
497     I_ arg, total_arg;
498     char *last_slash;
499
500     /* Remove directory from argv[0] -- default files in current directory */
501     if ((last_slash = (char *) strrchr(argv[0], 
502 #if !defined(mingw32_TARGET_OS)
503                                        '/')
504 #else
505                                        '\\')
506 #endif
507                                        ) != NULL) {
508         prog_name = last_slash+1;
509     } else {
510         prog_name = argv[0];
511     }
512
513     total_arg = *argc;
514     arg = 1;
515
516     *argc = 1;
517     *rts_argc = 0;
518
519     // process arguments from the ghc_rts_opts global variable first.
520     // (arguments from the GHCRTS environment variable and the command
521     // line override these).
522     {
523         if (ghc_rts_opts != NULL) {
524             splitRtsFlags(ghc_rts_opts, rts_argc, rts_argv);
525         }
526     }
527
528     // process arguments from the GHCRTS environment variable next
529     // (arguments from the command line override these).
530     {
531         char *ghc_rts = getenv("GHCRTS");
532
533         if (ghc_rts != NULL) {
534             splitRtsFlags(ghc_rts, rts_argc, rts_argv);
535         }
536     }
537
538     // Split arguments (argv) into PGM (argv) and RTS (rts_argv) parts
539     //   argv[0] must be PGM argument -- leave in argv
540
541     for (mode = PGM; arg < total_arg; arg++) {
542         // The '--RTS' argument disables all future +RTS ... -RTS processing.
543         if (strequal("--RTS", argv[arg])) {
544             arg++;
545             break;
546         }
547         // The '--' argument is passed through to the program, but
548         // disables all further +RTS ... -RTS processing.
549         else if (strequal("--", argv[arg])) {
550             break;
551         }
552         else if (strequal("+RTS", argv[arg])) {
553             mode = RTS;
554         }
555         else if (strequal("-RTS", argv[arg])) {
556             mode = PGM;
557         }
558         else if (mode == RTS && *rts_argc < MAX_RTS_ARGS-1) {
559             rts_argv[(*rts_argc)++] = argv[arg];
560         }
561         else if (mode == PGM) {
562             argv[(*argc)++] = argv[arg];
563         }
564         else {
565           barf("too many RTS arguments (max %d)", MAX_RTS_ARGS-1);
566         }
567     }
568     // process remaining program arguments
569     for (; arg < total_arg; arg++) {
570         argv[(*argc)++] = argv[arg];
571     }
572     argv[*argc] = (char *) 0;
573     rts_argv[*rts_argc] = (char *) 0;
574
575     // Process RTS (rts_argv) part: mainly to determine statsfile
576     for (arg = 0; arg < *rts_argc; arg++) {
577         if (rts_argv[arg][0] != '-') {
578             fflush(stdout);
579             prog_belch("unexpected RTS argument: %s", rts_argv[arg]);
580             error = rtsTrue;
581
582         } else {
583             switch(rts_argv[arg][1]) {
584
585               /* process: general args, then PROFILING-only ones,
586                  then CONCURRENT-only, PARallel-only, GRAN-only,
587                  TICKY-only (same order as defined in RtsFlags.lh);
588                  within those groups, mostly in case-insensitive
589                  alphabetical order.
590                  Final group is x*, which allows for more options.
591               */
592
593 #ifdef TICKY_TICKY
594 # define TICKY_BUILD_ONLY(x) x
595 #else
596 # define TICKY_BUILD_ONLY(x) \
597 prog_belch("GHC not built for: ticky-ticky stats"); \
598 error = rtsTrue;
599 #endif
600
601 #if defined(PROFILING) 
602 # define COST_CENTRE_USING_BUILD_ONLY(x) x
603 #else
604 # define COST_CENTRE_USING_BUILD_ONLY(x) \
605 prog_belch("GHC not built for: -prof or -parallel"); \
606 error = rtsTrue;
607 #endif
608
609 #ifdef PROFILING
610 # define PROFILING_BUILD_ONLY(x)   x
611 #else
612 # define PROFILING_BUILD_ONLY(x) \
613 prog_belch("GHC not built for: -prof"); \
614 error = rtsTrue;
615 #endif
616
617 #ifdef SMP
618 # define SMP_BUILD_ONLY(x)      x
619 #else
620 # define SMP_BUILD_ONLY(x) \
621 prog_belch("GHC not built for: -smp"); \
622 error = rtsTrue;
623 #endif
624
625 #ifdef PAR
626 # define PAR_BUILD_ONLY(x)      x
627 #else
628 # define PAR_BUILD_ONLY(x) \
629 prog_belch("GHC not built for: -parallel"); \
630 error = rtsTrue;
631 #endif
632
633 #if defined(SMP) || defined(PAR)
634 # define PAR_OR_SMP_BUILD_ONLY(x)      x
635 #else
636 # define PAR_OR_SMP_BUILD_ONLY(x) \
637 prog_belch("GHC not built for: -parallel or -smp"); \
638 error = rtsTrue;
639 #endif
640
641 #ifdef GRAN
642 # define GRAN_BUILD_ONLY(x)     x
643 #else
644 # define GRAN_BUILD_ONLY(x) \
645 prog_belch("GHC not built for: -gransim"); \
646 error = rtsTrue;
647 #endif
648
649               /* =========== GENERAL ========================== */
650               case '?':
651                 error = rtsTrue;
652                 break;
653
654               case 'A':
655                 RtsFlags.GcFlags.minAllocAreaSize
656                   = decode(rts_argv[arg]+2) / BLOCK_SIZE;
657                 if (RtsFlags.GcFlags.minAllocAreaSize <= 0) {
658                   bad_option(rts_argv[arg]);
659                 }
660                 break;
661
662               case 'B':
663                 RtsFlags.GcFlags.ringBell = rtsTrue;
664                 break;
665
666               case 'c':
667                   if (rts_argv[arg][2] != '\0') {
668                       RtsFlags.GcFlags.compactThreshold =
669                           atof(rts_argv[arg]+2);
670                   } else {
671                       RtsFlags.GcFlags.compact = rtsTrue;
672                   }
673                   break;
674
675               case 'F':
676                 RtsFlags.GcFlags.oldGenFactor = atof(rts_argv[arg]+2);
677               
678                 if (RtsFlags.GcFlags.oldGenFactor < 0)
679                   bad_option( rts_argv[arg] );
680                 break;
681               
682 #ifdef DEBUG
683               case 'D':
684               { 
685                   char *c;
686
687                   for (c  = rts_argv[arg] + 2; *c != '\0'; c++) {
688                       switch (*c) {
689                       case 's':
690                           RtsFlags.DebugFlags.scheduler = rtsTrue;
691                           break;
692                       case 'i':
693                           RtsFlags.DebugFlags.interpreter = rtsTrue;
694                           break;
695                       case 'c':
696                           RtsFlags.DebugFlags.codegen = rtsTrue;
697                           break;
698                       case 'w':
699                           RtsFlags.DebugFlags.weak = rtsTrue;
700                           break;
701                       case 'G':
702                           RtsFlags.DebugFlags.gccafs = rtsTrue;
703                           break;
704                       case 'g':
705                           RtsFlags.DebugFlags.gc = rtsTrue;
706                           break;
707                       case 'b':
708                           RtsFlags.DebugFlags.block_alloc = rtsTrue;
709                           break;
710                       case 'S':
711                           RtsFlags.DebugFlags.sanity = rtsTrue;
712                           break;
713                       case 't':
714                           RtsFlags.DebugFlags.stable = rtsTrue;
715                           break;
716                       case 'p':
717                           RtsFlags.DebugFlags.prof = rtsTrue;
718                           break;
719                       case 'r':
720                           RtsFlags.DebugFlags.gran = rtsTrue;
721                           break;
722                       case 'P':
723                           RtsFlags.DebugFlags.par = rtsTrue;
724                           break;
725                       case 'l':
726                           RtsFlags.DebugFlags.linker = rtsTrue;
727                           break;
728                       case 'a':
729                           RtsFlags.DebugFlags.apply = rtsTrue;
730                           break;
731                       default:
732                           bad_option( rts_argv[arg] );
733                       }
734                   }
735                   break;
736               }
737 #endif
738
739               case 'K':
740                 RtsFlags.GcFlags.maxStkSize = 
741                   decode(rts_argv[arg]+2) / sizeof(W_);
742
743                 if (RtsFlags.GcFlags.maxStkSize == 0) 
744                   bad_option( rts_argv[arg] );
745                 break;
746
747               case 'k':
748                 RtsFlags.GcFlags.initialStkSize = 
749                   decode(rts_argv[arg]+2) / sizeof(W_);
750
751                 if (RtsFlags.GcFlags.initialStkSize == 0) 
752                   bad_option( rts_argv[arg] );
753                 break;
754
755               case 'M':
756                 RtsFlags.GcFlags.maxHeapSize = 
757                   decode(rts_argv[arg]+2) / BLOCK_SIZE;
758                 /* user give size in *bytes* but "maxHeapSize" is in *blocks* */
759
760                 if (RtsFlags.GcFlags.maxHeapSize <= 0) {
761                   bad_option(rts_argv[arg]);
762                 }
763                 break;
764
765               case 'm':
766                 RtsFlags.GcFlags.pcFreeHeap = atof(rts_argv[arg]+2);
767
768                 if (RtsFlags.GcFlags.pcFreeHeap < 0 || 
769                     RtsFlags.GcFlags.pcFreeHeap > 100)
770                   bad_option( rts_argv[arg] );
771                 break;
772
773               case 'G':
774                 RtsFlags.GcFlags.generations = decode(rts_argv[arg]+2);
775                 if (RtsFlags.GcFlags.generations < 1) {
776                   bad_option(rts_argv[arg]);
777                 }
778                 break;
779
780               case 'T':
781                 RtsFlags.GcFlags.steps = decode(rts_argv[arg]+2);
782                 if (RtsFlags.GcFlags.steps < 1) {
783                   bad_option(rts_argv[arg]);
784                 }
785                 break;
786
787               case 'H':
788                 RtsFlags.GcFlags.heapSizeSuggestion = 
789                   decode(rts_argv[arg]+2) / BLOCK_SIZE;
790
791                 if (RtsFlags.GcFlags.heapSizeSuggestion <= 0) {
792                   bad_option(rts_argv[arg]);
793                 }
794                 break;
795
796 #ifdef RTS_GTK_FRONTPANEL
797               case 'f':
798                   RtsFlags.GcFlags.frontpanel = rtsTrue;
799                   break;
800 #endif
801
802               case 'S':
803                   RtsFlags.GcFlags.giveStats = VERBOSE_GC_STATS;
804                   goto stats;
805
806               case 's':
807                   RtsFlags.GcFlags.giveStats = SUMMARY_GC_STATS;
808                   goto stats;
809
810               case 't':
811                   RtsFlags.GcFlags.giveStats = ONELINE_GC_STATS;
812                   goto stats;
813
814             stats:
815 #ifdef PAR
816                 /* Opening all those files would almost certainly fail... */
817                 // RtsFlags.ParFlags.ParStats.Full = rtsTrue;
818                 RtsFlags.GcFlags.statsFile = stderr; /* temporary; ToDo: rm */
819 #else
820                   RtsFlags.GcFlags.statsFile
821                       = open_stats_file(arg, *argc, argv,
822                                         *rts_argc, rts_argv, STAT_FILENAME_FMT);
823                   
824                   if (RtsFlags.GcFlags.statsFile == NULL) error = rtsTrue;
825 #endif
826                   break;
827
828               case 'Z':
829                 RtsFlags.GcFlags.squeezeUpdFrames = rtsFalse;
830                 break;
831
832               /* =========== PROFILING ========================== */
833
834               case 'P': /* detailed cost centre profiling (time/alloc) */
835               case 'p': /* cost centre profiling (time/alloc) */
836                 COST_CENTRE_USING_BUILD_ONLY(
837                 switch (rts_argv[arg][2]) {
838                   case 'x':
839                     RtsFlags.CcFlags.doCostCentres = COST_CENTRES_XML;
840                     break;
841                   case 'a':
842                     RtsFlags.CcFlags.doCostCentres = COST_CENTRES_ALL;
843                     break;
844                   default:
845                       if (rts_argv[arg][1] == 'P') {
846                           RtsFlags.CcFlags.doCostCentres =
847                               COST_CENTRES_VERBOSE;
848                       } else {
849                           RtsFlags.CcFlags.doCostCentres =
850                               COST_CENTRES_SUMMARY;
851                       }
852                       break;
853                 }
854                 ) break;
855
856               case 'R':
857                   PROFILING_BUILD_ONLY(
858                       RtsFlags.ProfFlags.maxRetainerSetSize = atof(rts_argv[arg]+2);
859                   ) break;
860
861               case 'h': /* serial heap profile */
862 #if !defined(PROFILING) && defined(DEBUG)
863                 switch (rts_argv[arg][2]) {
864                   case '\0':
865                   case 'L':
866                     RtsFlags.ProfFlags.doHeapProfile = HEAP_BY_INFOPTR;
867                     break;
868                   case 'T':
869                     RtsFlags.ProfFlags.doHeapProfile = HEAP_BY_CLOSURE_TYPE;
870                     break;
871                   default:
872                     prog_belch("invalid heap profile option: %s",rts_argv[arg]);
873                     error = rtsTrue;
874                 }
875 #else
876                 PROFILING_BUILD_ONLY(
877                 switch (rts_argv[arg][2]) {
878                 case '\0':
879                 case 'C':
880                 case 'c':
881                 case 'M':
882                 case 'm':
883                 case 'D':
884                 case 'd':
885                 case 'Y':
886                 case 'y':
887                 case 'R':
888                 case 'r':
889                 case 'B':
890                 case 'b':
891                     if (rts_argv[arg][2] != '\0' && rts_argv[arg][3] != '\0') {
892                         {
893                             char *left  = strchr(rts_argv[arg], '{');
894                             char *right = strrchr(rts_argv[arg], '}');
895
896                             // curly braces are optional, for
897                             // backwards compat.
898                             if (left)
899                                 left = left+1;
900                             else
901                                 left = rts_argv[arg] + 3;
902
903                             if (!right)
904                                 right = rts_argv[arg] + strlen(rts_argv[arg]);
905
906                             *right = '\0';
907
908                             switch (rts_argv[arg][2]) {
909                             case 'c': // cost centre label select
910                                 RtsFlags.ProfFlags.ccSelector = left;
911                                 break;
912                             case 'C':
913                                 RtsFlags.ProfFlags.ccsSelector = left;
914                                 break;
915                             case 'M':
916                             case 'm': // cost centre module select
917                                 RtsFlags.ProfFlags.modSelector = left;
918                                 break;
919                             case 'D':
920                             case 'd': // closure descr select 
921                                 RtsFlags.ProfFlags.descrSelector = left;
922                                 break;
923                             case 'Y':
924                             case 'y': // closure type select
925                                 RtsFlags.ProfFlags.typeSelector = left;
926                                 break;
927                             case 'R':
928                             case 'r': // retainer select
929                                 RtsFlags.ProfFlags.retainerSelector = left;
930                                 break;
931                             case 'B':
932                             case 'b': // biography select
933                                 RtsFlags.ProfFlags.bioSelector = left;
934                                 break;
935                             }
936                         }
937                         break;
938                     }
939
940                     if (RtsFlags.ProfFlags.doHeapProfile != 0) {
941                         prog_belch("multiple heap profile options");
942                         error = rtsTrue;
943                         break;
944                     }
945
946                     switch (rts_argv[arg][2]) {
947                     case '\0':
948                     case 'C':
949                     case 'c':
950                         RtsFlags.ProfFlags.doHeapProfile = HEAP_BY_CCS;
951                         break;
952                     case 'M':
953                     case 'm':
954                           RtsFlags.ProfFlags.doHeapProfile = HEAP_BY_MOD;
955                           break;
956                     case 'D':
957                     case 'd':
958                           RtsFlags.ProfFlags.doHeapProfile = HEAP_BY_DESCR;
959                           break;
960                     case 'Y':
961                     case 'y':
962                           RtsFlags.ProfFlags.doHeapProfile = HEAP_BY_TYPE;
963                           break;
964                     case 'R':
965                     case 'r':
966                           RtsFlags.ProfFlags.doHeapProfile = HEAP_BY_RETAINER;
967                           break;
968                     case 'B':
969                     case 'b':
970                           RtsFlags.ProfFlags.doHeapProfile = HEAP_BY_LDV;
971                           break;
972                     }
973                     break;
974                       
975                 default:
976                     prog_belch("invalid heap profile option: %s",rts_argv[arg]);
977                     error = rtsTrue;
978                 }
979                 ) 
980 #endif // PROFILING
981                 break;
982
983 #if defined(PROFILING) 
984               case 'i': /* heap sample interval */
985                 if (rts_argv[arg][2] == '\0') {
986                   /* use default */
987                 } else {
988                     I_ cst; /* tmp */
989
990                     /* Convert to milliseconds */
991                     cst = (I_) ((atof(rts_argv[arg]+2) * 1000));
992                     cst = (cst / CS_MIN_MILLISECS) * CS_MIN_MILLISECS;
993                     if (cst != 0 && cst < CS_MIN_MILLISECS)
994                         cst = CS_MIN_MILLISECS;
995
996                     RtsFlags.ProfFlags.profileInterval = cst;
997                 }
998                 break;
999 #endif
1000
1001               /* =========== CONCURRENT ========================= */
1002               case 'C': /* context switch interval */
1003                 if (rts_argv[arg][2] == '\0')
1004                     RtsFlags.ConcFlags.ctxtSwitchTime = 0;
1005                 else {
1006                     I_ cst; /* tmp */
1007
1008                     /* Convert to milliseconds */
1009                     cst = (I_) ((atof(rts_argv[arg]+2) * 1000));
1010                     cst = (cst / CS_MIN_MILLISECS) * CS_MIN_MILLISECS;
1011                     if (cst != 0 && cst < CS_MIN_MILLISECS)
1012                         cst = CS_MIN_MILLISECS;
1013
1014                     RtsFlags.ConcFlags.ctxtSwitchTime = cst;
1015                 }
1016                 break;
1017
1018 #ifdef SMP
1019               case 'N':
1020                 SMP_BUILD_ONLY(
1021                 if (rts_argv[arg][2] != '\0') {
1022                     RtsFlags.ParFlags.nNodes
1023                       = strtol(rts_argv[arg]+2, (char **) NULL, 10);
1024                     if (RtsFlags.ParFlags.nNodes <= 0) {
1025                       prog_belch("bad value for -N");
1026                       error = rtsTrue;
1027                     }
1028                 }
1029                 ) break;
1030 #endif
1031               /* =========== PARALLEL =========================== */
1032               case 'e':
1033                 PAR_OR_SMP_BUILD_ONLY(
1034                 if (rts_argv[arg][2] != '\0') {
1035                     RtsFlags.ParFlags.maxLocalSparks
1036                       = strtol(rts_argv[arg]+2, (char **) NULL, 10);
1037                     if (RtsFlags.ParFlags.maxLocalSparks <= 0) {
1038                       prog_belch("bad value for -e");
1039                       error = rtsTrue;
1040                     }
1041                 }
1042                 ) break;
1043
1044               case 'q':
1045                 PAR_BUILD_ONLY(
1046                   process_par_option(arg, rts_argc, rts_argv, &error);
1047                 ) break;
1048
1049               /* =========== GRAN =============================== */
1050
1051               case 'b':
1052                 GRAN_BUILD_ONLY(
1053                   process_gran_option(arg, rts_argc, rts_argv, &error);
1054                 ) break;
1055
1056               /* =========== TICKY ============================== */
1057
1058               case 'r': /* Basic profiling stats */
1059                 TICKY_BUILD_ONLY(
1060
1061                 RtsFlags.TickyFlags.showTickyStats = rtsTrue;
1062                 RtsFlags.TickyFlags.tickyFile
1063                   = open_stats_file(arg, *argc, argv,
1064                         *rts_argc, rts_argv, TICKY_FILENAME_FMT);
1065
1066                 if (RtsFlags.TickyFlags.tickyFile == NULL) error = rtsTrue;
1067                 ) break;
1068
1069               /* =========== EXTENDED OPTIONS =================== */
1070
1071               case 'x': /* Extend the argument space */
1072                 switch(rts_argv[arg][2]) {
1073                   case '\0':
1074                     prog_belch("incomplete RTS option: %s",rts_argv[arg]);
1075                     error = rtsTrue;
1076                     break;
1077
1078                   case 'c': /* Debugging tool: show current cost centre on an exception */
1079                     PROFILING_BUILD_ONLY(
1080                         RtsFlags.ProfFlags.showCCSOnException = rtsTrue;
1081                         );
1082                     break;
1083
1084                 case 't':  /* Include memory used by TSOs in a heap profile */
1085                     PROFILING_BUILD_ONLY(
1086                         RtsFlags.ProfFlags.includeTSOs = rtsTrue;
1087                         );
1088                     break;
1089
1090                   /* The option prefix '-xx' is reserved for future extension.  KSW 1999-11. */
1091
1092                   default:
1093                     prog_belch("unknown RTS option: %s",rts_argv[arg]);
1094                     error = rtsTrue;
1095                     break;
1096                 }
1097                 break;  /* defensive programming */
1098
1099               /* =========== OH DEAR ============================ */
1100               default:
1101                 prog_belch("unknown RTS option: %s",rts_argv[arg]);
1102                 error = rtsTrue;
1103                 break;
1104             }
1105         }
1106     }
1107     if (error) {
1108         const char **p;
1109
1110         fflush(stdout);
1111         for (p = usage_text; *p; p++)
1112             belch("%s", *p);
1113         stg_exit(EXIT_FAILURE);
1114     }
1115 }
1116
1117 #if defined(GRAN)
1118
1119 //@node GranSim specific options, Aux fcts, Command-line option parsing routines
1120 //@subsection GranSim specific options
1121
1122 static void
1123 enable_GranSimLight(void) {
1124
1125     fprintf(stderr,"GrAnSim Light enabled (infinite number of processors;  0 communication costs)\n");
1126     RtsFlags.GranFlags.Light=rtsTrue;
1127     RtsFlags.GranFlags.Costs.latency = 
1128         RtsFlags.GranFlags.Costs.fetchtime = 
1129         RtsFlags.GranFlags.Costs.additional_latency =
1130         RtsFlags.GranFlags.Costs.gunblocktime = 
1131         RtsFlags.GranFlags.Costs.lunblocktime =
1132         RtsFlags.GranFlags.Costs.threadcreatetime = 
1133         RtsFlags.GranFlags.Costs.threadqueuetime =
1134         RtsFlags.GranFlags.Costs.threadscheduletime = 
1135         RtsFlags.GranFlags.Costs.threaddescheduletime =
1136         RtsFlags.GranFlags.Costs.threadcontextswitchtime = 0;
1137   
1138     RtsFlags.GranFlags.Costs.mpacktime = 
1139         RtsFlags.GranFlags.Costs.munpacktime = 0;
1140
1141     RtsFlags.GranFlags.DoFairSchedule = rtsTrue;
1142     RtsFlags.GranFlags.DoAsyncFetch = rtsFalse;
1143     RtsFlags.GranFlags.DoAlwaysCreateThreads = rtsTrue;
1144     /* FetchStrategy is irrelevant in GrAnSim-Light */
1145
1146     /* GrAnSim Light often creates an abundance of parallel threads,
1147        each with its own stack etc. Therefore, it's in general a good
1148        idea to use small stack chunks (use the -o<size> option to 
1149        increase it again). 
1150     */
1151     // RtsFlags.ConcFlags.stkChunkSize = 100;
1152
1153     RtsFlags.GranFlags.proc = 1; 
1154 }
1155
1156 static void
1157 process_gran_option(int arg, int *rts_argc, char *rts_argv[], rtsBool *error)
1158 {
1159     if (rts_argv[arg][1] != 'b') /* All GranSim options start with -b */
1160       return;
1161
1162     /* or a ridiculously idealised simulator */
1163     if(strcmp((rts_argv[arg]+2),"oring")==0) {
1164       RtsFlags.GranFlags.Costs.latency = 
1165         RtsFlags.GranFlags.Costs.fetchtime = 
1166         RtsFlags.GranFlags.Costs.additional_latency =
1167         RtsFlags.GranFlags.Costs.gunblocktime = 
1168         RtsFlags.GranFlags.Costs.lunblocktime =
1169         RtsFlags.GranFlags.Costs.threadcreatetime = 
1170         RtsFlags.GranFlags.Costs.threadqueuetime =
1171         RtsFlags.GranFlags.Costs.threadscheduletime = 
1172         RtsFlags.GranFlags.Costs.threaddescheduletime =
1173         RtsFlags.GranFlags.Costs.threadcontextswitchtime = 0;
1174
1175       RtsFlags.GranFlags.Costs.mpacktime = 
1176         RtsFlags.GranFlags.Costs.munpacktime = 0;
1177
1178       RtsFlags.GranFlags.Costs.arith_cost = 
1179         RtsFlags.GranFlags.Costs.float_cost = 
1180         RtsFlags.GranFlags.Costs.load_cost =
1181         RtsFlags.GranFlags.Costs.store_cost = 
1182         RtsFlags.GranFlags.Costs.branch_cost = 0;
1183
1184       RtsFlags.GranFlags.Costs.heapalloc_cost = 1;
1185
1186       /* ++RtsFlags.GranFlags.DoFairSchedule; */
1187       RtsFlags.GranFlags.DoStealThreadsFirst = rtsTrue;        /* -bZ */
1188       RtsFlags.GranFlags.DoThreadMigration   = rtsTrue;        /* -bM */
1189       RtsFlags.GranFlags.GranSimStats.Full   = rtsTrue;        /* -bP */
1190       return;
1191     }
1192
1193       /* or a somewhat idealised simulator */
1194       if(strcmp((rts_argv[arg]+2),"onzo")==0) {
1195         RtsFlags.GranFlags.Costs.latency = 
1196         RtsFlags.GranFlags.Costs.fetchtime = 
1197         RtsFlags.GranFlags.Costs.additional_latency =
1198         RtsFlags.GranFlags.Costs.gunblocktime = 
1199         RtsFlags.GranFlags.Costs.lunblocktime =
1200         RtsFlags.GranFlags.Costs.threadcreatetime = 
1201         RtsFlags.GranFlags.Costs.threadqueuetime =
1202         RtsFlags.GranFlags.Costs.threadscheduletime = 
1203         RtsFlags.GranFlags.Costs.threaddescheduletime =
1204         RtsFlags.GranFlags.Costs.threadcontextswitchtime = 0;
1205
1206         RtsFlags.GranFlags.Costs.mpacktime = 
1207         RtsFlags.GranFlags.Costs.munpacktime = 0;
1208         
1209         RtsFlags.GranFlags.Costs.heapalloc_cost = 1;
1210
1211         /* RtsFlags.GranFlags.DoFairSchedule  = rtsTrue; */       /* -b-R */
1212         /* RtsFlags.GranFlags.DoStealThreadsFirst = rtsTrue; */   /* -b-T */
1213         RtsFlags.GranFlags.DoAsyncFetch = rtsTrue;         /* -bZ */
1214         RtsFlags.GranFlags.DoThreadMigration  = rtsTrue;          /* -bM */
1215         RtsFlags.GranFlags.GranSimStats.Full  = rtsTrue;          /* -bP */
1216 #  if defined(GRAN_CHECK) && defined(GRAN)
1217         RtsFlags.GranFlags.Debug.event_stats = rtsTrue; /* print event statistics   */
1218 #  endif
1219         return;
1220       }
1221
1222       /* Communication and task creation cost parameters */
1223       switch(rts_argv[arg][2]) {
1224         case '.':
1225           IgnoreYields = rtsTrue; // HWL HACK
1226           break;
1227
1228         case ':':
1229           enable_GranSimLight();       /* set flags for GrAnSim-Light mode */
1230           break;
1231
1232         case 'l':
1233           if (rts_argv[arg][3] != '\0')
1234             {
1235               RtsFlags.GranFlags.Costs.gunblocktime = 
1236               RtsFlags.GranFlags.Costs.latency = decode(rts_argv[arg]+3);
1237               RtsFlags.GranFlags.Costs.fetchtime = 2*RtsFlags.GranFlags.Costs.latency;
1238             }
1239           else
1240             RtsFlags.GranFlags.Costs.latency = LATENCY;
1241           break;
1242
1243         case 'a':
1244           if (rts_argv[arg][3] != '\0')
1245             RtsFlags.GranFlags.Costs.additional_latency = decode(rts_argv[arg]+3);
1246           else
1247             RtsFlags.GranFlags.Costs.additional_latency = ADDITIONAL_LATENCY;
1248           break;
1249
1250         case 'm':
1251           if (rts_argv[arg][3] != '\0')
1252             RtsFlags.GranFlags.Costs.mpacktime = decode(rts_argv[arg]+3);
1253           else
1254             RtsFlags.GranFlags.Costs.mpacktime = MSGPACKTIME;
1255           break;
1256
1257         case 'x':
1258           if (rts_argv[arg][3] != '\0')
1259             RtsFlags.GranFlags.Costs.mtidytime = decode(rts_argv[arg]+3);
1260           else
1261             RtsFlags.GranFlags.Costs.mtidytime = 0;
1262           break;
1263
1264         case 'r':
1265           if (rts_argv[arg][3] != '\0')
1266             RtsFlags.GranFlags.Costs.munpacktime = decode(rts_argv[arg]+3);
1267           else
1268             RtsFlags.GranFlags.Costs.munpacktime = MSGUNPACKTIME;
1269           break;
1270           
1271         case 'g':
1272           if (rts_argv[arg][3] != '\0')
1273             RtsFlags.GranFlags.Costs.fetchtime = decode(rts_argv[arg]+3);
1274           else
1275             RtsFlags.GranFlags.Costs.fetchtime = FETCHTIME;
1276           break;
1277           
1278         case 'n':
1279           if (rts_argv[arg][3] != '\0')
1280             RtsFlags.GranFlags.Costs.gunblocktime = decode(rts_argv[arg]+3);
1281           else
1282             RtsFlags.GranFlags.Costs.gunblocktime = GLOBALUNBLOCKTIME;
1283           break;
1284
1285         case 'u':
1286           if (rts_argv[arg][3] != '\0')
1287             RtsFlags.GranFlags.Costs.lunblocktime = decode(rts_argv[arg]+3);
1288           else
1289             RtsFlags.GranFlags.Costs.lunblocktime = LOCALUNBLOCKTIME;
1290           break;
1291
1292         /* Thread-related metrics */
1293         case 't':
1294           if (rts_argv[arg][3] != '\0')
1295             RtsFlags.GranFlags.Costs.threadcreatetime = decode(rts_argv[arg]+3);
1296           else
1297             RtsFlags.GranFlags.Costs.threadcreatetime = THREADCREATETIME;
1298           break;
1299           
1300         case 'q':
1301           if (rts_argv[arg][3] != '\0')
1302             RtsFlags.GranFlags.Costs.threadqueuetime = decode(rts_argv[arg]+3);
1303           else
1304             RtsFlags.GranFlags.Costs.threadqueuetime = THREADQUEUETIME;
1305           break;
1306           
1307         case 'c':
1308           if (rts_argv[arg][3] != '\0')
1309             RtsFlags.GranFlags.Costs.threadscheduletime = decode(rts_argv[arg]+3);
1310           else
1311             RtsFlags.GranFlags.Costs.threadscheduletime = THREADSCHEDULETIME;
1312           
1313           RtsFlags.GranFlags.Costs.threadcontextswitchtime = RtsFlags.GranFlags.Costs.threadscheduletime
1314             + RtsFlags.GranFlags.Costs.threaddescheduletime;
1315           break;
1316
1317         case 'd':
1318           if (rts_argv[arg][3] != '\0')
1319             RtsFlags.GranFlags.Costs.threaddescheduletime = decode(rts_argv[arg]+3);
1320           else
1321             RtsFlags.GranFlags.Costs.threaddescheduletime = THREADDESCHEDULETIME;
1322           
1323           RtsFlags.GranFlags.Costs.threadcontextswitchtime = RtsFlags.GranFlags.Costs.threadscheduletime
1324             + RtsFlags.GranFlags.Costs.threaddescheduletime;
1325           break;
1326
1327         /* Instruction Cost Metrics */
1328         case 'A':
1329           if (rts_argv[arg][3] != '\0')
1330             RtsFlags.GranFlags.Costs.arith_cost = decode(rts_argv[arg]+3);
1331           else
1332             RtsFlags.GranFlags.Costs.arith_cost = ARITH_COST;
1333           break;
1334
1335         case 'F':
1336           if (rts_argv[arg][3] != '\0')
1337             RtsFlags.GranFlags.Costs.float_cost = decode(rts_argv[arg]+3);
1338           else
1339             RtsFlags.GranFlags.Costs.float_cost = FLOAT_COST;
1340           break;
1341                       
1342         case 'B':
1343           if (rts_argv[arg][3] != '\0')
1344             RtsFlags.GranFlags.Costs.branch_cost = decode(rts_argv[arg]+3);
1345           else
1346             RtsFlags.GranFlags.Costs.branch_cost = BRANCH_COST;
1347           break;
1348
1349         case 'L':
1350           if (rts_argv[arg][3] != '\0')
1351             RtsFlags.GranFlags.Costs.load_cost = decode(rts_argv[arg]+3);
1352           else
1353             RtsFlags.GranFlags.Costs.load_cost = LOAD_COST;
1354           break;
1355           
1356         case 'S':
1357           if (rts_argv[arg][3] != '\0')
1358             RtsFlags.GranFlags.Costs.store_cost = decode(rts_argv[arg]+3);
1359           else
1360             RtsFlags.GranFlags.Costs.store_cost = STORE_COST;
1361           break;
1362
1363         case 'H':
1364           if (rts_argv[arg][3] != '\0')
1365             RtsFlags.GranFlags.Costs.heapalloc_cost = decode(rts_argv[arg]+3);
1366           else
1367             RtsFlags.GranFlags.Costs.heapalloc_cost = 0;
1368           break;
1369
1370         case 'y':
1371           RtsFlags.GranFlags.DoAsyncFetch = rtsTrue;
1372           if (rts_argv[arg][3] != '\0')
1373             RtsFlags.GranFlags.FetchStrategy = decode(rts_argv[arg]+3);
1374           else
1375             RtsFlags.GranFlags.FetchStrategy = 2;
1376           if (RtsFlags.GranFlags.FetchStrategy == 0)
1377             RtsFlags.GranFlags.DoAsyncFetch = rtsFalse;
1378           break;
1379           
1380         case 'K':   /* sort overhead (per elem in spark list) */
1381           if (rts_argv[arg][3] != '\0')
1382             RtsFlags.GranFlags.Costs.pri_spark_overhead = decode(rts_argv[arg]+3);
1383           else
1384             RtsFlags.GranFlags.Costs.pri_spark_overhead = PRI_SPARK_OVERHEAD;
1385           fprintf(stderr,"Overhead for pri spark: %d (per elem).\n",
1386                          RtsFlags.GranFlags.Costs.pri_spark_overhead);
1387           break;
1388
1389         case 'O':  /* sort overhead (per elem in spark list) */
1390           if (rts_argv[arg][3] != '\0')
1391             RtsFlags.GranFlags.Costs.pri_sched_overhead = decode(rts_argv[arg]+3);
1392           else
1393             RtsFlags.GranFlags.Costs.pri_sched_overhead = PRI_SCHED_OVERHEAD;
1394           fprintf(stderr,"Overhead for pri sched: %d (per elem).\n",
1395                        RtsFlags.GranFlags.Costs.pri_sched_overhead);
1396           break;
1397
1398         /* General Parameters */
1399         case 'p':
1400           if (rts_argv[arg][3] != '\0')
1401             {
1402               RtsFlags.GranFlags.proc = decode(rts_argv[arg]+3);
1403               if (RtsFlags.GranFlags.proc==0) {
1404                   enable_GranSimLight(); /* set flags for GrAnSim-Light mode */
1405               } else if (RtsFlags.GranFlags.proc > MAX_PROC || 
1406                          RtsFlags.GranFlags.proc < 1)
1407                 {
1408                   fprintf(stderr,"setupRtsFlags: no more than %u processors allowed\n",
1409                           MAX_PROC);
1410                   *error = rtsTrue;
1411                 }
1412             }
1413           else
1414             RtsFlags.GranFlags.proc = MAX_PROC;
1415           break;
1416
1417         case 'f':
1418           RtsFlags.GranFlags.Fishing = rtsTrue;
1419           if (rts_argv[arg][3] != '\0')
1420             RtsFlags.GranFlags.maxFishes = decode(rts_argv[arg]+3);
1421           else
1422             RtsFlags.GranFlags.maxFishes = MAX_FISHES;
1423           break;
1424           
1425         case 'w':
1426           if (rts_argv[arg][3] != '\0')
1427             RtsFlags.GranFlags.time_slice = decode(rts_argv[arg]+3);
1428           else
1429             RtsFlags.GranFlags.time_slice = GRAN_TIME_SLICE;
1430           break;
1431           
1432         case 'C':
1433           RtsFlags.GranFlags.DoAlwaysCreateThreads=rtsTrue;
1434           RtsFlags.GranFlags.DoThreadMigration=rtsTrue;
1435           break;
1436
1437         case 'G':
1438           fprintf(stderr,"Bulk fetching enabled.\n");
1439           RtsFlags.GranFlags.DoBulkFetching=rtsTrue;
1440           break;
1441           
1442         case 'M':
1443           fprintf(stderr,"Thread migration enabled.\n");
1444           RtsFlags.GranFlags.DoThreadMigration=rtsTrue;
1445           break;
1446
1447         case 'R':
1448           fprintf(stderr,"Fair Scheduling enabled.\n");
1449           RtsFlags.GranFlags.DoFairSchedule=rtsTrue;
1450           break;
1451           
1452         case 'I':
1453           fprintf(stderr,"Priority Scheduling enabled.\n");
1454           RtsFlags.GranFlags.DoPriorityScheduling=rtsTrue;
1455           break;
1456
1457         case 'T':
1458           RtsFlags.GranFlags.DoStealThreadsFirst=rtsTrue;
1459           RtsFlags.GranFlags.DoThreadMigration=rtsTrue;
1460           break;
1461           
1462         case 'Z':
1463           RtsFlags.GranFlags.DoAsyncFetch=rtsTrue;
1464           break;
1465           
1466 /*          case 'z': */
1467 /*        RtsFlags.GranFlags.SimplifiedFetch=rtsTrue; */
1468 /*        break; */
1469           
1470         case 'N':
1471           RtsFlags.GranFlags.PreferSparksOfLocalNodes=rtsTrue;
1472           break;
1473           
1474         case 'b':
1475           RtsFlags.GranFlags.GranSimStats.Binary=rtsTrue;
1476           break;
1477           
1478         case 'P':
1479           /* format is -bP<c> where <c> is one char describing kind of profile */
1480           RtsFlags.GranFlags.GranSimStats.Full = rtsTrue;
1481           switch(rts_argv[arg][3]) {
1482           case '\0': break; // nothing special, just an ordinary profile
1483           case '0': RtsFlags.GranFlags.GranSimStats.Suppressed = rtsTrue;
1484             break;
1485           case 'b': RtsFlags.GranFlags.GranSimStats.Binary = rtsTrue;
1486             break;
1487           case 's': RtsFlags.GranFlags.GranSimStats.Sparks = rtsTrue;
1488             break;
1489           case 'h': RtsFlags.GranFlags.GranSimStats.Heap = rtsTrue;
1490             break;
1491           case 'n': RtsFlags.GranFlags.GranSimStats.NewLogfile = rtsTrue;
1492             break;
1493           case 'g': RtsFlags.GranFlags.GranSimStats.Global = rtsTrue;
1494             break;
1495           default: barf("Unknown option -bP%c", rts_argv[arg][3]);
1496           }
1497           break;
1498
1499         case 's':
1500           RtsFlags.GranFlags.GranSimStats.Sparks=rtsTrue;
1501           break;
1502
1503         case 'h':
1504           RtsFlags.GranFlags.GranSimStats.Heap=rtsTrue;
1505           break;
1506
1507         case 'Y':   /* syntax: -bY<n>[,<n>]  n ... pos int */ 
1508           if (rts_argv[arg][3] != '\0') {
1509             char *arg0, *tmp;
1510             
1511             arg0 = rts_argv[arg]+3;
1512             if ((tmp = strstr(arg0,","))==NULL) {
1513               RtsFlags.GranFlags.SparkPriority = decode(arg0);
1514               fprintf(stderr,"SparkPriority: %u.\n",RtsFlags.GranFlags.SparkPriority);
1515             } else {
1516               *(tmp++) = '\0'; 
1517               RtsFlags.GranFlags.SparkPriority = decode(arg0);
1518               RtsFlags.GranFlags.SparkPriority2 = decode(tmp);
1519               fprintf(stderr,"SparkPriority: %u.\n",
1520                       RtsFlags.GranFlags.SparkPriority);
1521               fprintf(stderr,"SparkPriority2:%u.\n",
1522                       RtsFlags.GranFlags.SparkPriority2);
1523               if (RtsFlags.GranFlags.SparkPriority2 < 
1524                   RtsFlags.GranFlags.SparkPriority) {
1525                 fprintf(stderr,"WARNING: 2nd pri < main pri (%u<%u); 2nd pri has no effect\n",
1526                         RtsFlags.GranFlags.SparkPriority2,
1527                         RtsFlags.GranFlags.SparkPriority);
1528               }
1529             }
1530           } else {
1531             /* plain pri spark is now invoked with -bX  
1532                RtsFlags.GranFlags.DoPrioritySparking = 1;
1533                fprintf(stderr,"PrioritySparking.\n");
1534             */
1535           }
1536           break;
1537
1538         case 'Q':
1539           if (rts_argv[arg][3] != '\0') {
1540             RtsFlags.GranFlags.ThunksToPack = decode(rts_argv[arg]+3);
1541           } else {
1542             RtsFlags.GranFlags.ThunksToPack = 1;
1543           }
1544           fprintf(stderr,"Thunks To Pack in one packet: %u.\n",
1545                   RtsFlags.GranFlags.ThunksToPack);
1546           break;
1547                       
1548         case 'e':
1549           RtsFlags.GranFlags.RandomSteal = rtsFalse;
1550           fprintf(stderr,"Deterministic mode (no random stealing)\n");
1551                       break;
1552
1553           /* The following class of options contains eXperimental */
1554           /* features in connection with exploiting granularity */
1555           /* information. I.e. if -bY is chosen these options */
1556           /* tell the RTS what to do with the supplied info --HWL */
1557
1558         case 'W':
1559           if (rts_argv[arg][3] != '\0') {
1560             RtsFlags.GranFlags.packBufferSize_internal = decode(rts_argv[arg]+3);
1561           } else {
1562             RtsFlags.GranFlags.packBufferSize_internal = GRANSIM_DEFAULT_PACK_BUFFER_SIZE;
1563           }
1564           fprintf(stderr,"Size of GranSim internal pack buffer: %u.\n",
1565                   RtsFlags.GranFlags.packBufferSize_internal);
1566           break;
1567                       
1568         case 'X':
1569           switch(rts_argv[arg][3]) {
1570             
1571             case '\0':
1572               RtsFlags.GranFlags.DoPrioritySparking = 1;
1573               fprintf(stderr,"Priority Sparking with Normal Priorities.\n");
1574               RtsFlags.GranFlags.InversePriorities = rtsFalse; 
1575               RtsFlags.GranFlags.RandomPriorities = rtsFalse;
1576               RtsFlags.GranFlags.IgnorePriorities = rtsFalse;
1577               break;
1578                         
1579             case 'I':
1580               RtsFlags.GranFlags.DoPrioritySparking = 1;
1581               fprintf(stderr,"Priority Sparking with Inverse Priorities.\n");
1582               RtsFlags.GranFlags.InversePriorities++; 
1583               break;
1584               
1585             case 'R': 
1586               RtsFlags.GranFlags.DoPrioritySparking = 1;
1587               fprintf(stderr,"Priority Sparking with Random Priorities.\n");
1588               RtsFlags.GranFlags.RandomPriorities++;
1589               break;
1590               
1591             case 'N':
1592               RtsFlags.GranFlags.DoPrioritySparking = 1;
1593               fprintf(stderr,"Priority Sparking with No Priorities.\n");
1594               RtsFlags.GranFlags.IgnorePriorities++;
1595               break;
1596               
1597             default:
1598               bad_option( rts_argv[arg] );
1599               break;
1600           }
1601           break;
1602
1603         case '-':
1604           switch(rts_argv[arg][3]) {
1605             
1606             case 'C':
1607               RtsFlags.GranFlags.DoAlwaysCreateThreads=rtsFalse;
1608               RtsFlags.GranFlags.DoThreadMigration=rtsFalse;
1609               break;
1610
1611             case 'G':
1612               RtsFlags.GranFlags.DoBulkFetching=rtsFalse;
1613               break;
1614               
1615             case 'M':
1616               RtsFlags.GranFlags.DoThreadMigration=rtsFalse;
1617               break;
1618
1619             case 'R':
1620               RtsFlags.GranFlags.DoFairSchedule=rtsFalse;
1621               break;
1622
1623             case 'T':
1624               RtsFlags.GranFlags.DoStealThreadsFirst=rtsFalse;
1625               RtsFlags.GranFlags.DoThreadMigration=rtsFalse;
1626               break;
1627
1628             case 'Z':
1629               RtsFlags.GranFlags.DoAsyncFetch=rtsFalse;
1630               break;
1631               
1632             case 'N':
1633               RtsFlags.GranFlags.PreferSparksOfLocalNodes=rtsFalse;
1634                          break;
1635                          
1636             case 'P':
1637               RtsFlags.GranFlags.GranSimStats.Suppressed=rtsTrue;
1638               break;
1639
1640             case 's':
1641               RtsFlags.GranFlags.GranSimStats.Sparks=rtsFalse;
1642               break;
1643             
1644             case 'h':
1645               RtsFlags.GranFlags.GranSimStats.Heap=rtsFalse;
1646               break;
1647             
1648             case 'b':
1649               RtsFlags.GranFlags.GranSimStats.Binary=rtsFalse;
1650               break;
1651                          
1652             case 'X':
1653               RtsFlags.GranFlags.DoPrioritySparking = rtsFalse;
1654               break;
1655
1656             case 'Y':
1657               RtsFlags.GranFlags.DoPrioritySparking = rtsFalse;
1658               RtsFlags.GranFlags.SparkPriority = rtsFalse;
1659               break;
1660
1661             case 'I':
1662               RtsFlags.GranFlags.DoPriorityScheduling = rtsFalse;
1663               break;
1664
1665             case 'e':
1666               RtsFlags.GranFlags.RandomSteal = rtsFalse;
1667               break;
1668
1669             default:
1670               bad_option( rts_argv[arg] );
1671               break;
1672           }
1673           break;
1674
1675 #  if defined(GRAN_CHECK) && defined(GRAN)
1676         case 'D':
1677           switch(rts_argv[arg][3]) {
1678             case 'Q':    /* Set pack buffer size (same as 'Q' in GUM) */
1679               if (rts_argv[arg][4] != '\0') {
1680                 RtsFlags.GranFlags.packBufferSize = decode(rts_argv[arg]+4);
1681                 fprintf(stderr,"Pack buffer size: %d\n",
1682                         RtsFlags.GranFlags.packBufferSize);
1683               } else {
1684                 fprintf(stderr, "setupRtsFlags: missing size of PackBuffer (for -Q)\n");
1685                 *error = rtsTrue;
1686               }
1687               break;
1688
1689           default:
1690               if (isdigit(rts_argv[arg][3])) {/* Set all debugging options in one */
1691                 /* hack warning: interpret the flags as a binary number */
1692                 nat n = decode(rts_argv[arg]+3);
1693                 set_GranSim_debug_options(n);
1694               } else {
1695                 nat i;
1696                 for (i=0; i<=MAX_GRAN_DEBUG_OPTION; i++) 
1697                   if (rts_argv[arg][3] == gran_debug_opts_flags[i])
1698                     break;
1699                 
1700                 if (i==MAX_GRAN_DEBUG_OPTION+1) {
1701                   fprintf(stderr, "Valid GranSim debug options are:\n");
1702                   help_GranSim_debug_options(MAX_GRAN_DEBUG_MASK);
1703                   bad_option( rts_argv[arg] );
1704                 } else { // flag found; now set it
1705                   set_GranSim_debug_options(GRAN_DEBUG_MASK(i));  // 2^i
1706                 }
1707               }
1708               break;
1709               
1710 #if 0
1711             case 'e':       /* event trace; also -bD1 */
1712               fprintf(stderr,"DEBUG: event_trace; printing event trace.\n");
1713               RtsFlags.GranFlags.Debug.event_trace = rtsTrue;
1714               /* RtsFlags.GranFlags.event_trace=rtsTrue; */
1715               break;
1716               
1717             case 'E':       /* event statistics; also -bD2 */
1718               fprintf(stderr,"DEBUG: event_stats; printing event statistics.\n");
1719               RtsFlags.GranFlags.Debug.event_stats = rtsTrue;
1720               /* RtsFlags.GranFlags.Debug |= 0x20; print event statistics   */
1721               break;
1722               
1723             case 'f':       /* thunkStealing; also -bD4 */
1724               fprintf(stderr,"DEBUG: thunkStealing; printing forwarding of FETCHNODES.\n");
1725               RtsFlags.GranFlags.Debug.thunkStealing = rtsTrue;
1726               /* RtsFlags.GranFlags.Debug |= 0x2;  print fwd messages */
1727               break;
1728
1729             case 'z':       /* blockOnFetch; also -bD8 */
1730               fprintf(stderr,"DEBUG: blockOnFetch; check for blocked on fetch.\n");
1731               RtsFlags.GranFlags.Debug.blockOnFetch = rtsTrue;
1732               /* RtsFlags.GranFlags.Debug |= 0x4; debug non-reschedule-on-fetch */
1733               break;
1734               
1735             case 't':       /* blockOnFetch_sanity; also -bD16 */  
1736               fprintf(stderr,"DEBUG: blockOnFetch_sanity; check for TSO asleep on fetch.\n");
1737               RtsFlags.GranFlags.Debug.blockOnFetch_sanity = rtsTrue;
1738               /* RtsFlags.GranFlags.Debug |= 0x10; debug TSO asleep for fetch  */
1739               break;
1740
1741             case 'S':       /* priSpark; also -bD32 */
1742               fprintf(stderr,"DEBUG: priSpark; priority sparking.\n");
1743               RtsFlags.GranFlags.Debug.priSpark = rtsTrue;
1744               break;
1745
1746             case 's':       /* priSched; also -bD64 */
1747               fprintf(stderr,"DEBUG: priSched; priority scheduling.\n");
1748               RtsFlags.GranFlags.Debug.priSched = rtsTrue;
1749               break;
1750
1751             case 'F':       /* findWork; also -bD128 */
1752               fprintf(stderr,"DEBUG: findWork; searching spark-pools (local & remote), thread queues for work.\n");
1753               RtsFlags.GranFlags.Debug.findWork = rtsTrue;
1754               break;
1755               
1756             case 'g':       /* globalBlock; also -bD256 */
1757               fprintf(stderr,"DEBUG: globalBlock; blocking on remote closures (FETCHMEs etc in GUM).\n");
1758               RtsFlags.GranFlags.Debug.globalBlock = rtsTrue;
1759               break;
1760               
1761             case 'G':       /* pack; also -bD512 */
1762               fprintf(stderr,"DEBUG: pack; routines for (un-)packing graph structures.\n");
1763               RtsFlags.GranFlags.Debug.pack = rtsTrue;
1764               break;
1765               
1766             case 'P':       /* packBuffer; also -bD1024 */
1767               fprintf(stderr,"DEBUG: packBuffer; routines handling pack buffer (GranSim internal!).\n");
1768               RtsFlags.GranFlags.Debug.packBuffer = rtsTrue;
1769               break;
1770               
1771             case 'o':       /* sortedQ; also -bD2048 */
1772               fprintf(stderr,"DEBUG: sortedQ; check whether spark/thread queues are sorted.\n");
1773               RtsFlags.GranFlags.Debug.sortedQ = rtsTrue;
1774               break;
1775               
1776             case 'r':       /* randomSteal; also -bD4096 */
1777               fprintf(stderr,"DEBUG: randomSteal; stealing sparks/threads from random PEs.\n");
1778               RtsFlags.GranFlags.Debug.randomSteal = rtsTrue;
1779               break;
1780               
1781             case 'q':       /* checkSparkQ; also -bD8192 */
1782               fprintf(stderr,"DEBUG: checkSparkQ; check consistency of the spark queues.\n");
1783               RtsFlags.GranFlags.Debug.checkSparkQ = rtsTrue;
1784               break;
1785               
1786             case ':':       /* checkLight; also -bD16384 */
1787               fprintf(stderr,"DEBUG: checkLight; check GranSim-Light setup.\n");
1788               RtsFlags.GranFlags.Debug.checkLight = rtsTrue;
1789               break;
1790               
1791             case 'b':       /* bq; also -bD32768 */
1792               fprintf(stderr,"DEBUG: bq; check blocking queues\n");
1793               RtsFlags.GranFlags.Debug.bq = rtsTrue;
1794               break;
1795               
1796             case 'd':       /* all options turned on */
1797               fprintf(stderr,"DEBUG: all options turned on.\n");
1798               set_GranSim_debug_options(MAX_GRAN_DEBUG_MASK);
1799               /* RtsFlags.GranFlags.Debug |= 0x40; */
1800               break;
1801
1802 /*          case '\0': */
1803 /*            RtsFlags.GranFlags.Debug = 1; */
1804 /*            break; */
1805 #endif
1806
1807           }
1808           break;
1809 #  endif  /* GRAN_CHECK */
1810       default:
1811         bad_option( rts_argv[arg] );
1812         break;
1813       }
1814 }
1815
1816 /*
1817   Interpret n as a binary number masking GranSim debug options and set the 
1818   correxponding option. See gran_debug_opts_strs for explanations of the flags.
1819 */
1820 static void
1821 set_GranSim_debug_options(nat n) {
1822   nat i;
1823
1824   for (i=0; i<=MAX_GRAN_DEBUG_OPTION; i++) 
1825     if ((n>>i)&1) {
1826       fprintf(stderr, gran_debug_opts_strs[i]);
1827       switch (i) {
1828         case 0: RtsFlags.GranFlags.Debug.event_trace   = rtsTrue;  break;
1829         case 1: RtsFlags.GranFlags.Debug.event_stats   = rtsTrue;  break;
1830         case 2: RtsFlags.GranFlags.Debug.bq            = rtsTrue;  break;
1831         case 3: RtsFlags.GranFlags.Debug.pack          = rtsTrue;  break;
1832         case 4: RtsFlags.GranFlags.Debug.checkSparkQ   = rtsTrue;  break;
1833         case 5: RtsFlags.GranFlags.Debug.thunkStealing = rtsTrue;  break;
1834         case 6: RtsFlags.GranFlags.Debug.randomSteal   = rtsTrue;  break;
1835         case 7: RtsFlags.GranFlags.Debug.findWork      = rtsTrue;  break;
1836         case 8: RtsFlags.GranFlags.Debug.unused        = rtsTrue;  break;
1837         case 9: RtsFlags.GranFlags.Debug.pri           = rtsTrue;  break;
1838         case 10: RtsFlags.GranFlags.Debug.checkLight   = rtsTrue;  break;
1839         case 11: RtsFlags.GranFlags.Debug.sortedQ      = rtsTrue;  break;
1840         case 12: RtsFlags.GranFlags.Debug.blockOnFetch = rtsTrue;  break;
1841         case 13: RtsFlags.GranFlags.Debug.packBuffer   = rtsTrue;  break;
1842         case 14: RtsFlags.GranFlags.Debug.blockOnFetch_sanity = rtsTrue;  break;
1843         default: barf("set_GranSim_debug_options: only %d debug options expected");
1844       } /* switch */
1845     } /* if */
1846 }
1847
1848 /*
1849   Print one line explanation for each of the GranSim debug options specified
1850   in the bitmask n.
1851 */
1852 static void
1853 help_GranSim_debug_options(nat n) {
1854   nat i;
1855
1856   for (i=0; i<=MAX_GRAN_DEBUG_OPTION; i++) 
1857     if ((n>>i)&1) 
1858       fprintf(stderr, gran_debug_opts_strs[i]);
1859 }
1860
1861 # elif defined(PAR)
1862
1863 static void
1864 process_par_option(int arg, int *rts_argc, char *rts_argv[], rtsBool *error)
1865 {
1866
1867   if (rts_argv[arg][1] != 'q') { /* All GUM options start with -q */
1868     belch("Warning: GUM option does not start with -q: %s", rts_argv[arg]);
1869     return;
1870   }
1871
1872   /* Communication and task creation cost parameters */
1873   switch(rts_argv[arg][2]) {
1874   case 'e':  /* -qe<n>  ... allow <n> local sparks */
1875     if (rts_argv[arg][3] != '\0') { /* otherwise, stick w/ the default */
1876       RtsFlags.ParFlags.maxLocalSparks
1877         = strtol(rts_argv[arg]+3, (char **) NULL, 10);
1878       
1879       if (RtsFlags.ParFlags.maxLocalSparks <= 0) {
1880         belch("setupRtsFlags: bad value for -e\n");
1881         *error = rtsTrue;
1882       }
1883     }
1884     IF_PAR_DEBUG(verbose,
1885                  belch("-qe<n>: max %d local sparks", 
1886                        RtsFlags.ParFlags.maxLocalSparks));
1887     break;
1888   
1889   case 't':
1890     if (rts_argv[arg][3] != '\0') {
1891       RtsFlags.ParFlags.maxThreads
1892         = strtol(rts_argv[arg]+3, (char **) NULL, 10);
1893     } else {
1894       belch("setupRtsFlags: missing size for -qt\n");
1895       *error = rtsTrue;
1896     }
1897     IF_PAR_DEBUG(verbose,
1898                  belch("-qt<n>: max %d threads", 
1899                        RtsFlags.ParFlags.maxThreads));
1900     break;
1901
1902   case 'f':
1903     if (rts_argv[arg][3] != '\0')
1904       RtsFlags.ParFlags.maxFishes = decode(rts_argv[arg]+3);
1905     else
1906       RtsFlags.ParFlags.maxFishes = MAX_FISHES;
1907     break;
1908     IF_PAR_DEBUG(verbose,
1909                  belch("-qf<n>: max %d fishes sent out at one time", 
1910                        RtsFlags.ParFlags.maxFishes));
1911     break;
1912   
1913   case 'F':
1914     if (rts_argv[arg][3] != '\0') {
1915       RtsFlags.ParFlags.fishDelay
1916         = strtol(rts_argv[arg]+3, (char **) NULL, 10);
1917     } else {
1918       belch("setupRtsFlags: missing fish delay time for -qF\n");
1919       *error = rtsTrue;
1920     }
1921     IF_PAR_DEBUG(verbose,
1922                  belch("-qF<n>: fish delay time %d us", 
1923                        RtsFlags.ParFlags.fishDelay));
1924     break;
1925
1926   case 'O':
1927     RtsFlags.ParFlags.outputDisabled = rtsTrue;
1928     IF_PAR_DEBUG(verbose,
1929                  belch("-qO: output disabled"));
1930     break;
1931   
1932   case 'g': /* -qg<n> ... globalisation scheme */
1933     if (rts_argv[arg][3] != '\0') {
1934       RtsFlags.ParFlags.globalising = decode(rts_argv[arg]+3);
1935     } else {
1936       belch("setupRtsFlags: missing identifier for globalisation scheme (for -qg)\n");
1937       *error = rtsTrue;
1938     }
1939     IF_PAR_DEBUG(verbose,
1940                  belch("-qg<n>: globalisation scheme set to  %d", 
1941                        RtsFlags.ParFlags.globalising));
1942     break;
1943
1944   case 'h': /* -qh<n> ... max number of thunks (except root) in packet */
1945     if (rts_argv[arg][3] != '\0') {
1946       RtsFlags.ParFlags.thunksToPack = decode(rts_argv[arg]+3);
1947     } else {
1948       belch("setupRtsFlags: missing number of thunks per packet (for -qh)\n");
1949       *error = rtsTrue;
1950     }
1951     IF_PAR_DEBUG(verbose,
1952                  belch("-qh<n>: thunks per packet set to %d", 
1953                        RtsFlags.ParFlags.thunksToPack));
1954     break;
1955
1956   case 'P': /* -qP for writing a log file */
1957     //RtsFlags.ParFlags.ParStats.Full = rtsFalse;
1958     /* same encoding as in GranSim after -bP */ 
1959     switch(rts_argv[arg][3]) {
1960     case '\0': RtsFlags.ParFlags.ParStats.Full = rtsTrue;
1961       break; // nothing special, just an ordinary profile
1962     case '0': RtsFlags.ParFlags.ParStats.Suppressed = rtsTrue;
1963         RtsFlags.ParFlags.ParStats.Full = rtsFalse;
1964       break;
1965     case 'b': RtsFlags.ParFlags.ParStats.Binary = rtsTrue;
1966       break;
1967     case 's': RtsFlags.ParFlags.ParStats.Sparks = rtsTrue;
1968       break;
1969       //case 'h': RtsFlags.parFlags.ParStats.Heap = rtsTrue;
1970       //  break;
1971     case 'n': RtsFlags.ParFlags.ParStats.NewLogfile = rtsTrue;
1972       break;
1973     case 'g': 
1974 # if defined(PAR_TICKY)
1975       RtsFlags.ParFlags.ParStats.Global = rtsTrue;
1976 # else 
1977       fprintf(stderr,"-qPg is only possible for a PAR_TICKY RTS, which this is not");
1978       stg_exit(EXIT_FAILURE);
1979 # endif
1980       break;
1981     default: barf("Unknown option -qP%c", rts_argv[arg][2]);
1982     }
1983     IF_PAR_DEBUG(verbose,
1984                  belch("(-qP) writing to log-file (RtsFlags.ParFlags.ParStats.Full=%s)",
1985                        (RtsFlags.ParFlags.ParStats.Full ? "rtsTrue" : "rtsFalse")));
1986     break;
1987   
1988   case 'Q': /* -qQ<n> ... set pack buffer size to <n> */
1989     if (rts_argv[arg][3] != '\0') {
1990       RtsFlags.ParFlags.packBufferSize = decode(rts_argv[arg]+3);
1991     } else {
1992       belch("setupRtsFlags: missing size of PackBuffer (for -qQ)\n");
1993       *error = rtsTrue;
1994     }
1995     IF_PAR_DEBUG(verbose,
1996                  belch("-qQ<n>: pack buffer size set to %d", 
1997                        RtsFlags.ParFlags.packBufferSize));
1998     break;
1999
2000   case 'R':
2001     RtsFlags.ParFlags.doFairScheduling = rtsTrue;
2002     IF_PAR_DEBUG(verbose,
2003                  belch("-qR: fair-ish scheduling"));
2004     break;
2005   
2006 # if defined(DEBUG)  
2007   case 'w':
2008     if (rts_argv[arg][3] != '\0') {
2009       RtsFlags.ParFlags.wait
2010         = strtol(rts_argv[arg]+3, (char **) NULL, 10);
2011     } else {
2012       RtsFlags.ParFlags.wait = 1000;
2013     }
2014     IF_PAR_DEBUG(verbose,
2015                  belch("-qw<n>: length of wait loop after synchr before reduction: %d", 
2016                        RtsFlags.ParFlags.wait));
2017     break;
2018
2019   case 'D':  /* -qD ... all the debugging options */
2020     if (isdigit(rts_argv[arg][3])) {/* Set all debugging options in one */
2021       /* hack warning: interpret the flags as a binary number */
2022       nat n = decode(rts_argv[arg]+3);
2023       set_par_debug_options(n);
2024     } else {
2025       nat i;
2026       for (i=0; i<=MAX_PAR_DEBUG_OPTION; i++) 
2027         if (rts_argv[arg][3] == par_debug_opts_flags[i])
2028           break;
2029         
2030       if (i==MAX_PAR_DEBUG_OPTION+1) {
2031         fprintf(stderr, "Valid GUM debug options are:\n");
2032         help_par_debug_options(MAX_PAR_DEBUG_MASK);
2033         bad_option( rts_argv[arg] );
2034       } else { // flag found; now set it
2035         set_par_debug_options(PAR_DEBUG_MASK(i));  // 2^i
2036       }
2037     }
2038     break;
2039 # endif
2040   default:
2041     belch("Unknown option -q%c (%d opts in total)", 
2042           rts_argv[arg][2], *rts_argc);
2043     break;
2044   } /* switch */
2045 }
2046
2047 /*
2048   Interpret n as a binary number masking Par debug options and set the 
2049   correxponding option. See par_debug_opts_strs for explanations of the flags.
2050 */
2051 static void
2052 set_par_debug_options(nat n) {
2053   nat i;
2054
2055   for (i=0; i<=MAX_PAR_DEBUG_OPTION; i++) 
2056     if ((n>>i)&1) {
2057       fprintf(stderr, par_debug_opts_strs[i]);
2058       switch (i) {
2059         case 0: RtsFlags.ParFlags.Debug.verbose       = rtsTrue;  break;
2060         case 1: RtsFlags.ParFlags.Debug.bq            = rtsTrue;  break;
2061         case 2: RtsFlags.ParFlags.Debug.schedule      = rtsTrue;  break;
2062         case 3: RtsFlags.ParFlags.Debug.free          = rtsTrue;  break;
2063         case 4: RtsFlags.ParFlags.Debug.resume        = rtsTrue;  break;
2064         case 5: RtsFlags.ParFlags.Debug.weight        = rtsTrue;  break;
2065         case 6: RtsFlags.ParFlags.Debug.fetch         = rtsTrue;  break;
2066           //case 7: RtsFlags.ParFlags.Debug.ack           = rtsTrue;  break;
2067         case 7: RtsFlags.ParFlags.Debug.fish          = rtsTrue;  break;
2068         case 8: RtsFlags.ParFlags.Debug.tables        = rtsTrue;  break;
2069         case 9: RtsFlags.ParFlags.Debug.packet        = rtsTrue;  break;
2070         case 10: RtsFlags.ParFlags.Debug.pack         = rtsTrue;  break;
2071         case 11: RtsFlags.ParFlags.Debug.paranoia     = rtsTrue;  break;
2072         default: barf("set_par_debug_options: only %d debug options expected",
2073                       MAX_PAR_DEBUG_OPTION);
2074       } /* switch */
2075     } /* if */
2076 }
2077
2078 /*
2079   Print one line explanation for each of the GranSim debug options specified
2080   in the bitmask n.
2081 */
2082 static void
2083 help_par_debug_options(nat n) {
2084   nat i;
2085
2086   for (i=0; i<=MAX_PAR_DEBUG_OPTION; i++) 
2087     if ((n>>i)&1) 
2088       fprintf(stderr, par_debug_opts_strs[i]);
2089 }
2090
2091 #endif /* PAR */
2092
2093 //@node Aux fcts,  , GranSim specific options
2094 //@subsection Aux fcts
2095
2096 static FILE *           /* return NULL on error */
2097 open_stats_file (
2098     I_ arg,
2099     int argc, char *argv[],
2100     int rts_argc, char *rts_argv[],
2101     const char *FILENAME_FMT)
2102 {
2103     FILE *f = NULL;
2104
2105     if (strequal(rts_argv[arg]+2, "stderr")) /* use real stderr */
2106         f = stderr;
2107     else if (rts_argv[arg][2] != '\0')      /* stats file specified */
2108         f = fopen(rts_argv[arg]+2,"w");
2109     else {
2110         char stats_filename[STATS_FILENAME_MAXLEN]; /* default <program>.<ext> */
2111         sprintf(stats_filename, FILENAME_FMT, argv[0]);
2112         f = fopen(stats_filename,"w");
2113     }
2114     if (f == NULL) {
2115         fprintf(stderr, "Can't open stats file %s\n", rts_argv[arg]+2);
2116     } else {
2117         /* Write argv and rtsv into start of stats file */
2118         I_ count;
2119         for(count = 0; count < argc; count++)
2120             fprintf(f, "%s ", argv[count]);
2121         fprintf(f, "+RTS ");
2122         for(count = 0; count < rts_argc; count++)
2123             fprintf(f, "%s ", rts_argv[count]);
2124         fprintf(f, "\n");
2125     }
2126
2127     return(f);
2128 }
2129
2130 static I_
2131 decode(const char *s)
2132 {
2133     I_ c;
2134     StgDouble m;
2135
2136     if (!*s)
2137         return 0;
2138
2139     m = atof(s);
2140     c = s[strlen(s)-1];
2141
2142     if (c == 'g' || c == 'G')
2143         m *= 1000*1000*1000;    /* UNchecked! */
2144     else if (c == 'm' || c == 'M')
2145         m *= 1000*1000;                 /* We do not use powers of 2 (1024) */
2146     else if (c == 'k' || c == 'K')      /* to avoid possible bad effects on */
2147         m *= 1000;                      /* a direct-mapped cache.           */ 
2148     else if (c == 'w' || c == 'W')
2149         m *= sizeof(W_);
2150
2151     return (I_)m;
2152 }
2153
2154 static void
2155 bad_option(const char *s)
2156 {
2157   prog_belch("bad RTS option: %s", s);
2158   stg_exit(EXIT_FAILURE);
2159 }