Currently race detector runtime maps shadow memory eagerly at process startup.
It works poorly on Windows, because Windows requires reservation in swap file
(especially problematic if several Go program runs at the same, each consuming GBs
of memory).
With this change race detector maps shadow memory lazily, so Go runtime must notify
about all new heap memory.
It will help with Windows port, but also eliminates scary 16TB virtual mememory
consumption in top output (which sometimes confuses some monitoring scripts).
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/
6811085
runtime·SysMap(p, n);
h->arena_used += n;
runtime·MHeap_MapBits(h);
+ if(raceenabled)
+ runtime·racemapshadow(p, n);
return p;
}
if(h->arena_used > h->arena_end)
h->arena_end = h->arena_used;
runtime·MHeap_MapBits(h);
+ if(raceenabled)
+ runtime·racemapshadow(p, n);
}
return p;
#include "race.h"
void runtime∕race·Initialize(void);
+void runtime∕race·MapShadow(void *addr, uintptr size);
void runtime∕race·Finalize(void);
void runtime∕race·FinalizerGoroutine(int32);
void runtime∕race·Read(int32 goid, void *addr, void *pc);
{
m->racecall = true;
runtime∕race·Initialize();
+ runtime∕race·MapShadow(noptrdata, enoptrbss - noptrdata);
m->racecall = false;
}
m->racecall = false;
}
+void
+runtime·racemapshadow(void *addr, uintptr size)
+{
+ m->racecall = true;
+ runtime∕race·MapShadow(addr, size);
+ m->racecall = false;
+}
+
// Called from instrumented code.
// If we split stack, getcallerpc() can return runtime·lessstack().
#pragma textflag 7
// Finalize race detection subsystem, does not return.
void runtime·racefini(void);
+void runtime·racemapshadow(void *addr, uintptr size);
void runtime·racemalloc(void *p, uintptr sz, void *pc);
void runtime·racefree(void *p);
void runtime·racegostart(int32 goid, void *pc);
/*
void __tsan_init(void);
void __tsan_fini(void);
+void __tsan_map_shadow(void *addr, void *size);
void __tsan_go_start(int pgoid, int chgoid, void *pc);
void __tsan_go_end(int goid);
void __tsan_read(int goid, void *addr, void *pc);
C.__tsan_fini()
}
+func MapShadow(addr, size uintptr) {
+ C.__tsan_map_shadow(unsafe.Pointer(addr), unsafe.Pointer(size))
+}
+
func FinalizerGoroutine(goid int32) {
C.__tsan_finalizer_goroutine(C.int(goid))
}
{
}
+
+void
+runtime·racemapshadow(void *addr, uintptr size)
+{
+ USED(addr);
+ USED(size);
+}
+
void
runtime·racewritepc(void *addr, void *pc)
{