]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: introduce GODEBUG env var
authorDmitriy Vyukov <dvyukov@google.com>
Fri, 28 Jun 2013 14:37:06 +0000 (18:37 +0400)
committerDmitriy Vyukov <dvyukov@google.com>
Fri, 28 Jun 2013 14:37:06 +0000 (18:37 +0400)
Currently it replaces GOGCTRACE env var (GODEBUG=gctrace=1).
The plan is to extend it with other type of debug tracing,
e.g. GODEBUG=gctrace=1,schedtrace=100.

R=rsc
CC=bradfitz, daniel.morsing, gobot, golang-dev
https://golang.org/cl/10026045

src/pkg/runtime/crash_test.go
src/pkg/runtime/extern.go
src/pkg/runtime/mgc0.c
src/pkg/runtime/mheap.c
src/pkg/runtime/proc.c
src/pkg/runtime/race/race_test.go
src/pkg/runtime/runtime.c
src/pkg/runtime/runtime.h

index 929d4a9636ba1cc8165b8b395530115a87069d1b..af192747022d26a51a5e066b58a4e2b48330b49e 100644 (file)
@@ -14,7 +14,7 @@ import (
        "text/template"
 )
 
-// testEnv excludes GOGCTRACE from the environment
+// testEnv excludes GODEBUG from the environment
 // to prevent its output from breaking tests that
 // are trying to parse other command output.
 func testEnv(cmd *exec.Cmd) *exec.Cmd {
@@ -22,7 +22,7 @@ func testEnv(cmd *exec.Cmd) *exec.Cmd {
                panic("environment already set")
        }
        for _, env := range os.Environ() {
-               if strings.HasPrefix(env, "GOGCTRACE=") {
+               if strings.HasPrefix(env, "GODEBUG=") {
                        continue
                }
                cmd.Env = append(cmd.Env, env)
index a7451e66302f901aa39c37fb46e45d4a08b81699..950c0be2575672cd5d5becacecf58fe6157405be 100644 (file)
@@ -21,10 +21,11 @@ is GOGC=100. Setting GOGC=off disables the garbage collector entirely.
 The runtime/debug package's SetGCPercent function allows changing this
 percentage at run time. See http://golang.org/pkg/runtime/debug/#SetGCPercent.
 
-The GOGCTRACE variable controls debug output from the garbage collector.
-Setting GOGCTRACE=1 causes the garbage collector to emit a single line to standard
+The GODEBUG variable controls debug output from the runtime. GODEBUG value is
+a comma-separated list of name=val pairs. Supported names are:
+gctrace: setting gctrace=1 causes the garbage collector to emit a single line to standard
 error at each collection, summarizing the amount of memory collected and the
-length of the pause. Setting GOGCTRACE=2 emits the same summary but also
+length of the pause. Setting gctrace=2 emits the same summary but also
 repeats each collection.
 
 The GOMAXPROCS variable limits the number of operating system threads that
index c9ac557154ccb827dd64389d2546b40990b53462..a819135901992874aa0098e9ae921c85d7a51148 100644 (file)
@@ -82,8 +82,6 @@ enum {
 //
 uint32 runtime·worldsema = 1;
 
-static int32 gctrace;
-
 typedef struct Obj Obj;
 struct Obj
 {
@@ -1950,7 +1948,6 @@ static FuncVal runfinqv = {runfinq};
 void
 runtime·gc(int32 force)
 {
-       byte *p;
        struct gc_args a;
        int32 i;
 
@@ -1978,10 +1975,6 @@ runtime·gc(int32 force)
                if(gcpercent == GcpercentUnknown)
                        gcpercent = readgogc();
                runtime·unlock(&runtime·mheap);
-
-               p = runtime·getenv("GOGCTRACE");
-               if(p != nil)
-                       gctrace = runtime·atoi(p);
        }
        if(gcpercent < 0)
                return;
@@ -2004,7 +1997,7 @@ runtime·gc(int32 force)
        // the root set down a bit (g0 stacks are not scanned, and
        // we don't need to scan gc's internal state).  Also an
        // enabler for copyable stacks.
-       for(i = 0; i < (gctrace > 1 ? 2 : 1); i++) {
+       for(i = 0; i < (runtime·debug.gctrace > 1 ? 2 : 1); i++) {
                if(g == m->g0) {
                        // already on g0
                        gc(&a);
@@ -2068,7 +2061,7 @@ gc(struct gc_args *args)
 
        heap0 = 0;
        obj0 = 0;
-       if(gctrace) {
+       if(runtime·debug.gctrace) {
                updatememstats(nil);
                heap0 = mstats.heap_alloc;
                obj0 = mstats.nmalloc - mstats.nfree;
@@ -2131,7 +2124,7 @@ gc(struct gc_args *args)
        if(mstats.debuggc)
                runtime·printf("pause %D\n", t4-t0);
 
-       if(gctrace) {
+       if(runtime·debug.gctrace) {
                updatememstats(&stats);
                heap1 = mstats.heap_alloc;
                obj1 = mstats.nmalloc - mstats.nfree;
index f988fe3f263ee837b06ed18c7a1231eebc9ed92c..e076d89f135a06162446b4c2d119d3481c48b424 100644 (file)
@@ -441,8 +441,6 @@ runtime·MHeap_Scavenger(void)
        uint64 tick, now, forcegc, limit;
        uint32 k;
        uintptr sumreleased;
-       byte *env;
-       bool trace;
        Note note, *notep;
 
        g->issystem = true;
@@ -459,11 +457,6 @@ runtime·MHeap_Scavenger(void)
        else
                tick = limit/2;
 
-       trace = false;
-       env = runtime·getenv("GOGCTRACE");
-       if(env != nil)
-               trace = runtime·atoi(env) > 0;
-
        h = &runtime·mheap;
        for(k=0;; k++) {
                runtime·noteclear(&note);
@@ -484,7 +477,7 @@ runtime·MHeap_Scavenger(void)
                        runtime·entersyscallblock();
                        runtime·notesleep(&note);
                        runtime·exitsyscall();
-                       if(trace)
+                       if(runtime·debug.gctrace > 0)
                                runtime·printf("scvg%d: GC forced\n", k);
                        runtime·lock(h);
                        now = runtime·nanotime();
@@ -492,7 +485,7 @@ runtime·MHeap_Scavenger(void)
                sumreleased = scavenge(now, limit);
                runtime·unlock(h);
 
-               if(trace) {
+               if(runtime·debug.gctrace > 0) {
                        if(sumreleased > 0)
                                runtime·printf("scvg%d: %p MB released\n", k, sumreleased>>20);
                        runtime·printf("scvg%d: inuse: %D, idle: %D, sys: %D, released: %D, consumed: %D (MB)\n",
index 44892e8540b3282eb6aac657bff5eeeb6e4bd16e..b93f4911d7b739d01ec87345211c66e3431ddbb2 100644 (file)
@@ -132,6 +132,7 @@ runtime·schedinit(void)
 
        runtime·goargs();
        runtime·goenvs();
+       runtime·parsedebugvars();
 
        // Allocate internal symbol table representation now, we need it for GC anyway.
        runtime·symtabinit();
index 47d34d7ad9c9f462d63fb3bde059a5df3777bc99..4776ae22daba8cfd792be470a4bb8c7d8e4ef4fe 100644 (file)
@@ -147,7 +147,7 @@ func runTests() ([]byte, error) {
        // It is required because the tests contain a lot of data races on the same addresses
        // (the tests are simple and the memory is constantly reused).
        for _, env := range os.Environ() {
-               if strings.HasPrefix(env, "GOMAXPROCS=") || strings.HasPrefix(env, "GOGCTRACE=") {
+               if strings.HasPrefix(env, "GOMAXPROCS=") || strings.HasPrefix(env, "GODEBUG=") {
                        continue
                }
                cmd.Env = append(cmd.Env, env)
index d62408118b42c2592a86955e9e71ee75394ca4a5..f59a3f4e80a664f84b7a2758eb63ada32f9bf59d 100644 (file)
@@ -365,3 +365,34 @@ runtime∕pprof·runtime_cyclesPerSecond(int64 res)
        res = runtime·tickspersecond();
        FLUSH(&res);
 }
+
+DebugVars      runtime·debug;
+
+static struct {
+       int8*   name;
+       int32*  value;
+} dbgvar[] = {
+       {"gctrace", &runtime·debug.gctrace},
+};
+
+void
+runtime·parsedebugvars(void)
+{
+       byte *p;
+       int32 i, n;
+
+       p = runtime·getenv("GODEBUG");
+       if(p == nil)
+               return;
+       for(;;) {
+               for(i=0; i<nelem(dbgvar); i++) {
+                       n = runtime·findnull((byte*)dbgvar[i].name);
+                       if(runtime·mcmp(p, (byte*)dbgvar[i].name, n) == 0 && p[n] == '=')
+                               *dbgvar[i].value = runtime·atoi(p+n+1);
+               }
+               p = runtime·strstr(p, (byte*)",");
+               if(p == nil)
+                       break;
+               p++;
+       }
+}
index 8b3f10f9459a9523bb01dcc648160e9163955be9..6c590be633573a197f513c92973c7839e81a7f43 100644 (file)
@@ -86,6 +86,7 @@ typedef       struct  ParFor          ParFor;
 typedef        struct  ParForThread    ParForThread;
 typedef        struct  CgoMal          CgoMal;
 typedef        struct  PollDesc        PollDesc;
+typedef        struct  DebugVars       DebugVars;
 
 /*
  * Per-CPU declaration.
@@ -525,6 +526,12 @@ struct CgoMal
        void    *alloc;
 };
 
+// Holds variables parsed from GODEBUG env var.
+struct DebugVars
+{
+       int32   gctrace;
+};
+
 /*
  * defined macros
  *    you need super-gopher-guru privilege
@@ -702,6 +709,7 @@ extern      uint32  runtime·maxstring;
 extern uint32  runtime·Hchansize;
 extern uint32  runtime·cpuid_ecx;
 extern uint32  runtime·cpuid_edx;
+extern DebugVars       runtime·debug;
 
 /*
  * common functions and data
@@ -841,6 +849,7 @@ int32       runtime·netpollopen(uintptr, PollDesc*);
 int32   runtime·netpollclose(uintptr);
 void   runtime·netpollready(G**, PollDesc*, int32);
 void   runtime·crash(void);
+void   runtime·parsedebugvars(void);
 void   _rt0_go(void);
 
 #pragma        varargck        argpos  runtime·printf 1