Commit fff63c24 authored by Keith Randall's avatar Keith Randall

runtime: WriteHeapDump dumps the heap to a file.

See http://golang.org/s/go13heapdump for the file format.

LGTM=rsc
R=rsc, bradfitz, dvyukov, khr
CC=golang-codereviews
https://golang.org/cl/37540043
parent bee3848f
...@@ -146,3 +146,8 @@ func SetMaxThreads(threads int) int { ...@@ -146,3 +146,8 @@ func SetMaxThreads(threads int) int {
// SetPanicOnFault applies only to the current goroutine. // SetPanicOnFault applies only to the current goroutine.
// It returns the previous setting. // It returns the previous setting.
func SetPanicOnFault(enabled bool) bool func SetPanicOnFault(enabled bool) bool
// WriteHeapDump writes a description of the heap and the objects in
// it to the given file descriptor.
// The heap dump format is defined at http://golang.org/s/go13heapdump.
func WriteHeapDump(fd uintptr)
This diff is collapsed.
...@@ -134,6 +134,20 @@ out: ...@@ -134,6 +134,20 @@ out:
return m; return m;
} }
// call the callback for every itab that is currently allocated.
void
runtime·iterate_itabs(void (*callback)(Itab*))
{
int32 i;
Itab *tab;
for(i = 0; i < nelem(hash); i++) {
for(tab = hash[i]; tab != nil; tab = tab->link) {
callback(tab);
}
}
}
static void static void
copyin(Type *t, void *src, void **dst) copyin(Type *t, void *src, void **dst)
{ {
......
...@@ -277,6 +277,7 @@ struct MStats ...@@ -277,6 +277,7 @@ struct MStats
#define mstats runtime·memStats #define mstats runtime·memStats
extern MStats mstats; extern MStats mstats;
void runtime·updatememstats(GCStats *stats);
// Size classes. Computed and initialized by InitSizes. // Size classes. Computed and initialized by InitSizes.
// //
......
...@@ -64,14 +64,8 @@ ...@@ -64,14 +64,8 @@
enum { enum {
Debug = 0, Debug = 0,
CollectStats = 0, CollectStats = 0,
ScanStackByFrames = 1,
IgnorePreciseGC = 0,
ConcurrentSweep = 1, ConcurrentSweep = 1,
// Four bits per word (see #defines below).
wordsPerBitmapWord = sizeof(void*)*8/4,
bitShift = sizeof(void*)*8/4,
WorkbufSize = 16*1024, WorkbufSize = 16*1024,
FinBlockSize = 4*1024, FinBlockSize = 4*1024,
...@@ -146,38 +140,6 @@ clearpools(void) ...@@ -146,38 +140,6 @@ clearpools(void)
} }
} }
// Bits in per-word bitmap.
// #defines because enum might not be able to hold the values.
//
// Each word in the bitmap describes wordsPerBitmapWord words
// of heap memory. There are 4 bitmap bits dedicated to each heap word,
// so on a 64-bit system there is one bitmap word per 16 heap words.
// The bits in the word are packed together by type first, then by
// heap location, so each 64-bit bitmap word consists of, from top to bottom,
// the 16 bitMarked bits for the corresponding heap words,
// then the 16 bitScan/bitBlockBoundary bits, then the 16 bitAllocated bits.
// This layout makes it easier to iterate over the bits of a given type.
//
// The bitmap starts at mheap.arena_start and extends *backward* from
// there. On a 64-bit system the off'th word in the arena is tracked by
// the off/16+1'th word before mheap.arena_start. (On a 32-bit system,
// the only difference is that the divisor is 8.)
//
// To pull out the bits corresponding to a given pointer p, we use:
//
// off = p - (uintptr*)mheap.arena_start; // word offset
// b = (uintptr*)mheap.arena_start - off/wordsPerBitmapWord - 1;
// shift = off % wordsPerBitmapWord
// bits = *b >> shift;
// /* then test bits & bitAllocated, bits & bitMarked, etc. */
//
#define bitAllocated ((uintptr)1<<(bitShift*0)) /* block start; eligible for garbage collection */
#define bitScan ((uintptr)1<<(bitShift*1)) /* when bitAllocated is set */
#define bitMarked ((uintptr)1<<(bitShift*2)) /* when bitAllocated is set */
#define bitBlockBoundary ((uintptr)1<<(bitShift*1)) /* when bitAllocated is NOT set - mark for FlagNoGC objects */
#define bitMask (bitAllocated | bitScan | bitMarked)
// Holding worldsema grants an M the right to try to stop the world. // Holding worldsema grants an M the right to try to stop the world.
// The procedure is: // The procedure is:
// //
...@@ -1270,6 +1232,7 @@ markroot(ParFor *desc, uint32 i) ...@@ -1270,6 +1232,7 @@ markroot(ParFor *desc, uint32 i)
USED(&desc); USED(&desc);
wbuf = getempty(nil); wbuf = getempty(nil);
// Note: if you add a case here, please also update heapdump.c:dumproots.
switch(i) { switch(i) {
case RootData: case RootData:
enqueue1(&wbuf, (Obj){data, edata - data, (uintptr)gcdata}); enqueue1(&wbuf, (Obj){data, edata - data, (uintptr)gcdata});
...@@ -1714,6 +1677,21 @@ runtime·queuefinalizer(byte *p, FuncVal *fn, uintptr nret, Type *fint, PtrType ...@@ -1714,6 +1677,21 @@ runtime·queuefinalizer(byte *p, FuncVal *fn, uintptr nret, Type *fint, PtrType
runtime·unlock(&gclock); runtime·unlock(&gclock);
} }
void
runtime·iterate_finq(void (*callback)(FuncVal*, byte*, uintptr, Type*, PtrType*))
{
FinBlock *fb;
Finalizer *f;
uintptr i;
for(fb = allfin; fb; fb = fb->alllink) {
for(i = 0; i < fb->cnt; i++) {
f = &fb->fin[i];
callback(f->fn, f->arg, f->nret, f->fint, f->ot);
}
}
}
void void
runtime·MSpan_EnsureSwept(MSpan *s) runtime·MSpan_EnsureSwept(MSpan *s)
{ {
...@@ -2120,8 +2098,8 @@ flushallmcaches(void) ...@@ -2120,8 +2098,8 @@ flushallmcaches(void)
} }
} }
static void void
updatememstats(GCStats *stats) runtime·updatememstats(GCStats *stats)
{ {
M *mp; M *mp;
MSpan *s; MSpan *s;
...@@ -2388,7 +2366,7 @@ gc(struct gc_args *args) ...@@ -2388,7 +2366,7 @@ gc(struct gc_args *args)
if(runtime·debug.gctrace) { if(runtime·debug.gctrace) {
heap1 = mstats.heap_alloc; heap1 = mstats.heap_alloc;
updatememstats(&stats); runtime·updatememstats(&stats);
if(heap1 != mstats.heap_alloc) { if(heap1 != mstats.heap_alloc) {
runtime·printf("runtime: mstats skew: heap=%D/%D\n", heap1, mstats.heap_alloc); runtime·printf("runtime: mstats skew: heap=%D/%D\n", heap1, mstats.heap_alloc);
runtime·throw("mstats skew"); runtime·throw("mstats skew");
...@@ -2488,7 +2466,7 @@ runtime·ReadMemStats(MStats *stats) ...@@ -2488,7 +2466,7 @@ runtime·ReadMemStats(MStats *stats)
runtime·semacquire(&runtime·worldsema, false); runtime·semacquire(&runtime·worldsema, false);
m->gcing = 1; m->gcing = 1;
runtime·stoptheworld(); runtime·stoptheworld();
updatememstats(nil); runtime·updatememstats(nil);
// Size of the trailing by_size array differs between Go and C, // Size of the trailing by_size array differs between Go and C,
// NumSizeClasses was changed, but we can not change Go struct because of backward compatibility. // NumSizeClasses was changed, but we can not change Go struct because of backward compatibility.
runtime·memcopy(runtime·sizeof_C_MStats, stats, &mstats); runtime·memcopy(runtime·sizeof_C_MStats, stats, &mstats);
......
...@@ -44,3 +44,44 @@ enum { ...@@ -44,3 +44,44 @@ enum {
// - at most GC_STACK_CAPACITY allocations because of GC_ARRAY_START // - at most GC_STACK_CAPACITY allocations because of GC_ARRAY_START
GC_STACK_CAPACITY = 8, GC_STACK_CAPACITY = 8,
}; };
enum {
ScanStackByFrames = 1,
IgnorePreciseGC = 0,
// Four bits per word (see #defines below).
wordsPerBitmapWord = sizeof(void*)*8/4,
bitShift = sizeof(void*)*8/4,
};
// Bits in per-word bitmap.
// #defines because enum might not be able to hold the values.
//
// Each word in the bitmap describes wordsPerBitmapWord words
// of heap memory. There are 4 bitmap bits dedicated to each heap word,
// so on a 64-bit system there is one bitmap word per 16 heap words.
// The bits in the word are packed together by type first, then by
// heap location, so each 64-bit bitmap word consists of, from top to bottom,
// the 16 bitMarked bits for the corresponding heap words,
// then the 16 bitScan/bitBlockBoundary bits, then the 16 bitAllocated bits.
// This layout makes it easier to iterate over the bits of a given type.
//
// The bitmap starts at mheap.arena_start and extends *backward* from
// there. On a 64-bit system the off'th word in the arena is tracked by
// the off/16+1'th word before mheap.arena_start. (On a 32-bit system,
// the only difference is that the divisor is 8.)
//
// To pull out the bits corresponding to a given pointer p, we use:
//
// off = p - (uintptr*)mheap.arena_start; // word offset
// b = (uintptr*)mheap.arena_start - off/wordsPerBitmapWord - 1;
// shift = off % wordsPerBitmapWord
// bits = *b >> shift;
// /* then test bits & bitAllocated, bits & bitMarked, etc. */
//
#define bitAllocated ((uintptr)1<<(bitShift*0)) /* block start; eligible for garbage collection */
#define bitScan ((uintptr)1<<(bitShift*1)) /* when bitAllocated is set */
#define bitMarked ((uintptr)1<<(bitShift*2)) /* when bitAllocated is set */
#define bitBlockBoundary ((uintptr)1<<(bitShift*1)) /* when bitAllocated is NOT set - mark for FlagNoGC objects */
#define bitMask (bitAllocated | bitScan | bitMarked)
...@@ -950,6 +950,8 @@ void _rt0_go(void); ...@@ -950,6 +950,8 @@ void _rt0_go(void);
void* runtime·funcdata(Func*, int32); void* runtime·funcdata(Func*, int32);
int32 runtime·setmaxthreads(int32); int32 runtime·setmaxthreads(int32);
G* runtime·timejump(void); G* runtime·timejump(void);
void runtime·iterate_itabs(void (*callback)(Itab*));
void runtime·iterate_finq(void (*callback)(FuncVal*, byte*, uintptr, Type*, PtrType*));
#pragma varargck argpos runtime·printf 1 #pragma varargck argpos runtime·printf 1
#pragma varargck type "c" int32 #pragma varargck type "c" int32
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment