#include <sys/types.h>
#endif
+#include <fs_rts.h>
+
// Flag Structure
RTS_FLAGS RtsFlags;
.stackOverflowHook = StackOverflowHook,
.outOfHeapHook = OutOfHeapHook,
.mallocFailHook = MallocFailHook,
- .gcDoneHook = NULL
+ .gcDoneHook = NULL,
+ .longGCSync = LongGCSync,
+ .longGCSyncEnd = LongGCSyncEnd
};
/*
RtsFlags.GcFlags.numa = false;
RtsFlags.GcFlags.numaMask = 1;
RtsFlags.GcFlags.ringBell = false;
+ RtsFlags.GcFlags.longGCSync = 0; /* detection turned off */
RtsFlags.DebugFlags.scheduler = false;
RtsFlags.DebugFlags.interpreter = false;
RtsFlags.TraceFlags.sparks_sampled= false;
RtsFlags.TraceFlags.sparks_full = false;
RtsFlags.TraceFlags.user = false;
+ RtsFlags.TraceFlags.trace_output = NULL;
#endif
#if defined(PROFILING)
RtsFlags.MiscFlags.install_signal_handlers = true;
RtsFlags.MiscFlags.install_seh_handlers = true;
+ RtsFlags.MiscFlags.generate_stack_trace = true;
+ RtsFlags.MiscFlags.generate_dump_file = false;
RtsFlags.MiscFlags.machineReadable = false;
+ RtsFlags.MiscFlags.internalCounters = false;
+ RtsFlags.MiscFlags.linkerAlwaysPic = DEFAULT_LINKER_ALWAYS_PIC;
RtsFlags.MiscFlags.linkerMemBase = 0;
#if defined(THREADED_RTS)
" -kc<size> Sets the stack chunk size (default 32k)",
" -kb<size> Sets the stack chunk buffer size (default 1k)",
"",
-" -A<size> Sets the minimum allocation area size (default 512k) Egs: -A1m -A10k",
+" -A<size> Sets the minimum allocation area size (default 1m) Egs: -A20m -A10k",
" -AL<size> Sets the amount of large-object memory that can be allocated",
" before a GC is triggered (default: the value of -A)",
+" -F<n> Sets the collecting threshold for old generations as a factor of",
+" the live data in that generation the last time it was collected",
+" (default: 2.0)",
" -n<size> Allocation area chunk size (0 = disabled, default: 0)",
" -O<size> Sets the minimum size of the old generation (default 1M)",
" -M<size> Sets the maximum heap size (default unlimited) Egs: -M256k -M1G",
" -Pa Give information about *all* cost centres in tree format",
" -pj Output cost-center profile in JSON format",
"",
+" -h Heap residency profile, by cost centre stack",
" -h<break-down> Heap residency profile (hp2ps) (output file <program>.hp)",
" break-down: c = cost centre stack (default)",
" m = module",
+" T = closure type",
" d = closure description",
" y = type description",
" r = retainer",
" -xt Include threads (TSOs) in a heap profile",
"",
" -xc Show current cost centre stack on raising an exception",
+#else /* PROFILING */
+" -h Heap residency profile (output file <program>.hp)",
+" -hT Produce a heap profile grouped by closure type",
#endif /* PROFILING */
#if defined(TRACING)
"",
-" -l[flags] Log events in binary format to the file <program>.eventlog",
+" -ol<file> Send binary eventlog to <file> (default: <program>.eventlog)",
+" -l[flags] Log events to a file",
# if defined(DEBUG)
" -v[flags] Log events to stderr",
# endif
" the initial enabled event classes are 'sgpu'",
#endif
-#if !defined(PROFILING)
-"",
-" -h Heap residency profile (output file <program>.hp)",
-#endif
" -i<sec> Time between heap profile samples (seconds, default: 0.1)",
"",
#if defined(TICKY_TICKY)
" Default: 0.02 sec.",
" -V<secs> Master tick interval in seconds (0 == disable timer).",
" This sets the resolution for -C and the heap profile timer -i,",
-" and is the frequence of time profile samples.",
+" and is the frequency of time profile samples.",
#if defined(PROFILING)
" Default: 0.001 sec.",
#else
" -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 for -A < 32M, 0 otherwise;"
+" (default: 1 for -A < 32M, 0 otherwise;",
" -qb alone turns off load-balancing)",
" -qn<n> Use <n> threads for parallel GC (defaults to value of -N)",
" -qa Use the OS to set thread affinity (experimental)",
#if defined(mingw32_HOST_OS)
" --install-seh-handlers=<yes|no>",
" Install exception handlers (default: yes)",
+" --generate-crash-dumps",
+" Generate Windows crash dumps, requires exception handlers",
+" to be installed. Implies --install-signal-handlers=yes.",
+" (default: no)",
+" --generate-stack-traces=<yes|no>",
+" Generate a stack trace when your application encounters a",
+" fatal error. When symbols are available an attempt will be",
+" made to resolve addresses to names. (default: yes)",
#endif
#if defined(THREADED_RTS)
" -e<n> Maximum number of outstanding local sparks (default: 4096)",
#endif
#if defined(x86_64_HOST_ARCH)
+#if !DEFAULT_LINKER_ALWAYS_PIC
+" -xp Assume that all object files were compiled with -fPIC",
+" -fexternal-dynamic-refs and load them anywhere in the address",
+" space",
+#endif
" -xm Base address to mmap memory in the GHCi linker",
" (hex; must be <80000000)",
#endif
} else {
/* 0 is dash, 1 is first letter */
- /* see Trac #9839 */
+ /* see #9839 */
unchecked_arg_start = 1;
switch(rts_argv[arg][1]) {
OPTION_UNSAFE;
RtsFlags.MiscFlags.install_seh_handlers = false;
}
+ else if (strequal("generate-stack-traces=yes",
+ &rts_argv[arg][2])) {
+ OPTION_UNSAFE;
+ RtsFlags.MiscFlags.generate_stack_trace = true;
+ }
+ else if (strequal("generate-stack-traces=no",
+ &rts_argv[arg][2])) {
+ OPTION_UNSAFE;
+ RtsFlags.MiscFlags.generate_stack_trace = false;
+ }
+ else if (strequal("generate-crash-dumps",
+ &rts_argv[arg][2])) {
+ OPTION_UNSAFE;
+ RtsFlags.MiscFlags.generate_dump_file = true;
+ }
else if (strequal("machine-readable",
&rts_argv[arg][2])) {
OPTION_UNSAFE;
RtsFlags.MiscFlags.machineReadable = true;
}
+ else if (strequal("internal-counters",
+ &rts_argv[arg][2])) {
+ OPTION_SAFE;
+ RtsFlags.MiscFlags.internalCounters = true;
+ }
else if (strequal("info",
&rts_argv[arg][2])) {
OPTION_SAFE;
- printRtsInfo();
+ printRtsInfo(rtsConfig);
stg_exit(0);
}
#if defined(THREADED_RTS)
else if (!strncmp("numa", &rts_argv[arg][2], 4)) {
+ if (!osBuiltWithNumaSupport()) {
+ errorBelch("%s: This GHC build was compiled without NUMA support.",
+ rts_argv[arg]);
+ error = true;
+ break;
+ }
OPTION_SAFE;
StgWord mask;
if (rts_argv[arg][6] == '=') {
}
}
#endif
+ else if (!strncmp("long-gc-sync=", &rts_argv[arg][2], 13)) {
+ OPTION_SAFE;
+ if (rts_argv[arg][2] == '\0') {
+ /* use default */
+ } else {
+ RtsFlags.GcFlags.longGCSync =
+ fsecondsToTime(atof(rts_argv[arg]+16));
+ }
+ break;
+ }
else {
OPTION_SAFE;
errorBelch("unknown RTS option: %s",rts_argv[arg]);
case 'K':
OPTION_UNSAFE;
RtsFlags.GcFlags.maxStkSize =
- decodeSize(rts_argv[arg], 2, sizeof(W_), HS_WORD_MAX)
+ decodeSize(rts_argv[arg], 2, 0, HS_WORD_MAX)
/ sizeof(W_);
break;
OPTION_SAFE;
THREADED_BUILD_ONLY(
if (rts_argv[arg][2] == '\0') {
-#if defined(PROFILING)
- RtsFlags.ParFlags.nCapabilities = 1;
-#else
RtsFlags.ParFlags.nCapabilities = getNumberOfProcessors();
-#endif
} else {
int nCapabilities;
OPTION_SAFE; /* but see extra checks below... */
}
) break;
- /* =========== TRACING ---------=================== */
+ /* =========== OUTPUT ============================ */
+
+ case 'o':
+ switch(rts_argv[arg][2]) {
+ case 'l':
+ OPTION_SAFE;
+ TRACING_BUILD_ONLY(
+ if (strlen(&rts_argv[arg][3]) == 0) {
+ errorBelch("-ol expects filename");
+ error = true;
+ } else {
+ RtsFlags.TraceFlags.trace_output =
+ strdup(&rts_argv[arg][3]);
+ }
+ );
+ break;
+
+ default:
+ errorBelch("Unknown output flag -o%c", rts_argv[arg][2]);
+ error = true;
+ }
+ break;
+
+ /* =========== TRACING ============================ */
case 'l':
OPTION_SAFE;
break;
#if defined(x86_64_HOST_ARCH)
+ case 'p': /* linkerAlwaysPic */
+ OPTION_UNSAFE;
+ RtsFlags.MiscFlags.linkerAlwaysPic = true;
+ break;
+
case 'm': /* linkerMemBase */
OPTION_UNSAFE;
if (rts_argv[arg][3] != '\0') {
break; /* defensive programming */
/* check the rest to be sure there is nothing afterwards.*/
- /* see Trac #9839 */
+ /* see #9839 */
check_rest:
{
/* start checking from the first unchecked position,
* not from index 2*/
- /* see Trac #9839 */
+ /* see #9839 */
if (rts_argv[arg][unchecked_arg_start] != '\0') {
errorBelch("flag -%c given an argument"
" when none was expected: %s",
// If allocation area is larger that CPU cache
// we can finish scanning quicker doing work-stealing
- // scan. Trac #9221
+ // scan. #9221
// 32M looks big enough not to fit into L2 cache
// of popular modern CPUs.
if (alloc_area_bytes >= 32 * 1024 * 1024) {
RtsFlags.ParFlags.parGcLoadBalancingGen = 1;
}
}
+
+ // We can't generate dumps without signal handlers
+ if (RtsFlags.MiscFlags.generate_dump_file) {
+ RtsFlags.MiscFlags.install_seh_handlers = true;
+ }
}
static void errorUsage (void)
f = NULL; /* NULL means use debugBelch */
} else {
if (*filename != '\0') { /* stats file specified */
- f = fopen(filename,"w");
+ f = __rts_fopen (filename,"w");
} else {
if (filename_fmt == NULL) {
errorBelch("Invalid stats filename format (NULL)\n");
char stats_filename[STATS_FILENAME_MAXLEN];
snprintf(stats_filename, STATS_FILENAME_MAXLEN, filename_fmt,
prog_name);
- f = fopen(stats_filename,"w");
+ f = __rts_fopen (stats_filename,"w");
}
if (f == NULL) {
errorBelch("Can't open stats file %s\n", filename);
case 'r':
case 'B':
case 'b':
+ case 'T':
if (arg[2] != '\0' && arg[3] != '\0') {
{
const char *left = strchr(arg, '{');
case 'b':
RtsFlags.ProfFlags.doHeapProfile = HEAP_BY_LDV;
break;
+ case 'T':
+ RtsFlags.ProfFlags.doHeapProfile = HEAP_BY_CLOSURE_TYPE;
+ break;
}
break;