[project @ 2004-08-13 13:04:50 by simonmar]
[ghc-hetmet.git] / ghc / rts / RtsFlags.c
index 24a4433..cf8d2c5 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: RtsFlags.c,v 1.55 2001/12/03 14:34:45 simonmar Exp $
+ * $Id: RtsFlags.c,v 1.75 2004/08/13 13:10:29 simonmar Exp $
  *
  * (c) The AQUA Project, Glasgow University, 1994-1997
  * (c) The GHC Team, 1998-1999
 #include "RtsFlags.h"
 #include "RtsUtils.h"
 #include "BlockAlloc.h"
-#include "Itimer.h"            /* CS_MIN_MILLISECS */
+#include "Timer.h"             /* CS_MIN_MILLISECS */
 #include "Profiling.h"
 
-#if defined(PROFILING) 
-#include "Itimer.h"
-#endif
-
 #ifdef HAVE_CTYPE_H
 #include <ctype.h>
 #endif
 
-extern struct RTS_FLAGS RtsFlags;
+#include <stdlib.h>
+#include <string.h>
+
+// Flag Structure
+RTS_FLAGS RtsFlags;
 
 /*
  * Split argument lists
  */
-int     prog_argc; /* an "int" so as to match normal "argc" */
+int     prog_argc = 0;    /* an "int" so as to match normal "argc" */
 char  **prog_argv = NULL;
-int     rts_argc;  /* ditto */
+char   *prog_name = NULL; /* 'basename' of prog_argv[0] */
+int     rts_argc = 0;  /* ditto */
 char   *rts_argv[MAX_RTS_ARGS];
 
 //@node Constants, Static function decls, Includes
@@ -56,41 +57,9 @@ char   *rts_argv[MAX_RTS_ARGS];
 #define RTS 1
 #define PGM 0
 
-char *debug_opts_strs[] = {
-  "DEBUG (-D1): scheduler\n",
-  "DEBUG (-D2): evaluator\n",
-  "DEBUG (-D4): codegen\n",
-  "DEBUG (-D8): weak\n",
-  "DEBUG (-D16): gccafs\n",
-  "DEBUG (-D32): gc\n",
-  "DEBUG (-D64): block\n",
-  "DEBUG (-D128): sanity\n",
-  "DEBUG (-D256): stable\n",
-  "DEBUG (-D512): prof\n",
-  "DEBUG (-D1024): gran\n",
-  "DEBUG (-D2048): par\n",
-  "DEBUG (-D4096): linker\n"
-};
-
-char *debug_opts_prefix[] = {
-  "_-", /* scheduler */
-  "_.", /* evaluator */
-  "_,", /* codegen */
-  "_;", /* weak */
-  "_~", /* gccafs */
-  "_@", /* gc */
-  "_#", /* block */
-  "_&", /* sanity */
-  "_:", /* stable */
-  "_!", /* prof */
-  "_=", /* gran */
-  "_=" /* par */
-  "_*" /* linker */
-};
-
 #if defined(GRAN)
 
-char *gran_debug_opts_strs[] = {
+static char *gran_debug_opts_strs[] = {
   "DEBUG (-bDe, -bD1): event_trace; printing event trace.\n",
   "DEBUG (-bDE, -bD2): event_stats; printing event statistics.\n",
   "DEBUG (-bDb, -bD4): bq; check blocking queues\n",
@@ -109,32 +78,13 @@ char *gran_debug_opts_strs[] = {
 };
 
 /* one character codes for the available debug options */
-char gran_debug_opts_flags[] = {
+static char gran_debug_opts_flags[] = {
   'e', 'E', 'b', 'G', 'q', 'f', 'r', 'F', 'u', 'S', ':', 'o', 'z', 'P', 't'
 };
 
-/* prefix strings printed with the debug messages of the corresponding type */
-char *gran_debug_opts_prefix[] = {
-  "", /* event_trace */ 
-  "", /* event_stats */
-  "##", /* bq */
-  "**", /* pack */
-  "^^", /* checkSparkQ */
-  "==", /* thunkStealing */
-  "^^", /* randomSteal */
-  "+-", /* findWork */
-  "", /* unused */
-  "++", /* pri */
-  "::", /* checkLight */
-  "##", /* sortedQ */
-  "", /* blockOnFetch */
-  "", /* packBuffer */
-  "" /* blockOnFetch_sanity */
-};
-
 #elif defined(PAR)
 
-char *par_debug_opts_strs[] = {
+static char *par_debug_opts_strs[] = {
   "DEBUG (-qDv, -qD1): verbose; be generally verbose with parallel related stuff.\n",
   "DEBUG (-qDq, -qD2): bq; print blocking queues.\n",
   "DEBUG (-qDs, -qD4): schedule; scheduling of parallel threads.\n",
@@ -152,27 +102,10 @@ char *par_debug_opts_strs[] = {
 };
 
 /* one character codes for the available debug options */
-char par_debug_opts_flags[] = {
+static char par_debug_opts_flags[] = {
   'v', 'q', 's', 'e', 'r', 'w', 'F', 'f', 'l', 'o', 'p', 'z'
 };
 
-/* prefix strings printed with the debug messages of the corresponding type */
-char *par_debug_opts_prefix[] = {
-  "  ", /* verbose */
-  "##", /* bq */
-  "--", /* schedule */
-  "!!", /* free */
-  "[]", /* resume */
-  ";;", /* weight */
-  "%%", /* fetch */
-  //",,", /* ack */
-  "$$", /* fish */
-  "", /* tables */
-  "**", /* packet */
-  "**" /* pack */
-  ":(" /* paranoia */
-};
-
 #endif /* PAR */
 
 //@node Static function decls, Command-line option parsing routines, Constants
@@ -202,10 +135,6 @@ static void process_par_option(int arg, int *rts_argc, char *rts_argv[], rtsBool
 static void set_par_debug_options(nat n);
 static void help_par_debug_options(nat n);
 #endif
-#if defined(DEBUG)
-static void set_debug_options(nat n);
-static void help_debug_options(nat n);
-#endif
 
 //@node Command-line option parsing routines, GranSim specific options, Static function decls
 //@subsection Command-line option parsing routines
@@ -219,7 +148,7 @@ void initRtsFlagsDefaults(void)
     RtsFlags.GcFlags.statsFile         = NULL;
     RtsFlags.GcFlags.giveStats         = NO_GC_STATS;
 
-    RtsFlags.GcFlags.maxStkSize                = (1024 * 1024) / sizeof(W_);
+    RtsFlags.GcFlags.maxStkSize                = (8 * 1024 * 1024) / sizeof(W_);
     RtsFlags.GcFlags.initialStkSize    = 1024 / sizeof(W_);
 
     RtsFlags.GcFlags.minAllocAreaSize   = (256 * 1024)        / BLOCK_SIZE;
@@ -244,6 +173,22 @@ void initRtsFlagsDefaults(void)
     RtsFlags.GcFlags.frontpanel         = rtsFalse;
 #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.block_alloc    = rtsFalse;
+    RtsFlags.DebugFlags.sanity         = rtsFalse;
+    RtsFlags.DebugFlags.stable         = rtsFalse;
+    RtsFlags.DebugFlags.prof           = rtsFalse;
+    RtsFlags.DebugFlags.gran           = rtsFalse;
+    RtsFlags.DebugFlags.par            = rtsFalse;
+    RtsFlags.DebugFlags.linker         = rtsFalse;
+#endif
+
 #if defined(PROFILING) || defined(PAR)
     RtsFlags.CcFlags.doCostCentres     = 0;
 #endif /* PROFILING or PAR */
@@ -251,12 +196,14 @@ void initRtsFlagsDefaults(void)
 #ifdef PROFILING
     RtsFlags.ProfFlags.doHeapProfile      = rtsFalse;
     RtsFlags.ProfFlags.profileInterval    = 100;
+    RtsFlags.ProfFlags.includeTSOs        = rtsFalse;
     RtsFlags.ProfFlags.showCCSOnException = rtsFalse;
     RtsFlags.ProfFlags.maxRetainerSetSize = 8;
     RtsFlags.ProfFlags.modSelector        = NULL;
     RtsFlags.ProfFlags.descrSelector      = NULL;
     RtsFlags.ProfFlags.typeSelector       = NULL;
     RtsFlags.ProfFlags.ccSelector         = NULL;
+    RtsFlags.ProfFlags.ccsSelector        = NULL;
     RtsFlags.ProfFlags.retainerSelector   = NULL;
     RtsFlags.ProfFlags.bioSelector        = NULL;
 
@@ -299,7 +246,7 @@ void initRtsFlagsDefaults(void)
 
 #if defined(GRAN)
     /* ToDo: check defaults for GranSim and GUM */
-    RtsFlags.GcFlags.maxStkSize                = (1024 * 1024) / sizeof(W_);
+    RtsFlags.GcFlags.maxStkSize                = (8 * 1024 * 1024) / sizeof(W_);
     RtsFlags.GcFlags.initialStkSize    = 1024 / sizeof(W_);
 
     RtsFlags.GranFlags.maxThreads      = 65536; // refers to mandatory threads
@@ -385,8 +332,8 @@ usage_text[] = {
 "",
 "  -?       Prints this message and exits; the program is not executed",
 "",
-"  -K<size> Sets the maximum stack size (default 1M)  Egs: -K32k   -K512k",
-"  -k<size> Sets the initial thread stack size (default 1k)  Egs: -K4k   -K2m",
+"  -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",
 "",
 "  -A<size> Sets the minimum allocation area size (default 256k) Egs: -A1m -A10k",
 "  -M<size> Sets the maximum heap size (default unlimited)  Egs: -M256k -M1G",
@@ -426,7 +373,8 @@ usage_text[] = {
 "                 r = retainer",
 "                 b = biography (LAG,DRAG,VOID,USE)",
 "  A subset of closures may be selected thusly:",
-"    -hc<cc>,...  specific cost centre(s) (NOT STACKS!)",
+"    -hc<cc>,...  specific cost centre(s) (top of stack only)",
+"    -hC<cc>,...  specific cost centre(s) (anywhere in stack)",
 "    -hm<mod>...  all cost centres from the specified modules(s)",
 "    -hd<des>,... closures with specified closure descriptions",
 "    -hy<typ>...  closures with specified type descriptions",
@@ -435,7 +383,9 @@ usage_text[] = {
 "",
 "  -R<size>       Set the maximum retainer set size (default: 8)",
 "",
-"  -i<msec>       Time between heap samples (msec, default: 100)",
+"  -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
@@ -459,6 +409,23 @@ usage_text[] = {
 "  -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",
+"",
+#if defined(DEBUG)
+"  -Ds  DEBUG: scheduler",
+"  -Di  DEBUG: interpreter",
+"  -Dc  DEBUG: codegen",
+"  -Dw  DEBUG: weak",
+"  -DG  DEBUG: gccafs",
+"  -Dg  DEBUG: gc",
+"  -Db  DEBUG: block",
+"  -DS  DEBUG: sanity",
+"  -Dt  DEBUG: stable",
+"  -Dp  DEBUG: prof",
+"  -Dr  DEBUG: gran",
+"  -DP  DEBUG: par",
+"  -Dl  DEBUG: linker",
+"",
+#endif // DEBUG
 #if defined(SMP)
 "  -N<n>     Use <n> OS threads (default: 1)",
 #endif
@@ -491,7 +458,7 @@ usage_text[] = {
 0
 };
 
-static __inline__ rtsBool
+STATIC_INLINE rtsBool
 strequal(const char *a, const char * b)
 {
     return(strcmp(a, b) == 0);
@@ -511,7 +478,7 @@ splitRtsFlags(char *s, int *rts_argc, char *rts_argv[])
        if (c1 == c2) { break; }
        
        if (*rts_argc < MAX_RTS_ARGS-1) {
-           s = malloc(c2-c1+1);
+           s = stgMallocBytes(c2-c1+1, "RtsFlags.c:splitRtsFlags()");
            strncpy(s, c1, c2-c1);
            s[c2-c1] = '\0';
            rts_argv[(*rts_argc)++] = s;
@@ -532,9 +499,17 @@ setupRtsFlags(int *argc, char *argv[], int *rts_argc, char *rts_argv[])
     char *last_slash;
 
     /* Remove directory from argv[0] -- default files in current directory */
-
-    if ((last_slash = (char *) strrchr(argv[0], '/')) != NULL)
-       strcpy(argv[0], last_slash+1);
+    if ((last_slash = (char *) strrchr(argv[0], 
+#if !defined(mingw32_TARGET_OS)
+                                      '/')
+#else
+                                      '\\')
+#endif
+                                      ) != NULL) {
+       prog_name = last_slash+1;
+    } else {
+       prog_name = argv[0];
+    }
 
     total_arg = *argc;
     arg = 1;
@@ -551,7 +526,7 @@ setupRtsFlags(int *argc, char *argv[], int *rts_argc, char *rts_argv[])
        }
     }
 
-    // process arguments from the GHCRTS environment variable first
+    // process arguments from the GHCRTS environment variable next
     // (arguments from the command line override these).
     {
        char *ghc_rts = getenv("GHCRTS");
@@ -620,7 +595,7 @@ setupRtsFlags(int *argc, char *argv[], int *rts_argc, char *rts_argv[])
 # define TICKY_BUILD_ONLY(x) x
 #else
 # define TICKY_BUILD_ONLY(x) \
-prog_belch("GHC not built for: ticky-ticky stats"); \
+prog_belch("not built for: ticky-ticky stats"); \
 error = rtsTrue;
 #endif
 
@@ -628,7 +603,7 @@ error = rtsTrue;
 # define COST_CENTRE_USING_BUILD_ONLY(x) x
 #else
 # define COST_CENTRE_USING_BUILD_ONLY(x) \
-prog_belch("GHC not built for: -prof or -parallel"); \
+prog_belch("not built for: -prof or -parallel"); \
 error = rtsTrue;
 #endif
 
@@ -636,7 +611,7 @@ error = rtsTrue;
 # define PROFILING_BUILD_ONLY(x)   x
 #else
 # define PROFILING_BUILD_ONLY(x) \
-prog_belch("GHC not built for: -prof"); \
+prog_belch("not built for: -prof"); \
 error = rtsTrue;
 #endif
 
@@ -644,7 +619,7 @@ error = rtsTrue;
 # define SMP_BUILD_ONLY(x)      x
 #else
 # define SMP_BUILD_ONLY(x) \
-prog_belch("GHC not built for: -smp"); \
+prog_belch("not built for: -smp"); \
 error = rtsTrue;
 #endif
 
@@ -652,7 +627,7 @@ error = rtsTrue;
 # define PAR_BUILD_ONLY(x)      x
 #else
 # define PAR_BUILD_ONLY(x) \
-prog_belch("GHC not built for: -parallel"); \
+prog_belch("not built for: -parallel"); \
 error = rtsTrue;
 #endif
 
@@ -660,7 +635,7 @@ error = rtsTrue;
 # define PAR_OR_SMP_BUILD_ONLY(x)      x
 #else
 # define PAR_OR_SMP_BUILD_ONLY(x) \
-prog_belch("GHC not built for: -parallel or -smp"); \
+prog_belch("not built for: -parallel or -smp"); \
 error = rtsTrue;
 #endif
 
@@ -668,7 +643,7 @@ error = rtsTrue;
 # define GRAN_BUILD_ONLY(x)     x
 #else
 # define GRAN_BUILD_ONLY(x) \
-prog_belch("GHC not built for: -gransim"); \
+prog_belch("not built for: -gransim"); \
 error = rtsTrue;
 #endif
 
@@ -707,12 +682,59 @@ error = rtsTrue;
              
 #ifdef DEBUG
              case 'D':
-               if (isdigit(rts_argv[arg][2])) {/* Set all debugging options in one */
-               /* hack warning: interpret the flags as a binary number */
-                 nat n = decode(rts_argv[arg]+2);
-                 set_debug_options(n);
-               }
-               break;
+             { 
+                 char *c;
+
+                 for (c  = rts_argv[arg] + 2; *c != '\0'; c++) {
+                     switch (*c) {
+                     case 's':
+                         RtsFlags.DebugFlags.scheduler = rtsTrue;
+                         break;
+                     case 'i':
+                         RtsFlags.DebugFlags.interpreter = rtsTrue;
+                         break;
+                     case 'c':
+                         RtsFlags.DebugFlags.codegen = rtsTrue;
+                         break;
+                     case 'w':
+                         RtsFlags.DebugFlags.weak = rtsTrue;
+                         break;
+                     case 'G':
+                         RtsFlags.DebugFlags.gccafs = rtsTrue;
+                         break;
+                     case 'g':
+                         RtsFlags.DebugFlags.gc = rtsTrue;
+                         break;
+                     case 'b':
+                         RtsFlags.DebugFlags.block_alloc = rtsTrue;
+                         break;
+                     case 'S':
+                         RtsFlags.DebugFlags.sanity = rtsTrue;
+                         break;
+                     case 't':
+                         RtsFlags.DebugFlags.stable = rtsTrue;
+                         break;
+                     case 'p':
+                         RtsFlags.DebugFlags.prof = rtsTrue;
+                         break;
+                     case 'r':
+                         RtsFlags.DebugFlags.gran = rtsTrue;
+                         break;
+                     case 'P':
+                         RtsFlags.DebugFlags.par = rtsTrue;
+                         break;
+                     case 'l':
+                         RtsFlags.DebugFlags.linker = rtsTrue;
+                         break;
+                     case 'a':
+                         RtsFlags.DebugFlags.apply = rtsTrue;
+                         break;
+                     default:
+                         bad_option( rts_argv[arg] );
+                     }
+                 }
+                 break;
+             }
 #endif
 
              case 'K':
@@ -835,10 +857,6 @@ error = rtsTrue;
              case 'R':
                  PROFILING_BUILD_ONLY(
                      RtsFlags.ProfFlags.maxRetainerSetSize = atof(rts_argv[arg]+2);
-                     
-                     if (RtsFlags.ProfFlags.maxRetainerSetSize < 0)
-                        bad_option( rts_argv[arg] );
-                     break;
                  ) break;
 
              case 'h': /* serial heap profile */
@@ -889,10 +907,12 @@ error = rtsTrue;
                            *right = '\0';
 
                            switch (rts_argv[arg][2]) {
-                           case 'C':
                            case 'c': // cost centre label select
                                RtsFlags.ProfFlags.ccSelector = left;
                                break;
+                           case 'C':
+                               RtsFlags.ProfFlags.ccsSelector = left;
+                               break;
                            case 'M':
                            case 'm': // cost centre module select
                                RtsFlags.ProfFlags.modSelector = left;
@@ -1058,8 +1078,15 @@ error = rtsTrue;
 
                   case 'c': /* Debugging tool: show current cost centre on an exception */
                     PROFILING_BUILD_ONLY(
-                    RtsFlags.ProfFlags.showCCSOnException = rtsTrue;
-                    ) break;
+                       RtsFlags.ProfFlags.showCCSOnException = rtsTrue;
+                       );
+                   break;
+
+               case 't':  /* Include memory used by TSOs in a heap profile */
+                   PROFILING_BUILD_ONLY(
+                       RtsFlags.ProfFlags.includeTSOs = rtsTrue;
+                       );
+                   break;
 
                   /* The option prefix '-xx' is reserved for future extension.  KSW 1999-11. */
 
@@ -1379,8 +1406,7 @@ process_gran_option(int arg, int *rts_argc, char *rts_argv[], rtsBool *error)
              } else if (RtsFlags.GranFlags.proc > MAX_PROC || 
                         RtsFlags.GranFlags.proc < 1)
                {
-                 fprintf(stderr,"setupRtsFlags: no more than %u processors
-allowed\n", 
+                 fprintf(stderr,"setupRtsFlags: no more than %u processors allowed\n",
                          MAX_PROC);
                  *error = rtsTrue;
                }
@@ -2065,44 +2091,6 @@ help_par_debug_options(nat n) {
 
 #endif /* PAR */
 
-#ifdef DEBUG
-static void
-set_debug_options(nat n) {
-  nat i;
-
-  for (i=0; i<=MAX_DEBUG_OPTION; i++) 
-    if ((n>>i)&1) {
-      fprintf(stderr, debug_opts_strs[i]);
-      switch (i) {
-        case 0: RtsFlags.DebugFlags.scheduler   = rtsTrue; break;
-        case 1: RtsFlags.DebugFlags.evaluator   = rtsTrue; break;
-        case 2: RtsFlags.DebugFlags.codegen     = rtsTrue; break;
-        case 3: RtsFlags.DebugFlags.weak        = rtsTrue; break;
-        case 4: RtsFlags.DebugFlags.gccafs      = rtsTrue; break;
-        case 5: RtsFlags.DebugFlags.gc          = rtsTrue; break;
-        case 6: RtsFlags.DebugFlags.block_alloc = rtsTrue; break;
-        case 7: RtsFlags.DebugFlags.sanity      = rtsTrue; break;
-        case 8: RtsFlags.DebugFlags.stable      = rtsTrue; break;
-        case 9: RtsFlags.DebugFlags.prof        = rtsTrue; break;
-        case 10:  RtsFlags.DebugFlags.gran       = rtsTrue; break;
-        case 11:  RtsFlags.DebugFlags.par        = rtsTrue; break;
-        case 12:  RtsFlags.DebugFlags.linker     = rtsTrue; break;
-        default: barf("set_debug_options: only %d debug options expected",
-                     MAX_DEBUG_OPTION);
-      } /* switch */
-    } /* if */
-}
-
-static void
-help_debug_options(nat n) {
-  nat i;
-
-  for (i=0; i<=MAX_DEBUG_OPTION; i++) 
-    if ((n>>i)&1) 
-      fprintf(stderr, debug_opts_strs[i]);
-}
-#endif /* DEBUG */
-
 //@node Aux fcts,  , GranSim specific options
 //@subsection Aux fcts