[project @ 1996-07-19 18:36:04 by partain]
[ghc-hetmet.git] / ghc / runtime / main / RtsFlags.lc
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1995
3 %
4 \section{Runtime-system runtime flags}
5
6 Everything to do with RTS runtime flags, including RTS parameters
7 that can be set by them, either directly or indirectly.
8
9 @rtsFlags.lh@ defines the data structure that holds all of them.
10
11 \begin{code}
12 #include "rtsdefs.h"
13
14 struct RTS_FLAGS RTSflags; /* actually declare the data structure */
15 struct ALL_FLAGS AllFlags;
16
17 /* some fwd decls */
18 static I_     decode(const char *);
19 static void   bad_option(const char *);
20 static FILE * open_stats_file (I_ arg,
21                 int argc, char *argv[], int rts_argc, char *rts_argv[],
22                 const char *FILENAME_FMT);
23 #ifdef GRAN
24 static void   process_gran_option(int arg, 
25                 int *rts_argc, char *rts_argv[], rtsBool *error);
26 #endif
27
28 /* extern decls */
29 long strtol  PROTO((const char *, char **, int));
30 \end{code}
31
32 %************************************************************************
33 %*                                                                      *
34 \subsection{Initial default values for @RTSFlags@}
35 %*                                                                      *
36 %************************************************************************
37
38 \begin{code}
39 void
40 initRtsFlagsDefaults (STG_NO_ARGS)
41 {
42     RTSflags.GcFlags.statsFile          = NULL;
43     RTSflags.GcFlags.giveStats          = NO_GC_STATS;
44
45     RTSflags.GcFlags.stksSize           = 0x10002;  /* 2^16 = 16Kwords = 64Kbytes */
46     RTSflags.GcFlags.heapSize           = 0x100002; /* 2^20 =  1Mwords =  4Mbytes  */
47     RTSflags.GcFlags.allocAreaSize      = 0x4002;   /* 2^14 = 16Kwords = 64Kbytes;
48                                                        plus 2 cache-friendly words */
49     RTSflags.GcFlags.allocAreaSizeGiven = rtsFalse;
50     RTSflags.GcFlags.specifiedOldGenSize= 0;    /* means: use all heap available */
51     RTSflags.GcFlags.pcFreeHeap         = 3;    /* 3% */
52     /* minAllocAreaSize is derived; set in initSM,
53        after we know pcFreeHeap and heapSize */
54
55     RTSflags.GcFlags.force2s            = rtsFalse;
56     RTSflags.GcFlags.forceGC            = rtsFalse;
57     RTSflags.GcFlags.forcingInterval    = 5000000; /* 5MB (or words?) */
58     RTSflags.GcFlags.ringBell           = rtsFalse;
59     RTSflags.GcFlags.trace              = 0; /* not turned on */
60
61     RTSflags.GcFlags.lazyBlackHoling    = rtsTrue;
62     RTSflags.GcFlags.doSelectorsAtGC    = rtsTrue;
63     RTSflags.GcFlags.squeezeUpdFrames   = rtsTrue;
64
65 #if defined(PROFILING) || defined(PAR)
66     RTSflags.CcFlags.doCostCentres      = 0;
67     RTSflags.CcFlags.sortBy             = SORTCC_TIME;
68
69     /* "ctxtSwitchTicks", "profilerTicks", & "msecsPerTick" are
70         derived info, so they are set after ctxtSwitchTime has been
71         determined.
72     */
73 #endif /* PROFILING or PAR */
74
75 #ifdef PROFILING
76     RTSflags.ProfFlags.doHeapProfile = rtsFalse;
77
78     RTSflags.ProfFlags.ccSelector    = NULL;
79     RTSflags.ProfFlags.modSelector   = NULL;
80     RTSflags.ProfFlags.grpSelector   = NULL;
81     RTSflags.ProfFlags.descrSelector = NULL;
82     RTSflags.ProfFlags.typeSelector  = NULL;
83     RTSflags.ProfFlags.kindSelector  = NULL;
84 #endif /* PROFILING */
85
86 #ifdef CONCURRENT
87     RTSflags.ConcFlags.ctxtSwitchTime   = CS_MIN_MILLISECS;  /* In milliseconds */
88     RTSflags.ConcFlags.maxThreads       = 32;
89     RTSflags.ConcFlags.stkChunkSize     = 1024;
90     RTSflags.ConcFlags.maxLocalSparks   = 500;
91 #endif /* CONCURRENT */
92
93 #ifdef PAR
94     RTSflags.ParFlags.parallelStats     = rtsFalse;
95     RTSflags.ParFlags.granSimStats      = rtsFalse;
96     RTSflags.ParFlags.granSimStats_Binary = rtsFalse;
97
98     RTSflags.ParFlags.outputDisabled    = rtsFalse;
99
100     RTSflags.ParFlags.packBufferSize    = 1024;
101 #endif /* PAR */
102
103 #ifdef GRAN
104     RTSflags.GranFlags.granSimStats     = rtsFalse;
105     RTSflags.GranFlags.granSimStats_suppressed  = rtsFalse;
106     RTSflags.GranFlags.granSimStats_Binary = rtsFalse;
107     RTSflags.GranFlags.granSimStats_Sparks = rtsFalse;
108     RTSflags.GranFlags.granSimStats_Heap = rtsFalse;
109     RTSflags.GranFlags.labelling        = rtsFalse;
110     RTSflags.GranFlags.packBufferSize   = 1024;
111     RTSflags.GranFlags.packBufferSize_internal = GRANSIM_DEFAULT_PACK_BUFFER_SIZE;
112
113     RTSflags.GranFlags.proc  = MAX_PROC;
114     RTSflags.GranFlags.max_fishes = MAX_FISHES;
115     RTSflags.GranFlags.time_slice = GRAN_TIME_SLICE;
116     RTSflags.GranFlags.Light = rtsFalse;
117
118     RTSflags.GranFlags.gran_latency =             LATENCY;          
119     RTSflags.GranFlags.gran_additional_latency =  ADDITIONAL_LATENCY; 
120     RTSflags.GranFlags.gran_fetchtime =           FETCHTIME; 
121     RTSflags.GranFlags.gran_lunblocktime =        LOCALUNBLOCKTIME; 
122     RTSflags.GranFlags.gran_gunblocktime =        GLOBALUNBLOCKTIME;
123     RTSflags.GranFlags.gran_mpacktime =           MSGPACKTIME;      
124     RTSflags.GranFlags.gran_munpacktime =         MSGUNPACKTIME;
125     RTSflags.GranFlags.gran_mtidytime =           MSGTIDYTIME;
126
127     RTSflags.GranFlags.gran_threadcreatetime =         THREADCREATETIME;
128     RTSflags.GranFlags.gran_threadqueuetime =          THREADQUEUETIME;
129     RTSflags.GranFlags.gran_threaddescheduletime =     THREADDESCHEDULETIME;
130     RTSflags.GranFlags.gran_threadscheduletime =       THREADSCHEDULETIME;
131     RTSflags.GranFlags.gran_threadcontextswitchtime =  THREADCONTEXTSWITCHTIME;
132
133     RTSflags.GranFlags.gran_arith_cost =         ARITH_COST;       
134     RTSflags.GranFlags.gran_branch_cost =        BRANCH_COST; 
135     RTSflags.GranFlags.gran_load_cost =          LOAD_COST;        
136     RTSflags.GranFlags.gran_store_cost =         STORE_COST; 
137     RTSflags.GranFlags.gran_float_cost =         FLOAT_COST;       
138
139     RTSflags.GranFlags.gran_heapalloc_cost =     HEAPALLOC_COST;
140
141     RTSflags.GranFlags.gran_pri_spark_overhead = PRI_SPARK_OVERHEAD;        
142     RTSflags.GranFlags.gran_pri_sched_overhead = PRI_SCHED_OVERHEAD;        
143
144     RTSflags.GranFlags.DoFairSchedule = rtsFalse;             
145     RTSflags.GranFlags.DoReScheduleOnFetch = rtsFalse;        
146     RTSflags.GranFlags.DoStealThreadsFirst = rtsFalse;        
147     RTSflags.GranFlags.SimplifiedFetch = rtsFalse;            
148     RTSflags.GranFlags.DoAlwaysCreateThreads = rtsFalse;      
149     RTSflags.GranFlags.DoGUMMFetching = rtsFalse;             
150     RTSflags.GranFlags.DoThreadMigration = rtsFalse;          
151     RTSflags.GranFlags.FetchStrategy = 2;                     
152     RTSflags.GranFlags.PreferSparksOfLocalNodes = rtsFalse;   
153     RTSflags.GranFlags.DoPrioritySparking = rtsFalse;         
154     RTSflags.GranFlags.DoPriorityScheduling = rtsFalse;       
155     RTSflags.GranFlags.SparkPriority = 0;
156     RTSflags.GranFlags.SparkPriority2 = 0; 
157     RTSflags.GranFlags.RandomPriorities = rtsFalse;           
158     RTSflags.GranFlags.InversePriorities = rtsFalse;          
159     RTSflags.GranFlags.IgnorePriorities = rtsFalse;           
160     RTSflags.GranFlags.ThunksToPack = 0;                      
161     RTSflags.GranFlags.RandomSteal = rtsTrue;
162     RTSflags.GranFlags.NoForward = rtsFalse;
163     RTSflags.GranFlags.PrintFetchMisses = rtsFalse;
164
165     RTSflags.GranFlags.debug = 0x0;
166     RTSflags.GranFlags.event_trace = rtsFalse;
167     RTSflags.GranFlags.event_trace_all = rtsFalse;
168 #endif
169
170 #ifdef TICKY_TICKY
171     RTSflags.TickyFlags.showTickyStats  = rtsFalse;
172     RTSflags.TickyFlags.tickyFile       = NULL;
173
174     AllFlags.doUpdEntryCounts           = rtsTrue; /*ToDo:move? */
175 #endif
176 }
177 \end{code}
178
179 %************************************************************************
180 %*                                                                      *
181 \subsection{Usage message for runtime-system (RTS) flags}
182 %*                                                                      *
183 %************************************************************************
184
185 \begin{code}
186 static const char *
187 usage_text[] = {
188 "",
189 "Usage: <prog> <args> [+RTS <rtsopts> | -RTS <args>] ... --RTS <args>",
190 "",
191 "   +RTS    Indicates run time system options follow",
192 "   -RTS    Indicates program arguments follow",
193 "  --RTS    Indicates that ALL subsequent arguments will be given to the",
194 "           program (including any of these RTS flags)",
195 "",
196 "The following run time system options are available:",
197 "",
198 "  -? -f    Prints this message and exits; the program is not executed",
199 "",
200 "  -K<size> Sets the stack size (default 64k)    Egs: -K32k   -K512k",
201 "  -H<size> Sets the heap size  (default 4M)          -H512k  -H16M",
202 "  -s<file> Summary GC statistics   (default file: <program>.stat)",
203 "  -S<file> Detailed GC statistics  (with -Sstderr going to stderr)",
204 "",
205 #if defined(GCap)
206 "  -M<n>%   Sets minimum size of alloc area as % of heap (default 3%)",
207 "  -A<size> Fixes size of alloc area, overriding any minimum (-A gives 64k)",
208 "  -G<size> Fixes size of major generation (default is dynamic threshold)",
209 "  -F2s     Forces program compiled for Appel gc to use 2s collection",
210 #else
211 # if defined(GCgn)
212 "  -A<size> Specifies size of alloc area (default 64k)",
213 "  -G<size> Fixes size of major generation (default is available heap)",
214 "  -F2s     Forces program compiled for Gen gc to use 2s collection",
215 # else
216 "  -M<n>%   Minimum % of heap which must be available (default 3%)",
217 "  -A<size> Fixes size of heap area allocated between GCs (-A gives 64k)",
218 # endif
219 #endif
220 "  -j<size> Forces major GC at every <size> bytes allocated",
221 #if defined(GCdu)
222 "  -u<percent> Fixes residency threshold at which mode switches (range 0.0..0.95)",
223 #endif
224 "",
225 "  -N       No black-holing during GC (for use when a signal handler is present)",
226 "  -Z       Don't squeeze out update frames on stack overflow",
227 "  -B       Sound the bell at the start of each (major) garbage collection",
228 #if defined(PROFILING) || defined(PAR)
229 "",
230 "  -p<sort> Produce cost centre time profile  (output file <program>.prof)",
231 "             sort: T = time (default), A = alloc, C = cost centre label",
232 "  -P<sort> Produce serial time profile (output file <program>.time)",
233 "             and a -p profile with detailed tick/alloc info",
234 # if defined(PROFILING)
235 "",
236 "  -h<break-down> Heap residency profile      (output file <program>.hp)",
237 "     break-down: C = cost centre (default), M = module, G = group",
238 "                 D = closure description, Y = type description",
239 "                 T<ints>,<start> = time closure created",
240 "                    ints:  no. of interval bands plotted (default 18)",
241 "                    start: seconds after which intervals start (default 0.0)",
242 "  A subset of closures may be selected by the attached cost centre using:",
243 "    -c{mod:lab,mod:lab...}, specific module:label cost centre(s)",
244 "    -m{mod,mod...} all cost centres from the specified modules(s)",
245 "    -g{grp,grp...} all cost centres from the specified group(s)",
246 "  Selections can also be made by description, type, kind and age:",
247 "    -d{des,des...} closures with specified closure descriptions",
248 "    -y{typ,typ...} closures with specified type descriptions",
249 "    -k{knd,knd...} closures of the specified kinds",
250 "    -a<age>        closures which survived <age> complete intervals",
251 "  The selection logic used is summarised as follows:",
252 "    ([-c] or [-m] or [-g]) and ([-d] or [-y] or [-k]) and [-a]",
253 "    where an option is true if not specified",
254 # endif
255 "",
256 "  -z<tbl><size>  set hash table <size> for <tbl> (C, M, G, D or Y)",
257 "",
258 "  -i<secs> Number of seconds in a profiling interval (default 1.0):",
259 "           heap profile (-h) and/or serial time profile (-P) frequency",
260 #endif /* PROFILING or PAR */
261 "",
262 #if defined(TICKY_TICKY)
263 "  -r<file>  Produce reduction profiling statistics (with -rstderr for stderr)",
264 "",
265 #endif
266 "  -T<level> Trace garbage collection execution (debugging)",
267 #ifdef CONCURRENT
268 "",
269 # ifdef PAR
270 "  -N<n>     Use <n> PVMish processors in parallel (default: 2)",
271 /* NB: the -N<n> is implemented by the driver!! */
272 # endif
273 "  -C<secs>  Context-switch interval in seconds",
274 "                (0 or no argument means switch as often as possible)",
275 "                the default is .01 sec; resolution is .01 sec",
276 "  -e<size>        Size of spark pools (default 100)",
277 # ifdef PAR
278 "  -q        Enable activity profile (output files in ~/<program>*.gr)",
279 "  -qb       Enable binary activity profile (output file /tmp/<program>.gb)",
280 "  -Q<size>  Set pack-buffer size (default: 1024)",
281 # else
282 "  -q[v]     Enable quasi-parallel profile (output file <program>.qp)",
283 # endif
284 "  -t<num>   Set maximum number of advisory threads per PE (default 32)",
285 "  -o<num>   Set stack chunk size (default 1024)",
286 # ifdef PAR
287 "  -d        Turn on PVM-ish debugging",
288 "  -O        Disable output for performance measurement",
289 # endif /* PAR */
290 # ifdef GRAN  /* ToDo: fill in decent Docu here */
291 "  -b...     All GranSim options start with -b, and there are many of them",
292 # endif
293 #endif /* CONCURRENT */
294 "",
295 "Other RTS options may be available for programs compiled a different way.",
296 "The GHC User's Guide has full details.",
297 "",
298 0
299 };
300 \end{code}
301
302 %************************************************************************
303 %*                                                                      *
304 \subsection{Processing command-line arguments to set @RTSFlags@}
305 %*                                                                      *
306 %************************************************************************
307
308 \begin{code}
309 #define RTS 1
310 #define PGM 0
311
312 #ifndef atof
313 extern double atof();
314 /* no proto because some machines use const and some do not */
315 #endif
316
317 static __inline__ rtsBool
318 strequal(const char *a, const char * b)
319 {
320     return(strcmp(a, b) == 0);
321 }
322
323 void
324 setupRtsFlags(int *argc, char *argv[], int *rts_argc, char *rts_argv[])
325 {
326     rtsBool error = rtsFalse;
327     I_ mode;
328     I_ arg, total_arg;
329     char *last_slash;
330
331     /* Remove directory from argv[0] -- default files in current directory */
332
333     if ((last_slash = (char *) strrchr(argv[0], '/')) != NULL)
334         strcpy(argv[0], last_slash+1);
335
336     /* Split arguments (argv) into PGM (argv) and RTS (rts_argv) parts */
337     /*   argv[0] must be PGM argument -- leave in argv                 */
338
339     total_arg = *argc;
340     arg = 1;
341
342     *argc = 1;
343     *rts_argc = 0;
344
345     for (mode = PGM; arg < total_arg && ! strequal("--RTS", argv[arg]); arg++) {
346         if (strequal("+RTS", argv[arg])) {
347             mode = RTS;
348         }
349         else if (strequal("-RTS", argv[arg])) {
350             mode = PGM;
351         }
352         else if (mode == RTS && *rts_argc < MAX_RTS_ARGS-1) {
353             rts_argv[(*rts_argc)++] = argv[arg];
354         }
355         else if (mode == PGM) {
356             argv[(*argc)++] = argv[arg];
357         }
358         else {
359             fflush(stdout);
360             fprintf(stderr, "setupRtsFlags: Too many RTS arguments (max %d)\n",
361                     MAX_RTS_ARGS-1);
362             EXIT(EXIT_FAILURE);
363         }
364     }
365     if (arg < total_arg) {
366         /* arg must be --RTS; process remaining program arguments */
367         while (++arg < total_arg) {
368             argv[(*argc)++] = argv[arg];
369         }
370     }
371     argv[*argc] = (char *) 0;
372     rts_argv[*rts_argc] = (char *) 0;
373
374     /* Process RTS (rts_argv) part: mainly to determine statsfile */
375
376     for (arg = 0; arg < *rts_argc; arg++) {
377         if (rts_argv[arg][0] != '-') {
378             fflush(stdout);
379             fprintf(stderr, "setupRtsFlags: Unexpected RTS argument: %s\n",
380                     rts_argv[arg]);
381             error = rtsTrue;
382
383         } else {
384             switch(rts_argv[arg][1]) {
385
386               /* process: general args, then PROFILING-only ones,
387                  then CONCURRENT-only, PARallel-only, GRAN-only,
388                  TICKY-only (same order as defined in RtsFlags.lh);
389                  within those groups, mostly in case-insensitive
390                  alphabetical order.
391               */
392
393 #ifdef TICKY_TICKY
394 # define TICKY_BUILD_ONLY(x) x
395 #else
396 # define TICKY_BUILD_ONLY(x) \
397 fprintf(stderr, "setupRtsFlags: GHC not built for: ticky-ticky stats\n"); \
398 error = rtsTrue;
399 #endif
400
401 #if (defined(PROFILING) || defined(PAR))
402 # define COST_CENTRE_USING_BUILD_ONLY(x) x
403 #else
404 # define COST_CENTRE_USING_BUILD_ONLY(x) \
405 fprintf(stderr, "setupRtsFlags: GHC not built for: -prof or -parallel\n"); \
406 error = rtsTrue;
407 #endif
408
409 #ifdef PROFILING
410 # define PROFILING_BUILD_ONLY(x)   x
411 #else
412 # define PROFILING_BUILD_ONLY(x) \
413 fprintf(stderr, "setupRtsFlags: GHC not built for: -prof\n"); \
414 error = rtsTrue;
415 #endif
416
417 #ifdef CONCURRENT
418 # define CONCURRENT_BUILD_ONLY(x)  x
419 #else
420 # define CONCURRENT_BUILD_ONLY(x) \
421 fprintf(stderr, "setupRtsFlags: GHC not built for: -concurrent\n"); \
422 error = rtsTrue;
423 #endif
424
425 #ifdef PAR
426 # define PAR_BUILD_ONLY(x)      x
427 #else
428 # define PAR_BUILD_ONLY(x) \
429 fprintf(stderr, "setupRtsFlags: GHC not built for: -parallel\n"); \
430 error = rtsTrue;
431 #endif
432
433 #ifdef GRAN
434 # define GRAN_BUILD_ONLY(x)     x
435 #else
436 # define GRAN_BUILD_ONLY(x) \
437 fprintf(stderr, "setupRtsFlags: GHC not built for: -gransim\n"); \
438 error = rtsTrue;
439 #endif
440
441               /* =========== GENERAL ========================== */
442               case '?':
443               case 'f':
444                 error = rtsTrue;
445                 break;
446
447               case 'A':
448                 RTSflags.GcFlags.allocAreaSize
449                   = decode(rts_argv[arg]+2) / sizeof(W_);
450                 RTSflags.GcFlags.allocAreaSizeGiven = rtsTrue;
451                 break;
452
453               case 'B':
454                 RTSflags.GcFlags.ringBell = rtsTrue;
455                 break;
456
457               case 'F':
458                 if (strequal(rts_argv[arg]+2, "2s")) {
459                     RTSflags.GcFlags.force2s = rtsTrue;
460                 } else {
461                     bad_option( rts_argv[arg] );
462                 }
463                 break;
464
465               case 'G':
466                 RTSflags.GcFlags.specifiedOldGenSize
467                   = decode(rts_argv[arg]+2) / sizeof(W_);
468                 break;
469
470               case 'K':
471                 RTSflags.GcFlags.stksSize = decode(rts_argv[arg]+2) / sizeof(W_);
472
473                 if (RTSflags.GcFlags.stksSize == 0) bad_option( rts_argv[arg] );
474                 break;
475
476               case 'H':
477                 RTSflags.GcFlags.heapSize = decode(rts_argv[arg]+2) / sizeof(W_);
478                 /* user give size in *bytes* but "heapSize" is in *words* */
479
480                 if (RTSflags.GcFlags.heapSize <= 0) bad_option(rts_argv[arg]);
481                 break;
482
483               case 'j': /* force GC option */
484                 RTSflags.GcFlags.forceGC = rtsTrue;
485                 if (rts_argv[arg][2]) {
486                     RTSflags.GcFlags.forcingInterval
487                         = decode(rts_argv[arg]+2) / sizeof(W_);
488                 }
489                 break;
490
491               case 'M':
492                 RTSflags.GcFlags.pcFreeHeap = atof(rts_argv[arg]+2);
493
494                 if (RTSflags.GcFlags.pcFreeHeap < 0 || RTSflags.GcFlags.pcFreeHeap > 100)
495                     bad_option( rts_argv[arg] );
496                 break;
497
498               case 'N':
499                 RTSflags.GcFlags.lazyBlackHoling = rtsFalse;
500                 break;
501
502               case 'n':
503                 RTSflags.GcFlags.doSelectorsAtGC = rtsFalse;
504                 break;
505
506               case 'S': /* NB: no difference at present ! */
507               case 's':
508                 RTSflags.GcFlags.giveStats ++; /* will be VERBOSE_GC_STATS */
509 #ifdef PAR
510                 /* Opening all those files would almost certainly fail... */
511                 RTSflags.ParFlags.parallelStats = rtsTrue;
512                 RTSflags.GcFlags.statsFile = stderr; /* temporary; ToDo: rm */
513 #else
514                 RTSflags.GcFlags.statsFile
515                   = open_stats_file(arg, *argc, argv,
516                         *rts_argc, rts_argv, STAT_FILENAME_FMT);
517
518                 if (RTSflags.GcFlags.statsFile == NULL) error = rtsTrue;
519 #endif
520                 break;
521
522               case 'T':
523                 if (rts_argv[arg][2] != '\0')
524                     RTSflags.GcFlags.trace
525                       = (W_) strtol(rts_argv[arg]+2, (char **)NULL, 0);
526                 else
527                     RTSflags.GcFlags.trace = 1; /* slightly weird; why, really? */
528                 break;
529
530               case 'Z':
531                 RTSflags.GcFlags.squeezeUpdFrames = rtsFalse;
532                 break;
533
534               /* =========== PROFILING ========================== */
535
536               case 'P': /* detailed cost centre profiling (time/alloc) */
537                 COST_CENTRE_USING_BUILD_ONLY(
538                 RTSflags.CcFlags.doCostCentres++;
539                 )
540               case 'p': /* cost centre profiling (time/alloc) */
541                 COST_CENTRE_USING_BUILD_ONLY(
542                 RTSflags.CcFlags.doCostCentres++;
543
544                 switch (rts_argv[arg][2]) {
545                   case SORTCC_LABEL:
546                   case SORTCC_TIME:
547                   case SORTCC_ALLOC:
548                         RTSflags.CcFlags.sortBy = rts_argv[arg][2];
549                     break;
550                   default:
551                     fprintf(stderr, "Invalid profiling sort option %s\n", rts_argv[arg]);
552                     error = rtsTrue;
553                 }
554                 ) break;
555
556               case 'i': /* serial profiling -- initial timer interval */
557                 COST_CENTRE_USING_BUILD_ONLY(
558                 interval_ticks = (I_) ((atof(rts_argv[arg]+2) * TICK_FREQUENCY));
559                 if (interval_ticks <= 0)
560                     interval_ticks = 1;
561                 ) break;
562
563               case 'h': /* serial heap profile */
564                 PROFILING_BUILD_ONLY(
565                 switch (rts_argv[arg][2]) {
566                   case '\0':
567                   case CCchar:
568                     RTSflags.ProfFlags.doHeapProfile = HEAP_BY_CC;
569                     break;
570                   case MODchar:
571                     RTSflags.ProfFlags.doHeapProfile = HEAP_BY_MOD;
572                     break;
573                   case GRPchar:
574                     RTSflags.ProfFlags.doHeapProfile = HEAP_BY_GRP;
575                     break;
576                   case DESCRchar:
577                     RTSflags.ProfFlags.doHeapProfile = HEAP_BY_DESCR;
578                     break;
579                   case TYPEchar:
580                     RTSflags.ProfFlags.doHeapProfile = HEAP_BY_TYPE;
581                     break;
582                   case TIMEchar:
583                     RTSflags.ProfFlags.doHeapProfile = HEAP_BY_TIME;
584                     if (rts_argv[arg][3]) {
585                         char *start_str = strchr(rts_argv[arg]+3, ',');
586                         I_ intervals;
587                         if (start_str) *start_str = '\0';
588
589                         if ((intervals = decode(rts_argv[arg]+3)) != 0) {
590                             time_intervals = (hash_t) intervals;
591                             /* ToDo: and what if it *is* zero intervals??? */
592                         }
593                         if (start_str) {
594                             earlier_ticks = (I_)((atof(start_str + 1) * TICK_FREQUENCY));
595                         }
596                     }
597                     break;
598                   default:
599                     fprintf(stderr, "Invalid heap profile option: %s\n",
600                             rts_argv[arg]);
601                     error = rtsTrue;
602                 }
603                 ) break;
604
605               case 'z': /* size of index tables */
606                 PROFILING_BUILD_ONLY(
607                 switch (rts_argv[arg][2]) {
608                   case CCchar:
609                     max_cc_no = (hash_t) decode(rts_argv[arg]+3);
610                     if (max_cc_no == 0) {
611                         fprintf(stderr, "Bad number of cost centres %s\n", rts_argv[arg]);
612                         error = rtsTrue;
613                     }
614                     break;
615                   case MODchar:
616                     max_mod_no = (hash_t) decode(rts_argv[arg]+3);
617                     if (max_mod_no == 0) {
618                         fprintf(stderr, "Bad number of modules %s\n", rts_argv[arg]);
619                         error = rtsTrue;
620                     }
621                     break;
622                   case GRPchar:
623                     max_grp_no = (hash_t) decode(rts_argv[arg]+3);
624                     if (max_grp_no == 0) {
625                         fprintf(stderr, "Bad number of groups %s\n", rts_argv[arg]);
626                         error = rtsTrue;
627                     }
628                     break;
629                   case DESCRchar:
630                     max_descr_no = (hash_t) decode(rts_argv[arg]+3);
631                     if (max_descr_no == 0) {
632                         fprintf(stderr, "Bad number of closure descriptions %s\n", rts_argv[arg]);
633                         error = rtsTrue;
634                     }
635                     break;
636                   case TYPEchar:
637                     max_type_no = (hash_t) decode(rts_argv[arg]+3);
638                     if (max_type_no == 0) {
639                         fprintf(stderr, "Bad number of type descriptions %s\n", rts_argv[arg]);
640                         error = rtsTrue;
641                     }
642                     break;
643                   default:
644                     fprintf(stderr, "Invalid index table size option: %s\n",
645                             rts_argv[arg]);
646                     error = rtsTrue;
647                 }
648                 ) break;
649
650               case 'c': /* cost centre label select */
651               case 'm': /* cost centre module select */
652               case 'g': /* cost centre group select */
653               case 'd': /* closure descr select */
654               case 'y': /* closure type select */
655               case 'k': /* closure kind select */
656                 PROFILING_BUILD_ONLY(
657                 {char *left  = strchr(rts_argv[arg], '{');
658                  char *right = strrchr(rts_argv[arg], '}');
659
660                 if (! left || ! right ||
661                         strrchr(rts_argv[arg], '{') != left ||
662                          strchr(rts_argv[arg], '}') != right) {
663                     fprintf(stderr, "Invalid heap profiling selection bracketing\n   %s\n", rts_argv[arg]);
664                     error = rtsTrue;
665                 } else {
666                     *right = '\0';
667                     switch (rts_argv[arg][1]) {
668                       case 'c': /* cost centre label select */
669                         RTSflags.ProfFlags.ccSelector = left + 1;
670                         break;
671                       case 'm': /* cost centre module select */
672                         RTSflags.ProfFlags.modSelector = left + 1;
673                         break;
674                       case 'g': /* cost centre group select */
675                         RTSflags.ProfFlags.grpSelector = left + 1;
676                         break;
677                       case 'd': /* closure descr select */
678                         RTSflags.ProfFlags.descrSelector = left + 1;
679                         break;
680                       case 't': /* closure type select */
681                         RTSflags.ProfFlags.typeSelector = left + 1;
682                         break;
683                       case 'k': /* closure kind select */
684                         RTSflags.ProfFlags.kindSelector = left + 1;
685                         break;
686                     }
687                 }}
688                 ) break;
689
690               /* =========== CONCURRENT ========================= */
691               case 'C': /* context switch interval */
692                 CONCURRENT_BUILD_ONLY (
693                 if (rts_argv[arg][2] == '\0')
694                     RTSflags.ConcFlags.ctxtSwitchTime = 0;
695                 else {
696                     I_ cst; /* tmp */
697
698                     /* Convert to milliseconds */
699                     cst = (I_) ((atof(rts_argv[arg]+2) * 1000));
700                     cst = (cst / CS_MIN_MILLISECS) * CS_MIN_MILLISECS;
701                     if (cst < CS_MIN_MILLISECS)
702                         cst = CS_MIN_MILLISECS;
703
704                     RTSflags.ConcFlags.ctxtSwitchTime = cst;
705                 }
706                 ) break;
707
708               case 't':
709                 CONCURRENT_BUILD_ONLY(
710                 if (rts_argv[arg][2] != '\0') {
711                     RTSflags.ConcFlags.maxThreads
712                       = strtol(rts_argv[arg]+2, (char **) NULL, 10);
713                 } else {
714                     fprintf(stderr, "setupRtsFlags: missing size for -t\n");
715                     error = rtsTrue;
716                 }
717                 ) break;
718
719               case 'o':
720                 CONCURRENT_BUILD_ONLY (
721                 if (rts_argv[arg][2] != '\0') {
722                     I_ size = decode(rts_argv[arg]+2);
723
724                     if (size < MIN_STKO_CHUNK_SIZE)
725                         size = MIN_STKO_CHUNK_SIZE;
726
727                     RTSflags.ConcFlags.stkChunkSize = size;
728                 } else {
729                     fprintf(stderr, "setupRtsFlags: missing size for -o\n");
730                     error = rtsTrue;
731                 }
732                 ) break;
733
734               /* =========== PARALLEL =========================== */
735               case 'e':
736                 CONCURRENT_BUILD_ONLY(
737                 if (rts_argv[arg][2] != '\0') { /* otherwise, stick w/ the default */
738
739                     RTSflags.ConcFlags.maxLocalSparks
740                       = strtol(rts_argv[arg]+2, (char **) NULL, 10);
741
742                     if (RTSflags.ConcFlags.maxLocalSparks <= 0) {
743                         fprintf(stderr, "setupRtsFlags: bad value for -e\n");
744                         error = rtsTrue;
745                     }
746                 }
747                 ) break;
748
749               case 'O':
750                 PAR_BUILD_ONLY(
751                 RTSflags.ParFlags.outputDisabled = rtsTrue;
752                 ) break;
753
754               case 'q': /* activity profile option */
755                 PAR_BUILD_ONLY(
756                 if (rts_argv[arg][2] == 'b')
757                     RTSflags.ParFlags.granSimStats_Binary = rtsTrue;
758                 else
759                     RTSflags.ParFlags.granSimStats = rtsTrue;
760                 ) break;
761
762 #if 0 /* or??? */
763               case 'q': /* quasi-parallel profile option */
764                 GRAN_BUILD_ONLY (
765                 if (rts_argv[arg][2] == 'v')
766                     do_qp_prof = 2;
767                 else
768                     do_qp_prof++;
769                 ) break;
770 #endif /* 0??? */
771
772               case 'Q': /* Set pack buffer size */
773                 PAR_BUILD_ONLY(
774                 if (rts_argv[arg][2] != '\0') {
775                     RTSflags.ParFlags.packBufferSize = decode(rts_argv[arg]+2);
776                 } else {
777                     fprintf(stderr, "setupRtsFlags: missing size of PackBuffer (for -Q)\n");
778                     error = rtsTrue;
779                 }
780                 ) break;
781
782               /* =========== GRAN =============================== */
783
784               case 'b':
785                 GRAN_BUILD_ONLY(
786                 process_gran_option(arg, rts_argc, rts_argv, &error);
787                 ) break;
788
789               /* =========== TICKY ============================== */
790
791               case 'r': /* Basic profiling stats */
792                 TICKY_BUILD_ONLY(
793
794                 RTSflags.TickyFlags.showTickyStats = rtsTrue;
795                 RTSflags.TickyFlags.tickyFile
796                   = open_stats_file(arg, *argc, argv,
797                         *rts_argc, rts_argv, TICKY_FILENAME_FMT);
798
799                 if (RTSflags.TickyFlags.tickyFile == NULL) error = rtsTrue;
800                 ) break;
801
802               /* =========== OH DEAR ============================ */
803               default:
804                 fprintf(stderr, "setupRtsFlags: Unknown RTS option: %s\n",rts_argv[arg]);
805                 error = rtsTrue;
806                 break;
807             }
808         }
809     }
810     if (error) {
811         const char **p;
812
813         fflush(stdout);
814         for (p = usage_text; *p; p++)
815             fprintf(stderr, "%s\n", *p);
816         EXIT(EXIT_FAILURE);
817     }
818
819 }
820
821 #if defined(GRAN)
822 void
823 enable_GrAnSimLight() {
824
825     fprintf(stderr,"GrAnSim Light enabled (infinite number of processors;  0 communication costs)\n");
826     RTSflags.GranFlags.Light=rtsTrue;
827     RTSflags.GranFlags.gran_latency = 
828         RTSflags.GranFlags.gran_fetchtime = 
829         RTSflags.GranFlags.gran_additional_latency =
830         RTSflags.GranFlags.gran_gunblocktime = 
831         RTSflags.GranFlags.gran_lunblocktime =
832         RTSflags.GranFlags.gran_threadcreatetime = 
833         RTSflags.GranFlags.gran_threadqueuetime =
834         RTSflags.GranFlags.gran_threadscheduletime = 
835         RTSflags.GranFlags.gran_threaddescheduletime =
836         RTSflags.GranFlags.gran_threadcontextswitchtime = 0;
837   
838     RTSflags.GranFlags.gran_mpacktime = 
839         RTSflags.GranFlags.gran_munpacktime = 0;
840
841     RTSflags.GranFlags.DoFairSchedule = rtsTrue;
842     RTSflags.GranFlags.DoReScheduleOnFetch = rtsFalse;
843     RTSflags.GranFlags.DoAlwaysCreateThreads = rtsTrue;
844     /* FetchStrategy is irrelevant in GrAnSim-Light */
845
846     /* GrAnSim Light often creates an abundance of parallel threads,
847        each with its own stack etc. Therefore, it's in general a good
848        idea to use small stack chunks (use the -o<size> option to 
849        increase it again). 
850     */
851     RTSflags.ConcFlags.stkChunkSize = 100;
852
853     RTSflags.GranFlags.proc = 1; 
854 }
855
856 static void
857 process_gran_option(int arg, int *rts_argc, char *rts_argv[], rtsBool *error)
858 {
859     if (rts_argv[arg][1] != 'b') /* All GranSim options start with -b */
860       return;
861
862       /* Should we emulate hbcpp */
863       if(strcmp((rts_argv[arg]+2),"roken")==0) {
864         RTSflags.GranFlags.DoAlwaysCreateThreads=rtsTrue;
865         strcpy(rts_argv[arg]+2,"oring");
866       }
867
868       /* or a ridiculously idealised simulator */
869       if(strcmp((rts_argv[arg]+2),"oring")==0) {
870         RTSflags.GranFlags.gran_latency = 
871         RTSflags.GranFlags.gran_fetchtime = 
872         RTSflags.GranFlags.gran_additional_latency =
873         RTSflags.GranFlags.gran_gunblocktime = 
874         RTSflags.GranFlags.gran_lunblocktime =
875         RTSflags.GranFlags.gran_threadcreatetime = 
876         RTSflags.GranFlags.gran_threadqueuetime =
877         RTSflags.GranFlags.gran_threadscheduletime = 
878         RTSflags.GranFlags.gran_threaddescheduletime =
879         RTSflags.GranFlags.gran_threadcontextswitchtime = 0;
880
881         RTSflags.GranFlags.gran_mpacktime = 
882         RTSflags.GranFlags.gran_munpacktime = 0;
883
884         RTSflags.GranFlags.gran_arith_cost = 
885         RTSflags.GranFlags.gran_float_cost = 
886         RTSflags.GranFlags.gran_load_cost =
887         RTSflags.GranFlags.gran_store_cost = 
888         RTSflags.GranFlags.gran_branch_cost = 0;
889
890         RTSflags.GranFlags.gran_heapalloc_cost = 1;
891
892         /* ++RTSflags.GranFlags.DoFairSchedule; */
893         RTSflags.GranFlags.DoStealThreadsFirst = rtsTrue;         /* -bZ */
894         RTSflags.GranFlags.DoThreadMigration  = rtsTrue;          /* -bM */
895         RTSflags.GranFlags.granSimStats = rtsTrue;                /* -bP */
896         return;
897       }
898
899       /* or a somewhat idealised simulator */
900       if(strcmp((rts_argv[arg]+2),"onzo")==0) {
901         RTSflags.GranFlags.gran_latency = 
902         RTSflags.GranFlags.gran_fetchtime = 
903         RTSflags.GranFlags.gran_additional_latency =
904         RTSflags.GranFlags.gran_gunblocktime = 
905         RTSflags.GranFlags.gran_lunblocktime =
906         RTSflags.GranFlags.gran_threadcreatetime = 
907         RTSflags.GranFlags.gran_threadqueuetime =
908         RTSflags.GranFlags.gran_threadscheduletime = 
909         RTSflags.GranFlags.gran_threaddescheduletime =
910         RTSflags.GranFlags.gran_threadcontextswitchtime = 0;
911
912         RTSflags.GranFlags.gran_mpacktime = 
913         RTSflags.GranFlags.gran_munpacktime = 0;
914         
915         RTSflags.GranFlags.gran_heapalloc_cost = 1;
916
917         /* RTSflags.GranFlags.DoFairSchedule  = rtsTrue; */       /* -b-R */
918         /* RTSflags.GranFlags.DoStealThreadsFirst = rtsTrue; */   /* -b-T */
919         RTSflags.GranFlags.DoReScheduleOnFetch = rtsTrue;         /* -bZ */
920         RTSflags.GranFlags.DoThreadMigration  = rtsTrue;          /* -bM */
921         RTSflags.GranFlags.granSimStats = rtsTrue;                /* -bP */
922 #  if defined(GRAN_CHECK) && defined(GRAN)
923         RTSflags.GranFlags.debug = 0x20;       /* print event statistics   */
924 #  endif
925         return;
926       }
927
928       /* Communication and task creation cost parameters */
929       switch(rts_argv[arg][2]) {
930         case ':':
931           enable_GrAnSimLight();       /* set flags for GrAnSim-Light mode */
932           break;
933
934         case 'l':
935           if (rts_argv[arg][3] != '\0')
936             {
937               RTSflags.GranFlags.gran_gunblocktime = 
938               RTSflags.GranFlags.gran_latency = decode(rts_argv[arg]+3);
939               RTSflags.GranFlags.gran_fetchtime = 2*RTSflags.GranFlags.gran_latency;
940             }
941           else
942             RTSflags.GranFlags.gran_latency = LATENCY;
943           break;
944
945         case 'a':
946           if (rts_argv[arg][3] != '\0')
947             RTSflags.GranFlags.gran_additional_latency = decode(rts_argv[arg]+3);
948           else
949             RTSflags.GranFlags.gran_additional_latency = ADDITIONAL_LATENCY;
950           break;
951
952         case 'm':
953           if (rts_argv[arg][3] != '\0')
954             RTSflags.GranFlags.gran_mpacktime = decode(rts_argv[arg]+3);
955           else
956             RTSflags.GranFlags.gran_mpacktime = MSGPACKTIME;
957           break;
958
959         case 'x':
960           if (rts_argv[arg][3] != '\0')
961             RTSflags.GranFlags.gran_mtidytime = decode(rts_argv[arg]+3);
962           else
963             RTSflags.GranFlags.gran_mtidytime = 0;
964           break;
965
966         case 'r':
967           if (rts_argv[arg][3] != '\0')
968             RTSflags.GranFlags.gran_munpacktime = decode(rts_argv[arg]+3);
969           else
970             RTSflags.GranFlags.gran_munpacktime = MSGUNPACKTIME;
971           break;
972           
973         case 'g':
974           if (rts_argv[arg][3] != '\0')
975             RTSflags.GranFlags.gran_fetchtime = decode(rts_argv[arg]+3);
976           else
977             RTSflags.GranFlags.gran_fetchtime = FETCHTIME;
978           break;
979           
980         case 'n':
981           if (rts_argv[arg][3] != '\0')
982             RTSflags.GranFlags.gran_gunblocktime = decode(rts_argv[arg]+3);
983           else
984             RTSflags.GranFlags.gran_gunblocktime = GLOBALUNBLOCKTIME;
985           break;
986
987         case 'u':
988           if (rts_argv[arg][3] != '\0')
989             RTSflags.GranFlags.gran_lunblocktime = decode(rts_argv[arg]+3);
990           else
991             RTSflags.GranFlags.gran_lunblocktime = LOCALUNBLOCKTIME;
992           break;
993
994         /* Thread-related metrics */
995         case 't':
996           if (rts_argv[arg][3] != '\0')
997             RTSflags.GranFlags.gran_threadcreatetime = decode(rts_argv[arg]+3);
998           else
999             RTSflags.GranFlags.gran_threadcreatetime = THREADCREATETIME;
1000           break;
1001           
1002         case 'q':
1003           if (rts_argv[arg][3] != '\0')
1004             RTSflags.GranFlags.gran_threadqueuetime = decode(rts_argv[arg]+3);
1005           else
1006             RTSflags.GranFlags.gran_threadqueuetime = THREADQUEUETIME;
1007           break;
1008           
1009         case 'c':
1010           if (rts_argv[arg][3] != '\0')
1011             RTSflags.GranFlags.gran_threadscheduletime = decode(rts_argv[arg]+3);
1012           else
1013             RTSflags.GranFlags.gran_threadscheduletime = THREADSCHEDULETIME;
1014           
1015           RTSflags.GranFlags.gran_threadcontextswitchtime = RTSflags.GranFlags.gran_threadscheduletime
1016             + RTSflags.GranFlags.gran_threaddescheduletime;
1017           break;
1018
1019         case 'd':
1020           if (rts_argv[arg][3] != '\0')
1021             RTSflags.GranFlags.gran_threaddescheduletime = decode(rts_argv[arg]+3);
1022           else
1023             RTSflags.GranFlags.gran_threaddescheduletime = THREADDESCHEDULETIME;
1024           
1025           RTSflags.GranFlags.gran_threadcontextswitchtime = RTSflags.GranFlags.gran_threadscheduletime
1026             + RTSflags.GranFlags.gran_threaddescheduletime;
1027           break;
1028
1029         /* Instruction Cost Metrics */
1030         case 'A':
1031           if (rts_argv[arg][3] != '\0')
1032             RTSflags.GranFlags.gran_arith_cost = decode(rts_argv[arg]+3);
1033           else
1034             RTSflags.GranFlags.gran_arith_cost = ARITH_COST;
1035           break;
1036
1037         case 'F':
1038           if (rts_argv[arg][3] != '\0')
1039             RTSflags.GranFlags.gran_float_cost = decode(rts_argv[arg]+3);
1040           else
1041             RTSflags.GranFlags.gran_float_cost = FLOAT_COST;
1042           break;
1043                       
1044         case 'B':
1045           if (rts_argv[arg][3] != '\0')
1046             RTSflags.GranFlags.gran_branch_cost = decode(rts_argv[arg]+3);
1047           else
1048             RTSflags.GranFlags.gran_branch_cost = BRANCH_COST;
1049           break;
1050
1051         case 'L':
1052           if (rts_argv[arg][3] != '\0')
1053             RTSflags.GranFlags.gran_load_cost = decode(rts_argv[arg]+3);
1054           else
1055             RTSflags.GranFlags.gran_load_cost = LOAD_COST;
1056           break;
1057           
1058         case 'S':
1059           if (rts_argv[arg][3] != '\0')
1060             RTSflags.GranFlags.gran_store_cost = decode(rts_argv[arg]+3);
1061           else
1062             RTSflags.GranFlags.gran_store_cost = STORE_COST;
1063           break;
1064
1065         case 'H':
1066           if (rts_argv[arg][3] != '\0')
1067             RTSflags.GranFlags.gran_heapalloc_cost = decode(rts_argv[arg]+3);
1068           else
1069             RTSflags.GranFlags.gran_heapalloc_cost = 0;
1070           break;
1071
1072         case 'y':
1073           RTSflags.GranFlags.DoReScheduleOnFetch = rtsTrue;
1074           if (rts_argv[arg][3] != '\0')
1075             RTSflags.GranFlags.FetchStrategy = decode(rts_argv[arg]+3);
1076           if (RTSflags.GranFlags.FetchStrategy == 0)
1077             RTSflags.GranFlags.DoReScheduleOnFetch = rtsFalse;
1078           else
1079             RTSflags.GranFlags.FetchStrategy = 2; /* default: fetch everything */
1080           break;
1081           
1082         case 'K':   /* sort overhead (per elem in spark list) */
1083           if (rts_argv[arg][3] != '\0')
1084             RTSflags.GranFlags.gran_pri_spark_overhead = decode(rts_argv[arg]+3);
1085           else
1086             RTSflags.GranFlags.gran_pri_spark_overhead = PRI_SPARK_OVERHEAD;
1087           fprintf(stderr,"Overhead for pri spark: %d (per elem).\n",
1088                          RTSflags.GranFlags.gran_pri_spark_overhead);
1089           break;
1090
1091         case 'O':  /* sort overhead (per elem in spark list) */
1092           if (rts_argv[arg][3] != '\0')
1093             RTSflags.GranFlags.gran_pri_sched_overhead = decode(rts_argv[arg]+3);
1094           else
1095             RTSflags.GranFlags.gran_pri_sched_overhead = PRI_SCHED_OVERHEAD;
1096           fprintf(stderr,"Overhead for pri sched: %d (per elem).\n",
1097                        RTSflags.GranFlags.gran_pri_sched_overhead);
1098           break;
1099
1100         /* General Parameters */
1101         case 'p':
1102           if (rts_argv[arg][3] != '\0')
1103             {
1104               RTSflags.GranFlags.proc = decode(rts_argv[arg]+3);
1105               if (RTSflags.GranFlags.proc==0) {
1106                   enable_GrAnSimLight(); /* set flags for GrAnSim-Light mode */
1107               } else if (RTSflags.GranFlags.proc > MAX_PROC || 
1108                          RTSflags.GranFlags.proc < 1)
1109                 {
1110                   fprintf(stderr,"setupRtsFlags: no more than %u processors
1111 allowed\n", 
1112                           MAX_PROC);
1113                   *error = rtsTrue;
1114                 }
1115             }
1116           else
1117             RTSflags.GranFlags.proc = MAX_PROC;
1118           break;
1119
1120         case 'f':
1121           if (rts_argv[arg][3] != '\0')
1122             RTSflags.GranFlags.max_fishes = decode(rts_argv[arg]+3);
1123           else
1124             RTSflags.GranFlags.max_fishes = 1;
1125           break;
1126           
1127         case 'w':
1128           if (rts_argv[arg][3] != '\0')
1129             RTSflags.GranFlags.time_slice = decode(rts_argv[arg]+3);
1130           else
1131             RTSflags.GranFlags.time_slice = GRAN_TIME_SLICE;
1132           break;
1133           
1134         case 'C':
1135           RTSflags.GranFlags.DoAlwaysCreateThreads=rtsTrue;
1136           RTSflags.GranFlags.DoThreadMigration=rtsTrue;
1137           break;
1138
1139         case 'G':
1140           fprintf(stderr,"Bulk fetching enabled.\n");
1141           RTSflags.GranFlags.DoGUMMFetching=rtsTrue;
1142           break;
1143           
1144         case 'M':
1145           fprintf(stderr,"Thread migration enabled.\n");
1146           RTSflags.GranFlags.DoThreadMigration=rtsTrue;
1147           break;
1148
1149         case 'R':
1150           fprintf(stderr,"Fair Scheduling enabled.\n");
1151           RTSflags.GranFlags.DoFairSchedule=rtsTrue;
1152           break;
1153           
1154         case 'I':
1155           fprintf(stderr,"Priority Scheduling enabled.\n");
1156           RTSflags.GranFlags.DoPriorityScheduling=rtsTrue;
1157           break;
1158
1159         case 'T':
1160           RTSflags.GranFlags.DoStealThreadsFirst=rtsTrue;
1161           RTSflags.GranFlags.DoThreadMigration=rtsTrue;
1162           break;
1163           
1164         case 'Z':
1165           RTSflags.GranFlags.DoReScheduleOnFetch=rtsTrue;
1166           break;
1167           
1168         case 'z':
1169           RTSflags.GranFlags.SimplifiedFetch=rtsTrue;
1170           break;
1171           
1172         case 'N':
1173           RTSflags.GranFlags.PreferSparksOfLocalNodes=rtsTrue;
1174           break;
1175           
1176         case 'b':
1177           RTSflags.GranFlags.granSimStats_Binary=rtsTrue;
1178           break;
1179           
1180         case 'P':
1181           RTSflags.GranFlags.granSimStats=rtsTrue;
1182           break;
1183
1184         case 's':
1185           RTSflags.GranFlags.granSimStats_Sparks=rtsTrue;
1186           break;
1187
1188         case 'h':
1189           RTSflags.GranFlags.granSimStats_Heap=rtsTrue;
1190           break;
1191
1192         case 'U':
1193           RTSflags.GranFlags.labelling=rtsTrue;
1194           break;
1195
1196         case 'Y':   /* syntax: -bY<n>[,<n>]  n ... pos int */ 
1197           if (rts_argv[arg][3] != '\0') {
1198             char *arg0, *tmp;
1199             
1200             arg0 = rts_argv[arg]+3;
1201             if ((tmp = strstr(arg0,","))==NULL) {
1202               RTSflags.GranFlags.SparkPriority = decode(arg0);
1203               fprintf(stderr,"SparkPriority: %u.\n",RTSflags.GranFlags.SparkPriority);
1204             } else {
1205               *(tmp++) = '\0'; 
1206               RTSflags.GranFlags.SparkPriority = decode(arg0);
1207               RTSflags.GranFlags.SparkPriority2 = decode(tmp);
1208               fprintf(stderr,"SparkPriority: %u.\n",
1209                       RTSflags.GranFlags.SparkPriority);
1210               fprintf(stderr,"SparkPriority2:%u.\n",
1211                       RTSflags.GranFlags.SparkPriority2);
1212               if (RTSflags.GranFlags.SparkPriority2 < 
1213                   RTSflags.GranFlags.SparkPriority) {
1214                 fprintf(stderr,"WARNING: 2nd pri < main pri (%u<%u); 2nd pri has no effect\n",
1215                         RTSflags.GranFlags.SparkPriority2,
1216                         RTSflags.GranFlags.SparkPriority);
1217               }
1218             }
1219           } else {
1220             /* plain pri spark is now invoked with -bX  
1221                RTSflags.GranFlags.DoPrioritySparking = 1;
1222                fprintf(stderr,"PrioritySparking.\n");
1223             */
1224           }
1225           break;
1226
1227         case 'Q':
1228           if (rts_argv[arg][3] != '\0') {
1229             RTSflags.GranFlags.ThunksToPack = decode(rts_argv[arg]+3);
1230           } else {
1231             RTSflags.GranFlags.ThunksToPack = 1;
1232           }
1233           fprintf(stderr,"Thunks To Pack in one packet: %u.\n",
1234                   RTSflags.GranFlags.ThunksToPack);
1235           break;
1236                       
1237         case 'e':
1238           RTSflags.GranFlags.RandomSteal = rtsFalse;
1239           fprintf(stderr,"Deterministic mode (no random stealing)\n");
1240                       break;
1241
1242           /* The following class of options contains eXperimental */
1243           /* features in connection with exploiting granularity */
1244           /* information. I.e. if -bY is chosen these options */
1245           /* tell the RTS what to do with the supplied info --HWL */
1246         case 'X':
1247           switch(rts_argv[arg][3]) {
1248             
1249             case '\0':
1250               RTSflags.GranFlags.DoPrioritySparking = 1;
1251               fprintf(stderr,"Priority Sparking with Normal Priorities.\n");
1252               RTSflags.GranFlags.InversePriorities = rtsFalse; 
1253               RTSflags.GranFlags.RandomPriorities = rtsFalse;
1254               RTSflags.GranFlags.IgnorePriorities = rtsFalse;
1255               break;
1256                         
1257             case 'I':
1258               RTSflags.GranFlags.DoPrioritySparking = 1;
1259               fprintf(stderr,"Priority Sparking with Inverse Priorities.\n");
1260               RTSflags.GranFlags.InversePriorities++; 
1261               break;
1262               
1263             case 'R': 
1264               RTSflags.GranFlags.DoPrioritySparking = 1;
1265               fprintf(stderr,"Priority Sparking with Random Priorities.\n");
1266               RTSflags.GranFlags.RandomPriorities++;
1267               break;
1268               
1269             case 'N':
1270               RTSflags.GranFlags.DoPrioritySparking = 1;
1271               fprintf(stderr,"Priority Sparking with No Priorities.\n");
1272               RTSflags.GranFlags.IgnorePriorities++;
1273               break;
1274               
1275             default:
1276               bad_option( rts_argv[arg] );
1277               break;
1278           }
1279           break;
1280
1281         case '-':
1282           switch(rts_argv[arg][3]) {
1283             
1284             case 'C':
1285               RTSflags.GranFlags.DoAlwaysCreateThreads=rtsFalse;
1286               RTSflags.GranFlags.DoThreadMigration=rtsFalse;
1287               break;
1288
1289             case 'G':
1290               RTSflags.GranFlags.DoGUMMFetching=rtsFalse;
1291               break;
1292               
1293             case 'M':
1294               RTSflags.GranFlags.DoThreadMigration=rtsFalse;
1295               break;
1296
1297             case 'R':
1298               RTSflags.GranFlags.DoFairSchedule=rtsFalse;
1299               break;
1300
1301             case 'T':
1302               RTSflags.GranFlags.DoStealThreadsFirst=rtsFalse;
1303               RTSflags.GranFlags.DoThreadMigration=rtsFalse;
1304               break;
1305
1306             case 'Z':
1307               RTSflags.GranFlags.DoReScheduleOnFetch=rtsFalse;
1308               break;
1309               
1310             case 'N':
1311               RTSflags.GranFlags.PreferSparksOfLocalNodes=rtsFalse;
1312                          break;
1313                          
1314             case 'P':
1315               RTSflags.GranFlags.granSimStats_suppressed=rtsTrue;
1316               break;
1317
1318             case 's':
1319               RTSflags.GranFlags.granSimStats_Sparks=rtsFalse;
1320               break;
1321             
1322             case 'h':
1323               RTSflags.GranFlags.granSimStats_Heap=rtsFalse;
1324               break;
1325             
1326             case 'b':
1327               RTSflags.GranFlags.granSimStats_Binary=rtsFalse;
1328               break;
1329                          
1330             case 'X':
1331               RTSflags.GranFlags.DoPrioritySparking = rtsFalse;
1332               break;
1333
1334             case 'Y':
1335               RTSflags.GranFlags.DoPrioritySparking = rtsFalse;
1336               RTSflags.GranFlags.SparkPriority = rtsFalse;
1337               break;
1338
1339             case 'I':
1340               RTSflags.GranFlags.DoPriorityScheduling = rtsFalse;
1341               break;
1342
1343             case 'e':
1344               RTSflags.GranFlags.RandomSteal = rtsFalse;
1345               break;
1346
1347             default:
1348               bad_option( rts_argv[arg] );
1349               break;
1350           }
1351           break;
1352
1353 #  if defined(GRAN_CHECK) && defined(GRAN)
1354         case 'D':
1355           switch(rts_argv[arg][3]) {
1356             case 'Q':    /* Set pack buffer size (same as 'Q' in GUM) */
1357               if (rts_argv[arg][4] != '\0') {
1358                 RTSflags.GranFlags.packBufferSize = decode(rts_argv[arg]+4);
1359                 fprintf(stderr,"Pack buffer size: %d\n",
1360                         RTSflags.GranFlags.packBufferSize);
1361               } else {
1362                 fprintf(stderr, "setupRtsFlags: missing size of PackBuffer (for -Q)\n");
1363                 error = rtsTrue;
1364               }
1365               break;
1366
1367             case 'e':       /* event trace */
1368               fprintf(stderr,"Printing event trace.\n");
1369               RTSflags.GranFlags.event_trace=rtsTrue;
1370               break;
1371               
1372             case 'f':
1373               fprintf(stderr,"Printing forwarding of FETCHNODES.\n");
1374               RTSflags.GranFlags.debug |= 0x2; /* print fwd messages */
1375               break;
1376
1377             case 'z':
1378               fprintf(stderr,"Check for blocked on fetch.\n");
1379               RTSflags.GranFlags.debug |= 0x4; /* debug non-reschedule-on-fetch */
1380               break;
1381               
1382             case 't':
1383               fprintf(stderr,"Check for TSO asleep on fetch.\n");
1384               RTSflags.GranFlags.debug |= 0x10; /* debug TSO asleep for fetch  */
1385               break;
1386
1387             case 'E':
1388               fprintf(stderr,"Printing event statistics.\n");
1389               RTSflags.GranFlags.debug |= 0x20; /* print event statistics   */
1390               break;
1391               
1392             case 'F':
1393               fprintf(stderr,"Prohibiting forward.\n");
1394               RTSflags.GranFlags.NoForward = rtsTrue; /* prohibit forwarding   */
1395               break;
1396               
1397             case 'm':
1398               fprintf(stderr,"Printing fetch misses.\n");
1399               RTSflags.GranFlags.PrintFetchMisses = rtsTrue; /* prohibit forwarding   */
1400               break;
1401
1402             case 'd':
1403               fprintf(stderr,"Debug mode.\n");
1404               RTSflags.GranFlags.debug |= 0x40; 
1405                             break;
1406
1407             case 'D':
1408               fprintf(stderr,"Severe debug mode.\n");
1409               RTSflags.GranFlags.debug |= 0x80; 
1410               break;
1411               
1412             case 'q':
1413               fprintf(stderr,"FULL event trace.\n");
1414               RTSflags.GranFlags.event_trace_all =rtsTrue;
1415               break;
1416
1417             case 'G':
1418               fprintf(stderr,"Debugging packet fetching.\n");
1419               RTSflags.GranFlags.debug |= 0x100; 
1420               break;
1421               
1422             case 'n':
1423               fprintf(stderr,"Ignore events till end of time slice\n");
1424               RTSflags.GranFlags.debug |= 0x200; 
1425               IgnoreEvents = rtsTrue;
1426               break;
1427
1428             case 'S':
1429               fprintf(stderr,"Check that spark queues are sorted.\n");
1430               RTSflags.GranFlags.debug |= 0x400; 
1431               break;
1432
1433             case 'H':
1434               fprintf(stderr,"Print heap allocation messages (RBH).\n");
1435               RTSflags.GranFlags.debug |= 0x800; 
1436               break;
1437
1438             case 'p':
1439               fprintf(stderr,"Debug breadth-first pruning.\n");
1440               RTSflags.GranFlags.debug |= 0x1000; 
1441               break;
1442               
1443             case 'r':
1444               fprintf(stderr,"Debug random stealing.\n");
1445               RTSflags.GranFlags.debug |= 0x2000; 
1446               break;
1447
1448             case 'B':
1449               fprintf(stderr,"Debug busyness.\n");
1450               RTSflags.GranFlags.debug |= 0x4000; 
1451               break;
1452
1453             case 's':
1454               fprintf(stderr,"Debug spark-queue manipulations.\n");
1455               RTSflags.GranFlags.debug |= 0x10000; 
1456               break;
1457               
1458             case ':':
1459               fprintf(stderr,"Debug GrAnSim Light.\n");
1460               RTSflags.GranFlags.debug |= 0x20000; 
1461               break;
1462               
1463             case '\0':
1464               RTSflags.GranFlags.debug = 1;
1465               break;
1466
1467             default:
1468               bad_option( rts_argv[arg] );
1469               break;
1470           }
1471           break;
1472 #  endif  /* GRAN_CHECK */
1473       default:
1474         bad_option( rts_argv[arg] );
1475         break;
1476      }
1477 }      
1478 #endif /* GRAN */
1479 \end{code}
1480
1481 %************************************************************************
1482 %*                                                                      *
1483 \subsection{Profiling RTS Arguments}
1484 %*                                                                      *
1485 %************************************************************************
1486
1487 \begin{code}
1488 I_ MaxResidency = 0;     /* in words; for stats only */
1489 I_ ResidencySamples = 0; /* for stats only */
1490
1491 void
1492 initSM(void)
1493 {
1494     RTSflags.GcFlags.minAllocAreaSize
1495       = (I_) (RTSflags.GcFlags.heapSize * RTSflags.GcFlags.pcFreeHeap / 100);
1496     /*
1497         This needs to be here, in case the user changed some of these
1498         values with a "hook".
1499     */
1500 }
1501 \end{code}
1502
1503 %************************************************************************
1504 %*                                                                      *
1505 \subsection{Utility bits}
1506 %*                                                                      *
1507 %************************************************************************
1508
1509 \begin{code}
1510 static FILE *           /* return NULL on error */
1511 open_stats_file (
1512     I_ arg,
1513     int argc, char *argv[],
1514     int rts_argc, char *rts_argv[],
1515     const char *FILENAME_FMT)
1516 {
1517     FILE *f = NULL;
1518
1519     if (strequal(rts_argv[arg]+2, "stderr")) /* use real stderr */
1520         f = stderr;
1521     else if (rts_argv[arg][2] != '\0')      /* stats file specified */
1522         f = fopen(rts_argv[arg]+2,"w");
1523     else {
1524         char stats_filename[STATS_FILENAME_MAXLEN]; /* default <program>.<ext> */
1525         sprintf(stats_filename, FILENAME_FMT, argv[0]);
1526         f = fopen(stats_filename,"w");
1527     }
1528     if (f == NULL) {
1529         fprintf(stderr, "Can't open stats file %s\n", rts_argv[arg]+2);
1530     } else {
1531         /* Write argv and rtsv into start of stats file */
1532         I_ count;
1533         for(count = 0; count < argc; count++)
1534             fprintf(f, "%s ", argv[count]);
1535         fprintf(f, "+RTS ");
1536         for(count = 0; count < rts_argc; count++)
1537             fprintf(f, "%s ", rts_argv[count]);
1538         fprintf(f, "\n");
1539     }
1540
1541     return(f);
1542 }
1543
1544 static I_
1545 decode(const char *s)
1546 {
1547     I_ c;
1548     StgDouble m;
1549
1550     if (!*s)
1551         return 0;
1552
1553     m = atof(s);
1554     c = s[strlen(s)-1];
1555
1556     if (c == 'g' || c == 'G')
1557         m *= 1000*1000*1000;    /* UNchecked! */
1558     else if (c == 'm' || c == 'M')
1559         m *= 1000*1000;                 /* We do not use powers of 2 (1024) */
1560     else if (c == 'k' || c == 'K')      /* to avoid possible bad effects on */
1561         m *= 1000;                      /* a direct-mapped cache.           */ 
1562     else if (c == 'w' || c == 'W')
1563         m *= sizeof(W_);
1564
1565     return (I_)m;
1566 }
1567
1568 static void
1569 bad_option(const char *s)
1570 {
1571   fflush(stdout);
1572   fprintf(stderr, "initSM: Bad RTS option: %s\n", s);
1573   EXIT(EXIT_FAILURE);
1574 }               
1575 \end{code}