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