#include "PosixSource.h"
#include "Rts.h"
-#include "RtsFlags.h"
+
#include "RtsUtils.h"
#include "Profiling.h"
#include <ctype.h>
#endif
-#include <stdlib.h>
#include <string.h>
// Flag Structure
const char *FILENAME_FMT,
FILE **file_ret);
-static I_ decode(const char *s);
+static StgWord64 decodeSize(const char *flag, nat offset, StgWord64 min, StgWord64 max);
static void bad_option(const char *s);
/* -----------------------------------------------------------------------------
RtsFlags.GcFlags.minOldGenSize = (1024 * 1024) / BLOCK_SIZE;
RtsFlags.GcFlags.maxHeapSize = 0; /* off by default */
RtsFlags.GcFlags.heapSizeSuggestion = 0; /* none */
+ RtsFlags.GcFlags.heapSizeSuggestionAuto = rtsFalse;
RtsFlags.GcFlags.pcFreeHeap = 3; /* 3% */
RtsFlags.GcFlags.oldGenFactor = 2;
RtsFlags.GcFlags.generations = 2;
RtsFlags.DebugFlags.stable = rtsFalse;
RtsFlags.DebugFlags.stm = rtsFalse;
RtsFlags.DebugFlags.prof = rtsFalse;
- RtsFlags.DebugFlags.eventlog = rtsFalse;
RtsFlags.DebugFlags.apply = rtsFalse;
RtsFlags.DebugFlags.linker = rtsFalse;
RtsFlags.DebugFlags.squeeze = rtsFalse;
RtsFlags.DebugFlags.hpc = rtsFalse;
- RtsFlags.DebugFlags.timestamp = rtsFalse;
+ RtsFlags.DebugFlags.sparks = rtsFalse;
#endif
#if defined(PROFILING)
RtsFlags.ProfFlags.bioSelector = NULL;
#endif
-#ifdef EVENTLOG
- RtsFlags.EventLogFlags.doEventLogging = rtsFalse;
+#ifdef TRACING
+ RtsFlags.TraceFlags.tracing = TRACE_NONE;
+ RtsFlags.TraceFlags.timestamp = rtsFalse;
+ RtsFlags.TraceFlags.scheduler = rtsFalse;
#endif
RtsFlags.MiscFlags.tickInterval = 20; /* In milliseconds */
RtsFlags.ParFlags.migrate = rtsTrue;
RtsFlags.ParFlags.wakeupMigrate = rtsFalse;
RtsFlags.ParFlags.parGcEnabled = 1;
- RtsFlags.ParFlags.parGcGen = 1;
- RtsFlags.ParFlags.parGcLoadBalancing = 1;
+ RtsFlags.ParFlags.parGcGen = 0;
+ RtsFlags.ParFlags.parGcLoadBalancingEnabled = rtsTrue;
+ RtsFlags.ParFlags.parGcLoadBalancingGen = 1;
RtsFlags.ParFlags.setAffinity = 0;
#endif
" -m<n> Minimum % of heap which must be available (default 3%)",
" -G<n> Number of generations (default: 2)",
" -T<n> Number of steps in younger generations (default: 2)",
-" -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",
+" -c<n> Use in-place compaction instead of copying in the oldest generation",
+" when live data is at least <n>% of the maximum heap size set with",
+" -M (default: 30%)",
+" -c Use in-place compaction for all oldest generation collections",
+" (the default is to use copying)",
" -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
#endif /* PROFILING or PAR */
-#ifdef EVENTLOG
+#ifdef TRACING
+"",
+" -v Log events to stderr",
+" -l Log events in binary format to the file <program>.eventlog",
+" -vt Include time stamps when tracing events to stderr with -v",
"",
-" -l Log runtime events (generates binary trace file <program>.eventlog)",
+" -ls Log scheduler events",
"",
#endif
" This sets the resolution for -C and the profile timer -i.",
" Default: 0.02 sec.",
"",
-" -vt Time-stamp debug messages",
-"",
#if defined(DEBUG)
" -Ds DEBUG: scheduler",
" -Di DEBUG: interpreter",
" -Dm DEBUG: stm",
" -Dz DEBUG: stack squezing",
" -Dc DEBUG: program coverage",
+" -Dr DEBUG: sparks",
+"",
+" NOTE: all -D options also enable -v automatically. Use -l to create a",
+" binary event log file instead.",
"",
#endif /* DEBUG */
#if defined(THREADED_RTS) && !defined(NOSMP)
" -N<n> Use <n> processors (default: 1)",
" -N Determine the number of processors to use automatically",
-" -q1 Use one OS thread for GC (turns off parallel GC)",
-" -qg<n> Use parallel GC only for generations >= <n> (default: 1)",
-" -qb Disable load-balancing in the parallel GC",
-" -qa Use the OS to set thread affinity",
+" -qg[<n>] Use parallel GC only for generations >= <n>",
+" (default: 0, -qg alone turns off parallel GC)",
+" -qb[<n>] Use load-balancing in the parallel GC only for generations >= <n>",
+" (default: 1, -qb alone turns off load-balancing)",
+" -qa Use the OS to set thread affinity (experimental)",
" -qm Don't automatically migrate threads between CPUs",
" -qw Migrate a thread to the current CPU when it is woken up",
#endif
error = rtsTrue;
#endif
-#ifdef EVENTLOG
-# define EVENTLOG_BUILD_ONLY(x) x
+#ifdef TRACING
+# define TRACING_BUILD_ONLY(x) x
#else
-# define EVENTLOG_BUILD_ONLY(x) \
+# define TRACING_BUILD_ONLY(x) \
errorBelch("not built for: -par-prof"); \
error = rtsTrue;
#endif
}
break;
case 'A':
- RtsFlags.GcFlags.minAllocAreaSize
- = decode(rts_argv[arg]+2) / BLOCK_SIZE;
- if (RtsFlags.GcFlags.minAllocAreaSize <= 0) {
- bad_option(rts_argv[arg]);
- }
- break;
+ RtsFlags.GcFlags.minAllocAreaSize
+ = decodeSize(rts_argv[arg], 2, BLOCK_SIZE, HS_INT_MAX)
+ / BLOCK_SIZE;
+ break;
#ifdef USE_PAPI
case 'a':
case 'p':
RtsFlags.DebugFlags.prof = rtsTrue;
break;
- case 'e':
- RtsFlags.DebugFlags.eventlog = rtsTrue;
- break;
case 'l':
RtsFlags.DebugFlags.linker = rtsTrue;
break;
case 'c':
RtsFlags.DebugFlags.hpc = rtsTrue;
break;
+ case 'r':
+ RtsFlags.DebugFlags.sparks = rtsTrue;
+ break;
default:
bad_option( rts_argv[arg] );
}
}
+ // -Dx also turns on -v. Use -l to direct trace
+ // events to the .eventlog file instead.
+ RtsFlags.TraceFlags.tracing = TRACE_STDERR;
break;
}
#endif
case 'K':
- RtsFlags.GcFlags.maxStkSize =
- decode(rts_argv[arg]+2) / sizeof(W_);
-
- if (RtsFlags.GcFlags.maxStkSize == 0)
- bad_option( rts_argv[arg] );
- break;
+ RtsFlags.GcFlags.maxStkSize =
+ decodeSize(rts_argv[arg], 2, 1, HS_WORD_MAX) / sizeof(W_);
+ break;
case 'k':
- RtsFlags.GcFlags.initialStkSize =
- decode(rts_argv[arg]+2) / sizeof(W_);
-
- if (RtsFlags.GcFlags.initialStkSize == 0)
- bad_option( rts_argv[arg] );
- break;
+ RtsFlags.GcFlags.initialStkSize =
+ decodeSize(rts_argv[arg], 2, 1, HS_WORD_MAX) / sizeof(W_);
+ break;
case 'M':
- RtsFlags.GcFlags.maxHeapSize =
- decode(rts_argv[arg]+2) / BLOCK_SIZE;
- /* user give size in *bytes* but "maxHeapSize" is in *blocks* */
-
- if (RtsFlags.GcFlags.maxHeapSize <= 0) {
- bad_option(rts_argv[arg]);
- }
- break;
+ RtsFlags.GcFlags.maxHeapSize =
+ decodeSize(rts_argv[arg], 2, BLOCK_SIZE, HS_WORD_MAX) / BLOCK_SIZE;
+ /* user give size in *bytes* but "maxHeapSize" is in *blocks* */
+ break;
case 'm':
- RtsFlags.GcFlags.pcFreeHeap = atof(rts_argv[arg]+2);
+ RtsFlags.GcFlags.pcFreeHeap = atof(rts_argv[arg]+2);
- if (RtsFlags.GcFlags.pcFreeHeap < 0 ||
- RtsFlags.GcFlags.pcFreeHeap > 100)
- bad_option( rts_argv[arg] );
- break;
+ if (RtsFlags.GcFlags.pcFreeHeap < 0 ||
+ RtsFlags.GcFlags.pcFreeHeap > 100)
+ bad_option( rts_argv[arg] );
+ break;
case 'G':
- RtsFlags.GcFlags.generations = decode(rts_argv[arg]+2);
- if (RtsFlags.GcFlags.generations < 1) {
- bad_option(rts_argv[arg]);
- }
- break;
+ RtsFlags.GcFlags.generations =
+ decodeSize(rts_argv[arg], 2, 1, HS_INT_MAX);
+ break;
- case 'T':
- RtsFlags.GcFlags.steps = decode(rts_argv[arg]+2);
- if (RtsFlags.GcFlags.steps < 1) {
- bad_option(rts_argv[arg]);
- }
+ case 'T':
+ RtsFlags.GcFlags.steps =
+ decodeSize(rts_argv[arg], 2, 1, HS_INT_MAX);
break;
case 'H':
- RtsFlags.GcFlags.heapSizeSuggestion =
- decode(rts_argv[arg]+2) / BLOCK_SIZE;
- break;
+ if (rts_argv[arg][2] == '\0') {
+ RtsFlags.GcFlags.heapSizeSuggestionAuto = rtsTrue;
+ } else {
+ RtsFlags.GcFlags.heapSizeSuggestion =
+ (nat)(decodeSize(rts_argv[arg], 2, BLOCK_SIZE, HS_WORD_MAX) / BLOCK_SIZE);
+ }
+ break;
#ifdef RTS_GTK_FRONTPANEL
case 'f':
/* =========== PROFILING ========================== */
case 'l':
-#ifdef EVENTLOG
- RtsFlags.EventLogFlags.doEventLogging = rtsTrue;
+#ifdef TRACING
+ switch(rts_argv[arg][2]) {
+ case '\0':
+ RtsFlags.TraceFlags.tracing = TRACE_EVENTLOG;
+ break;
+ case 's':
+ RtsFlags.TraceFlags.tracing = TRACE_EVENTLOG;
+ RtsFlags.TraceFlags.scheduler = rtsTrue;
+ break;
+ default:
+ errorBelch("unknown RTS option: %s",rts_argv[arg]);
+ error = rtsTrue;
+ break;
+ }
#else
- errorBelch("not built for: -eventlog");
+ errorBelch("not built for: -eventlog");
#endif
- break;
+ break;
case 'P': /* detailed cost centre profiling (time/alloc) */
case 'p': /* cost centre profiling (time/alloc) */
errorBelch("incomplete RTS option: %s",rts_argv[arg]);
error = rtsTrue;
break;
- case '1':
- RtsFlags.ParFlags.parGcEnabled = rtsFalse;
- break;
case 'g':
- if (rts_argv[arg][3] != '\0') {
+ if (rts_argv[arg][3] == '\0') {
+ RtsFlags.ParFlags.parGcEnabled = rtsFalse;
+ } else {
+ RtsFlags.ParFlags.parGcEnabled = rtsTrue;
RtsFlags.ParFlags.parGcGen
= strtol(rts_argv[arg]+3, (char **) NULL, 10);
- } else {
- errorBelch("bad value for -qg");
- error = rtsTrue;
}
break;
case 'b':
- RtsFlags.ParFlags.parGcLoadBalancing = rtsFalse;
- break;
+ if (rts_argv[arg][3] == '\0') {
+ RtsFlags.ParFlags.parGcLoadBalancingEnabled = rtsFalse;
+ }
+ else {
+ RtsFlags.ParFlags.parGcLoadBalancingEnabled = rtsTrue;
+ RtsFlags.ParFlags.parGcLoadBalancingGen
+ = strtol(rts_argv[arg]+3, (char **) NULL, 10);
+ }
+ break;
case 'a':
RtsFlags.ParFlags.setAffinity = rtsTrue;
break;
case 'v':
switch(rts_argv[arg][2]) {
- case '\0':
- errorBelch("incomplete RTS option: %s",rts_argv[arg]);
- error = rtsTrue;
- break;
+#ifdef TRACING
+ case '\0':
+ RtsFlags.TraceFlags.tracing = TRACE_STDERR;
+ break;
case 't':
- RtsFlags.DebugFlags.timestamp = rtsTrue;
+ RtsFlags.TraceFlags.timestamp = rtsTrue;
break;
+#endif
case 's':
case 'g':
// ignored for backwards-compat
-static I_
-decode(const char *s)
+static StgWord64
+decodeSize(const char *flag, nat offset, StgWord64 min, StgWord64 max)
{
- I_ c;
+ char c;
+ const char *s;
StgDouble m;
+ StgWord64 val;
+
+ s = flag + offset;
if (!*s)
- return 0;
+ {
+ m = 0;
+ }
+ else
+ {
+ m = atof(s);
+ c = s[strlen(s)-1];
+
+ if (c == 'g' || c == 'G')
+ m *= 1024*1024*1024;
+ else if (c == 'm' || c == 'M')
+ m *= 1024*1024;
+ else if (c == 'k' || c == 'K')
+ m *= 1024;
+ else if (c == 'w' || c == 'W')
+ m *= sizeof(W_);
+ }
- m = atof(s);
- c = s[strlen(s)-1];
+ val = (StgWord64)m;
- 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_);
+ if (m < 0 || val < min || val > max) {
+ // printf doesn't like 64-bit format specs on Windows
+ // apparently, so fall back to unsigned long.
+ errorBelch("error in RTS option %s: size outside allowed range (%lu - %lu)", flag, (lnat)min, (lnat)max);
+ stg_exit(EXIT_FAILURE);
+ }
- return (I_)m;
+ return val;
}
-static void
+static void GNU_ATTRIBUTE(__noreturn__)
bad_option(const char *s)
{
errorBelch("bad RTS option: %s", s);
full_prog_argv[argc] = NULL;
}
+void
+freeFullProgArgv (void)
+{
+ int i;
+
+ if (full_prog_argv != NULL) {
+ for (i = 0; i < full_prog_argc; i++) {
+ stgFree(full_prog_argv[i]);
+ }
+ stgFree(full_prog_argv);
+ }
+
+ full_prog_argc = 0;
+ full_prog_argv = NULL;
+}