Add ASSERTs to all calls of nameModule
[ghc-hetmet.git] / rts / RtsFlags.c
index 47ad794..497cd88 100644 (file)
@@ -28,6 +28,8 @@ 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];
@@ -145,11 +147,24 @@ void initRtsFlagsDefaults(void)
 #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;
@@ -189,8 +204,8 @@ void initRtsFlagsDefaults(void)
     RtsFlags.ProfFlags.bioSelector        = NULL;
 #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;
 
@@ -198,6 +213,7 @@ void initRtsFlagsDefaults(void)
     RtsFlags.ParFlags.nNodes           = 1;
     RtsFlags.ParFlags.migrate           = rtsTrue;
     RtsFlags.ParFlags.wakeupMigrate     = rtsFalse;
+    RtsFlags.ParFlags.gcThreads         = 1;
 #endif
 
 #ifdef PAR
@@ -302,10 +318,12 @@ void initRtsFlagsDefaults(void)
 
     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
 }
 
@@ -322,6 +340,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<size> Sets the maximum stack size (default 8M)  Egs: -K32k   -K512k",
 "  -k<size> Sets the initial thread stack size (default 1k)  Egs: -k4k   -k2m",
@@ -335,13 +354,14 @@ usage_text[] = {
 "  -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
@@ -429,7 +449,8 @@ usage_text[] = {
 "",
 #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
@@ -668,6 +689,11 @@ error = rtsTrue;
                                &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;
@@ -699,6 +725,14 @@ 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] );
                }
@@ -718,6 +752,10 @@ error = rtsTrue;
                  }
                  break;
 
+              case 'w':
+               RtsFlags.GcFlags.sweep = rtsTrue;
+               break;
+
              case 'F':
                RtsFlags.GcFlags.oldGenFactor = atof(rts_argv[arg]+2);
              
@@ -839,10 +877,6 @@ error = rtsTrue;
              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
@@ -884,7 +918,7 @@ error = rtsTrue;
                { 
                    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; }
                }
@@ -1093,10 +1127,30 @@ error = rtsTrue;
                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;
 
@@ -1176,6 +1230,9 @@ error = rtsTrue;
                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;
@@ -1192,6 +1249,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;
@@ -1222,13 +1289,20 @@ error = 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,
@@ -1255,8 +1329,13 @@ error = rtsTrue;
         RtsFlags.ConcFlags.ctxtSwitchTicks = 0;
     }
 
-    RtsFlags.ProfFlags.profileIntervalTicks =
-        RtsFlags.ProfFlags.profileInterval / RtsFlags.MiscFlags.tickInterval;
+    if (RtsFlags.ProfFlags.profileInterval > 0) {
+        RtsFlags.ProfFlags.profileIntervalTicks =
+            RtsFlags.ProfFlags.profileInterval / 
+            RtsFlags.MiscFlags.tickInterval;
+    } else {
+        RtsFlags.ProfFlags.profileIntervalTicks = 0;
+    }
 
     if (error) {
        const char **p;
@@ -2264,16 +2343,17 @@ open_stats_file (
 {
     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;
@@ -2377,3 +2457,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;
+}
+