aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime
diff options
context:
space:
mode:
authorDmitriy Vyukov <dvyukov@google.com>2013-06-28 18:37:06 +0400
committerDmitriy Vyukov <dvyukov@google.com>2013-06-28 18:37:06 +0400
commit4b536a550f1a9edd7be5c777dfb5eb906320eb89 (patch)
treeb372383d0e4c6b715a2baf475d68391f40d1a652 /src/pkg/runtime
parent1e112cd59f560129f4dca5e9af7c3cbc445850b6 (diff)
downloadgo-4b536a550f1a9edd7be5c777dfb5eb906320eb89.tar.xz
runtime: introduce GODEBUG env var
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
Diffstat (limited to 'src/pkg/runtime')
-rw-r--r--src/pkg/runtime/crash_test.go4
-rw-r--r--src/pkg/runtime/extern.go7
-rw-r--r--src/pkg/runtime/mgc0.c13
-rw-r--r--src/pkg/runtime/mheap.c11
-rw-r--r--src/pkg/runtime/proc.c1
-rw-r--r--src/pkg/runtime/race/race_test.go2
-rw-r--r--src/pkg/runtime/runtime.c31
-rw-r--r--src/pkg/runtime/runtime.h9
8 files changed, 53 insertions, 25 deletions
diff --git a/src/pkg/runtime/crash_test.go b/src/pkg/runtime/crash_test.go
index 929d4a9636..af19274702 100644
--- a/src/pkg/runtime/crash_test.go
+++ b/src/pkg/runtime/crash_test.go
@@ -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)
diff --git a/src/pkg/runtime/extern.go b/src/pkg/runtime/extern.go
index a7451e6630..950c0be257 100644
--- a/src/pkg/runtime/extern.go
+++ b/src/pkg/runtime/extern.go
@@ -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
diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c
index c9ac557154..a819135901 100644
--- a/src/pkg/runtime/mgc0.c
+++ b/src/pkg/runtime/mgc0.c
@@ -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;
diff --git a/src/pkg/runtime/mheap.c b/src/pkg/runtime/mheap.c
index f988fe3f26..e076d89f13 100644
--- a/src/pkg/runtime/mheap.c
+++ b/src/pkg/runtime/mheap.c
@@ -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",
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index 44892e8540..b93f4911d7 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -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();
diff --git a/src/pkg/runtime/race/race_test.go b/src/pkg/runtime/race/race_test.go
index 47d34d7ad9..4776ae22da 100644
--- a/src/pkg/runtime/race/race_test.go
+++ b/src/pkg/runtime/race/race_test.go
@@ -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)
diff --git a/src/pkg/runtime/runtime.c b/src/pkg/runtime/runtime.c
index d62408118b..f59a3f4e80 100644
--- a/src/pkg/runtime/runtime.c
+++ b/src/pkg/runtime/runtime.c
@@ -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++;
+ }
+}
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index 8b3f10f945..6c590be633 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -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