[project @ 1996-07-25 20:43:49 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; see GranSim User's Guide for details",
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                     PAR_BUILD_ONLY(
552                     break; /* we do not care about sortBy for parallel */
553                     )
554                     PROFILING_BUILD_ONLY(
555                     fprintf(stderr, "Invalid profiling sort option %s\n", rts_argv[arg]);
556                     error = rtsTrue;
557                     )
558                 }
559                 ) break;
560
561               case 'i': /* serial profiling -- initial timer interval */
562                 COST_CENTRE_USING_BUILD_ONLY(
563                 interval_ticks = (I_) ((atof(rts_argv[arg]+2) * TICK_FREQUENCY));
564                 if (interval_ticks <= 0)
565                     interval_ticks = 1;
566                 ) break;
567
568               case 'h': /* serial heap profile */
569                 PROFILING_BUILD_ONLY(
570                 switch (rts_argv[arg][2]) {
571                   case '\0':
572                   case CCchar:
573                     RTSflags.ProfFlags.doHeapProfile = HEAP_BY_CC;
574                     break;
575                   case MODchar:
576                     RTSflags.ProfFlags.doHeapProfile = HEAP_BY_MOD;
577                     break;
578                   case GRPchar:
579                     RTSflags.ProfFlags.doHeapProfile = HEAP_BY_GRP;
580                     break;
581                   case DESCRchar:
582                     RTSflags.ProfFlags.doHeapProfile = HEAP_BY_DESCR;
583                     break;
584                   case TYPEchar:
585                     RTSflags.ProfFlags.doHeapProfile = HEAP_BY_TYPE;
586                     break;
587                   case TIMEchar:
588                     RTSflags.ProfFlags.doHeapProfile = HEAP_BY_TIME;
589                     if (rts_argv[arg][3]) {
590                         char *start_str = strchr(rts_argv[arg]+3, ',');
591                         I_ intervals;
592                         if (start_str) *start_str = '\0';
593
594                         if ((intervals = decode(rts_argv[arg]+3)) != 0) {
595                             time_intervals = (hash_t) intervals;
596                             /* ToDo: and what if it *is* zero intervals??? */
597                         }
598                         if (start_str) {
599                             earlier_ticks = (I_)((atof(start_str + 1) * TICK_FREQUENCY));
600                         }
601                     }
602                     break;
603                   default:
604                     fprintf(stderr, "Invalid heap profile option: %s\n",
605                             rts_argv[arg]);
606                     error = rtsTrue;
607                 }
608                 ) break;
609
610               case 'z': /* size of index tables */
611                 PROFILING_BUILD_ONLY(
612                 switch (rts_argv[arg][2]) {
613                   case CCchar:
614                     max_cc_no = (hash_t) decode(rts_argv[arg]+3);
615                     if (max_cc_no == 0) {
616                         fprintf(stderr, "Bad number of cost centres %s\n", rts_argv[arg]);
617                         error = rtsTrue;
618                     }
619                     break;
620                   case MODchar:
621                     max_mod_no = (hash_t) decode(rts_argv[arg]+3);
622                     if (max_mod_no == 0) {
623                         fprintf(stderr, "Bad number of modules %s\n", rts_argv[arg]);
624                         error = rtsTrue;
625                     }
626                     break;
627                   case GRPchar:
628                     max_grp_no = (hash_t) decode(rts_argv[arg]+3);
629                     if (max_grp_no == 0) {
630                         fprintf(stderr, "Bad number of groups %s\n", rts_argv[arg]);
631                         error = rtsTrue;
632                     }
633                     break;
634                   case DESCRchar:
635                     max_descr_no = (hash_t) decode(rts_argv[arg]+3);
636                     if (max_descr_no == 0) {
637                         fprintf(stderr, "Bad number of closure descriptions %s\n", rts_argv[arg]);
638                         error = rtsTrue;
639                     }
640                     break;
641                   case TYPEchar:
642                     max_type_no = (hash_t) decode(rts_argv[arg]+3);
643                     if (max_type_no == 0) {
644                         fprintf(stderr, "Bad number of type descriptions %s\n", rts_argv[arg]);
645                         error = rtsTrue;
646                     }
647                     break;
648                   default:
649                     fprintf(stderr, "Invalid index table size option: %s\n",
650                             rts_argv[arg]);
651                     error = rtsTrue;
652                 }
653                 ) break;
654
655               case 'c': /* cost centre label select */
656               case 'm': /* cost centre module select */
657               case 'g': /* cost centre group select */
658               case 'd': /* closure descr select */
659               case 'y': /* closure type select */
660               case 'k': /* closure kind select */
661                 PROFILING_BUILD_ONLY(
662                 {char *left  = strchr(rts_argv[arg], '{');
663                  char *right = strrchr(rts_argv[arg], '}');
664
665                 if (! left || ! right ||
666                         strrchr(rts_argv[arg], '{') != left ||
667                          strchr(rts_argv[arg], '}') != right) {
668                     fprintf(stderr, "Invalid heap profiling selection bracketing\n   %s\n", rts_argv[arg]);
669                     error = rtsTrue;
670                 } else {
671                     *right = '\0';
672                     switch (rts_argv[arg][1]) {
673                       case 'c': /* cost centre label select */
674                         RTSflags.ProfFlags.ccSelector = left + 1;
675                         break;
676                       case 'm': /* cost centre module select */
677                         RTSflags.ProfFlags.modSelector = left + 1;
678                         break;
679                       case 'g': /* cost centre group select */
680                         RTSflags.ProfFlags.grpSelector = left + 1;
681                         break;
682                       case 'd': /* closure descr select */
683                         RTSflags.ProfFlags.descrSelector = left + 1;
684                         break;
685                       case 't': /* closure type select */
686                         RTSflags.ProfFlags.typeSelector = left + 1;
687                         break;
688                       case 'k': /* closure kind select */
689                         RTSflags.ProfFlags.kindSelector = left + 1;
690                         break;
691                     }
692                 }}
693                 ) break;
694
695               /* =========== CONCURRENT ========================= */
696               case 'C': /* context switch interval */
697                 CONCURRENT_BUILD_ONLY (
698                 if (rts_argv[arg][2] == '\0')
699                     RTSflags.ConcFlags.ctxtSwitchTime = 0;
700                 else {
701                     I_ cst; /* tmp */
702
703                     /* Convert to milliseconds */
704                     cst = (I_) ((atof(rts_argv[arg]+2) * 1000));
705                     cst = (cst / CS_MIN_MILLISECS) * CS_MIN_MILLISECS;
706                     if (cst < CS_MIN_MILLISECS)
707                         cst = CS_MIN_MILLISECS;
708
709                     RTSflags.ConcFlags.ctxtSwitchTime = cst;
710                 }
711                 ) break;
712
713               case 't':
714                 CONCURRENT_BUILD_ONLY(
715                 if (rts_argv[arg][2] != '\0') {
716                     RTSflags.ConcFlags.maxThreads
717                       = strtol(rts_argv[arg]+2, (char **) NULL, 10);
718                 } else {
719                     fprintf(stderr, "setupRtsFlags: missing size for -t\n");
720                     error = rtsTrue;
721                 }
722                 ) break;
723
724               case 'o':
725                 CONCURRENT_BUILD_ONLY (
726                 if (rts_argv[arg][2] != '\0') {
727                     I_ size = decode(rts_argv[arg]+2);
728
729                     if (size < MIN_STKO_CHUNK_SIZE)
730                         size = MIN_STKO_CHUNK_SIZE;
731
732                     RTSflags.ConcFlags.stkChunkSize = size;
733                 } else {
734                     fprintf(stderr, "setupRtsFlags: missing size for -o\n");
735                     error = rtsTrue;
736                 }
737                 ) break;
738
739               /* =========== PARALLEL =========================== */
740               case 'e':
741                 CONCURRENT_BUILD_ONLY(
742                 if (rts_argv[arg][2] != '\0') { /* otherwise, stick w/ the default */
743
744                     RTSflags.ConcFlags.maxLocalSparks
745                       = strtol(rts_argv[arg]+2, (char **) NULL, 10);
746
747                     if (RTSflags.ConcFlags.maxLocalSparks <= 0) {
748                         fprintf(stderr, "setupRtsFlags: bad value for -e\n");
749                         error = rtsTrue;
750                     }
751                 }
752                 ) break;
753
754               case 'O':
755                 PAR_BUILD_ONLY(
756                 RTSflags.ParFlags.outputDisabled = rtsTrue;
757                 ) break;
758
759               case 'q': /* activity profile option */
760                 PAR_BUILD_ONLY(
761                 if (rts_argv[arg][2] == 'b')
762                     RTSflags.ParFlags.granSimStats_Binary = rtsTrue;
763                 else
764                     RTSflags.ParFlags.granSimStats = rtsTrue;
765                 ) break;
766
767 #if 0 /* or??? */
768               case 'q': /* quasi-parallel profile option */
769                 GRAN_BUILD_ONLY (
770                 if (rts_argv[arg][2] == 'v')
771                     do_qp_prof = 2;
772                 else
773                     do_qp_prof++;
774                 ) break;
775 #endif /* 0??? */
776
777               case 'Q': /* Set pack buffer size */
778                 PAR_BUILD_ONLY(
779                 if (rts_argv[arg][2] != '\0') {
780                     RTSflags.ParFlags.packBufferSize = decode(rts_argv[arg]+2);
781                 } else {
782                     fprintf(stderr, "setupRtsFlags: missing size of PackBuffer (for -Q)\n");
783                     error = rtsTrue;
784                 }
785                 ) break;
786
787               /* =========== GRAN =============================== */
788
789               case 'b':
790                 GRAN_BUILD_ONLY(
791                 process_gran_option(arg, rts_argc, rts_argv, &error);
792                 ) break;
793
794               /* =========== TICKY ============================== */
795
796               case 'r': /* Basic profiling stats */
797                 TICKY_BUILD_ONLY(
798
799                 RTSflags.TickyFlags.showTickyStats = rtsTrue;
800                 RTSflags.TickyFlags.tickyFile
801                   = open_stats_file(arg, *argc, argv,
802                         *rts_argc, rts_argv, TICKY_FILENAME_FMT);
803
804                 if (RTSflags.TickyFlags.tickyFile == NULL) error = rtsTrue;
805                 ) break;
806
807               /* =========== OH DEAR ============================ */
808               default:
809                 fprintf(stderr, "setupRtsFlags: Unknown RTS option: %s\n",rts_argv[arg]);
810                 error = rtsTrue;
811                 break;
812             }
813         }
814     }
815     if (error) {
816         const char **p;
817
818         fflush(stdout);
819         for (p = usage_text; *p; p++)
820             fprintf(stderr, "%s\n", *p);
821         EXIT(EXIT_FAILURE);
822     }
823
824 }
825
826 #if defined(GRAN)
827 void
828 enable_GrAnSimLight() {
829
830     fprintf(stderr,"GrAnSim Light enabled (infinite number of processors;  0 communication costs)\n");
831     RTSflags.GranFlags.Light=rtsTrue;
832     RTSflags.GranFlags.gran_latency = 
833         RTSflags.GranFlags.gran_fetchtime = 
834         RTSflags.GranFlags.gran_additional_latency =
835         RTSflags.GranFlags.gran_gunblocktime = 
836         RTSflags.GranFlags.gran_lunblocktime =
837         RTSflags.GranFlags.gran_threadcreatetime = 
838         RTSflags.GranFlags.gran_threadqueuetime =
839         RTSflags.GranFlags.gran_threadscheduletime = 
840         RTSflags.GranFlags.gran_threaddescheduletime =
841         RTSflags.GranFlags.gran_threadcontextswitchtime = 0;
842   
843     RTSflags.GranFlags.gran_mpacktime = 
844         RTSflags.GranFlags.gran_munpacktime = 0;
845
846     RTSflags.GranFlags.DoFairSchedule = rtsTrue;
847     RTSflags.GranFlags.DoReScheduleOnFetch = rtsFalse;
848     RTSflags.GranFlags.DoAlwaysCreateThreads = rtsTrue;
849     /* FetchStrategy is irrelevant in GrAnSim-Light */
850
851     /* GrAnSim Light often creates an abundance of parallel threads,
852        each with its own stack etc. Therefore, it's in general a good
853        idea to use small stack chunks (use the -o<size> option to 
854        increase it again). 
855     */
856     RTSflags.ConcFlags.stkChunkSize = 100;
857
858     RTSflags.GranFlags.proc = 1; 
859 }
860
861 static void
862 process_gran_option(int arg, int *rts_argc, char *rts_argv[], rtsBool *error)
863 {
864     if (rts_argv[arg][1] != 'b') /* All GranSim options start with -b */
865       return;
866
867       /* Should we emulate hbcpp */
868       if(strcmp((rts_argv[arg]+2),"roken")==0) {
869         RTSflags.GranFlags.DoAlwaysCreateThreads=rtsTrue;
870         strcpy(rts_argv[arg]+2,"oring");
871       }
872
873       /* or a ridiculously idealised simulator */
874       if(strcmp((rts_argv[arg]+2),"oring")==0) {
875         RTSflags.GranFlags.gran_latency = 
876         RTSflags.GranFlags.gran_fetchtime = 
877         RTSflags.GranFlags.gran_additional_latency =
878         RTSflags.GranFlags.gran_gunblocktime = 
879         RTSflags.GranFlags.gran_lunblocktime =
880         RTSflags.GranFlags.gran_threadcreatetime = 
881         RTSflags.GranFlags.gran_threadqueuetime =
882         RTSflags.GranFlags.gran_threadscheduletime = 
883         RTSflags.GranFlags.gran_threaddescheduletime =
884         RTSflags.GranFlags.gran_threadcontextswitchtime = 0;
885
886         RTSflags.GranFlags.gran_mpacktime = 
887         RTSflags.GranFlags.gran_munpacktime = 0;
888
889         RTSflags.GranFlags.gran_arith_cost = 
890         RTSflags.GranFlags.gran_float_cost = 
891         RTSflags.GranFlags.gran_load_cost =
892         RTSflags.GranFlags.gran_store_cost = 
893         RTSflags.GranFlags.gran_branch_cost = 0;
894
895         RTSflags.GranFlags.gran_heapalloc_cost = 1;
896
897         /* ++RTSflags.GranFlags.DoFairSchedule; */
898         RTSflags.GranFlags.DoStealThreadsFirst = rtsTrue;         /* -bZ */
899         RTSflags.GranFlags.DoThreadMigration  = rtsTrue;          /* -bM */
900         RTSflags.GranFlags.granSimStats = rtsTrue;                /* -bP */
901         return;
902       }
903
904       /* or a somewhat idealised simulator */
905       if(strcmp((rts_argv[arg]+2),"onzo")==0) {
906         RTSflags.GranFlags.gran_latency = 
907         RTSflags.GranFlags.gran_fetchtime = 
908         RTSflags.GranFlags.gran_additional_latency =
909         RTSflags.GranFlags.gran_gunblocktime = 
910         RTSflags.GranFlags.gran_lunblocktime =
911         RTSflags.GranFlags.gran_threadcreatetime = 
912         RTSflags.GranFlags.gran_threadqueuetime =
913         RTSflags.GranFlags.gran_threadscheduletime = 
914         RTSflags.GranFlags.gran_threaddescheduletime =
915         RTSflags.GranFlags.gran_threadcontextswitchtime = 0;
916
917         RTSflags.GranFlags.gran_mpacktime = 
918         RTSflags.GranFlags.gran_munpacktime = 0;
919         
920         RTSflags.GranFlags.gran_heapalloc_cost = 1;
921
922         /* RTSflags.GranFlags.DoFairSchedule  = rtsTrue; */       /* -b-R */
923         /* RTSflags.GranFlags.DoStealThreadsFirst = rtsTrue; */   /* -b-T */
924         RTSflags.GranFlags.DoReScheduleOnFetch = rtsTrue;         /* -bZ */
925         RTSflags.GranFlags.DoThreadMigration  = rtsTrue;          /* -bM */
926         RTSflags.GranFlags.granSimStats = rtsTrue;                /* -bP */
927 #  if defined(GRAN_CHECK) && defined(GRAN)
928         RTSflags.GranFlags.debug = 0x20;       /* print event statistics   */
929 #  endif
930         return;
931       }
932
933       /* Communication and task creation cost parameters */
934       switch(rts_argv[arg][2]) {
935         case ':':
936           enable_GrAnSimLight();       /* set flags for GrAnSim-Light mode */
937           break;
938
939         case 'l':
940           if (rts_argv[arg][3] != '\0')
941             {
942               RTSflags.GranFlags.gran_gunblocktime = 
943               RTSflags.GranFlags.gran_latency = decode(rts_argv[arg]+3);
944               RTSflags.GranFlags.gran_fetchtime = 2*RTSflags.GranFlags.gran_latency;
945             }
946           else
947             RTSflags.GranFlags.gran_latency = LATENCY;
948           break;
949
950         case 'a':
951           if (rts_argv[arg][3] != '\0')
952             RTSflags.GranFlags.gran_additional_latency = decode(rts_argv[arg]+3);
953           else
954             RTSflags.GranFlags.gran_additional_latency = ADDITIONAL_LATENCY;
955           break;
956
957         case 'm':
958           if (rts_argv[arg][3] != '\0')
959             RTSflags.GranFlags.gran_mpacktime = decode(rts_argv[arg]+3);
960           else
961             RTSflags.GranFlags.gran_mpacktime = MSGPACKTIME;
962           break;
963
964         case 'x':
965           if (rts_argv[arg][3] != '\0')
966             RTSflags.GranFlags.gran_mtidytime = decode(rts_argv[arg]+3);
967           else
968             RTSflags.GranFlags.gran_mtidytime = 0;
969           break;
970
971         case 'r':
972           if (rts_argv[arg][3] != '\0')
973             RTSflags.GranFlags.gran_munpacktime = decode(rts_argv[arg]+3);
974           else
975             RTSflags.GranFlags.gran_munpacktime = MSGUNPACKTIME;
976           break;
977           
978         case 'g':
979           if (rts_argv[arg][3] != '\0')
980             RTSflags.GranFlags.gran_fetchtime = decode(rts_argv[arg]+3);
981           else
982             RTSflags.GranFlags.gran_fetchtime = FETCHTIME;
983           break;
984           
985         case 'n':
986           if (rts_argv[arg][3] != '\0')
987             RTSflags.GranFlags.gran_gunblocktime = decode(rts_argv[arg]+3);
988           else
989             RTSflags.GranFlags.gran_gunblocktime = GLOBALUNBLOCKTIME;
990           break;
991
992         case 'u':
993           if (rts_argv[arg][3] != '\0')
994             RTSflags.GranFlags.gran_lunblocktime = decode(rts_argv[arg]+3);
995           else
996             RTSflags.GranFlags.gran_lunblocktime = LOCALUNBLOCKTIME;
997           break;
998
999         /* Thread-related metrics */
1000         case 't':
1001           if (rts_argv[arg][3] != '\0')
1002             RTSflags.GranFlags.gran_threadcreatetime = decode(rts_argv[arg]+3);
1003           else
1004             RTSflags.GranFlags.gran_threadcreatetime = THREADCREATETIME;
1005           break;
1006           
1007         case 'q':
1008           if (rts_argv[arg][3] != '\0')
1009             RTSflags.GranFlags.gran_threadqueuetime = decode(rts_argv[arg]+3);
1010           else
1011             RTSflags.GranFlags.gran_threadqueuetime = THREADQUEUETIME;
1012           break;
1013           
1014         case 'c':
1015           if (rts_argv[arg][3] != '\0')
1016             RTSflags.GranFlags.gran_threadscheduletime = decode(rts_argv[arg]+3);
1017           else
1018             RTSflags.GranFlags.gran_threadscheduletime = THREADSCHEDULETIME;
1019           
1020           RTSflags.GranFlags.gran_threadcontextswitchtime = RTSflags.GranFlags.gran_threadscheduletime
1021             + RTSflags.GranFlags.gran_threaddescheduletime;
1022           break;
1023
1024         case 'd':
1025           if (rts_argv[arg][3] != '\0')
1026             RTSflags.GranFlags.gran_threaddescheduletime = decode(rts_argv[arg]+3);
1027           else
1028             RTSflags.GranFlags.gran_threaddescheduletime = THREADDESCHEDULETIME;
1029           
1030           RTSflags.GranFlags.gran_threadcontextswitchtime = RTSflags.GranFlags.gran_threadscheduletime
1031             + RTSflags.GranFlags.gran_threaddescheduletime;
1032           break;
1033
1034         /* Instruction Cost Metrics */
1035         case 'A':
1036           if (rts_argv[arg][3] != '\0')
1037             RTSflags.GranFlags.gran_arith_cost = decode(rts_argv[arg]+3);
1038           else
1039             RTSflags.GranFlags.gran_arith_cost = ARITH_COST;
1040           break;
1041
1042         case 'F':
1043           if (rts_argv[arg][3] != '\0')
1044             RTSflags.GranFlags.gran_float_cost = decode(rts_argv[arg]+3);
1045           else
1046             RTSflags.GranFlags.gran_float_cost = FLOAT_COST;
1047           break;
1048                       
1049         case 'B':
1050           if (rts_argv[arg][3] != '\0')
1051             RTSflags.GranFlags.gran_branch_cost = decode(rts_argv[arg]+3);
1052           else
1053             RTSflags.GranFlags.gran_branch_cost = BRANCH_COST;
1054           break;
1055
1056         case 'L':
1057           if (rts_argv[arg][3] != '\0')
1058             RTSflags.GranFlags.gran_load_cost = decode(rts_argv[arg]+3);
1059           else
1060             RTSflags.GranFlags.gran_load_cost = LOAD_COST;
1061           break;
1062           
1063         case 'S':
1064           if (rts_argv[arg][3] != '\0')
1065             RTSflags.GranFlags.gran_store_cost = decode(rts_argv[arg]+3);
1066           else
1067             RTSflags.GranFlags.gran_store_cost = STORE_COST;
1068           break;
1069
1070         case 'H':
1071           if (rts_argv[arg][3] != '\0')
1072             RTSflags.GranFlags.gran_heapalloc_cost = decode(rts_argv[arg]+3);
1073           else
1074             RTSflags.GranFlags.gran_heapalloc_cost = 0;
1075           break;
1076
1077         case 'y':
1078           RTSflags.GranFlags.DoReScheduleOnFetch = rtsTrue;
1079           if (rts_argv[arg][3] != '\0')
1080             RTSflags.GranFlags.FetchStrategy = decode(rts_argv[arg]+3);
1081           if (RTSflags.GranFlags.FetchStrategy == 0)
1082             RTSflags.GranFlags.DoReScheduleOnFetch = rtsFalse;
1083           else
1084             RTSflags.GranFlags.FetchStrategy = 2; /* default: fetch everything */
1085           break;
1086           
1087         case 'K':   /* sort overhead (per elem in spark list) */
1088           if (rts_argv[arg][3] != '\0')
1089             RTSflags.GranFlags.gran_pri_spark_overhead = decode(rts_argv[arg]+3);
1090           else
1091             RTSflags.GranFlags.gran_pri_spark_overhead = PRI_SPARK_OVERHEAD;
1092           fprintf(stderr,"Overhead for pri spark: %d (per elem).\n",
1093                          RTSflags.GranFlags.gran_pri_spark_overhead);
1094           break;
1095
1096         case 'O':  /* sort overhead (per elem in spark list) */
1097           if (rts_argv[arg][3] != '\0')
1098             RTSflags.GranFlags.gran_pri_sched_overhead = decode(rts_argv[arg]+3);
1099           else
1100             RTSflags.GranFlags.gran_pri_sched_overhead = PRI_SCHED_OVERHEAD;
1101           fprintf(stderr,"Overhead for pri sched: %d (per elem).\n",
1102                        RTSflags.GranFlags.gran_pri_sched_overhead);
1103           break;
1104
1105         /* General Parameters */
1106         case 'p':
1107           if (rts_argv[arg][3] != '\0')
1108             {
1109               RTSflags.GranFlags.proc = decode(rts_argv[arg]+3);
1110               if (RTSflags.GranFlags.proc==0) {
1111                   enable_GrAnSimLight(); /* set flags for GrAnSim-Light mode */
1112               } else if (RTSflags.GranFlags.proc > MAX_PROC || 
1113                          RTSflags.GranFlags.proc < 1)
1114                 {
1115                   fprintf(stderr,"setupRtsFlags: no more than %u processors
1116 allowed\n", 
1117                           MAX_PROC);
1118                   *error = rtsTrue;
1119                 }
1120             }
1121           else
1122             RTSflags.GranFlags.proc = MAX_PROC;
1123           break;
1124
1125         case 'f':
1126           if (rts_argv[arg][3] != '\0')
1127             RTSflags.GranFlags.max_fishes = decode(rts_argv[arg]+3);
1128           else
1129             RTSflags.GranFlags.max_fishes = 1;
1130           break;
1131           
1132         case 'w':
1133           if (rts_argv[arg][3] != '\0')
1134             RTSflags.GranFlags.time_slice = decode(rts_argv[arg]+3);
1135           else
1136             RTSflags.GranFlags.time_slice = GRAN_TIME_SLICE;
1137           break;
1138           
1139         case 'C':
1140           RTSflags.GranFlags.DoAlwaysCreateThreads=rtsTrue;
1141           RTSflags.GranFlags.DoThreadMigration=rtsTrue;
1142           break;
1143
1144         case 'G':
1145           fprintf(stderr,"Bulk fetching enabled.\n");
1146           RTSflags.GranFlags.DoGUMMFetching=rtsTrue;
1147           break;
1148           
1149         case 'M':
1150           fprintf(stderr,"Thread migration enabled.\n");
1151           RTSflags.GranFlags.DoThreadMigration=rtsTrue;
1152           break;
1153
1154         case 'R':
1155           fprintf(stderr,"Fair Scheduling enabled.\n");
1156           RTSflags.GranFlags.DoFairSchedule=rtsTrue;
1157           break;
1158           
1159         case 'I':
1160           fprintf(stderr,"Priority Scheduling enabled.\n");
1161           RTSflags.GranFlags.DoPriorityScheduling=rtsTrue;
1162           break;
1163
1164         case 'T':
1165           RTSflags.GranFlags.DoStealThreadsFirst=rtsTrue;
1166           RTSflags.GranFlags.DoThreadMigration=rtsTrue;
1167           break;
1168           
1169         case 'Z':
1170           RTSflags.GranFlags.DoReScheduleOnFetch=rtsTrue;
1171           break;
1172           
1173         case 'z':
1174           RTSflags.GranFlags.SimplifiedFetch=rtsTrue;
1175           break;
1176           
1177         case 'N':
1178           RTSflags.GranFlags.PreferSparksOfLocalNodes=rtsTrue;
1179           break;
1180           
1181         case 'b':
1182           RTSflags.GranFlags.granSimStats_Binary=rtsTrue;
1183           break;
1184           
1185         case 'P':
1186           RTSflags.GranFlags.granSimStats=rtsTrue;
1187           break;
1188
1189         case 's':
1190           RTSflags.GranFlags.granSimStats_Sparks=rtsTrue;
1191           break;
1192
1193         case 'h':
1194           RTSflags.GranFlags.granSimStats_Heap=rtsTrue;
1195           break;
1196
1197         case 'U':
1198           RTSflags.GranFlags.labelling=rtsTrue;
1199           break;
1200
1201         case 'Y':   /* syntax: -bY<n>[,<n>]  n ... pos int */ 
1202           if (rts_argv[arg][3] != '\0') {
1203             char *arg0, *tmp;
1204             
1205             arg0 = rts_argv[arg]+3;
1206             if ((tmp = strstr(arg0,","))==NULL) {
1207               RTSflags.GranFlags.SparkPriority = decode(arg0);
1208               fprintf(stderr,"SparkPriority: %u.\n",RTSflags.GranFlags.SparkPriority);
1209             } else {
1210               *(tmp++) = '\0'; 
1211               RTSflags.GranFlags.SparkPriority = decode(arg0);
1212               RTSflags.GranFlags.SparkPriority2 = decode(tmp);
1213               fprintf(stderr,"SparkPriority: %u.\n",
1214                       RTSflags.GranFlags.SparkPriority);
1215               fprintf(stderr,"SparkPriority2:%u.\n",
1216                       RTSflags.GranFlags.SparkPriority2);
1217               if (RTSflags.GranFlags.SparkPriority2 < 
1218                   RTSflags.GranFlags.SparkPriority) {
1219                 fprintf(stderr,"WARNING: 2nd pri < main pri (%u<%u); 2nd pri has no effect\n",
1220                         RTSflags.GranFlags.SparkPriority2,
1221                         RTSflags.GranFlags.SparkPriority);
1222               }
1223             }
1224           } else {
1225             /* plain pri spark is now invoked with -bX  
1226                RTSflags.GranFlags.DoPrioritySparking = 1;
1227                fprintf(stderr,"PrioritySparking.\n");
1228             */
1229           }
1230           break;
1231
1232         case 'Q':
1233           if (rts_argv[arg][3] != '\0') {
1234             RTSflags.GranFlags.ThunksToPack = decode(rts_argv[arg]+3);
1235           } else {
1236             RTSflags.GranFlags.ThunksToPack = 1;
1237           }
1238           fprintf(stderr,"Thunks To Pack in one packet: %u.\n",
1239                   RTSflags.GranFlags.ThunksToPack);
1240           break;
1241                       
1242         case 'e':
1243           RTSflags.GranFlags.RandomSteal = rtsFalse;
1244           fprintf(stderr,"Deterministic mode (no random stealing)\n");
1245                       break;
1246
1247           /* The following class of options contains eXperimental */
1248           /* features in connection with exploiting granularity */
1249           /* information. I.e. if -bY is chosen these options */
1250           /* tell the RTS what to do with the supplied info --HWL */
1251
1252         case 'W':
1253           if (rts_argv[arg][3] != '\0') {
1254             RTSflags.GranFlags.packBufferSize_internal = decode(rts_argv[arg]+3);
1255           } else {
1256             RTSflags.GranFlags.packBufferSize_internal = GRANSIM_DEFAULT_PACK_BUFFER_SIZE;
1257           }
1258           fprintf(stderr,"Size of GranSim internal pack buffer: %u.\n",
1259                   RTSflags.GranFlags.packBufferSize_internal);
1260           break;
1261                       
1262         case 'X':
1263           switch(rts_argv[arg][3]) {
1264             
1265             case '\0':
1266               RTSflags.GranFlags.DoPrioritySparking = 1;
1267               fprintf(stderr,"Priority Sparking with Normal Priorities.\n");
1268               RTSflags.GranFlags.InversePriorities = rtsFalse; 
1269               RTSflags.GranFlags.RandomPriorities = rtsFalse;
1270               RTSflags.GranFlags.IgnorePriorities = rtsFalse;
1271               break;
1272                         
1273             case 'I':
1274               RTSflags.GranFlags.DoPrioritySparking = 1;
1275               fprintf(stderr,"Priority Sparking with Inverse Priorities.\n");
1276               RTSflags.GranFlags.InversePriorities++; 
1277               break;
1278               
1279             case 'R': 
1280               RTSflags.GranFlags.DoPrioritySparking = 1;
1281               fprintf(stderr,"Priority Sparking with Random Priorities.\n");
1282               RTSflags.GranFlags.RandomPriorities++;
1283               break;
1284               
1285             case 'N':
1286               RTSflags.GranFlags.DoPrioritySparking = 1;
1287               fprintf(stderr,"Priority Sparking with No Priorities.\n");
1288               RTSflags.GranFlags.IgnorePriorities++;
1289               break;
1290               
1291             default:
1292               bad_option( rts_argv[arg] );
1293               break;
1294           }
1295           break;
1296
1297         case '-':
1298           switch(rts_argv[arg][3]) {
1299             
1300             case 'C':
1301               RTSflags.GranFlags.DoAlwaysCreateThreads=rtsFalse;
1302               RTSflags.GranFlags.DoThreadMigration=rtsFalse;
1303               break;
1304
1305             case 'G':
1306               RTSflags.GranFlags.DoGUMMFetching=rtsFalse;
1307               break;
1308               
1309             case 'M':
1310               RTSflags.GranFlags.DoThreadMigration=rtsFalse;
1311               break;
1312
1313             case 'R':
1314               RTSflags.GranFlags.DoFairSchedule=rtsFalse;
1315               break;
1316
1317             case 'T':
1318               RTSflags.GranFlags.DoStealThreadsFirst=rtsFalse;
1319               RTSflags.GranFlags.DoThreadMigration=rtsFalse;
1320               break;
1321
1322             case 'Z':
1323               RTSflags.GranFlags.DoReScheduleOnFetch=rtsFalse;
1324               break;
1325               
1326             case 'N':
1327               RTSflags.GranFlags.PreferSparksOfLocalNodes=rtsFalse;
1328                          break;
1329                          
1330             case 'P':
1331               RTSflags.GranFlags.granSimStats_suppressed=rtsTrue;
1332               break;
1333
1334             case 's':
1335               RTSflags.GranFlags.granSimStats_Sparks=rtsFalse;
1336               break;
1337             
1338             case 'h':
1339               RTSflags.GranFlags.granSimStats_Heap=rtsFalse;
1340               break;
1341             
1342             case 'b':
1343               RTSflags.GranFlags.granSimStats_Binary=rtsFalse;
1344               break;
1345                          
1346             case 'X':
1347               RTSflags.GranFlags.DoPrioritySparking = rtsFalse;
1348               break;
1349
1350             case 'Y':
1351               RTSflags.GranFlags.DoPrioritySparking = rtsFalse;
1352               RTSflags.GranFlags.SparkPriority = rtsFalse;
1353               break;
1354
1355             case 'I':
1356               RTSflags.GranFlags.DoPriorityScheduling = rtsFalse;
1357               break;
1358
1359             case 'e':
1360               RTSflags.GranFlags.RandomSteal = rtsFalse;
1361               break;
1362
1363             default:
1364               bad_option( rts_argv[arg] );
1365               break;
1366           }
1367           break;
1368
1369 #  if defined(GRAN_CHECK) && defined(GRAN)
1370         case 'D':
1371           switch(rts_argv[arg][3]) {
1372             case 'Q':    /* Set pack buffer size (same as 'Q' in GUM) */
1373               if (rts_argv[arg][4] != '\0') {
1374                 RTSflags.GranFlags.packBufferSize = decode(rts_argv[arg]+4);
1375                 fprintf(stderr,"Pack buffer size: %d\n",
1376                         RTSflags.GranFlags.packBufferSize);
1377               } else {
1378                 fprintf(stderr, "setupRtsFlags: missing size of PackBuffer (for -Q)\n");
1379                 error = rtsTrue;
1380               }
1381               break;
1382
1383             case 'e':       /* event trace */
1384               fprintf(stderr,"Printing event trace.\n");
1385               RTSflags.GranFlags.event_trace=rtsTrue;
1386               break;
1387               
1388             case 'f':
1389               fprintf(stderr,"Printing forwarding of FETCHNODES.\n");
1390               RTSflags.GranFlags.debug |= 0x2; /* print fwd messages */
1391               break;
1392
1393             case 'z':
1394               fprintf(stderr,"Check for blocked on fetch.\n");
1395               RTSflags.GranFlags.debug |= 0x4; /* debug non-reschedule-on-fetch */
1396               break;
1397               
1398             case 't':
1399               fprintf(stderr,"Check for TSO asleep on fetch.\n");
1400               RTSflags.GranFlags.debug |= 0x10; /* debug TSO asleep for fetch  */
1401               break;
1402
1403             case 'E':
1404               fprintf(stderr,"Printing event statistics.\n");
1405               RTSflags.GranFlags.debug |= 0x20; /* print event statistics   */
1406               break;
1407               
1408             case 'F':
1409               fprintf(stderr,"Prohibiting forward.\n");
1410               RTSflags.GranFlags.NoForward = rtsTrue; /* prohibit forwarding   */
1411               break;
1412               
1413             case 'm':
1414               fprintf(stderr,"Printing fetch misses.\n");
1415               RTSflags.GranFlags.PrintFetchMisses = rtsTrue; /* prohibit forwarding   */
1416               break;
1417
1418             case 'd':
1419               fprintf(stderr,"Debug mode.\n");
1420               RTSflags.GranFlags.debug |= 0x40; 
1421                             break;
1422
1423             case 'D':
1424               fprintf(stderr,"Severe debug mode.\n");
1425               RTSflags.GranFlags.debug |= 0x80; 
1426               break;
1427               
1428             case 'q':
1429               fprintf(stderr,"FULL event trace.\n");
1430               RTSflags.GranFlags.event_trace_all =rtsTrue;
1431               break;
1432
1433             case 'G':
1434               fprintf(stderr,"Debugging packet fetching.\n");
1435               RTSflags.GranFlags.debug |= 0x100; 
1436               break;
1437               
1438             case 'n':
1439               fprintf(stderr,"Ignore events till end of time slice\n");
1440               RTSflags.GranFlags.debug |= 0x200; 
1441               IgnoreEvents = rtsTrue;
1442               break;
1443
1444             case 'S':
1445               fprintf(stderr,"Check that spark queues are sorted.\n");
1446               RTSflags.GranFlags.debug |= 0x400; 
1447               break;
1448
1449             case 'H':
1450               fprintf(stderr,"Print heap allocation messages (RBH).\n");
1451               RTSflags.GranFlags.debug |= 0x800; 
1452               break;
1453
1454             case 'p':
1455               fprintf(stderr,"Debug breadth-first pruning.\n");
1456               RTSflags.GranFlags.debug |= 0x1000; 
1457               break;
1458               
1459             case 'r':
1460               fprintf(stderr,"Debug random stealing.\n");
1461               RTSflags.GranFlags.debug |= 0x2000; 
1462               break;
1463
1464             case 'B':
1465               fprintf(stderr,"Debug busyness.\n");
1466               RTSflags.GranFlags.debug |= 0x4000; 
1467               break;
1468
1469             case 'P':
1470               fprintf(stderr,"Debug pack buffer handling.\n");
1471               RTSflags.GranFlags.debug |= 0x8000; 
1472               break;
1473
1474             case 's':
1475               fprintf(stderr,"Debug spark-queue manipulations.\n");
1476               RTSflags.GranFlags.debug |= 0x10000; 
1477               break;
1478               
1479             case ':':
1480               fprintf(stderr,"Debug GrAnSim Light.\n");
1481               RTSflags.GranFlags.debug |= 0x20000; 
1482               break;
1483               
1484             case '\0':
1485               RTSflags.GranFlags.debug = 1;
1486               break;
1487
1488             default:
1489               bad_option( rts_argv[arg] );
1490               break;
1491           }
1492           break;
1493 #  endif  /* GRAN_CHECK */
1494       default:
1495         bad_option( rts_argv[arg] );
1496         break;
1497      }
1498 }      
1499 #endif /* GRAN */
1500 \end{code}
1501
1502 %************************************************************************
1503 %*                                                                      *
1504 \subsection{Profiling RTS Arguments}
1505 %*                                                                      *
1506 %************************************************************************
1507
1508 \begin{code}
1509 I_ MaxResidency = 0;     /* in words; for stats only */
1510 I_ ResidencySamples = 0; /* for stats only */
1511
1512 void
1513 initSM(void)
1514 {
1515     RTSflags.GcFlags.minAllocAreaSize
1516       = (I_) (RTSflags.GcFlags.heapSize * RTSflags.GcFlags.pcFreeHeap / 100);
1517     /*
1518         This needs to be here, in case the user changed some of these
1519         values with a "hook".
1520     */
1521 }
1522 \end{code}
1523
1524 %************************************************************************
1525 %*                                                                      *
1526 \subsection{Utility bits}
1527 %*                                                                      *
1528 %************************************************************************
1529
1530 \begin{code}
1531 static FILE *           /* return NULL on error */
1532 open_stats_file (
1533     I_ arg,
1534     int argc, char *argv[],
1535     int rts_argc, char *rts_argv[],
1536     const char *FILENAME_FMT)
1537 {
1538     FILE *f = NULL;
1539
1540     if (strequal(rts_argv[arg]+2, "stderr")) /* use real stderr */
1541         f = stderr;
1542     else if (rts_argv[arg][2] != '\0')      /* stats file specified */
1543         f = fopen(rts_argv[arg]+2,"w");
1544     else {
1545         char stats_filename[STATS_FILENAME_MAXLEN]; /* default <program>.<ext> */
1546         sprintf(stats_filename, FILENAME_FMT, argv[0]);
1547         f = fopen(stats_filename,"w");
1548     }
1549     if (f == NULL) {
1550         fprintf(stderr, "Can't open stats file %s\n", rts_argv[arg]+2);
1551     } else {
1552         /* Write argv and rtsv into start of stats file */
1553         I_ count;
1554         for(count = 0; count < argc; count++)
1555             fprintf(f, "%s ", argv[count]);
1556         fprintf(f, "+RTS ");
1557         for(count = 0; count < rts_argc; count++)
1558             fprintf(f, "%s ", rts_argv[count]);
1559         fprintf(f, "\n");
1560     }
1561
1562     return(f);
1563 }
1564
1565 static I_
1566 decode(const char *s)
1567 {
1568     I_ c;
1569     StgDouble m;
1570
1571     if (!*s)
1572         return 0;
1573
1574     m = atof(s);
1575     c = s[strlen(s)-1];
1576
1577     if (c == 'g' || c == 'G')
1578         m *= 1000*1000*1000;    /* UNchecked! */
1579     else if (c == 'm' || c == 'M')
1580         m *= 1000*1000;                 /* We do not use powers of 2 (1024) */
1581     else if (c == 'k' || c == 'K')      /* to avoid possible bad effects on */
1582         m *= 1000;                      /* a direct-mapped cache.           */ 
1583     else if (c == 'w' || c == 'W')
1584         m *= sizeof(W_);
1585
1586     return (I_)m;
1587 }
1588
1589 static void
1590 bad_option(const char *s)
1591 {
1592   fflush(stdout);
1593   fprintf(stderr, "initSM: Bad RTS option: %s\n", s);
1594   EXIT(EXIT_FAILURE);
1595 }               
1596 \end{code}