diff options
Diffstat (limited to 'src/runtime/race.c')
-rw-r--r-- | src/runtime/race.c | 347 |
1 files changed, 0 insertions, 347 deletions
diff --git a/src/runtime/race.c b/src/runtime/race.c deleted file mode 100644 index 5b0d11664..000000000 --- a/src/runtime/race.c +++ /dev/null @@ -1,347 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Implementation of the race detector API. -// +build race - -#include "runtime.h" -#include "arch_GOARCH.h" -#include "malloc.h" -#include "race.h" -#include "type.h" -#include "typekind.h" -#include "textflag.h" - -// Race runtime functions called via runtime·racecall. -void __tsan_init(void); -void __tsan_fini(void); -void __tsan_map_shadow(void); -void __tsan_finalizer_goroutine(void); -void __tsan_go_start(void); -void __tsan_go_end(void); -void __tsan_malloc(void); -void __tsan_acquire(void); -void __tsan_release(void); -void __tsan_release_merge(void); -void __tsan_go_ignore_sync_begin(void); -void __tsan_go_ignore_sync_end(void); - -// Mimic what cmd/cgo would do. -#pragma cgo_import_static __tsan_init -#pragma cgo_import_static __tsan_fini -#pragma cgo_import_static __tsan_map_shadow -#pragma cgo_import_static __tsan_finalizer_goroutine -#pragma cgo_import_static __tsan_go_start -#pragma cgo_import_static __tsan_go_end -#pragma cgo_import_static __tsan_malloc -#pragma cgo_import_static __tsan_acquire -#pragma cgo_import_static __tsan_release -#pragma cgo_import_static __tsan_release_merge -#pragma cgo_import_static __tsan_go_ignore_sync_begin -#pragma cgo_import_static __tsan_go_ignore_sync_end - -// These are called from race_amd64.s. -#pragma cgo_import_static __tsan_read -#pragma cgo_import_static __tsan_read_pc -#pragma cgo_import_static __tsan_read_range -#pragma cgo_import_static __tsan_write -#pragma cgo_import_static __tsan_write_pc -#pragma cgo_import_static __tsan_write_range -#pragma cgo_import_static __tsan_func_enter -#pragma cgo_import_static __tsan_func_exit - -#pragma cgo_import_static __tsan_go_atomic32_load -#pragma cgo_import_static __tsan_go_atomic64_load -#pragma cgo_import_static __tsan_go_atomic32_store -#pragma cgo_import_static __tsan_go_atomic64_store -#pragma cgo_import_static __tsan_go_atomic32_exchange -#pragma cgo_import_static __tsan_go_atomic64_exchange -#pragma cgo_import_static __tsan_go_atomic32_fetch_add -#pragma cgo_import_static __tsan_go_atomic64_fetch_add -#pragma cgo_import_static __tsan_go_atomic32_compare_exchange -#pragma cgo_import_static __tsan_go_atomic64_compare_exchange - -extern byte runtime·noptrdata[]; -extern byte runtime·enoptrdata[]; -extern byte runtime·data[]; -extern byte runtime·edata[]; -extern byte runtime·bss[]; -extern byte runtime·ebss[]; -extern byte runtime·noptrbss[]; -extern byte runtime·enoptrbss[]; - -// start/end of global data (data+bss). -uintptr runtime·racedatastart; -uintptr runtime·racedataend; -// start/end of heap for race_amd64.s -uintptr runtime·racearenastart; -uintptr runtime·racearenaend; - -void runtime·racefuncenter(void *callpc); -void runtime·racefuncexit(void); -void runtime·racereadrangepc1(void *addr, uintptr sz, void *pc); -void runtime·racewriterangepc1(void *addr, uintptr sz, void *pc); -void runtime·racesymbolizethunk(void*); - -// racecall allows calling an arbitrary function f from C race runtime -// with up to 4 uintptr arguments. -void runtime·racecall(void(*f)(void), ...); - -// checks if the address has shadow (i.e. heap or data/bss) -#pragma textflag NOSPLIT -static bool -isvalidaddr(uintptr addr) -{ - if(addr >= runtime·racearenastart && addr < runtime·racearenaend) - return true; - if(addr >= runtime·racedatastart && addr < runtime·racedataend) - return true; - return false; -} - -#pragma textflag NOSPLIT -uintptr -runtime·raceinit(void) -{ - uintptr racectx, start, end, size; - - // cgo is required to initialize libc, which is used by race runtime - if(!runtime·iscgo) - runtime·throw("raceinit: race build must use cgo"); - runtime·racecall(__tsan_init, &racectx, runtime·racesymbolizethunk); - // Round data segment to page boundaries, because it's used in mmap(). - // The relevant sections are noptrdata, data, bss, noptrbss. - // In external linking mode, there may be other non-Go data mixed in, - // and the sections may even occur out of order. - // Work out a conservative range of addresses. - start = ~(uintptr)0; - end = 0; - if(start > (uintptr)runtime·noptrdata) - start = (uintptr)runtime·noptrdata; - if(start > (uintptr)runtime·data) - start = (uintptr)runtime·data; - if(start > (uintptr)runtime·noptrbss) - start = (uintptr)runtime·noptrbss; - if(start > (uintptr)runtime·bss) - start = (uintptr)runtime·bss; - if(end < (uintptr)runtime·enoptrdata) - end = (uintptr)runtime·enoptrdata; - if(end < (uintptr)runtime·edata) - end = (uintptr)runtime·edata; - if(end < (uintptr)runtime·enoptrbss) - end = (uintptr)runtime·enoptrbss; - if(end < (uintptr)runtime·ebss) - end = (uintptr)runtime·ebss; - start = start & ~(PageSize-1); - size = ROUND(end - start, PageSize); - runtime·racecall(__tsan_map_shadow, start, size); - runtime·racedatastart = start; - runtime·racedataend = start + size; - return racectx; -} - -#pragma textflag NOSPLIT -void -runtime·racefini(void) -{ - runtime·racecall(__tsan_fini); -} - -#pragma textflag NOSPLIT -void -runtime·racemapshadow(void *addr, uintptr size) -{ - if(runtime·racearenastart == 0) - runtime·racearenastart = (uintptr)addr; - if(runtime·racearenaend < (uintptr)addr+size) - runtime·racearenaend = (uintptr)addr+size; - runtime·racecall(__tsan_map_shadow, addr, size); -} - -#pragma textflag NOSPLIT -void -runtime·racemalloc(void *p, uintptr sz) -{ - runtime·racecall(__tsan_malloc, p, sz); -} - -#pragma textflag NOSPLIT -uintptr -runtime·racegostart(void *pc) -{ - uintptr racectx; - G *spawng; - - if(g->m->curg != nil) - spawng = g->m->curg; - else - spawng = g; - - runtime·racecall(__tsan_go_start, spawng->racectx, &racectx, pc); - return racectx; -} - -#pragma textflag NOSPLIT -void -runtime·racegoend(void) -{ - runtime·racecall(__tsan_go_end, g->racectx); -} - -#pragma textflag NOSPLIT -void -runtime·racewriterangepc(void *addr, uintptr sz, void *callpc, void *pc) -{ - if(g != g->m->curg) { - // The call is coming from manual instrumentation of Go code running on g0/gsignal. - // Not interesting. - return; - } - if(callpc != nil) - runtime·racefuncenter(callpc); - runtime·racewriterangepc1(addr, sz, pc); - if(callpc != nil) - runtime·racefuncexit(); -} - -#pragma textflag NOSPLIT -void -runtime·racereadrangepc(void *addr, uintptr sz, void *callpc, void *pc) -{ - if(g != g->m->curg) { - // The call is coming from manual instrumentation of Go code running on g0/gsignal. - // Not interesting. - return; - } - if(callpc != nil) - runtime·racefuncenter(callpc); - runtime·racereadrangepc1(addr, sz, pc); - if(callpc != nil) - runtime·racefuncexit(); -} - -#pragma textflag NOSPLIT -void -runtime·racewriteobjectpc(void *addr, Type *t, void *callpc, void *pc) -{ - uint8 kind; - - kind = t->kind & KindMask; - if(kind == KindArray || kind == KindStruct) - runtime·racewriterangepc(addr, t->size, callpc, pc); - else - runtime·racewritepc(addr, callpc, pc); -} - -#pragma textflag NOSPLIT -void -runtime·racereadobjectpc(void *addr, Type *t, void *callpc, void *pc) -{ - uint8 kind; - - kind = t->kind & KindMask; - if(kind == KindArray || kind == KindStruct) - runtime·racereadrangepc(addr, t->size, callpc, pc); - else - runtime·racereadpc(addr, callpc, pc); -} - -#pragma textflag NOSPLIT -void -runtime·raceacquire(void *addr) -{ - runtime·raceacquireg(g, addr); -} - -#pragma textflag NOSPLIT -void -runtime·raceacquireg(G *gp, void *addr) -{ - if(g->raceignore || !isvalidaddr((uintptr)addr)) - return; - runtime·racecall(__tsan_acquire, gp->racectx, addr); -} - -#pragma textflag NOSPLIT -void -runtime·racerelease(void *addr) -{ - if(g->raceignore || !isvalidaddr((uintptr)addr)) - return; - runtime·racereleaseg(g, addr); -} - -#pragma textflag NOSPLIT -void -runtime·racereleaseg(G *gp, void *addr) -{ - if(g->raceignore || !isvalidaddr((uintptr)addr)) - return; - runtime·racecall(__tsan_release, gp->racectx, addr); -} - -#pragma textflag NOSPLIT -void -runtime·racereleasemerge(void *addr) -{ - runtime·racereleasemergeg(g, addr); -} - -#pragma textflag NOSPLIT -void -runtime·racereleasemergeg(G *gp, void *addr) -{ - if(g->raceignore || !isvalidaddr((uintptr)addr)) - return; - runtime·racecall(__tsan_release_merge, gp->racectx, addr); -} - -#pragma textflag NOSPLIT -void -runtime·racefingo(void) -{ - runtime·racecall(__tsan_finalizer_goroutine, g->racectx); -} - -// func RaceAcquire(addr unsafe.Pointer) -#pragma textflag NOSPLIT -void -runtime·RaceAcquire(void *addr) -{ - runtime·raceacquire(addr); -} - -// func RaceRelease(addr unsafe.Pointer) -#pragma textflag NOSPLIT -void -runtime·RaceRelease(void *addr) -{ - runtime·racerelease(addr); -} - -// func RaceReleaseMerge(addr unsafe.Pointer) -#pragma textflag NOSPLIT -void -runtime·RaceReleaseMerge(void *addr) -{ - runtime·racereleasemerge(addr); -} - -// func RaceDisable() -#pragma textflag NOSPLIT -void -runtime·RaceDisable(void) -{ - if(g->raceignore++ == 0) - runtime·racecall(__tsan_go_ignore_sync_begin, g->racectx); -} - -// func RaceEnable() -#pragma textflag NOSPLIT -void -runtime·RaceEnable(void) -{ - if(--g->raceignore == 0) - runtime·racecall(__tsan_go_ignore_sync_end, g->racectx); -} |