2 % (c) The GRASP/AQUA Project, Glasgow University, 1995
4 \section{Runtime-system runtime flags}
6 Everything to do with RTS runtime flags, including RTS parameters
7 that can be set by them, either directly or indirectly.
9 @rtsFlags.lh@ defines the data structure that holds all of them.
14 struct RTS_FLAGS RTSflags; /* actually declare the data structure */
15 struct ALL_FLAGS AllFlags;
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);
25 long strtol PROTO((const char *, char **, int));
28 %************************************************************************
30 \subsection{Initial default values for @RTSFlags@}
32 %************************************************************************
36 initRtsFlagsDefaults (STG_NO_ARGS)
38 RTSflags.GcFlags.statsFile = NULL;
39 RTSflags.GcFlags.giveStats = NO_GC_STATS;
41 RTSflags.GcFlags.stksSize = 0x10002; /* 2^16 = 16Kwords = 64Kbytes */
42 RTSflags.GcFlags.heapSize = 0x100002; /* 2^20 = 1Mwords = 4Mbytes */
43 RTSflags.GcFlags.allocAreaSize = 0x4002; /* 2^14 = 16Kwords = 64Kbytes;
44 plus 2 cache-friendly words */
45 RTSflags.GcFlags.allocAreaSizeGiven = rtsFalse;
46 RTSflags.GcFlags.specifiedOldGenSize= 0; /* means: use all heap available */
47 RTSflags.GcFlags.pcFreeHeap = 3; /* 3% */
48 /* minAllocAreaSize is derived; set in initSM,
49 after we know pcFreeHeap and heapSize */
51 RTSflags.GcFlags.force2s = rtsFalse;
52 RTSflags.GcFlags.forceGC = rtsFalse;
53 RTSflags.GcFlags.forcingInterval = 5000000; /* 5MB (or words?) */
54 RTSflags.GcFlags.ringBell = rtsFalse;
55 RTSflags.GcFlags.trace = 0; /* not turned on */
57 RTSflags.GcFlags.lazyBlackHoling = rtsTrue;
58 RTSflags.GcFlags.doSelectorsAtGC = rtsTrue;
59 RTSflags.GcFlags.squeezeUpdFrames = rtsTrue;
61 #if defined(PROFILING) || defined(PAR)
62 RTSflags.CcFlags.doCostCentres = 0;
63 RTSflags.CcFlags.sortBy = SORTCC_TIME;
65 /* "ctxtSwitchTicks", "profilerTicks", & "msecsPerTick" are
66 derived info, so they are set after ctxtSwitchTime has been
69 #endif /* PROFILING or PAR */
72 RTSflags.ProfFlags.doHeapProfile = rtsFalse;
73 #endif /* PROFILING */
76 RTSflags.ConcFlags.ctxtSwitchTime = CS_MIN_MILLISECS; /* In milliseconds */
77 RTSflags.ConcFlags.maxThreads = 32;
78 RTSflags.ConcFlags.stkChunkSize = 1024;
79 RTSflags.ConcFlags.maxLocalSparks = 500;
80 #endif /* CONCURRENT */
83 RTSflags.ParFlags.parallelStats = rtsFalse;
84 RTSflags.ParFlags.granSimStats = rtsFalse;
85 RTSflags.ParFlags.granSimStats_Binary = rtsFalse;
87 RTSflags.ParFlags.outputDisabled = rtsFalse;
89 RTSflags.ParFlags.packBufferSize = 1024;
93 RTSflags.TickyFlags.showTickyStats = rtsFalse;
94 RTSflags.TickyFlags.tickyFile = NULL;
96 AllFlags.doUpdEntryCounts = rtsTrue; /*ToDo:move? */
101 %************************************************************************
103 \subsection{Usage message for runtime-system (RTS) flags}
105 %************************************************************************
111 "Usage: <prog> <args> [+RTS <rtsopts> | -RTS <args>] ... --RTS <args>",
113 " +RTS Indicates run time system options follow",
114 " -RTS Indicates program arguments follow",
115 " --RTS Indicates that ALL subsequent arguments will be given to the",
116 " program (including any of these RTS flags)",
118 "The following run time system options are available:",
120 " -? -f Prints this message and exits; the program is not executed",
122 " -K<size> Sets the stack size (default 64k) Egs: -K32k -K512k",
123 " -H<size> Sets the heap size (default 4M) -H512k -H16M",
124 " -s<file> Summary GC statistics (default file: <program>.stat)",
125 " -S<file> Detailed GC statistics (with -Sstderr going to stderr)",
128 " -M<n>% Sets minimum size of alloc area as % of heap (default 3%)",
129 " -A<size> Fixes size of alloc area, overriding any minimum (-A gives 64k)",
130 " -G<size> Fixes size of major generation (default is dynamic threshold)",
131 " -F2s Forces program compiled for Appel gc to use 2s collection",
134 " -A<size> Specifies size of alloc area (default 64k)",
135 " -G<size> Fixes size of major generation (default is available heap)",
136 " -F2s Forces program compiled for Gen gc to use 2s collection",
138 " -M<n>% Minimum % of heap which must be available (default 3%)",
139 " -A<size> Fixes size of heap area allocated between GCs (-A gives 64k)",
142 " -j<size> Forces major GC at every <size> bytes allocated",
144 " -u<percent> Fixes residency threshold at which mode switches (range 0.0..0.95)",
147 " -N No black-holing during GC (for use when a signal handler is present)",
148 " -Z Don't squeeze out update frames on stack overflow",
149 " -B Sound the bell at the start of each (major) garbage collection",
150 #if defined(PROFILING) || defined(PAR)
152 " -p<sort> Produce cost centre time profile (output file <program>.prof)",
153 " sort: T = time (default), A = alloc, C = cost centre label",
154 " -P<sort> Produce serial time profile (output file <program>.time)",
155 " and a -p profile with detailed caf/enter/tick/alloc info",
156 # if defined(PROFILING)
158 " -h<break-down> Heap residency profile (output file <program>.hp)",
159 " break-down: C = cost centre (default), M = module, G = group",
160 " D = closure description, Y = type description",
161 " T<ints>,<start> = time closure created",
162 " ints: no. of interval bands plotted (default 18)",
163 " start: seconds after which intervals start (default 0.0)",
164 " A subset of closures may be selected by the attached cost centre using:",
165 " -c{mod:lab,mod:lab...}, specific module:label cost centre(s)",
166 " -m{mod,mod...} all cost centres from the specified modules(s)",
167 " -g{grp,grp...} all cost centres from the specified group(s)",
168 " Selections can also be made by description, type, kind and age:",
169 " -d{des,des...} closures with specified closure descriptions",
170 " -y{typ,typ...} closures with specified type descriptions",
171 " -k{knd,knd...} closures of the specified kinds",
172 " -a<age> closures which survived <age> complete intervals",
173 " The selection logic used is summarised as follows:",
174 " ([-c] or [-m] or [-g]) and ([-d] or [-y] or [-k]) and [-a]",
175 " where an option is true if not specified",
178 " -z<tbl><size> set hash table <size> for <tbl> (C, M, G, D or Y)",
180 " -i<secs> Number of seconds in a profiling interval (default 1.0):",
181 " heap profile (-h) and/or serial time profile (-P) frequency",
182 #endif /* PROFILING or PAR */
184 #if defined(TICKY_TICKY)
185 " -r<file> Produce reduction profiling statistics (with -rstderr for stderr)",
188 " -T<level> Trace garbage collection execution (debugging)",
192 " -N<n> Use <n> PVMish processors in parallel (default: 2)",
193 /* NB: the -N<n> is implemented by the driver!! */
195 " -C<secs> Context-switch interval in seconds",
196 " (0 or no argument means switch as often as possible)",
197 " the default is .01 sec; resolution is .01 sec",
198 " -e<size> Size of spark pools (default 100)",
200 " -q Enable activity profile (output files in ~/<program>*.gr)",
201 " -qb Enable binary activity profile (output file /tmp/<program>.gb)",
202 " -Q<size> Set pack-buffer size (default: 1024)",
204 " -q[v] Enable quasi-parallel profile (output file <program>.qp)",
206 " -t<num> Set maximum number of advisory threads per PE (default 32)",
207 " -o<num> Set stack chunk size (default 1024)",
209 " -d Turn on PVM-ish debugging",
210 " -O Disable output for performance measurement",
212 #endif /* CONCURRENT */
214 "Other RTS options may be available for programs compiled a different way.",
215 "The GHC User's Guide has full details.",
221 %************************************************************************
223 \subsection{Processing command-line arguments to set @RTSFlags@}
225 %************************************************************************
232 extern double atof();
233 /* no proto because some machines use const and some do not */
236 static __inline__ rtsBool
237 strequal(const char *a, const char * b)
239 return(strcmp(a, b) == 0);
243 setupRtsFlags(int *argc, char *argv[], int *rts_argc, char *rts_argv[])
245 rtsBool error = rtsFalse;
250 /* Remove directory from argv[0] -- default files in current directory */
252 if ((last_slash = (char *) strrchr(argv[0], '/')) != NULL)
253 strcpy(argv[0], last_slash+1);
255 /* Split arguments (argv) into PGM (argv) and RTS (rts_argv) parts */
256 /* argv[0] must be PGM argument -- leave in argv */
264 for (mode = PGM; arg < total_arg && ! strequal("--RTS", argv[arg]); arg++) {
265 if (strequal("+RTS", argv[arg])) {
268 else if (strequal("-RTS", argv[arg])) {
271 else if (mode == RTS && *rts_argc < MAX_RTS_ARGS-1) {
272 rts_argv[(*rts_argc)++] = argv[arg];
274 else if (mode == PGM) {
275 argv[(*argc)++] = argv[arg];
279 fprintf(stderr, "setupRtsFlags: Too many RTS arguments (max %d)\n",
284 if (arg < total_arg) {
285 /* arg must be --RTS; process remaining program arguments */
286 while (++arg < total_arg) {
287 argv[(*argc)++] = argv[arg];
290 argv[*argc] = (char *) 0;
291 rts_argv[*rts_argc] = (char *) 0;
293 /* Process RTS (rts_argv) part: mainly to determine statsfile */
295 for (arg = 0; arg < *rts_argc; arg++) {
296 if (rts_argv[arg][0] != '-') {
298 fprintf(stderr, "setupRtsFlags: Unexpected RTS argument: %s\n",
303 switch(rts_argv[arg][1]) {
305 /* process: general args, then PROFILING-only ones,
306 then CONCURRENT-only, PARallel-only, GRAN-only,
307 TICKY-only (same order as defined in RtsFlags.lh);
308 within those groups, mostly in case-insensitive
313 # define TICKY_BUILD_ONLY(x) x
315 # define TICKY_BUILD_ONLY(x) \
316 fprintf(stderr, "setupRtsFlags: GHC not built for: ticky-ticky stats\n"); \
320 #if (defined(PROFILING) || defined(PAR))
321 # define COST_CENTRE_USING_BUILD_ONLY(x) x
323 # define COST_CENTRE_USING_BUILD_ONLY(x) \
324 fprintf(stderr, "setupRtsFlags: GHC not built for: -prof or -parallel\n"); \
329 # define PROFILING_BUILD_ONLY(x)
331 # define PROFILING_BUILD_ONLY(x) \
332 fprintf(stderr, "setupRtsFlags: GHC not built for: -prof\n"); \
337 # define CONCURRENT_BUILD_ONLY(x)
339 # define CONCURRENT_BUILD_ONLY(x) \
340 fprintf(stderr, "setupRtsFlags: GHC not built for: -concurrent\n"); \
345 # define PAR_BUILD_ONLY(x)
347 # define PAR_BUILD_ONLY(x) \
348 fprintf(stderr, "setupRtsFlags: GHC not built for: -parallel\n"); \
353 # define GRAN_BUILD_ONLY(x)
355 # define GRAN_BUILD_ONLY(x) \
356 fprintf(stderr, "setupRtsFlags: GHC not built for: -gransim\n"); \
360 /* =========== GENERAL ========================== */
367 RTSflags.GcFlags.allocAreaSize
368 = decode(rts_argv[arg]+2) / sizeof(W_);
369 RTSflags.GcFlags.allocAreaSizeGiven = rtsTrue;
373 RTSflags.GcFlags.ringBell = rtsTrue;
377 if (strequal(rts_argv[arg]+2, "2s")) {
378 RTSflags.GcFlags.force2s = rtsTrue;
380 bad_option( rts_argv[arg] );
385 RTSflags.GcFlags.specifiedOldGenSize
386 = decode(rts_argv[arg]+2) / sizeof(W_);
390 RTSflags.GcFlags.stksSize = decode(rts_argv[arg]+2) / sizeof(W_);
392 if (RTSflags.GcFlags.stksSize == 0) bad_option( rts_argv[arg] );
396 RTSflags.GcFlags.heapSize = decode(rts_argv[arg]+2) / sizeof(W_);
397 /* user give size in *bytes* but "heapSize" is in *words* */
399 if (RTSflags.GcFlags.heapSize <= 0) bad_option(rts_argv[arg]);
402 case 'j': /* force GC option */
403 RTSflags.GcFlags.forceGC = rtsTrue;
404 if (rts_argv[arg][2]) {
405 RTSflags.GcFlags.forcingInterval
406 = decode(rts_argv[arg]+2) / sizeof(W_);
411 RTSflags.GcFlags.pcFreeHeap = atof(rts_argv[arg]+2);
413 if (RTSflags.GcFlags.pcFreeHeap < 0 || RTSflags.GcFlags.pcFreeHeap > 100)
414 bad_option( rts_argv[arg] );
418 RTSflags.GcFlags.lazyBlackHoling = rtsFalse;
422 RTSflags.GcFlags.doSelectorsAtGC = rtsFalse;
425 case 'S': /* NB: no difference at present ! */
427 RTSflags.GcFlags.giveStats ++; /* will be VERBOSE_GC_STATS */
429 /* Opening all those files would almost certainly fail... */
430 RTSflags.ParFlags.parallelStats = rtsTrue;
431 RTSflags.GcFlags.statsFile = stderr; /* temporary; ToDo: rm */
433 RTSflags.GcFlags.statsFile
434 = open_stats_file(arg, *argc, argv,
435 *rts_argc, rts_argv, STAT_FILENAME_FMT);
437 if (RTSflags.GcFlags.statsFile == NULL) error = rtsTrue;
442 if (rts_argv[arg][2] != '\0')
443 RTSflags.GcFlags.trace
444 = (W_) strtol(rts_argv[arg]+2, (char **)NULL, 0);
446 RTSflags.GcFlags.trace = 1; /* slightly weird; why, really? */
450 RTSflags.GcFlags.squeezeUpdFrames = rtsFalse;
453 /* =========== PROFILING ========================== */
455 case 'P': /* detailed cost centre profiling (time/alloc) */
456 COST_CENTRE_USING_BUILD_ONLY(
457 RTSflags.CcFlags.doCostCentres++;
459 case 'p': /* cost centre profiling (time/alloc) */
460 COST_CENTRE_USING_BUILD_ONLY(
461 RTSflags.CcFlags.doCostCentres++;
463 switch (rts_argv[arg][2]) {
467 RTSflags.CcFlags.sortBy = rts_argv[arg][2];
470 fprintf(stderr, "Invalid profiling sort option %s\n", rts_argv[arg]);
475 case 'i': /* serial profiling -- initial timer interval */
476 COST_CENTRE_USING_BUILD_ONLY(
477 interval_ticks = (I_) ((atof(rts_argv[arg]+2) * TICK_FREQUENCY));
478 if (interval_ticks <= 0)
482 case 'h': /* serial heap profile */
483 PROFILING_BUILD_ONLY(
484 switch (rts_argv[arg][2]) {
487 RTSflags.ProfFlags.doHeapProfile = HEAP_BY_CC;
490 RTSflags.ProfFlags.doHeapProfile = HEAP_BY_MOD;
493 RTSflags.ProfFlags.doHeapProfile = HEAP_BY_GRP;
496 RTSflags.ProfFlags.doHeapProfile = HEAP_BY_DESCR;
499 RTSflags.ProfFlags.doHeapProfile = HEAP_BY_TYPE;
502 RTSflags.ProfFlags.doHeapProfile = HEAP_BY_TIME;
503 if (rts_argv[arg][3]) {
504 char *start_str = strchr(rts_argv[arg]+3, ',');
506 if (start_str) *start_str = '\0';
508 if ((intervals = decode(rts_argv[arg]+3)) != 0) {
509 time_intervals = (hash_t) intervals;
510 /* ToDo: and what if it *is* zero intervals??? */
513 earlier_ticks = (I_)((atof(start_str + 1) * TICK_FREQUENCY));
518 fprintf(stderr, "Invalid heap profile option: %s\n",
524 case 'z': /* size of index tables */
525 PROFILING_BUILD_ONLY(
526 switch (rts_argv[arg][2]) {
528 max_cc_no = (hash_t) decode(rts_argv[arg]+3);
529 if (max_cc_no == 0) {
530 fprintf(stderr, "Bad number of cost centres %s\n", rts_argv[arg]);
535 max_mod_no = (hash_t) decode(rts_argv[arg]+3);
536 if (max_mod_no == 0) {
537 fprintf(stderr, "Bad number of modules %s\n", rts_argv[arg]);
542 max_grp_no = (hash_t) decode(rts_argv[arg]+3);
543 if (max_grp_no == 0) {
544 fprintf(stderr, "Bad number of groups %s\n", rts_argv[arg]);
549 max_descr_no = (hash_t) decode(rts_argv[arg]+3);
550 if (max_descr_no == 0) {
551 fprintf(stderr, "Bad number of closure descriptions %s\n", rts_argv[arg]);
556 max_type_no = (hash_t) decode(rts_argv[arg]+3);
557 if (max_type_no == 0) {
558 fprintf(stderr, "Bad number of type descriptions %s\n", rts_argv[arg]);
563 fprintf(stderr, "Invalid index table size option: %s\n",
569 case 'c': /* cost centre label select */
570 case 'm': /* cost centre module select */
571 case 'g': /* cost centre group select */
572 case 'd': /* closure descr select */
573 case 'y': /* closure type select */
574 case 'k': /* closure kind select */
575 PROFILING_BUILD_ONLY(
577 left = strchr(rts_argv[arg], '{');
578 right = strrchr(rts_argv[arg], '}');
579 if (! left || ! right ||
580 strrchr(rts_argv[arg], '{') != left ||
581 strchr(rts_argv[arg], '}') != right) {
582 fprintf(stderr, "Invalid heap profiling selection bracketing\n %s\n", rts_argv[arg]);
586 switch (rts_argv[arg][1]) {
587 case 'c': /* cost centre label select */
588 select_cc = left + 1;
590 case 'm': /* cost centre module select */
591 select_mod = left + 1;
593 case 'g': /* cost centre group select */
594 select_grp = left + 1;
596 case 'd': /* closure descr select */
597 select_descr = left + 1;
599 case 't': /* closure type select */
600 select_type = left + 1;
602 case 'k': /* closure kind select */
603 select_kind = left + 1;
609 /* =========== CONCURRENT ========================= */
610 case 'C': /* context switch interval */
611 CONCURRENT_BUILD_ONLY (
612 if (rts_argv[arg][2] == '\0')
613 RTSflags.ConcFlags.ctxtSwitchTime = 0;
617 /* Convert to milliseconds */
618 cst = (I_) ((atof(rts_argv[arg]+2) * 1000));
619 cst = (cst / CS_MIN_MILLISECS) * CS_MIN_MILLISECS;
620 if (cst < CS_MIN_MILLISECS)
621 cst = CS_MIN_MILLISECS;
623 RTSflags.ConcFlags.ctxtSwitchTime = cst;
628 CONCURRENT_BUILD_ONLY(
629 if (rts_argv[arg][2] != '\0') {
630 RTSflags.ConcFlags.maxThreads
631 = strtol(rts_argv[arg]+2, (char **) NULL, 10);
633 fprintf(stderr, "setupRtsFlags: missing size for -t\n");
639 CONCURRENT_BUILD_ONLY (
640 if (rts_argv[arg][2] != '\0') {
641 I_ size = decode(rts_argv[arg]+2);
643 if (size < MIN_STKO_CHUNK_SIZE)
644 size = MIN_STKO_CHUNK_SIZE;
646 RTSflags.ConcFlags.stkChunkSize = size;
648 fprintf(stderr, "setupRtsFlags: missing size for -o\n");
653 /* =========== PARALLEL =========================== */
655 CONCURRENT_BUILD_ONLY(
656 if (rts_argv[arg][2] != '\0') { /* otherwise, stick w/ the default */
658 RTSflags.ConcFlags.maxLocalSparks
659 = strtol(rts_argv[arg]+2, (char **) NULL, 10);
661 if (RTSflags.ConcFlags.maxLocalSparks <= 0) {
662 fprintf(stderr, "setupRtsFlags: bad value for -e\n");
670 RTSflags.ParFlags.outputDisabled = rtsTrue;
673 case 'q': /* activity profile option */
675 if (rts_argv[arg][2] == 'b')
676 RTSflags.ParFlags.granSimStats_Binary = rtsTrue;
678 RTSflags.ParFlags.granSimStats = rtsTrue;
682 case 'q': /* quasi-parallel profile option */
684 if (rts_argv[arg][2] == 'v')
691 case 'Q': /* Set pack buffer size */
693 if (rts_argv[arg][2] != '\0') {
694 RTSflags.ParFlags.packBufferSize = decode(rts_argv[arg]+2);
696 fprintf(stderr, "setupRtsFlags: missing size of PackBuffer (for -Q)\n");
701 /* =========== GRAN =============================== */
705 process_gran_option();
708 /* =========== TICKY ============================== */
710 case 'r': /* Basic profiling stats */
713 RTSflags.TickyFlags.showTickyStats = rtsTrue;
714 RTSflags.TickyFlags.tickyFile
715 = open_stats_file(arg, *argc, argv,
716 *rts_argc, rts_argv, TICKY_FILENAME_FMT);
718 if (RTSflags.TickyFlags.tickyFile == NULL) error = rtsTrue;
721 /* =========== OH DEAR ============================ */
723 fprintf(stderr, "setupRtsFlags: Unknown RTS option: %s\n",rts_argv[arg]);
733 for (p = usage_text; *p; p++)
734 fprintf(stderr, "%s\n", *p);
742 process_gran_option()
744 if (rts_argv[arg][2] != '\0') {
746 /* Should we emulate hbcpp */
747 if(strequal((rts_argv[arg]+2),"roken")) {
748 ++DoAlwaysCreateThreads;
749 strcpy(rts_argv[arg]+2,"oring");
752 /* or a ridiculously idealised simulator */
753 if(strequal((rts_argv[arg]+2),"oring")) {
754 gran_latency = gran_fetchtime = gran_additional_latency =
755 gran_gunblocktime = gran_lunblocktime
756 = gran_threadcreatetime = gran_threadqueuetime
757 = gran_threadscheduletime = gran_threaddescheduletime
758 = gran_threadcontextswitchtime
761 gran_mpacktime = gran_munpacktime = 0;
763 gran_arith_cost = gran_float_cost = gran_load_cost
764 = gran_store_cost = gran_branch_cost = 0;
766 gran_heapalloc_cost = 1;
768 /* ++DoFairSchedule; */
769 ++DoStealThreadsFirst;
771 RTSflags.ParFlags.granSimStats = rtsTrue;
774 /* or a ridiculously idealised simulator */
775 if(strequal((rts_argv[arg]+2),"onzo")) {
776 gran_latency = gran_fetchtime = gran_additional_latency =
777 gran_gunblocktime = gran_lunblocktime
778 = gran_threadcreatetime = gran_threadqueuetime
779 = gran_threadscheduletime = gran_threaddescheduletime
780 = gran_threadcontextswitchtime
783 gran_mpacktime = gran_munpacktime = 0;
785 /* Keep default values for these
786 gran_arith_cost = gran_float_cost = gran_load_cost
787 = gran_store_cost = gran_branch_cost = 0;
790 gran_heapalloc_cost = 1;
792 /* ++DoFairSchedule; */ /* -b-R */
793 /* ++DoStealThreadsFirst; */ /* -b-T */
794 ++DoReScheduleOnFetch; /* -bZ */
795 ++DoThreadMigration; /* -bM */
796 RTSflags.ParFlags.granSimStats = rtsTrue; /* -bP */
797 # if defined(GRAN_CHECK) && defined(GRAN)
798 debug = 0x20; /* print event statistics */
802 /* Communication and task creation cost parameters */
803 else switch(rts_argv[arg][2]) {
805 if (rts_argv[arg][3] != '\0')
807 gran_gunblocktime = gran_latency = decode(rts_argv[arg]+3);
808 gran_fetchtime = 2* gran_latency;
811 gran_latency = LATENCY;
815 if (rts_argv[arg][3] != '\0')
816 gran_additional_latency = decode(rts_argv[arg]+3);
818 gran_additional_latency = ADDITIONAL_LATENCY;
822 if (rts_argv[arg][3] != '\0')
823 gran_mpacktime = decode(rts_argv[arg]+3);
825 gran_mpacktime = MSGPACKTIME;
829 if (rts_argv[arg][3] != '\0')
830 gran_mtidytime = decode(rts_argv[arg]+3);
836 if (rts_argv[arg][3] != '\0')
837 gran_munpacktime = decode(rts_argv[arg]+3);
839 gran_munpacktime = MSGUNPACKTIME;
843 if (rts_argv[arg][3] != '\0')
844 gran_fetchtime = decode(rts_argv[arg]+3);
846 gran_fetchtime = FETCHTIME;
850 if (rts_argv[arg][3] != '\0')
851 gran_gunblocktime = decode(rts_argv[arg]+3);
853 gran_gunblocktime = GLOBALUNBLOCKTIME;
857 if (rts_argv[arg][3] != '\0')
858 gran_lunblocktime = decode(rts_argv[arg]+3);
860 gran_lunblocktime = LOCALUNBLOCKTIME;
863 /* Thread-related metrics */
865 if (rts_argv[arg][3] != '\0')
866 gran_threadcreatetime = decode(rts_argv[arg]+3);
868 gran_threadcreatetime = THREADCREATETIME;
872 if (rts_argv[arg][3] != '\0')
873 gran_threadqueuetime = decode(rts_argv[arg]+3);
875 gran_threadqueuetime = THREADQUEUETIME;
879 if (rts_argv[arg][3] != '\0')
880 gran_threadscheduletime = decode(rts_argv[arg]+3);
882 gran_threadscheduletime = THREADSCHEDULETIME;
884 gran_threadcontextswitchtime = gran_threadscheduletime
885 + gran_threaddescheduletime;
889 if (rts_argv[arg][3] != '\0')
890 gran_threaddescheduletime = decode(rts_argv[arg]+3);
892 gran_threaddescheduletime = THREADDESCHEDULETIME;
894 gran_threadcontextswitchtime = gran_threadscheduletime
895 + gran_threaddescheduletime;
898 /* Instruction Cost Metrics */
900 if (rts_argv[arg][3] != '\0')
901 gran_arith_cost = decode(rts_argv[arg]+3);
903 gran_arith_cost = ARITH_COST;
907 if (rts_argv[arg][3] != '\0')
908 gran_float_cost = decode(rts_argv[arg]+3);
910 gran_float_cost = FLOAT_COST;
914 if (rts_argv[arg][3] != '\0')
915 gran_branch_cost = decode(rts_argv[arg]+3);
917 gran_branch_cost = BRANCH_COST;
921 if (rts_argv[arg][3] != '\0')
922 gran_load_cost = decode(rts_argv[arg]+3);
924 gran_load_cost = LOAD_COST;
928 if (rts_argv[arg][3] != '\0')
929 gran_store_cost = decode(rts_argv[arg]+3);
931 gran_store_cost = STORE_COST;
935 if (rts_argv[arg][3] != '\0')
936 gran_heapalloc_cost = decode(rts_argv[arg]+3);
938 gran_heapalloc_cost = 0;
942 if (rts_argv[arg][3] != '\0')
943 FetchStrategy = decode(rts_argv[arg]+3);
945 FetchStrategy = 4; /* default: fetch everything */
948 /* General Parameters */
950 if (rts_argv[arg][3] != '\0')
952 max_proc = decode(rts_argv[arg]+3);
953 if(max_proc > MAX_PROC || max_proc < 1)
955 fprintf(stderr,"setupRtsFlags: no more than %u processors allowed\n", MAX_PROC);
964 ++DoAlwaysCreateThreads;
981 ++DoStealThreadsFirst;
986 ++DoReScheduleOnFetch;
994 ++PreferSparksOfLocalNodes;
998 RTSflags.ParFlags.granSimStats_Binary = rtsTrue;
1002 RTSflags.ParFlags.granSimStats = rtsTrue;
1010 switch(rts_argv[arg][3]) {
1013 DoAlwaysCreateThreads=0;
1014 DoThreadMigration=0;
1022 DoThreadMigration=0;
1030 DoStealThreadsFirst=0;
1031 DoThreadMigration=0;
1035 DoReScheduleOnFetch=0;
1039 PreferSparksOfLocalNodes=0;
1043 RTSflags.ParFlags.granSimStats = rtsFalse;
1052 RTSflags.ParFlags.granSimStats_Binary = rtsFalse;
1056 bad_option( rts_argv[arg] );
1061 # if defined(GRAN_CHECK) && defined(GRAN)
1063 switch(rts_argv[arg][3]) {
1064 case 'e': /* event trace */
1065 fprintf(stderr,"Printing event trace.\n");
1070 fprintf(stderr,"Printing forwarding of FETCHNODES.\n");
1071 debug |= 0x2; /* print fwd messages */
1075 fprintf(stderr,"Check for blocked on fetch.\n");
1076 debug |= 0x4; /* debug non-reschedule-on-fetch */
1080 fprintf(stderr,"Check for TSO asleep on fetch.\n");
1081 debug |= 0x10; /* debug TSO asleep for fetch */
1085 fprintf(stderr,"Printing event statistics.\n");
1086 debug |= 0x20; /* print event statistics */
1090 fprintf(stderr,"Prohibiting forward.\n");
1091 NoForward = 1; /* prohibit forwarding */
1095 fprintf(stderr,"Printing fetch misses.\n");
1096 PrintFetchMisses = 1; /* prohibit forwarding */
1100 fprintf(stderr,"Debug mode.\n");
1105 fprintf(stderr,"Severe debug mode.\n");
1114 bad_option( rts_argv[arg] );
1120 bad_option( rts_argv[arg] );
1125 RTSflags.ConcFlags.ctxtSwitchTime = 0;
1130 %************************************************************************
1132 \subsection{Profiling RTS Arguments}
1134 %************************************************************************
1137 I_ MaxResidency = 0; /* in words; for stats only */
1138 I_ ResidencySamples = 0; /* for stats only */
1143 RTSflags.GcFlags.minAllocAreaSize
1144 = (I_) (RTSflags.GcFlags.heapSize * RTSflags.GcFlags.pcFreeHeap / 100);
1146 This needs to be here, in case the user changed some of these
1147 values with a "hook".
1152 %************************************************************************
1154 \subsection{Utility bits}
1156 %************************************************************************
1159 static FILE * /* return NULL on error */
1162 int argc, char *argv[],
1163 int rts_argc, char *rts_argv[],
1164 const char *FILENAME_FMT)
1168 if (strequal(rts_argv[arg]+2, "stderr")) /* use real stderr */
1170 else if (rts_argv[arg][2] != '\0') /* stats file specified */
1171 f = fopen(rts_argv[arg]+2,"w");
1173 char stats_filename[STATS_FILENAME_MAXLEN]; /* default <program>.<ext> */
1174 sprintf(stats_filename, FILENAME_FMT, argv[0]);
1175 f = fopen(stats_filename,"w");
1178 fprintf(stderr, "Can't open stats file %s\n", rts_argv[arg]+2);
1180 /* Write argv and rtsv into start of stats file */
1182 for(count = 0; count < argc; count++)
1183 fprintf(f, "%s ", argv[count]);
1184 fprintf(f, "+RTS ");
1185 for(count = 0; count < rts_argc; count++)
1186 fprintf(f, "%s ", rts_argv[count]);
1194 decode(const char *s)
1205 if (c == 'g' || c == 'G')
1206 m *= 1000*1000*1000; /* UNchecked! */
1207 else if (c == 'm' || c == 'M')
1208 m *= 1000*1000; /* We do not use powers of 2 (1024) */
1209 else if (c == 'k' || c == 'K') /* to avoid possible bad effects on */
1210 m *= 1000; /* a direct-mapped cache. */
1211 else if (c == 'w' || c == 'W')
1218 bad_option(const char *s)
1221 fprintf(stderr, "initSM: Bad RTS option: %s\n", s);