]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: add GODEBUG option for an electric fence like heap mode
authorCarl Shapiro <cshapiro@google.com>
Fri, 6 Dec 2013 22:40:45 +0000 (14:40 -0800)
committerCarl Shapiro <cshapiro@google.com>
Fri, 6 Dec 2013 22:40:45 +0000 (14:40 -0800)
When enabled this new debugging mode will allocate objects on
their own page and never recycle memory addresses.  This is an
essential tool to root cause a broad class of heap corruption.

R=golang-dev, dave, daniel.morsing, dvyukov, rsc, iant, cshapiro
CC=golang-dev
https://golang.org/cl/22060046

src/pkg/runtime/extern.go
src/pkg/runtime/malloc.goc
src/pkg/runtime/mgc0.c
src/pkg/runtime/runtime.c
src/pkg/runtime/runtime.h

index b76c47fca2b55dcfc2439319845caa5e650133fc..c96dc10384e490db71e47c55a1431c888ba9ef21 100644 (file)
@@ -24,20 +24,24 @@ percentage at run time. See http://golang.org/pkg/runtime/debug/#SetGCPercent.
 The GODEBUG variable controls debug output from the runtime. GODEBUG value is
 a comma-separated list of name=val pairs. Supported names are:
 
+       allocfreetrace: setting allocfreetrace=1 causes every allocation to be
+       profiled and a stack trace printed on each object's allocation and free.
+
+       efence: setting efence=1 causes the allocator to run in a mode
+       where each object is allocated on a unique page and addresses are
+       never recycled.
+
        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 gctrace=2 emits the same summary but also
        repeats each collection.
 
-       schedtrace: setting schedtrace=X causes the scheduler to emit a single line to standard
-       error every X milliseconds, summarizing the scheduler state.
-
        scheddetail: setting schedtrace=X and scheddetail=1 causes the scheduler to emit
        detailed multiline info every X milliseconds, describing state of the scheduler,
        processors, threads and goroutines.
 
-       allocfreetrace: setting allocfreetrace=1 causes every allocation to be
-       profiled and a stack trace printed on each object's allocation and free.
+       schedtrace: setting schedtrace=X causes the scheduler to emit a single line to standard
+       error every X milliseconds, summarizing the scheduler state.
 
 The GOMAXPROCS variable limits the number of operating system threads that
 can execute user-level Go code simultaneously. There is no limit to the number of threads
index 46d6450c066cfa6a194c95f0240183a1fd6094f1..cd124f0f7177fa9163bbf66741c3e50c9132eaaf 100644 (file)
@@ -58,7 +58,7 @@ runtime·mallocgc(uintptr size, uintptr typ, uint32 flag)
                size += sizeof(uintptr);
 
        c = m->mcache;
-       if(size <= MaxSmallSize) {
+       if(!runtime·debug.efence && size <= MaxSmallSize) {
                // Allocate from mcache free lists.
                // Inlined version of SizeToClass().
                if(size <= 1024-8)
@@ -196,7 +196,10 @@ runtime·free(void *v)
                // they might coalesce v into other spans and change the bitmap further.
                runtime·markfreed(v, size);
                runtime·unmarkspan(v, 1<<PageShift);
-               runtime·MHeap_Free(&runtime·mheap, s, 1);
+               if(runtime·debug.efence)
+                       runtime·SysFree((void*)(s->start<<PageShift), size, &mstats.heap_sys);
+               else
+                       runtime·MHeap_Free(&runtime·mheap, s, 1);
                c->local_nlargefree++;
                c->local_largefree += size;
        } else {
index f0ac6dcb88d1288ca9960ba57e1bf271c56658d9..a69154a79dd2814dff17c104330a1245085bdba2 100644 (file)
@@ -1797,7 +1797,10 @@ sweepspan(ParFor *desc, uint32 idx)
                        // Free large span.
                        runtime·unmarkspan(p, 1<<PageShift);
                        *(uintptr*)p = (uintptr)0xdeaddeaddeaddeadll;   // needs zeroing
-                       runtime·MHeap_Free(&runtime·mheap, s, 1);
+                       if(runtime·debug.efence)
+                               runtime·SysFree(p, size, &mstats.gc_sys);
+                       else
+                               runtime·MHeap_Free(&runtime·mheap, s, 1);
                        c->local_nlargefree++;
                        c->local_largefree += size;
                } else {
index 63b78eb55f9321c684603a3c94f60ea9cb5d53fd..9a8eb0e3402be4c12172787d3157e852066e7151 100644 (file)
@@ -388,6 +388,7 @@ static struct {
        int32*  value;
 } dbgvar[] = {
        {"allocfreetrace", &runtime·debug.allocfreetrace},
+       {"efence", &runtime·debug.efence},
        {"gctrace", &runtime·debug.gctrace},
        {"scheddetail", &runtime·debug.scheddetail},
        {"schedtrace", &runtime·debug.schedtrace},
index 8183e7c810754a147fba4702f1f0017b1df468e1..eba26081d6785316765924cc9299d7021f062202 100644 (file)
@@ -534,6 +534,7 @@ struct CgoMal
 struct DebugVars
 {
        int32   allocfreetrace;
+       int32   efence;
        int32   gctrace;
        int32   scheddetail;
        int32   schedtrace;