*/
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];
#endif
RtsFlags.GcFlags.compact = rtsFalse;
RtsFlags.GcFlags.compactThreshold = 30.0;
+ RtsFlags.GcFlags.sweep = rtsFalse;
#ifdef RTS_GTK_FRONTPANEL
RtsFlags.GcFlags.frontpanel = rtsFalse;
#endif
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.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.ccsSelector = NULL;
RtsFlags.ProfFlags.retainerSelector = NULL;
RtsFlags.ProfFlags.bioSelector = NULL;
-
-#elif defined(DEBUG)
- RtsFlags.ProfFlags.doHeapProfile = rtsFalse;
#endif
- RtsFlags.MiscFlags.tickInterval = 50; /* In milliseconds */
- RtsFlags.ConcFlags.ctxtSwitchTime = 50; /* In milliseconds */
+ RtsFlags.MiscFlags.tickInterval = 20; /* In milliseconds */
+ RtsFlags.ConcFlags.ctxtSwitchTime = 20; /* In milliseconds */
RtsFlags.MiscFlags.install_signal_handlers = rtsTrue;
RtsFlags.ParFlags.nNodes = 1;
RtsFlags.ParFlags.migrate = rtsTrue;
RtsFlags.ParFlags.wakeupMigrate = rtsFalse;
+ RtsFlags.ParFlags.gcThreads = 1;
#endif
#ifdef PAR
RtsFlags.TraceFlags.timestamp = rtsFalse;
RtsFlags.TraceFlags.sched = rtsFalse;
+ RtsFlags.TraceFlags.gc = rtsFalse;
#ifdef USE_PAPI
/* By default no special measurements taken */
RtsFlags.PapiFlags.eventType = 0;
+ RtsFlags.PapiFlags.numUserEvents = 0;
#endif
}
"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<size> Sets the maximum stack size (default 8M) Egs: -K32k -K512k",
" -k<size> Sets the initial thread stack size (default 1k) Egs: -k4k -k2m",
" -c<n> Auto-enable compaction of the oldest generation when live data is",
" at least <n>% of the maximum heap size set with -M (default: 30%)",
" -c Enable compaction for all major collections",
+" -w Use mark-region for the oldest generation (experimental)",
#if defined(THREADED_RTS)
" -I<sec> Perform full GC after <sec> idle time (default: 0.3, 0 == off)",
#endif
"",
-" -t<file> One-line GC statistics (default file: <program>.stat)",
-" -s<file> Summary GC statistics (with -Sstderr going to stderr)",
-" -S<file> Detailed GC statistics",
+" -t[<file>] One-line GC statistics (if <file> omitted, uses stderr)",
+" -s[<file>] Summary GC statistics (if <file> omitted, uses stderr)",
+" -S[<file>] Detailed GC statistics (if <file> omitted, uses stderr)",
#ifdef RTS_GTK_FRONTPANEL
" -f Display front panel (requires X11 & GTK+)",
#endif
" -L<chars> Maximum length of a cost-centre stack in a heap profile",
" (default: 25)",
"",
-" -i<sec> Time between heap samples (seconds, default: 0.1)",
-"",
" -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 ticky-ticky statistics (with -rstderr for stderr)",
" -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.",
+" -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.",
"",
"",
#endif /* DEBUG */
#if defined(THREADED_RTS) && !defined(NOSMP)
-" -N<n> Use <n> OS threads (default: 1)",
+" -N<n> Use <n> OS threads (default: 1) (also sets -g)",
+" -g<n> Use <n> OS threads for GC (default: 1)",
" -qm Don't automatically migrate threads between CPUs",
" -qw Migrate a thread to the current CPU when it is woken up",
#endif
&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;
case 'e':
RtsFlags.PapiFlags.eventType = PAPI_FLAG_CB_EVENTS;
break;
+ case '+':
+ if (RtsFlags.PapiFlags.numUserEvents >= MAX_PAPI_USER_EVENTS) {
+ errorBelch("maximum number of PAPI events reached");
+ stg_exit(EXIT_FAILURE);
+ }
+ RtsFlags.PapiFlags.eventType = PAPI_USER_EVENTS;
+ RtsFlags.PapiFlags.userEvents[RtsFlags.PapiFlags.numUserEvents++] = rts_argv[arg] + 3;
+ break;
default:
bad_option( rts_argv[arg] );
}
}
break;
+ case 'w':
+ RtsFlags.GcFlags.sweep = rtsTrue;
+ break;
+
case 'F':
RtsFlags.GcFlags.oldGenFactor = atof(rts_argv[arg]+2);
case 'H':
RtsFlags.GcFlags.heapSizeSuggestion =
decode(rts_argv[arg]+2) / BLOCK_SIZE;
-
- if (RtsFlags.GcFlags.heapSizeSuggestion <= 0) {
- bad_option(rts_argv[arg]);
- }
break;
#ifdef RTS_GTK_FRONTPANEL
{
int r;
r = open_stats_file(arg, *argc, argv,
- *rts_argc, rts_argv, STAT_FILENAME_FMT,
+ *rts_argc, rts_argv, NULL,
&RtsFlags.GcFlags.statsFile);
if (r == -1) { error = rtsTrue; }
}
}
) 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 */
RtsFlags.ProfFlags.profileInterval = cst;
}
break;
-#endif
/* =========== CONCURRENT ========================= */
case 'C': /* context switch interval */
if (rts_argv[arg][2] != '\0') {
RtsFlags.ParFlags.nNodes
= strtol(rts_argv[arg]+2, (char **) NULL, 10);
+ // set -g at the same time as -N by default
+ RtsFlags.ParFlags.gcThreads = RtsFlags.ParFlags.nNodes;
if (RtsFlags.ParFlags.nNodes <= 0) {
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 'g':
+ THREADED_BUILD_ONLY(
+ if (rts_argv[arg][2] != '\0') {
+ RtsFlags.ParFlags.gcThreads
+ = strtol(rts_argv[arg]+2, (char **) NULL, 10);
+ if (RtsFlags.ParFlags.gcThreads <= 0) {
+ errorBelch("bad value for -g");
+ error = rtsTrue;
+ }
}
) break;
case 's':
RtsFlags.TraceFlags.sched = rtsTrue;
break;
+ case 'g':
+ RtsFlags.TraceFlags.gc = rtsTrue;
+ break;
default:
errorBelch("unknown RTS option: %s",rts_argv[arg]);
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;
}
}
- // 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.MiscFlags.tickInterval <= 0) {
+ 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);
}
-#ifdef PROFILING
if (RtsFlags.ProfFlags.profileInterval > 0) {
RtsFlags.MiscFlags.tickInterval =
stg_min(RtsFlags.ProfFlags.profileInterval,
RtsFlags.MiscFlags.tickInterval);
}
-#endif
if (RtsFlags.ConcFlags.ctxtSwitchTime > 0) {
RtsFlags.ConcFlags.ctxtSwitchTicks =
RtsFlags.ConcFlags.ctxtSwitchTicks = 0;
}
-#ifdef PROFILING
- RtsFlags.ProfFlags.profileIntervalTicks =
- RtsFlags.ProfFlags.profileInterval / RtsFlags.MiscFlags.tickInterval;
-#endif
+ if (RtsFlags.ProfFlags.profileInterval > 0) {
+ RtsFlags.ProfFlags.profileIntervalTicks =
+ RtsFlags.ProfFlags.profileInterval /
+ RtsFlags.MiscFlags.tickInterval;
+ } else {
+ RtsFlags.ProfFlags.profileIntervalTicks = 0;
+ }
if (error) {
const char **p;
{
FILE *f = NULL;
- if (strequal(rts_argv[arg]+2, "stderr")) { /* use debugBelch */
+ if (strequal(rts_argv[arg]+2, "stderr")
+ || (FILENAME_FMT == NULL && rts_argv[arg][2] == '\0')) {
f = NULL; /* NULL means use debugBelch */
} 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 <program>.<ext> */
- sprintf(stats_filename, FILENAME_FMT, argv[0]);
- f = fopen(stats_filename,"w");
- }
+ if (rts_argv[arg][2] != '\0') { /* stats file specified */
+ f = fopen(rts_argv[arg]+2,"w");
+ } else {
+ char stats_filename[STATS_FILENAME_MAXLEN]; /* default <program>.<ext> */
+ sprintf(stats_filename, FILENAME_FMT, argv[0]);
+ f = fopen(stats_filename,"w");
+ }
if (f == NULL) {
errorBelch("Can't open stats file %s\n", rts_argv[arg]+2);
return -1;
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;
+}
+