X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=rts%2FRtsFlags.c;h=f8c8403328eeffccddb95c4592d68ab85b8584d3;hp=0f83b3356c3a23ba8bb7275f2196ef9fa4c3b1db;hb=842e9d6628a27cf1f420d53f6a5901935dc50c54;hpb=0065d5ab628975892cea1ec7303f968c3338cbe1 diff --git a/rts/RtsFlags.c b/rts/RtsFlags.c index 0f83b33..f8c8403 100644 --- a/rts/RtsFlags.c +++ b/rts/RtsFlags.c @@ -1,32 +1,16 @@ - /* ----------------------------------------------------------------------------- * * (c) The AQUA Project, Glasgow University, 1994-1997 - * (c) The GHC Team, 1998-1999 + * (c) The GHC Team, 1998-2006 * * Functions for parsing the argument list. * * ---------------------------------------------------------------------------*/ -//@menu -//* Includes:: -//* Constants:: -//* Static function decls:: -//* Command-line option parsing routines:: -//* GranSim specific options:: -//* Aux fcts:: -//@end menu -//*/ - -//@node Includes, Constants -//@subsection Includes - #include "PosixSource.h" #include "Rts.h" #include "RtsFlags.h" #include "RtsUtils.h" -#include "BlockAlloc.h" -#include "Timer.h" /* CS_MIN_MILLISECS */ #include "Profiling.h" #ifdef HAVE_CTYPE_H @@ -44,13 +28,12 @@ RTS_FLAGS RtsFlags; */ int prog_argc = 0; /* an "int" so as to match normal "argc" */ char **prog_argv = NULL; +int full_prog_argc = 0; /* an "int" so as to match normal "argc" */ +char **full_prog_argv = NULL; char *prog_name = NULL; /* 'basename' of prog_argv[0] */ int rts_argc = 0; /* ditto */ char *rts_argv[MAX_RTS_ARGS]; -//@node Constants, Static function decls, Includes -//@subsection Constants - /* * constants, used later */ @@ -108,9 +91,6 @@ static char par_debug_opts_flags[] = { #endif /* PAR */ -//@node Static function decls, Command-line option parsing routines, Constants -//@subsection Static function decls - /* ----------------------------------------------------------------------------- Static function decls -------------------------------------------------------------------------- */ @@ -137,9 +117,6 @@ static void set_par_debug_options(nat n); static void help_par_debug_options(nat n); #endif -//@node Command-line option parsing routines, GranSim specific options, Static function decls -//@subsection Command-line option parsing routines - /* ----------------------------------------------------------------------------- * Command-line option parsing routines. * ---------------------------------------------------------------------------*/ @@ -173,12 +150,23 @@ void initRtsFlagsDefaults(void) #ifdef RTS_GTK_FRONTPANEL RtsFlags.GcFlags.frontpanel = rtsFalse; #endif - RtsFlags.GcFlags.idleGCDelayTicks = 300 / TICK_MILLISECS; /* ticks */ + RtsFlags.GcFlags.idleGCDelayTime = 300; /* millisecs */ + +#if osf3_HOST_OS +/* ToDo: Perhaps by adjusting this value we can make linking without + * -static work (i.e., not generate a core-dumping executable)? */ +# if SIZEOF_VOID_P == 8 + RtsFlags.GcFlags.heapBase = 0x180000000L; +# else +# error I have no idea where to begin the heap on a non-64-bit osf3 machine. +# endif +#else + RtsFlags.GcFlags.heapBase = 0; /* means don't care */ +#endif #ifdef DEBUG RtsFlags.DebugFlags.scheduler = rtsFalse; RtsFlags.DebugFlags.interpreter = rtsFalse; - RtsFlags.DebugFlags.codegen = rtsFalse; RtsFlags.DebugFlags.weak = rtsFalse; RtsFlags.DebugFlags.gccafs = rtsFalse; RtsFlags.DebugFlags.gc = rtsFalse; @@ -191,18 +179,21 @@ void initRtsFlagsDefaults(void) RtsFlags.DebugFlags.par = rtsFalse; RtsFlags.DebugFlags.linker = rtsFalse; RtsFlags.DebugFlags.squeeze = rtsFalse; + RtsFlags.DebugFlags.hpc = rtsFalse; #endif #if defined(PROFILING) || defined(PAR) RtsFlags.CcFlags.doCostCentres = 0; #endif /* PROFILING or PAR */ -#ifdef PROFILING RtsFlags.ProfFlags.doHeapProfile = rtsFalse; RtsFlags.ProfFlags.profileInterval = 100; + +#ifdef PROFILING RtsFlags.ProfFlags.includeTSOs = rtsFalse; RtsFlags.ProfFlags.showCCSOnException = rtsFalse; RtsFlags.ProfFlags.maxRetainerSetSize = 8; + RtsFlags.ProfFlags.ccsLength = 25; RtsFlags.ProfFlags.modSelector = NULL; RtsFlags.ProfFlags.descrSelector = NULL; RtsFlags.ProfFlags.typeSelector = NULL; @@ -210,12 +201,12 @@ void initRtsFlagsDefaults(void) RtsFlags.ProfFlags.ccsSelector = NULL; RtsFlags.ProfFlags.retainerSelector = NULL; RtsFlags.ProfFlags.bioSelector = NULL; - -#elif defined(DEBUG) - RtsFlags.ProfFlags.doHeapProfile = rtsFalse; #endif - RtsFlags.ConcFlags.ctxtSwitchTime = CS_MIN_MILLISECS; /* In milliseconds */ + RtsFlags.MiscFlags.tickInterval = 20; /* In milliseconds */ + RtsFlags.ConcFlags.ctxtSwitchTime = 20; /* In milliseconds */ + + RtsFlags.MiscFlags.install_signal_handlers = rtsTrue; #ifdef THREADED_RTS RtsFlags.ParFlags.nNodes = 1; @@ -322,6 +313,14 @@ void initRtsFlagsDefaults(void) RtsFlags.TickyFlags.showTickyStats = rtsFalse; RtsFlags.TickyFlags.tickyFile = NULL; #endif + + RtsFlags.TraceFlags.timestamp = rtsFalse; + RtsFlags.TraceFlags.sched = rtsFalse; + +#ifdef USE_PAPI + /* By default no special measurements taken */ + RtsFlags.PapiFlags.eventType = 0; +#endif } static const char * @@ -337,6 +336,7 @@ usage_text[] = { "The following run time system options are available:", "", " -? Prints this message and exits; the program is not executed", +" --info Print information about the RTS used by this program", "", " -K Sets the maximum stack size (default 8M) Egs: -K32k -K512k", " -k Sets the initial thread stack size (default 1k) Egs: -k4k -k2m", @@ -391,38 +391,43 @@ usage_text[] = { " -hb... closures with specified biographies (lag,drag,void,use)", "", " -R Set the maximum retainer set size (default: 8)", -"", -" -i Time between heap samples (seconds, default: 0.1)", +"", +" -L Maximum length of a cost-centre stack in a heap profile", +" (default: 25)", "", " -xt Include threads (TSOs) in a heap profile", "", " -xc Show current cost centre stack on raising an exception", +"", # endif #endif /* PROFILING or PAR */ -#if !defined(PROFILING) && defined(DEBUG) +#if !defined(PROFILING) "", -" -h Debugging Heap residency profile", -" (output file .hp)", -" break-down: L = closure label (default)", -" T = closure type (constructor, thunk etc.)", +" -hT Heap residency profile (output file .hp)", #endif +" -i Time between heap samples (seconds, default: 0.1)", "", #if defined(TICKY_TICKY) -" -r Produce reduction profiling statistics (with -rstderr for stderr)", +" -r Produce ticky-ticky statistics (with -rstderr for stderr)", "", #endif #if defined(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 .02 sec; resolution is .02 sec", +" -C Context-switch interval in seconds.", +" 0 or no argument means switch as often as possible.", +" Default: 0.02 sec; resolution is set by -V below.", +" -V Master tick interval in seconds (0 == disable timer).", +" This sets the resolution for -C and the profile timer -i.", +" Default: 0.02 sec.", +"", +" -vs Trace scheduler events (see also -Ds with -debug)", +" -vt Time-stamp trace messages", "", #if defined(DEBUG) " -Ds DEBUG: scheduler", " -Di DEBUG: interpreter", -" -Dc DEBUG: codegen", " -Dw DEBUG: weak", " -DG DEBUG: gccafs", " -Dg DEBUG: gc", @@ -435,13 +440,16 @@ usage_text[] = { " -Dl DEBUG: linker", " -Dm DEBUG: stm", " -Dz DEBUG: stack squezing", +" -Dc DEBUG: program coverage", "", #endif /* DEBUG */ -#if defined(THREADED_RTS) +#if defined(THREADED_RTS) && !defined(NOSMP) " -N Use OS threads (default: 1)", " -qm Don't automatically migrate threads between CPUs", " -qw Migrate a thread to the current CPU when it is woken up", #endif +" --install-signal-handlers=", +" Install signal handlers (default: yes)", #if defined(THREADED_RTS) || defined(PAR) " -e Size of spark pools (default 100)", #endif @@ -462,6 +470,17 @@ usage_text[] = { #if defined(GRAN) /* ToDo: fill in decent Docu here */ " -b... All GranSim options start with -b; see GranSim User's Guide for details", #endif +#if defined(USE_PAPI) +" -aX CPU performance counter measurements using PAPI", +" (use with the -s option). X is one of:", +"", +/* " y - cycles", */ +" 1 - level 1 cache misses", +" 2 - level 2 cache misses", +" b - branch mispredictions", +" s - stalled cycles", +" e - cache miss and branch misprediction events", +#endif "", "RTS options may also be specified using the GHCRTS environment variable.", "", @@ -652,6 +671,28 @@ error = rtsTrue; error = rtsTrue; break; + /* This isn't going to allow us to keep related options + together as we add more --* flags. We really need a + proper options parser. */ + case '-': + if (strequal("install-signal-handlers=yes", + &rts_argv[arg][2])) { + RtsFlags.MiscFlags.install_signal_handlers = rtsTrue; + } + else if (strequal("install-signal-handlers=no", + &rts_argv[arg][2])) { + RtsFlags.MiscFlags.install_signal_handlers = rtsFalse; + } + else if (strequal("info", + &rts_argv[arg][2])) { + printRtsInfo(); + exit(0); + } + else { + errorBelch("unknown RTS option: %s",rts_argv[arg]); + error = rtsTrue; + } + break; case 'A': RtsFlags.GcFlags.minAllocAreaSize = decode(rts_argv[arg]+2) / BLOCK_SIZE; @@ -660,6 +701,30 @@ error = rtsTrue; } break; +#ifdef USE_PAPI + case 'a': + switch(rts_argv[arg][2]) { + case '1': + RtsFlags.PapiFlags.eventType = PAPI_FLAG_CACHE_L1; + break; + case '2': + RtsFlags.PapiFlags.eventType = PAPI_FLAG_CACHE_L2; + break; + case 'b': + RtsFlags.PapiFlags.eventType = PAPI_FLAG_BRANCH; + break; + case 's': + RtsFlags.PapiFlags.eventType = PAPI_FLAG_STALLS; + break; + case 'e': + RtsFlags.PapiFlags.eventType = PAPI_FLAG_CB_EVENTS; + break; + default: + bad_option( rts_argv[arg] ); + } + break; +#endif + case 'B': RtsFlags.GcFlags.ringBell = rtsTrue; break; @@ -693,9 +758,6 @@ error = rtsTrue; case 'i': RtsFlags.DebugFlags.interpreter = rtsTrue; break; - case 'c': - RtsFlags.DebugFlags.codegen = rtsTrue; - break; case 'w': RtsFlags.DebugFlags.weak = rtsTrue; break; @@ -735,6 +797,9 @@ error = rtsTrue; case 'z': RtsFlags.DebugFlags.squeeze = rtsTrue; break; + case 'c': + RtsFlags.DebugFlags.hpc = rtsTrue; + break; default: bad_option( rts_argv[arg] ); } @@ -812,14 +877,9 @@ error = rtsTrue; } else { I_ cst; /* tmp */ - /* Convert to ticks */ + /* Convert to millisecs */ cst = (I_) ((atof(rts_argv[arg]+2) * 1000)); - if (cst > 0 && cst < TICK_MILLISECS) { - cst = TICK_MILLISECS; - } else { - cst = cst / TICK_MILLISECS; - } - RtsFlags.GcFlags.idleGCDelayTicks = cst; + RtsFlags.GcFlags.idleGCDelayTime = cst; } break; @@ -883,14 +943,17 @@ error = rtsTrue; PROFILING_BUILD_ONLY( RtsFlags.ProfFlags.maxRetainerSetSize = atof(rts_argv[arg]+2); ) break; - + case 'L': + PROFILING_BUILD_ONLY( + RtsFlags.ProfFlags.ccsLength = atof(rts_argv[arg]+2); + if(RtsFlags.ProfFlags.ccsLength <= 0) { + bad_option(rts_argv[arg]); + } + ) break; case 'h': /* serial heap profile */ -#if !defined(PROFILING) && defined(DEBUG) +#if !defined(PROFILING) switch (rts_argv[arg][2]) { case '\0': - case 'L': - RtsFlags.ProfFlags.doHeapProfile = HEAP_BY_INFOPTR; - break; case 'T': RtsFlags.ProfFlags.doHeapProfile = HEAP_BY_CLOSURE_TYPE; break; @@ -1006,7 +1069,6 @@ error = rtsTrue; #endif /* PROFILING */ break; -#if defined(PROFILING) case 'i': /* heap sample interval */ if (rts_argv[arg][2] == '\0') { /* use default */ @@ -1015,14 +1077,9 @@ error = rtsTrue; /* Convert to milliseconds */ cst = (I_) ((atof(rts_argv[arg]+2) * 1000)); - cst = (cst / CS_MIN_MILLISECS) * CS_MIN_MILLISECS; - if (cst != 0 && cst < CS_MIN_MILLISECS) - cst = CS_MIN_MILLISECS; - RtsFlags.ProfFlags.profileInterval = cst; } break; -#endif /* =========== CONCURRENT ========================= */ case 'C': /* context switch interval */ @@ -1033,15 +1090,24 @@ error = rtsTrue; /* Convert to milliseconds */ cst = (I_) ((atof(rts_argv[arg]+2) * 1000)); - cst = (cst / CS_MIN_MILLISECS) * CS_MIN_MILLISECS; - if (cst != 0 && cst < CS_MIN_MILLISECS) - cst = CS_MIN_MILLISECS; - RtsFlags.ConcFlags.ctxtSwitchTime = cst; } break; -#ifdef THREADED_RTS + case 'V': /* master tick interval */ + if (rts_argv[arg][2] == '\0') { + // turns off ticks completely + RtsFlags.MiscFlags.tickInterval = 0; + } else { + I_ cst; /* tmp */ + + /* Convert to milliseconds */ + cst = (I_) ((atof(rts_argv[arg]+2) * 1000)); + RtsFlags.MiscFlags.tickInterval = cst; + } + break; + +#if defined(THREADED_RTS) && !defined(NOSMP) case 'N': THREADED_BUILD_ONLY( if (rts_argv[arg][2] != '\0') { @@ -1051,10 +1117,16 @@ error = rtsTrue; errorBelch("bad value for -N"); error = rtsTrue; } +#if defined(PROFILING) + if (RtsFlags.ParFlags.nNodes > 1) { + errorBelch("bad option %s: only -N1 is supported with profiling", rts_argv[arg]); + error = rtsTrue; + } +#endif } ) break; - case 'q': + case 'q': switch (rts_argv[arg][2]) { case '\0': errorBelch("incomplete RTS option: %s",rts_argv[arg]); @@ -1116,6 +1188,27 @@ error = rtsTrue; } ) break; + /* =========== TRACING ---------=================== */ + + case 'v': + switch(rts_argv[arg][2]) { + case '\0': + errorBelch("incomplete RTS option: %s",rts_argv[arg]); + error = rtsTrue; + break; + case 't': + RtsFlags.TraceFlags.timestamp = rtsTrue; + break; + case 's': + RtsFlags.TraceFlags.sched = rtsTrue; + break; + default: + errorBelch("unknown RTS option: %s",rts_argv[arg]); + error = rtsTrue; + break; + } + break; + /* =========== EXTENDED OPTIONS =================== */ case 'x': /* Extend the argument space */ @@ -1125,6 +1218,16 @@ error = rtsTrue; error = rtsTrue; break; + case 'b': /* heapBase in hex; undocumented */ + if (rts_argv[arg][3] != '\0') { + RtsFlags.GcFlags.heapBase + = strtol(rts_argv[arg]+3, (char **) NULL, 16); + } else { + errorBelch("-xb: requires argument"); + error = rtsTrue; + } + break; + case 'c': /* Debugging tool: show current cost centre on an exception */ PROFILING_BUILD_ONLY( RtsFlags.ProfFlags.showCCSOnException = rtsTrue; @@ -1154,6 +1257,55 @@ error = rtsTrue; } } } + + if (RtsFlags.MiscFlags.tickInterval < 0) { + RtsFlags.MiscFlags.tickInterval = 50; + } + + // If the master timer is disabled, turn off the other timers. + if (RtsFlags.MiscFlags.tickInterval == 0) { + RtsFlags.ConcFlags.ctxtSwitchTime = 0; + RtsFlags.GcFlags.idleGCDelayTime = 0; + RtsFlags.ProfFlags.profileInterval = 0; + } + + // Determine what tick interval we should use for the RTS timer + // by taking the shortest of the various intervals that we need to + // monitor. + if (RtsFlags.ConcFlags.ctxtSwitchTime > 0) { + RtsFlags.MiscFlags.tickInterval = + stg_min(RtsFlags.ConcFlags.ctxtSwitchTime, + RtsFlags.MiscFlags.tickInterval); + } + + if (RtsFlags.GcFlags.idleGCDelayTime > 0) { + RtsFlags.MiscFlags.tickInterval = + stg_min(RtsFlags.GcFlags.idleGCDelayTime, + RtsFlags.MiscFlags.tickInterval); + } + + if (RtsFlags.ProfFlags.profileInterval > 0) { + RtsFlags.MiscFlags.tickInterval = + stg_min(RtsFlags.ProfFlags.profileInterval, + RtsFlags.MiscFlags.tickInterval); + } + + if (RtsFlags.ConcFlags.ctxtSwitchTime > 0) { + RtsFlags.ConcFlags.ctxtSwitchTicks = + RtsFlags.ConcFlags.ctxtSwitchTime / + RtsFlags.MiscFlags.tickInterval; + } else { + RtsFlags.ConcFlags.ctxtSwitchTicks = 0; + } + + if (RtsFlags.ProfFlags.profileInterval > 0) { + RtsFlags.ProfFlags.profileIntervalTicks = + RtsFlags.ProfFlags.profileInterval / + RtsFlags.MiscFlags.tickInterval; + } else { + RtsFlags.ProfFlags.profileIntervalTicks = 0; + } + if (error) { const char **p; @@ -1166,9 +1318,6 @@ error = rtsTrue; #if defined(GRAN) -//@node GranSim specific options, Aux fcts, Command-line option parsing routines -//@subsection GranSim specific options - static void enable_GranSimLight(void) { @@ -2140,9 +2289,6 @@ help_par_debug_options(nat n) { #endif /* PAR */ -//@node Aux fcts, , GranSim specific options -//@subsection Aux fcts - static void stats_fprintf(FILE *f, char *s, ...) { @@ -2279,3 +2425,29 @@ setProgArgv(int argc, char *argv[]) prog_argv = argv; setProgName(prog_argv); } + +/* These functions record and recall the full arguments, including the + +RTS ... -RTS options. The reason for adding them was so that the + ghc-inplace program can pass /all/ the arguments on to the real ghc. */ +void +getFullProgArgv(int *argc, char **argv[]) +{ + if (argc) { *argc = full_prog_argc; } + if (argv) { *argv = full_prog_argv; } +} + +void +setFullProgArgv(int argc, char *argv[]) +{ + int i; + full_prog_argc = argc; + full_prog_argv = stgCallocBytes(argc + 1, sizeof (char *), + "setFullProgArgv 1"); + for (i = 0; i < argc; i++) { + full_prog_argv[i] = stgMallocBytes(strlen(argv[i]) + 1, + "setFullProgArgv 2"); + strcpy(full_prog_argv[i], argv[i]); + } + full_prog_argv[argc] = NULL; +} +