% % (c) The GRASP/AQUA Project, Glasgow University, 1995 % \section{Runtime-system runtime flags} Everything to do with RTS runtime flags, including RTS parameters that can be set by them, either directly or indirectly. @rtsFlags.lh@ defines the data structure that holds all of them. \begin{code} #include "rtsdefs.h" struct RTS_FLAGS RTSflags; /* actually declare the data structure */ struct ALL_FLAGS AllFlags; /* some fwd decls */ static I_ decode(const char *); static void bad_option(const char *); static FILE * open_stats_file (I_ arg, int argc, char *argv[], int rts_argc, char *rts_argv[], const char *FILENAME_FMT); #ifdef GRAN static void process_gran_option(int arg, int *rts_argc, char *rts_argv[], rtsBool *error); #endif /* extern decls */ long strtol PROTO((const char *, char **, int)); \end{code} %************************************************************************ %* * \subsection{Initial default values for @RTSFlags@} %* * %************************************************************************ \begin{code} void initRtsFlagsDefaults (STG_NO_ARGS) { RTSflags.GcFlags.statsFile = NULL; RTSflags.GcFlags.giveStats = NO_GC_STATS; RTSflags.GcFlags.stksSize = 0x10002; /* 2^16 = 16Kwords = 64Kbytes */ RTSflags.GcFlags.heapSize = 0x100002; /* 2^20 = 1Mwords = 4Mbytes */ RTSflags.GcFlags.allocAreaSize = 0x4002; /* 2^14 = 16Kwords = 64Kbytes; plus 2 cache-friendly words */ RTSflags.GcFlags.allocAreaSizeGiven = rtsFalse; RTSflags.GcFlags.specifiedOldGenSize= 0; /* means: use all heap available */ RTSflags.GcFlags.pcFreeHeap = 3; /* 3% */ /* minAllocAreaSize is derived; set in initSM, after we know pcFreeHeap and heapSize */ RTSflags.GcFlags.force2s = rtsFalse; RTSflags.GcFlags.forceGC = rtsFalse; RTSflags.GcFlags.forcingInterval = 5000000; /* 5MB (or words?) */ RTSflags.GcFlags.ringBell = rtsFalse; RTSflags.GcFlags.trace = 0; /* not turned on */ RTSflags.GcFlags.lazyBlackHoling = rtsTrue; RTSflags.GcFlags.doSelectorsAtGC = rtsTrue; RTSflags.GcFlags.squeezeUpdFrames = rtsTrue; #if defined(PROFILING) || defined(PAR) RTSflags.CcFlags.doCostCentres = 0; RTSflags.CcFlags.sortBy = SORTCC_TIME; /* "ctxtSwitchTicks", "profilerTicks", & "msecsPerTick" are derived info, so they are set after ctxtSwitchTime has been determined. */ #endif /* PROFILING or PAR */ #ifdef PROFILING RTSflags.ProfFlags.doHeapProfile = rtsFalse; RTSflags.ProfFlags.ccSelector = NULL; RTSflags.ProfFlags.modSelector = NULL; RTSflags.ProfFlags.grpSelector = NULL; RTSflags.ProfFlags.descrSelector = NULL; RTSflags.ProfFlags.typeSelector = NULL; RTSflags.ProfFlags.kindSelector = NULL; #endif /* PROFILING */ #ifdef CONCURRENT RTSflags.ConcFlags.ctxtSwitchTime = CS_MIN_MILLISECS; /* In milliseconds */ RTSflags.ConcFlags.maxThreads = 32; RTSflags.ConcFlags.stkChunkSize = 1024; RTSflags.ConcFlags.maxLocalSparks = 500; #endif /* CONCURRENT */ #ifdef PAR RTSflags.ParFlags.parallelStats = rtsFalse; RTSflags.ParFlags.granSimStats = rtsFalse; RTSflags.ParFlags.granSimStats_Binary = rtsFalse; RTSflags.ParFlags.outputDisabled = rtsFalse; RTSflags.ParFlags.packBufferSize = 1024; #endif /* PAR */ #ifdef GRAN RTSflags.GranFlags.granSimStats = rtsFalse; RTSflags.GranFlags.granSimStats_suppressed = rtsFalse; RTSflags.GranFlags.granSimStats_Binary = rtsFalse; RTSflags.GranFlags.granSimStats_Sparks = rtsFalse; RTSflags.GranFlags.granSimStats_Heap = rtsFalse; RTSflags.GranFlags.labelling = rtsFalse; RTSflags.GranFlags.packBufferSize = 1024; RTSflags.GranFlags.packBufferSize_internal = GRANSIM_DEFAULT_PACK_BUFFER_SIZE; RTSflags.GranFlags.proc = MAX_PROC; RTSflags.GranFlags.max_fishes = MAX_FISHES; RTSflags.GranFlags.time_slice = GRAN_TIME_SLICE; RTSflags.GranFlags.Light = rtsFalse; RTSflags.GranFlags.gran_latency = LATENCY; RTSflags.GranFlags.gran_additional_latency = ADDITIONAL_LATENCY; RTSflags.GranFlags.gran_fetchtime = FETCHTIME; RTSflags.GranFlags.gran_lunblocktime = LOCALUNBLOCKTIME; RTSflags.GranFlags.gran_gunblocktime = GLOBALUNBLOCKTIME; RTSflags.GranFlags.gran_mpacktime = MSGPACKTIME; RTSflags.GranFlags.gran_munpacktime = MSGUNPACKTIME; RTSflags.GranFlags.gran_mtidytime = MSGTIDYTIME; RTSflags.GranFlags.gran_threadcreatetime = THREADCREATETIME; RTSflags.GranFlags.gran_threadqueuetime = THREADQUEUETIME; RTSflags.GranFlags.gran_threaddescheduletime = THREADDESCHEDULETIME; RTSflags.GranFlags.gran_threadscheduletime = THREADSCHEDULETIME; RTSflags.GranFlags.gran_threadcontextswitchtime = THREADCONTEXTSWITCHTIME; RTSflags.GranFlags.gran_arith_cost = ARITH_COST; RTSflags.GranFlags.gran_branch_cost = BRANCH_COST; RTSflags.GranFlags.gran_load_cost = LOAD_COST; RTSflags.GranFlags.gran_store_cost = STORE_COST; RTSflags.GranFlags.gran_float_cost = FLOAT_COST; RTSflags.GranFlags.gran_heapalloc_cost = HEAPALLOC_COST; RTSflags.GranFlags.gran_pri_spark_overhead = PRI_SPARK_OVERHEAD; RTSflags.GranFlags.gran_pri_sched_overhead = PRI_SCHED_OVERHEAD; RTSflags.GranFlags.DoFairSchedule = rtsFalse; RTSflags.GranFlags.DoReScheduleOnFetch = rtsFalse; RTSflags.GranFlags.DoStealThreadsFirst = rtsFalse; RTSflags.GranFlags.SimplifiedFetch = rtsFalse; RTSflags.GranFlags.DoAlwaysCreateThreads = rtsFalse; RTSflags.GranFlags.DoGUMMFetching = rtsFalse; RTSflags.GranFlags.DoThreadMigration = rtsFalse; RTSflags.GranFlags.FetchStrategy = 2; RTSflags.GranFlags.PreferSparksOfLocalNodes = rtsFalse; RTSflags.GranFlags.DoPrioritySparking = rtsFalse; RTSflags.GranFlags.DoPriorityScheduling = rtsFalse; RTSflags.GranFlags.SparkPriority = 0; RTSflags.GranFlags.SparkPriority2 = 0; RTSflags.GranFlags.RandomPriorities = rtsFalse; RTSflags.GranFlags.InversePriorities = rtsFalse; RTSflags.GranFlags.IgnorePriorities = rtsFalse; RTSflags.GranFlags.ThunksToPack = 0; RTSflags.GranFlags.RandomSteal = rtsTrue; RTSflags.GranFlags.NoForward = rtsFalse; RTSflags.GranFlags.PrintFetchMisses = rtsFalse; RTSflags.GranFlags.debug = 0x0; RTSflags.GranFlags.event_trace = rtsFalse; RTSflags.GranFlags.event_trace_all = rtsFalse; #endif #ifdef TICKY_TICKY RTSflags.TickyFlags.showTickyStats = rtsFalse; RTSflags.TickyFlags.tickyFile = NULL; AllFlags.doUpdEntryCounts = rtsTrue; /*ToDo:move? */ #endif } \end{code} %************************************************************************ %* * \subsection{Usage message for runtime-system (RTS) flags} %* * %************************************************************************ \begin{code} static const char * usage_text[] = { "", "Usage: [+RTS | -RTS ] ... --RTS ", "", " +RTS Indicates run time system options follow", " -RTS Indicates program arguments follow", " --RTS Indicates that ALL subsequent arguments will be given to the", " program (including any of these RTS flags)", "", "The following run time system options are available:", "", " -? -f Prints this message and exits; the program is not executed", "", " -K Sets the stack size (default 64k) Egs: -K32k -K512k", " -H Sets the heap size (default 4M) -H512k -H16M", " -s Summary GC statistics (default file: .stat)", " -S Detailed GC statistics (with -Sstderr going to stderr)", "", #if defined(GCap) " -M% Sets minimum size of alloc area as % of heap (default 3%)", " -A Fixes size of alloc area, overriding any minimum (-A gives 64k)", " -G Fixes size of major generation (default is dynamic threshold)", " -F2s Forces program compiled for Appel gc to use 2s collection", #else # if defined(GCgn) " -A Specifies size of alloc area (default 64k)", " -G Fixes size of major generation (default is available heap)", " -F2s Forces program compiled for Gen gc to use 2s collection", # else " -M% Minimum % of heap which must be available (default 3%)", " -A Fixes size of heap area allocated between GCs (-A gives 64k)", # endif #endif " -j Forces major GC at every bytes allocated", #if defined(GCdu) " -u Fixes residency threshold at which mode switches (range 0.0..0.95)", #endif "", " -N No black-holing during GC (for use when a signal handler is present)", " -Z Don't squeeze out update frames on stack overflow", " -B Sound the bell at the start of each (major) garbage collection", #if defined(PROFILING) || defined(PAR) "", " -p Produce cost centre time profile (output file .prof)", " sort: T = time (default), A = alloc, C = cost centre label", " -P Produce serial time profile (output file .time)", " and a -p profile with detailed tick/alloc info", # if defined(PROFILING) "", " -h Heap residency profile (output file .hp)", " break-down: C = cost centre (default), M = module, G = group", " D = closure description, Y = type description", " T, = time closure created", " ints: no. of interval bands plotted (default 18)", " start: seconds after which intervals start (default 0.0)", " A subset of closures may be selected by the attached cost centre using:", " -c{mod:lab,mod:lab...}, specific module:label cost centre(s)", " -m{mod,mod...} all cost centres from the specified modules(s)", " -g{grp,grp...} all cost centres from the specified group(s)", " Selections can also be made by description, type, kind and age:", " -d{des,des...} closures with specified closure descriptions", " -y{typ,typ...} closures with specified type descriptions", " -k{knd,knd...} closures of the specified kinds", " -a closures which survived complete intervals", " The selection logic used is summarised as follows:", " ([-c] or [-m] or [-g]) and ([-d] or [-y] or [-k]) and [-a]", " where an option is true if not specified", # endif "", " -z set hash table for (C, M, G, D or Y)", "", " -i Number of seconds in a profiling interval (default 1.0):", " heap profile (-h) and/or serial time profile (-P) frequency", #endif /* PROFILING or PAR */ "", #if defined(TICKY_TICKY) " -r Produce reduction profiling statistics (with -rstderr for stderr)", "", #endif " -T Trace garbage collection execution (debugging)", #ifdef CONCURRENT "", # ifdef PAR " -N Use PVMish processors in parallel (default: 2)", /* NB: the -N is implemented by the driver!! */ # endif " -C Context-switch interval in seconds", " (0 or no argument means switch as often as possible)", " the default is .01 sec; resolution is .01 sec", " -e Size of spark pools (default 100)", # ifdef PAR " -q Enable activity profile (output files in ~/*.gr)", " -qb Enable binary activity profile (output file /tmp/.gb)", " -Q Set pack-buffer size (default: 1024)", # else " -q[v] Enable quasi-parallel profile (output file .qp)", # endif " -t Set maximum number of advisory threads per PE (default 32)", " -o Set stack chunk size (default 1024)", # ifdef PAR " -d Turn on PVM-ish debugging", " -O Disable output for performance measurement", # endif /* PAR */ # ifdef GRAN /* ToDo: fill in decent Docu here */ " -b... All GranSim options start with -b; see GranSim User's Guide for details", # endif #endif /* CONCURRENT */ "", "Other RTS options may be available for programs compiled a different way.", "The GHC User's Guide has full details.", "", 0 }; \end{code} %************************************************************************ %* * \subsection{Processing command-line arguments to set @RTSFlags@} %* * %************************************************************************ \begin{code} #define RTS 1 #define PGM 0 #ifndef atof extern double atof(); /* no proto because some machines use const and some do not */ #endif static __inline__ rtsBool strequal(const char *a, const char * b) { return(strcmp(a, b) == 0); } void setupRtsFlags(int *argc, char *argv[], int *rts_argc, char *rts_argv[]) { rtsBool error = rtsFalse; I_ mode; I_ arg, total_arg; char *last_slash; /* Remove directory from argv[0] -- default files in current directory */ if ((last_slash = (char *) strrchr(argv[0], '/')) != NULL) strcpy(argv[0], last_slash+1); /* Split arguments (argv) into PGM (argv) and RTS (rts_argv) parts */ /* argv[0] must be PGM argument -- leave in argv */ total_arg = *argc; arg = 1; *argc = 1; *rts_argc = 0; for (mode = PGM; arg < total_arg && ! strequal("--RTS", argv[arg]); arg++) { if (strequal("+RTS", argv[arg])) { mode = RTS; } else if (strequal("-RTS", argv[arg])) { mode = PGM; } else if (mode == RTS && *rts_argc < MAX_RTS_ARGS-1) { rts_argv[(*rts_argc)++] = argv[arg]; } else if (mode == PGM) { argv[(*argc)++] = argv[arg]; } else { fflush(stdout); fprintf(stderr, "setupRtsFlags: Too many RTS arguments (max %d)\n", MAX_RTS_ARGS-1); EXIT(EXIT_FAILURE); } } if (arg < total_arg) { /* arg must be --RTS; process remaining program arguments */ while (++arg < total_arg) { argv[(*argc)++] = argv[arg]; } } argv[*argc] = (char *) 0; rts_argv[*rts_argc] = (char *) 0; /* Process RTS (rts_argv) part: mainly to determine statsfile */ for (arg = 0; arg < *rts_argc; arg++) { if (rts_argv[arg][0] != '-') { fflush(stdout); fprintf(stderr, "setupRtsFlags: Unexpected RTS argument: %s\n", rts_argv[arg]); error = rtsTrue; } else { switch(rts_argv[arg][1]) { /* process: general args, then PROFILING-only ones, then CONCURRENT-only, PARallel-only, GRAN-only, TICKY-only (same order as defined in RtsFlags.lh); within those groups, mostly in case-insensitive alphabetical order. */ #ifdef TICKY_TICKY # define TICKY_BUILD_ONLY(x) x #else # define TICKY_BUILD_ONLY(x) \ fprintf(stderr, "setupRtsFlags: GHC not built for: ticky-ticky stats\n"); \ error = rtsTrue; #endif #if (defined(PROFILING) || defined(PAR)) # define COST_CENTRE_USING_BUILD_ONLY(x) x #else # define COST_CENTRE_USING_BUILD_ONLY(x) \ fprintf(stderr, "setupRtsFlags: GHC not built for: -prof or -parallel\n"); \ error = rtsTrue; #endif #ifdef PROFILING # define PROFILING_BUILD_ONLY(x) x #else # define PROFILING_BUILD_ONLY(x) \ fprintf(stderr, "setupRtsFlags: GHC not built for: -prof\n"); \ error = rtsTrue; #endif #ifdef CONCURRENT # define CONCURRENT_BUILD_ONLY(x) x #else # define CONCURRENT_BUILD_ONLY(x) \ fprintf(stderr, "setupRtsFlags: GHC not built for: -concurrent\n"); \ error = rtsTrue; #endif #ifdef PAR # define PAR_BUILD_ONLY(x) x #else # define PAR_BUILD_ONLY(x) \ fprintf(stderr, "setupRtsFlags: GHC not built for: -parallel\n"); \ error = rtsTrue; #endif #ifdef GRAN # define GRAN_BUILD_ONLY(x) x #else # define GRAN_BUILD_ONLY(x) \ fprintf(stderr, "setupRtsFlags: GHC not built for: -gransim\n"); \ error = rtsTrue; #endif /* =========== GENERAL ========================== */ case '?': case 'f': error = rtsTrue; break; case 'A': RTSflags.GcFlags.allocAreaSize = decode(rts_argv[arg]+2) / sizeof(W_); RTSflags.GcFlags.allocAreaSizeGiven = rtsTrue; break; case 'B': RTSflags.GcFlags.ringBell = rtsTrue; break; case 'F': if (strequal(rts_argv[arg]+2, "2s")) { RTSflags.GcFlags.force2s = rtsTrue; } else { bad_option( rts_argv[arg] ); } break; case 'G': RTSflags.GcFlags.specifiedOldGenSize = decode(rts_argv[arg]+2) / sizeof(W_); break; case 'K': RTSflags.GcFlags.stksSize = decode(rts_argv[arg]+2) / sizeof(W_); if (RTSflags.GcFlags.stksSize == 0) bad_option( rts_argv[arg] ); break; case 'H': RTSflags.GcFlags.heapSize = decode(rts_argv[arg]+2) / sizeof(W_); /* user give size in *bytes* but "heapSize" is in *words* */ if (RTSflags.GcFlags.heapSize <= 0) bad_option(rts_argv[arg]); break; case 'j': /* force GC option */ RTSflags.GcFlags.forceGC = rtsTrue; if (rts_argv[arg][2]) { RTSflags.GcFlags.forcingInterval = decode(rts_argv[arg]+2) / sizeof(W_); } break; case 'M': RTSflags.GcFlags.pcFreeHeap = atof(rts_argv[arg]+2); if (RTSflags.GcFlags.pcFreeHeap < 0 || RTSflags.GcFlags.pcFreeHeap > 100) bad_option( rts_argv[arg] ); break; case 'N': RTSflags.GcFlags.lazyBlackHoling = rtsFalse; break; case 'n': RTSflags.GcFlags.doSelectorsAtGC = rtsFalse; break; case 'S': /* NB: no difference at present ! */ case 's': RTSflags.GcFlags.giveStats ++; /* will be VERBOSE_GC_STATS */ #ifdef PAR /* Opening all those files would almost certainly fail... */ RTSflags.ParFlags.parallelStats = rtsTrue; RTSflags.GcFlags.statsFile = stderr; /* temporary; ToDo: rm */ #else RTSflags.GcFlags.statsFile = open_stats_file(arg, *argc, argv, *rts_argc, rts_argv, STAT_FILENAME_FMT); if (RTSflags.GcFlags.statsFile == NULL) error = rtsTrue; #endif break; case 'T': if (rts_argv[arg][2] != '\0') RTSflags.GcFlags.trace = (W_) strtol(rts_argv[arg]+2, (char **)NULL, 0); else RTSflags.GcFlags.trace = 1; /* slightly weird; why, really? */ break; case 'Z': RTSflags.GcFlags.squeezeUpdFrames = rtsFalse; break; /* =========== PROFILING ========================== */ case 'P': /* detailed cost centre profiling (time/alloc) */ COST_CENTRE_USING_BUILD_ONLY( RTSflags.CcFlags.doCostCentres++; ) case 'p': /* cost centre profiling (time/alloc) */ COST_CENTRE_USING_BUILD_ONLY( RTSflags.CcFlags.doCostCentres++; switch (rts_argv[arg][2]) { case SORTCC_LABEL: case SORTCC_TIME: case SORTCC_ALLOC: RTSflags.CcFlags.sortBy = rts_argv[arg][2]; break; default: PAR_BUILD_ONLY( break; /* we do not care about sortBy for parallel */ ) PROFILING_BUILD_ONLY( fprintf(stderr, "Invalid profiling sort option %s\n", rts_argv[arg]); error = rtsTrue; ) } ) break; case 'i': /* serial profiling -- initial timer interval */ COST_CENTRE_USING_BUILD_ONLY( interval_ticks = (I_) ((atof(rts_argv[arg]+2) * TICK_FREQUENCY)); if (interval_ticks <= 0) interval_ticks = 1; ) break; case 'h': /* serial heap profile */ PROFILING_BUILD_ONLY( switch (rts_argv[arg][2]) { case '\0': case CCchar: RTSflags.ProfFlags.doHeapProfile = HEAP_BY_CC; break; case MODchar: RTSflags.ProfFlags.doHeapProfile = HEAP_BY_MOD; break; case GRPchar: RTSflags.ProfFlags.doHeapProfile = HEAP_BY_GRP; break; case DESCRchar: RTSflags.ProfFlags.doHeapProfile = HEAP_BY_DESCR; break; case TYPEchar: RTSflags.ProfFlags.doHeapProfile = HEAP_BY_TYPE; break; case TIMEchar: RTSflags.ProfFlags.doHeapProfile = HEAP_BY_TIME; if (rts_argv[arg][3]) { char *start_str = strchr(rts_argv[arg]+3, ','); I_ intervals; if (start_str) *start_str = '\0'; if ((intervals = decode(rts_argv[arg]+3)) != 0) { time_intervals = (hash_t) intervals; /* ToDo: and what if it *is* zero intervals??? */ } if (start_str) { earlier_ticks = (I_)((atof(start_str + 1) * TICK_FREQUENCY)); } } break; default: fprintf(stderr, "Invalid heap profile option: %s\n", rts_argv[arg]); error = rtsTrue; } ) break; case 'z': /* size of index tables */ PROFILING_BUILD_ONLY( switch (rts_argv[arg][2]) { case CCchar: max_cc_no = (hash_t) decode(rts_argv[arg]+3); if (max_cc_no == 0) { fprintf(stderr, "Bad number of cost centres %s\n", rts_argv[arg]); error = rtsTrue; } break; case MODchar: max_mod_no = (hash_t) decode(rts_argv[arg]+3); if (max_mod_no == 0) { fprintf(stderr, "Bad number of modules %s\n", rts_argv[arg]); error = rtsTrue; } break; case GRPchar: max_grp_no = (hash_t) decode(rts_argv[arg]+3); if (max_grp_no == 0) { fprintf(stderr, "Bad number of groups %s\n", rts_argv[arg]); error = rtsTrue; } break; case DESCRchar: max_descr_no = (hash_t) decode(rts_argv[arg]+3); if (max_descr_no == 0) { fprintf(stderr, "Bad number of closure descriptions %s\n", rts_argv[arg]); error = rtsTrue; } break; case TYPEchar: max_type_no = (hash_t) decode(rts_argv[arg]+3); if (max_type_no == 0) { fprintf(stderr, "Bad number of type descriptions %s\n", rts_argv[arg]); error = rtsTrue; } break; default: fprintf(stderr, "Invalid index table size option: %s\n", rts_argv[arg]); error = rtsTrue; } ) break; case 'c': /* cost centre label select */ case 'm': /* cost centre module select */ case 'g': /* cost centre group select */ case 'd': /* closure descr select */ case 'y': /* closure type select */ case 'k': /* closure kind select */ PROFILING_BUILD_ONLY( {char *left = strchr(rts_argv[arg], '{'); char *right = strrchr(rts_argv[arg], '}'); if (! left || ! right || strrchr(rts_argv[arg], '{') != left || strchr(rts_argv[arg], '}') != right) { fprintf(stderr, "Invalid heap profiling selection bracketing\n %s\n", rts_argv[arg]); error = rtsTrue; } else { *right = '\0'; switch (rts_argv[arg][1]) { case 'c': /* cost centre label select */ RTSflags.ProfFlags.ccSelector = left + 1; break; case 'm': /* cost centre module select */ RTSflags.ProfFlags.modSelector = left + 1; break; case 'g': /* cost centre group select */ RTSflags.ProfFlags.grpSelector = left + 1; break; case 'd': /* closure descr select */ RTSflags.ProfFlags.descrSelector = left + 1; break; case 't': /* closure type select */ RTSflags.ProfFlags.typeSelector = left + 1; break; case 'k': /* closure kind select */ RTSflags.ProfFlags.kindSelector = left + 1; break; } }} ) break; /* =========== CONCURRENT ========================= */ case 'C': /* context switch interval */ CONCURRENT_BUILD_ONLY ( if (rts_argv[arg][2] == '\0') RTSflags.ConcFlags.ctxtSwitchTime = 0; else { I_ cst; /* tmp */ /* Convert to milliseconds */ cst = (I_) ((atof(rts_argv[arg]+2) * 1000)); cst = (cst / CS_MIN_MILLISECS) * CS_MIN_MILLISECS; if (cst < CS_MIN_MILLISECS) cst = CS_MIN_MILLISECS; RTSflags.ConcFlags.ctxtSwitchTime = cst; } ) break; case 't': CONCURRENT_BUILD_ONLY( if (rts_argv[arg][2] != '\0') { RTSflags.ConcFlags.maxThreads = strtol(rts_argv[arg]+2, (char **) NULL, 10); } else { fprintf(stderr, "setupRtsFlags: missing size for -t\n"); error = rtsTrue; } ) break; case 'o': CONCURRENT_BUILD_ONLY ( if (rts_argv[arg][2] != '\0') { I_ size = decode(rts_argv[arg]+2); if (size < MIN_STKO_CHUNK_SIZE) size = MIN_STKO_CHUNK_SIZE; RTSflags.ConcFlags.stkChunkSize = size; } else { fprintf(stderr, "setupRtsFlags: missing size for -o\n"); error = rtsTrue; } ) break; /* =========== PARALLEL =========================== */ case 'e': CONCURRENT_BUILD_ONLY( if (rts_argv[arg][2] != '\0') { /* otherwise, stick w/ the default */ RTSflags.ConcFlags.maxLocalSparks = strtol(rts_argv[arg]+2, (char **) NULL, 10); if (RTSflags.ConcFlags.maxLocalSparks <= 0) { fprintf(stderr, "setupRtsFlags: bad value for -e\n"); error = rtsTrue; } } ) break; case 'O': PAR_BUILD_ONLY( RTSflags.ParFlags.outputDisabled = rtsTrue; ) break; case 'q': /* activity profile option */ PAR_BUILD_ONLY( if (rts_argv[arg][2] == 'b') RTSflags.ParFlags.granSimStats_Binary = rtsTrue; else RTSflags.ParFlags.granSimStats = rtsTrue; ) break; #if 0 /* or??? */ case 'q': /* quasi-parallel profile option */ GRAN_BUILD_ONLY ( if (rts_argv[arg][2] == 'v') do_qp_prof = 2; else do_qp_prof++; ) break; #endif /* 0??? */ case 'Q': /* Set pack buffer size */ PAR_BUILD_ONLY( if (rts_argv[arg][2] != '\0') { RTSflags.ParFlags.packBufferSize = decode(rts_argv[arg]+2); } else { fprintf(stderr, "setupRtsFlags: missing size of PackBuffer (for -Q)\n"); error = rtsTrue; } ) break; /* =========== GRAN =============================== */ case 'b': GRAN_BUILD_ONLY( process_gran_option(arg, rts_argc, rts_argv, &error); ) break; /* =========== TICKY ============================== */ case 'r': /* Basic profiling stats */ TICKY_BUILD_ONLY( RTSflags.TickyFlags.showTickyStats = rtsTrue; RTSflags.TickyFlags.tickyFile = open_stats_file(arg, *argc, argv, *rts_argc, rts_argv, TICKY_FILENAME_FMT); if (RTSflags.TickyFlags.tickyFile == NULL) error = rtsTrue; ) break; /* =========== OH DEAR ============================ */ default: fprintf(stderr, "setupRtsFlags: Unknown RTS option: %s\n",rts_argv[arg]); error = rtsTrue; break; } } } if (error) { const char **p; fflush(stdout); for (p = usage_text; *p; p++) fprintf(stderr, "%s\n", *p); EXIT(EXIT_FAILURE); } } #if defined(GRAN) void enable_GrAnSimLight() { fprintf(stderr,"GrAnSim Light enabled (infinite number of processors; 0 communication costs)\n"); RTSflags.GranFlags.Light=rtsTrue; RTSflags.GranFlags.gran_latency = RTSflags.GranFlags.gran_fetchtime = RTSflags.GranFlags.gran_additional_latency = RTSflags.GranFlags.gran_gunblocktime = RTSflags.GranFlags.gran_lunblocktime = RTSflags.GranFlags.gran_threadcreatetime = RTSflags.GranFlags.gran_threadqueuetime = RTSflags.GranFlags.gran_threadscheduletime = RTSflags.GranFlags.gran_threaddescheduletime = RTSflags.GranFlags.gran_threadcontextswitchtime = 0; RTSflags.GranFlags.gran_mpacktime = RTSflags.GranFlags.gran_munpacktime = 0; RTSflags.GranFlags.DoFairSchedule = rtsTrue; RTSflags.GranFlags.DoReScheduleOnFetch = rtsFalse; RTSflags.GranFlags.DoAlwaysCreateThreads = rtsTrue; /* FetchStrategy is irrelevant in GrAnSim-Light */ /* GrAnSim Light often creates an abundance of parallel threads, each with its own stack etc. Therefore, it's in general a good idea to use small stack chunks (use the -o option to increase it again). */ RTSflags.ConcFlags.stkChunkSize = 100; RTSflags.GranFlags.proc = 1; } static void process_gran_option(int arg, int *rts_argc, char *rts_argv[], rtsBool *error) { if (rts_argv[arg][1] != 'b') /* All GranSim options start with -b */ return; /* Should we emulate hbcpp */ if(strcmp((rts_argv[arg]+2),"roken")==0) { RTSflags.GranFlags.DoAlwaysCreateThreads=rtsTrue; strcpy(rts_argv[arg]+2,"oring"); } /* or a ridiculously idealised simulator */ if(strcmp((rts_argv[arg]+2),"oring")==0) { RTSflags.GranFlags.gran_latency = RTSflags.GranFlags.gran_fetchtime = RTSflags.GranFlags.gran_additional_latency = RTSflags.GranFlags.gran_gunblocktime = RTSflags.GranFlags.gran_lunblocktime = RTSflags.GranFlags.gran_threadcreatetime = RTSflags.GranFlags.gran_threadqueuetime = RTSflags.GranFlags.gran_threadscheduletime = RTSflags.GranFlags.gran_threaddescheduletime = RTSflags.GranFlags.gran_threadcontextswitchtime = 0; RTSflags.GranFlags.gran_mpacktime = RTSflags.GranFlags.gran_munpacktime = 0; RTSflags.GranFlags.gran_arith_cost = RTSflags.GranFlags.gran_float_cost = RTSflags.GranFlags.gran_load_cost = RTSflags.GranFlags.gran_store_cost = RTSflags.GranFlags.gran_branch_cost = 0; RTSflags.GranFlags.gran_heapalloc_cost = 1; /* ++RTSflags.GranFlags.DoFairSchedule; */ RTSflags.GranFlags.DoStealThreadsFirst = rtsTrue; /* -bZ */ RTSflags.GranFlags.DoThreadMigration = rtsTrue; /* -bM */ RTSflags.GranFlags.granSimStats = rtsTrue; /* -bP */ return; } /* or a somewhat idealised simulator */ if(strcmp((rts_argv[arg]+2),"onzo")==0) { RTSflags.GranFlags.gran_latency = RTSflags.GranFlags.gran_fetchtime = RTSflags.GranFlags.gran_additional_latency = RTSflags.GranFlags.gran_gunblocktime = RTSflags.GranFlags.gran_lunblocktime = RTSflags.GranFlags.gran_threadcreatetime = RTSflags.GranFlags.gran_threadqueuetime = RTSflags.GranFlags.gran_threadscheduletime = RTSflags.GranFlags.gran_threaddescheduletime = RTSflags.GranFlags.gran_threadcontextswitchtime = 0; RTSflags.GranFlags.gran_mpacktime = RTSflags.GranFlags.gran_munpacktime = 0; RTSflags.GranFlags.gran_heapalloc_cost = 1; /* RTSflags.GranFlags.DoFairSchedule = rtsTrue; */ /* -b-R */ /* RTSflags.GranFlags.DoStealThreadsFirst = rtsTrue; */ /* -b-T */ RTSflags.GranFlags.DoReScheduleOnFetch = rtsTrue; /* -bZ */ RTSflags.GranFlags.DoThreadMigration = rtsTrue; /* -bM */ RTSflags.GranFlags.granSimStats = rtsTrue; /* -bP */ # if defined(GRAN_CHECK) && defined(GRAN) RTSflags.GranFlags.debug = 0x20; /* print event statistics */ # endif return; } /* Communication and task creation cost parameters */ switch(rts_argv[arg][2]) { case ':': enable_GrAnSimLight(); /* set flags for GrAnSim-Light mode */ break; case 'l': if (rts_argv[arg][3] != '\0') { RTSflags.GranFlags.gran_gunblocktime = RTSflags.GranFlags.gran_latency = decode(rts_argv[arg]+3); RTSflags.GranFlags.gran_fetchtime = 2*RTSflags.GranFlags.gran_latency; } else RTSflags.GranFlags.gran_latency = LATENCY; break; case 'a': if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.gran_additional_latency = decode(rts_argv[arg]+3); else RTSflags.GranFlags.gran_additional_latency = ADDITIONAL_LATENCY; break; case 'm': if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.gran_mpacktime = decode(rts_argv[arg]+3); else RTSflags.GranFlags.gran_mpacktime = MSGPACKTIME; break; case 'x': if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.gran_mtidytime = decode(rts_argv[arg]+3); else RTSflags.GranFlags.gran_mtidytime = 0; break; case 'r': if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.gran_munpacktime = decode(rts_argv[arg]+3); else RTSflags.GranFlags.gran_munpacktime = MSGUNPACKTIME; break; case 'g': if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.gran_fetchtime = decode(rts_argv[arg]+3); else RTSflags.GranFlags.gran_fetchtime = FETCHTIME; break; case 'n': if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.gran_gunblocktime = decode(rts_argv[arg]+3); else RTSflags.GranFlags.gran_gunblocktime = GLOBALUNBLOCKTIME; break; case 'u': if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.gran_lunblocktime = decode(rts_argv[arg]+3); else RTSflags.GranFlags.gran_lunblocktime = LOCALUNBLOCKTIME; break; /* Thread-related metrics */ case 't': if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.gran_threadcreatetime = decode(rts_argv[arg]+3); else RTSflags.GranFlags.gran_threadcreatetime = THREADCREATETIME; break; case 'q': if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.gran_threadqueuetime = decode(rts_argv[arg]+3); else RTSflags.GranFlags.gran_threadqueuetime = THREADQUEUETIME; break; case 'c': if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.gran_threadscheduletime = decode(rts_argv[arg]+3); else RTSflags.GranFlags.gran_threadscheduletime = THREADSCHEDULETIME; RTSflags.GranFlags.gran_threadcontextswitchtime = RTSflags.GranFlags.gran_threadscheduletime + RTSflags.GranFlags.gran_threaddescheduletime; break; case 'd': if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.gran_threaddescheduletime = decode(rts_argv[arg]+3); else RTSflags.GranFlags.gran_threaddescheduletime = THREADDESCHEDULETIME; RTSflags.GranFlags.gran_threadcontextswitchtime = RTSflags.GranFlags.gran_threadscheduletime + RTSflags.GranFlags.gran_threaddescheduletime; break; /* Instruction Cost Metrics */ case 'A': if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.gran_arith_cost = decode(rts_argv[arg]+3); else RTSflags.GranFlags.gran_arith_cost = ARITH_COST; break; case 'F': if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.gran_float_cost = decode(rts_argv[arg]+3); else RTSflags.GranFlags.gran_float_cost = FLOAT_COST; break; case 'B': if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.gran_branch_cost = decode(rts_argv[arg]+3); else RTSflags.GranFlags.gran_branch_cost = BRANCH_COST; break; case 'L': if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.gran_load_cost = decode(rts_argv[arg]+3); else RTSflags.GranFlags.gran_load_cost = LOAD_COST; break; case 'S': if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.gran_store_cost = decode(rts_argv[arg]+3); else RTSflags.GranFlags.gran_store_cost = STORE_COST; break; case 'H': if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.gran_heapalloc_cost = decode(rts_argv[arg]+3); else RTSflags.GranFlags.gran_heapalloc_cost = 0; break; case 'y': RTSflags.GranFlags.DoReScheduleOnFetch = rtsTrue; if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.FetchStrategy = decode(rts_argv[arg]+3); if (RTSflags.GranFlags.FetchStrategy == 0) RTSflags.GranFlags.DoReScheduleOnFetch = rtsFalse; else RTSflags.GranFlags.FetchStrategy = 2; /* default: fetch everything */ break; case 'K': /* sort overhead (per elem in spark list) */ if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.gran_pri_spark_overhead = decode(rts_argv[arg]+3); else RTSflags.GranFlags.gran_pri_spark_overhead = PRI_SPARK_OVERHEAD; fprintf(stderr,"Overhead for pri spark: %d (per elem).\n", RTSflags.GranFlags.gran_pri_spark_overhead); break; case 'O': /* sort overhead (per elem in spark list) */ if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.gran_pri_sched_overhead = decode(rts_argv[arg]+3); else RTSflags.GranFlags.gran_pri_sched_overhead = PRI_SCHED_OVERHEAD; fprintf(stderr,"Overhead for pri sched: %d (per elem).\n", RTSflags.GranFlags.gran_pri_sched_overhead); break; /* General Parameters */ case 'p': if (rts_argv[arg][3] != '\0') { RTSflags.GranFlags.proc = decode(rts_argv[arg]+3); if (RTSflags.GranFlags.proc==0) { enable_GrAnSimLight(); /* set flags for GrAnSim-Light mode */ } else if (RTSflags.GranFlags.proc > MAX_PROC || RTSflags.GranFlags.proc < 1) { fprintf(stderr,"setupRtsFlags: no more than %u processors allowed\n", MAX_PROC); *error = rtsTrue; } } else RTSflags.GranFlags.proc = MAX_PROC; break; case 'f': if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.max_fishes = decode(rts_argv[arg]+3); else RTSflags.GranFlags.max_fishes = 1; break; case 'w': if (rts_argv[arg][3] != '\0') RTSflags.GranFlags.time_slice = decode(rts_argv[arg]+3); else RTSflags.GranFlags.time_slice = GRAN_TIME_SLICE; break; case 'C': RTSflags.GranFlags.DoAlwaysCreateThreads=rtsTrue; RTSflags.GranFlags.DoThreadMigration=rtsTrue; break; case 'G': fprintf(stderr,"Bulk fetching enabled.\n"); RTSflags.GranFlags.DoGUMMFetching=rtsTrue; break; case 'M': fprintf(stderr,"Thread migration enabled.\n"); RTSflags.GranFlags.DoThreadMigration=rtsTrue; break; case 'R': fprintf(stderr,"Fair Scheduling enabled.\n"); RTSflags.GranFlags.DoFairSchedule=rtsTrue; break; case 'I': fprintf(stderr,"Priority Scheduling enabled.\n"); RTSflags.GranFlags.DoPriorityScheduling=rtsTrue; break; case 'T': RTSflags.GranFlags.DoStealThreadsFirst=rtsTrue; RTSflags.GranFlags.DoThreadMigration=rtsTrue; break; case 'Z': RTSflags.GranFlags.DoReScheduleOnFetch=rtsTrue; break; case 'z': RTSflags.GranFlags.SimplifiedFetch=rtsTrue; break; case 'N': RTSflags.GranFlags.PreferSparksOfLocalNodes=rtsTrue; break; case 'b': RTSflags.GranFlags.granSimStats_Binary=rtsTrue; break; case 'P': RTSflags.GranFlags.granSimStats=rtsTrue; break; case 's': RTSflags.GranFlags.granSimStats_Sparks=rtsTrue; break; case 'h': RTSflags.GranFlags.granSimStats_Heap=rtsTrue; break; case 'U': RTSflags.GranFlags.labelling=rtsTrue; break; case 'Y': /* syntax: -bY[,] n ... pos int */ if (rts_argv[arg][3] != '\0') { char *arg0, *tmp; arg0 = rts_argv[arg]+3; if ((tmp = strstr(arg0,","))==NULL) { RTSflags.GranFlags.SparkPriority = decode(arg0); fprintf(stderr,"SparkPriority: %u.\n",RTSflags.GranFlags.SparkPriority); } else { *(tmp++) = '\0'; RTSflags.GranFlags.SparkPriority = decode(arg0); RTSflags.GranFlags.SparkPriority2 = decode(tmp); fprintf(stderr,"SparkPriority: %u.\n", RTSflags.GranFlags.SparkPriority); fprintf(stderr,"SparkPriority2:%u.\n", RTSflags.GranFlags.SparkPriority2); if (RTSflags.GranFlags.SparkPriority2 < RTSflags.GranFlags.SparkPriority) { fprintf(stderr,"WARNING: 2nd pri < main pri (%u<%u); 2nd pri has no effect\n", RTSflags.GranFlags.SparkPriority2, RTSflags.GranFlags.SparkPriority); } } } else { /* plain pri spark is now invoked with -bX RTSflags.GranFlags.DoPrioritySparking = 1; fprintf(stderr,"PrioritySparking.\n"); */ } break; case 'Q': if (rts_argv[arg][3] != '\0') { RTSflags.GranFlags.ThunksToPack = decode(rts_argv[arg]+3); } else { RTSflags.GranFlags.ThunksToPack = 1; } fprintf(stderr,"Thunks To Pack in one packet: %u.\n", RTSflags.GranFlags.ThunksToPack); break; case 'e': RTSflags.GranFlags.RandomSteal = rtsFalse; fprintf(stderr,"Deterministic mode (no random stealing)\n"); break; /* The following class of options contains eXperimental */ /* features in connection with exploiting granularity */ /* information. I.e. if -bY is chosen these options */ /* tell the RTS what to do with the supplied info --HWL */ case 'W': if (rts_argv[arg][3] != '\0') { RTSflags.GranFlags.packBufferSize_internal = decode(rts_argv[arg]+3); } else { RTSflags.GranFlags.packBufferSize_internal = GRANSIM_DEFAULT_PACK_BUFFER_SIZE; } fprintf(stderr,"Size of GranSim internal pack buffer: %u.\n", RTSflags.GranFlags.packBufferSize_internal); break; case 'X': switch(rts_argv[arg][3]) { case '\0': RTSflags.GranFlags.DoPrioritySparking = 1; fprintf(stderr,"Priority Sparking with Normal Priorities.\n"); RTSflags.GranFlags.InversePriorities = rtsFalse; RTSflags.GranFlags.RandomPriorities = rtsFalse; RTSflags.GranFlags.IgnorePriorities = rtsFalse; break; case 'I': RTSflags.GranFlags.DoPrioritySparking = 1; fprintf(stderr,"Priority Sparking with Inverse Priorities.\n"); RTSflags.GranFlags.InversePriorities++; break; case 'R': RTSflags.GranFlags.DoPrioritySparking = 1; fprintf(stderr,"Priority Sparking with Random Priorities.\n"); RTSflags.GranFlags.RandomPriorities++; break; case 'N': RTSflags.GranFlags.DoPrioritySparking = 1; fprintf(stderr,"Priority Sparking with No Priorities.\n"); RTSflags.GranFlags.IgnorePriorities++; break; default: bad_option( rts_argv[arg] ); break; } break; case '-': switch(rts_argv[arg][3]) { case 'C': RTSflags.GranFlags.DoAlwaysCreateThreads=rtsFalse; RTSflags.GranFlags.DoThreadMigration=rtsFalse; break; case 'G': RTSflags.GranFlags.DoGUMMFetching=rtsFalse; break; case 'M': RTSflags.GranFlags.DoThreadMigration=rtsFalse; break; case 'R': RTSflags.GranFlags.DoFairSchedule=rtsFalse; break; case 'T': RTSflags.GranFlags.DoStealThreadsFirst=rtsFalse; RTSflags.GranFlags.DoThreadMigration=rtsFalse; break; case 'Z': RTSflags.GranFlags.DoReScheduleOnFetch=rtsFalse; break; case 'N': RTSflags.GranFlags.PreferSparksOfLocalNodes=rtsFalse; break; case 'P': RTSflags.GranFlags.granSimStats_suppressed=rtsTrue; break; case 's': RTSflags.GranFlags.granSimStats_Sparks=rtsFalse; break; case 'h': RTSflags.GranFlags.granSimStats_Heap=rtsFalse; break; case 'b': RTSflags.GranFlags.granSimStats_Binary=rtsFalse; break; case 'X': RTSflags.GranFlags.DoPrioritySparking = rtsFalse; break; case 'Y': RTSflags.GranFlags.DoPrioritySparking = rtsFalse; RTSflags.GranFlags.SparkPriority = rtsFalse; break; case 'I': RTSflags.GranFlags.DoPriorityScheduling = rtsFalse; break; case 'e': RTSflags.GranFlags.RandomSteal = rtsFalse; break; default: bad_option( rts_argv[arg] ); break; } break; # if defined(GRAN_CHECK) && defined(GRAN) case 'D': switch(rts_argv[arg][3]) { case 'Q': /* Set pack buffer size (same as 'Q' in GUM) */ if (rts_argv[arg][4] != '\0') { RTSflags.GranFlags.packBufferSize = decode(rts_argv[arg]+4); fprintf(stderr,"Pack buffer size: %d\n", RTSflags.GranFlags.packBufferSize); } else { fprintf(stderr, "setupRtsFlags: missing size of PackBuffer (for -Q)\n"); error = rtsTrue; } break; case 'e': /* event trace */ fprintf(stderr,"Printing event trace.\n"); RTSflags.GranFlags.event_trace=rtsTrue; break; case 'f': fprintf(stderr,"Printing forwarding of FETCHNODES.\n"); RTSflags.GranFlags.debug |= 0x2; /* print fwd messages */ break; case 'z': fprintf(stderr,"Check for blocked on fetch.\n"); RTSflags.GranFlags.debug |= 0x4; /* debug non-reschedule-on-fetch */ break; case 't': fprintf(stderr,"Check for TSO asleep on fetch.\n"); RTSflags.GranFlags.debug |= 0x10; /* debug TSO asleep for fetch */ break; case 'E': fprintf(stderr,"Printing event statistics.\n"); RTSflags.GranFlags.debug |= 0x20; /* print event statistics */ break; case 'F': fprintf(stderr,"Prohibiting forward.\n"); RTSflags.GranFlags.NoForward = rtsTrue; /* prohibit forwarding */ break; case 'm': fprintf(stderr,"Printing fetch misses.\n"); RTSflags.GranFlags.PrintFetchMisses = rtsTrue; /* prohibit forwarding */ break; case 'd': fprintf(stderr,"Debug mode.\n"); RTSflags.GranFlags.debug |= 0x40; break; case 'D': fprintf(stderr,"Severe debug mode.\n"); RTSflags.GranFlags.debug |= 0x80; break; case 'q': fprintf(stderr,"FULL event trace.\n"); RTSflags.GranFlags.event_trace_all =rtsTrue; break; case 'G': fprintf(stderr,"Debugging packet fetching.\n"); RTSflags.GranFlags.debug |= 0x100; break; case 'n': fprintf(stderr,"Ignore events till end of time slice\n"); RTSflags.GranFlags.debug |= 0x200; IgnoreEvents = rtsTrue; break; case 'S': fprintf(stderr,"Check that spark queues are sorted.\n"); RTSflags.GranFlags.debug |= 0x400; break; case 'H': fprintf(stderr,"Print heap allocation messages (RBH).\n"); RTSflags.GranFlags.debug |= 0x800; break; case 'p': fprintf(stderr,"Debug breadth-first pruning.\n"); RTSflags.GranFlags.debug |= 0x1000; break; case 'r': fprintf(stderr,"Debug random stealing.\n"); RTSflags.GranFlags.debug |= 0x2000; break; case 'B': fprintf(stderr,"Debug busyness.\n"); RTSflags.GranFlags.debug |= 0x4000; break; case 'P': fprintf(stderr,"Debug pack buffer handling.\n"); RTSflags.GranFlags.debug |= 0x8000; break; case 's': fprintf(stderr,"Debug spark-queue manipulations.\n"); RTSflags.GranFlags.debug |= 0x10000; break; case ':': fprintf(stderr,"Debug GrAnSim Light.\n"); RTSflags.GranFlags.debug |= 0x20000; break; case '\0': RTSflags.GranFlags.debug = 1; break; default: bad_option( rts_argv[arg] ); break; } break; # endif /* GRAN_CHECK */ default: bad_option( rts_argv[arg] ); break; } } #endif /* GRAN */ \end{code} %************************************************************************ %* * \subsection{Profiling RTS Arguments} %* * %************************************************************************ \begin{code} I_ MaxResidency = 0; /* in words; for stats only */ I_ ResidencySamples = 0; /* for stats only */ void initSM(void) { RTSflags.GcFlags.minAllocAreaSize = (I_) (RTSflags.GcFlags.heapSize * RTSflags.GcFlags.pcFreeHeap / 100); /* This needs to be here, in case the user changed some of these values with a "hook". */ } \end{code} %************************************************************************ %* * \subsection{Utility bits} %* * %************************************************************************ \begin{code} static FILE * /* return NULL on error */ open_stats_file ( I_ arg, int argc, char *argv[], int rts_argc, char *rts_argv[], const char *FILENAME_FMT) { FILE *f = NULL; if (strequal(rts_argv[arg]+2, "stderr")) /* use real stderr */ f = stderr; else if (rts_argv[arg][2] != '\0') /* stats file specified */ f = fopen(rts_argv[arg]+2,"w"); else { char stats_filename[STATS_FILENAME_MAXLEN]; /* default . */ sprintf(stats_filename, FILENAME_FMT, argv[0]); f = fopen(stats_filename,"w"); } if (f == NULL) { fprintf(stderr, "Can't open stats file %s\n", rts_argv[arg]+2); } else { /* Write argv and rtsv into start of stats file */ I_ count; for(count = 0; count < argc; count++) fprintf(f, "%s ", argv[count]); fprintf(f, "+RTS "); for(count = 0; count < rts_argc; count++) fprintf(f, "%s ", rts_argv[count]); fprintf(f, "\n"); } return(f); } static I_ decode(const char *s) { I_ c; StgDouble m; if (!*s) return 0; m = atof(s); c = s[strlen(s)-1]; if (c == 'g' || c == 'G') m *= 1000*1000*1000; /* UNchecked! */ else if (c == 'm' || c == 'M') m *= 1000*1000; /* We do not use powers of 2 (1024) */ else if (c == 'k' || c == 'K') /* to avoid possible bad effects on */ m *= 1000; /* a direct-mapped cache. */ else if (c == 'w' || c == 'W') m *= sizeof(W_); return (I_)m; } static void bad_option(const char *s) { fflush(stdout); fprintf(stderr, "initSM: Bad RTS option: %s\n", s); EXIT(EXIT_FAILURE); } \end{code}