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
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
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)
// 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 {
// 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 {
int32* value;
} dbgvar[] = {
{"allocfreetrace", &runtime·debug.allocfreetrace},
+ {"efence", &runtime·debug.efence},
{"gctrace", &runtime·debug.gctrace},
{"scheddetail", &runtime·debug.scheddetail},
{"schedtrace", &runtime·debug.schedtrace},
struct DebugVars
{
int32 allocfreetrace;
+ int32 efence;
int32 gctrace;
int32 scheddetail;
int32 schedtrace;