mirror of
https://github.com/golang/go
synced 2024-10-04 20:21:22 -06:00
256 lines
4.8 KiB
C
256 lines
4.8 KiB
C
|
// 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"
|
|||
|
|
|||
|
void runtime∕race·Initialize(void);
|
|||
|
void runtime∕race·Finalize(void);
|
|||
|
void runtime∕race·FinalizerGoroutine(int32);
|
|||
|
void runtime∕race·Read(int32 goid, void *addr, void *pc);
|
|||
|
void runtime∕race·Write(int32 goid, void *addr, void *pc);
|
|||
|
void runtime∕race·FuncEnter(int32 goid, void *pc);
|
|||
|
void runtime∕race·FuncExit(int32 goid);
|
|||
|
void runtime∕race·Malloc(int32 goid, void *p, uintptr sz, void *pc);
|
|||
|
void runtime∕race·Free(void *p);
|
|||
|
void runtime∕race·GoStart(int32 pgoid, int32 chgoid, void *pc);
|
|||
|
void runtime∕race·GoEnd(int32 goid);
|
|||
|
void runtime∕race·Acquire(int32 goid, void *addr);
|
|||
|
void runtime∕race·Release(int32 goid, void *addr);
|
|||
|
void runtime∕race·ReleaseMerge(int32 goid, void *addr);
|
|||
|
|
|||
|
extern byte noptrdata[];
|
|||
|
extern byte enoptrbss[];
|
|||
|
|
|||
|
static bool onstack(uintptr argp);
|
|||
|
|
|||
|
void
|
|||
|
runtime·raceinit(void)
|
|||
|
{
|
|||
|
m->racecall = true;
|
|||
|
runtime∕race·Initialize();
|
|||
|
m->racecall = false;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
runtime·racefini(void)
|
|||
|
{
|
|||
|
m->racecall = true;
|
|||
|
runtime∕race·Finalize();
|
|||
|
m->racecall = false;
|
|||
|
}
|
|||
|
|
|||
|
// Called from instrumented code.
|
|||
|
void
|
|||
|
runtime·racewrite(uintptr addr)
|
|||
|
{
|
|||
|
if(!onstack(addr)) {
|
|||
|
m->racecall = true;
|
|||
|
runtime∕race·Write(g->goid-1, (void*)addr, runtime·getcallerpc(&addr));
|
|||
|
m->racecall = false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Called from instrumented code.
|
|||
|
void
|
|||
|
runtime·raceread(uintptr addr)
|
|||
|
{
|
|||
|
if(!onstack(addr)) {
|
|||
|
m->racecall = true;
|
|||
|
runtime∕race·Read(g->goid-1, (void*)addr, runtime·getcallerpc(&addr));
|
|||
|
m->racecall = false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Called from instrumented code.
|
|||
|
void
|
|||
|
runtime·racefuncenter(void)
|
|||
|
{
|
|||
|
uintptr pc;
|
|||
|
|
|||
|
runtime·callers(2, &pc, 1);
|
|||
|
m->racecall = true;
|
|||
|
runtime∕race·FuncEnter(g->goid-1, (void*)pc);
|
|||
|
m->racecall = false;
|
|||
|
}
|
|||
|
|
|||
|
// Called from instrumented code.
|
|||
|
void
|
|||
|
runtime·racefuncexit(void)
|
|||
|
{
|
|||
|
m->racecall = true;
|
|||
|
runtime∕race·FuncExit(g->goid-1);
|
|||
|
m->racecall = false;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
runtime·racemalloc(void *p, uintptr sz, void *pc)
|
|||
|
{
|
|||
|
m->racecall = true;
|
|||
|
runtime∕race·Malloc(g->goid-1, p, sz, pc);
|
|||
|
m->racecall = false;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
runtime·racefree(void *p)
|
|||
|
{
|
|||
|
m->racecall = true;
|
|||
|
runtime∕race·Free(p);
|
|||
|
m->racecall = false;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
runtime·racegostart(int32 goid, void *pc)
|
|||
|
{
|
|||
|
m->racecall = true;
|
|||
|
runtime∕race·GoStart(g->goid-1, goid-1, pc);
|
|||
|
m->racecall = false;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
runtime·racegoend(int32 goid)
|
|||
|
{
|
|||
|
m->racecall = true;
|
|||
|
runtime∕race·GoEnd(goid-1);
|
|||
|
m->racecall = false;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
runtime·racewritepc(void *addr, void *pc)
|
|||
|
{
|
|||
|
if(!onstack((uintptr)addr)) {
|
|||
|
m->racecall = true;
|
|||
|
runtime∕race·Write(g->goid-1, addr, pc);
|
|||
|
m->racecall = false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
runtime·racereadpc(void *addr, void *pc)
|
|||
|
{
|
|||
|
if(!onstack((uintptr)addr)) {
|
|||
|
m->racecall = true;
|
|||
|
runtime∕race·Read(g->goid-1, addr, pc);
|
|||
|
m->racecall = false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
runtime·raceacquire(void *addr)
|
|||
|
{
|
|||
|
runtime·raceacquireg(g, addr);
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
runtime·raceacquireg(G *gp, void *addr)
|
|||
|
{
|
|||
|
if(g->raceignore)
|
|||
|
return;
|
|||
|
m->racecall = true;
|
|||
|
runtime∕race·Acquire(gp->goid-1, addr);
|
|||
|
m->racecall = false;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
runtime·racerelease(void *addr)
|
|||
|
{
|
|||
|
runtime·racereleaseg(g, addr);
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
runtime·racereleaseg(G *gp, void *addr)
|
|||
|
{
|
|||
|
if(g->raceignore)
|
|||
|
return;
|
|||
|
m->racecall = true;
|
|||
|
runtime∕race·Release(gp->goid-1, addr);
|
|||
|
m->racecall = false;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
runtime·racereleasemerge(void *addr)
|
|||
|
{
|
|||
|
runtime·racereleasemergeg(g, addr);
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
runtime·racereleasemergeg(G *gp, void *addr)
|
|||
|
{
|
|||
|
if(g->raceignore)
|
|||
|
return;
|
|||
|
m->racecall = true;
|
|||
|
runtime∕race·ReleaseMerge(gp->goid-1, addr);
|
|||
|
m->racecall = false;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
runtime·racefingo(void)
|
|||
|
{
|
|||
|
m->racecall = true;
|
|||
|
runtime∕race·FinalizerGoroutine(g->goid - 1);
|
|||
|
m->racecall = false;
|
|||
|
}
|
|||
|
|
|||
|
// func RaceAcquire(addr unsafe.Pointer)
|
|||
|
void
|
|||
|
runtime·RaceAcquire(void *addr)
|
|||
|
{
|
|||
|
runtime·raceacquire(addr);
|
|||
|
}
|
|||
|
|
|||
|
// func RaceRelease(addr unsafe.Pointer)
|
|||
|
void
|
|||
|
runtime·RaceRelease(void *addr)
|
|||
|
{
|
|||
|
runtime·racerelease(addr);
|
|||
|
}
|
|||
|
|
|||
|
// func RaceReleaseMerge(addr unsafe.Pointer)
|
|||
|
void
|
|||
|
runtime·RaceReleaseMerge(void *addr)
|
|||
|
{
|
|||
|
runtime·racereleasemerge(addr);
|
|||
|
}
|
|||
|
|
|||
|
// func RaceSemacquire(s *uint32)
|
|||
|
void runtime·RaceSemacquire(uint32 *s)
|
|||
|
{
|
|||
|
runtime·semacquire(s);
|
|||
|
}
|
|||
|
|
|||
|
// func RaceSemrelease(s *uint32)
|
|||
|
void runtime·RaceSemrelease(uint32 *s)
|
|||
|
{
|
|||
|
runtime·semrelease(s);
|
|||
|
}
|
|||
|
|
|||
|
// func RaceDisable()
|
|||
|
void runtime·RaceDisable(void)
|
|||
|
{
|
|||
|
g->raceignore++;
|
|||
|
}
|
|||
|
|
|||
|
// func RaceEnable()
|
|||
|
void runtime·RaceEnable(void)
|
|||
|
{
|
|||
|
g->raceignore--;
|
|||
|
}
|
|||
|
|
|||
|
static bool
|
|||
|
onstack(uintptr argp)
|
|||
|
{
|
|||
|
// noptrdata, data, bss, noptrbss
|
|||
|
// the layout is in ../../cmd/ld/data.c
|
|||
|
if((byte*)argp >= noptrdata && (byte*)argp < enoptrbss)
|
|||
|
return false;
|
|||
|
if((byte*)argp >= runtime·mheap.arena_start && (byte*)argp < runtime·mheap.arena_used)
|
|||
|
return false;
|
|||
|
return true;
|
|||
|
}
|