Commit 1a19f01a authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

runtime/race: lazily allocate shadow memory

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
parent a3a72447
......@@ -434,6 +434,8 @@ runtime·MHeap_SysAlloc(MHeap *h, uintptr n)
runtime·SysMap(p, n);
h->arena_used += n;
runtime·MHeap_MapBits(h);
if(raceenabled)
runtime·racemapshadow(p, n);
return p;
}
......@@ -460,6 +462,8 @@ runtime·MHeap_SysAlloc(MHeap *h, uintptr n)
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;
......
......@@ -11,6 +11,7 @@
#include "race.h"
void runtimerace·Initialize(void);
void runtimerace·MapShadow(void *addr, uintptr size);
void runtimerace·Finalize(void);
void runtimerace·FinalizerGoroutine(int32);
void runtimerace·Read(int32 goid, void *addr, void *pc);
......@@ -35,6 +36,7 @@ runtime·raceinit(void)
{
m->racecall = true;
runtimerace·Initialize();
runtimerace·MapShadow(noptrdata, enoptrbss - noptrdata);
m->racecall = false;
}
......@@ -46,6 +48,14 @@ runtime·racefini(void)
m->racecall = false;
}
void
runtime·racemapshadow(void *addr, uintptr size)
{
m->racecall = true;
runtimerace·MapShadow(addr, size);
m->racecall = false;
}
// Called from instrumented code.
// If we split stack, getcallerpc() can return runtime·lessstack().
#pragma textflag 7
......
......@@ -15,6 +15,7 @@ void runtime·raceinit(void);
// 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);
......
......@@ -10,6 +10,7 @@ package race
/*
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);
......@@ -38,6 +39,10 @@ func Finalize() {
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))
}
......
......@@ -17,6 +17,14 @@ runtime·racefini(void)
{
}
void
runtime·racemapshadow(void *addr, uintptr size)
{
USED(addr);
USED(size);
}
void
runtime·racewritepc(void *addr, void *pc)
{
......
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