-
/* -----------------------------------------------------------------------------
*
* (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
int rts_argc = 0; /* ditto */
char *rts_argv[MAX_RTS_ARGS];
-//@node Constants, Static function decls, Includes
-//@subsection Constants
-
/*
* constants, used later
*/
#endif /* PAR */
-//@node Static function decls, Command-line option parsing routines, Constants
-//@subsection Static function decls
-
/* -----------------------------------------------------------------------------
Static function decls
-------------------------------------------------------------------------- */
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.
* ---------------------------------------------------------------------------*/
#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;
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;
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 = 50; /* In milliseconds */
+ RtsFlags.ConcFlags.ctxtSwitchTime = 50; /* In milliseconds */
+
+ RtsFlags.MiscFlags.install_signal_handlers = rtsTrue;
#ifdef THREADED_RTS
RtsFlags.ParFlags.nNodes = 1;
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 *
" -hb<bio>... closures with specified biographies (lag,drag,void,use)",
"",
" -R<size> Set the maximum retainer set size (default: 8)",
-"",
-" -i<sec> Time between heap samples (seconds, default: 0.1)",
+"",
+" -L<chars> 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<break-down> Debugging Heap residency profile",
-" (output file <program>.hp)",
-" break-down: L = closure label (default)",
-" T = closure type (constructor, thunk etc.)",
+" -hT Heap residency profile (output file <program>.hp)",
#endif
+" -i<sec> Time between heap samples (seconds, default: 0.1)",
"",
#if defined(TICKY_TICKY)
-" -r<file> Produce reduction profiling statistics (with -rstderr for stderr)",
+" -r<file> Produce ticky-ticky statistics (with -rstderr for stderr)",
"",
#endif
#if defined(PAR)
" -N<n> Use <n> PVMish processors in parallel (default: 2)",
/* NB: the -N<n> is implemented by the driver!! */
#endif
-" -C<secs> 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<secs> 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<secs> 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",
" -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<n> Use <n> 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=<yes|no>",
+" Install signal handlers (default: yes)",
#if defined(THREADED_RTS) || defined(PAR)
" -e<size> Size of spark pools (default 100)",
#endif
#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<file> 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.",
"",
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 {
+ errorBelch("unknown RTS option: %s",rts_argv[arg]);
+ error = rtsTrue;
+ }
+ break;
case 'A':
RtsFlags.GcFlags.minAllocAreaSize
= decode(rts_argv[arg]+2) / BLOCK_SIZE;
}
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;
case 'i':
RtsFlags.DebugFlags.interpreter = rtsTrue;
break;
- case 'c':
- RtsFlags.DebugFlags.codegen = rtsTrue;
- break;
case 'w':
RtsFlags.DebugFlags.weak = rtsTrue;
break;
case 'z':
RtsFlags.DebugFlags.squeeze = rtsTrue;
break;
+ case 'c':
+ RtsFlags.DebugFlags.hpc = rtsTrue;
+ break;
default:
bad_option( rts_argv[arg] );
}
} 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;
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;
#endif /* PROFILING */
break;
-#if defined(PROFILING)
case 'i': /* heap sample interval */
if (rts_argv[arg][2] == '\0') {
/* use default */
/* 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 */
/* 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') {
}
) break;
- case 'q':
+ case 'q':
switch (rts_argv[arg][2]) {
case '\0':
errorBelch("incomplete RTS option: %s",rts_argv[arg]);
}
) 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 */
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;
}
}
}
+
+ 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;
#if defined(GRAN)
-//@node GranSim specific options, Aux fcts, Command-line option parsing routines
-//@subsection GranSim specific options
-
static void
enable_GranSimLight(void) {
#endif /* PAR */
-//@node Aux fcts, , GranSim specific options
-//@subsection Aux fcts
-
static void
stats_fprintf(FILE *f, char *s, ...)
{