Commit 91f0f181 authored by Dmitriy Vyukov's avatar Dmitriy Vyukov Committed by Russ Cox

runtime: fix data race in findfunc()

The data race can lead to reads of partially
initialized concurrently mutated symbol data.
The change also adds a simple sanity test
for Caller() and FuncForPC().

R=rsc
CC=golang-dev
https://golang.org/cl/4817058
parent eb2b3f5d
...@@ -354,6 +354,12 @@ TEXT runtime·atomicstorep(SB), 7, $0 ...@@ -354,6 +354,12 @@ TEXT runtime·atomicstorep(SB), 7, $0
XCHGL AX, 0(BX) XCHGL AX, 0(BX)
RET RET
TEXT runtime·atomicstore(SB), 7, $0
MOVL 4(SP), BX
MOVL 8(SP), AX
XCHGL AX, 0(BX)
RET
// void jmpdefer(fn, sp); // void jmpdefer(fn, sp);
// called from deferreturn. // called from deferreturn.
// 1. pop the caller // 1. pop the caller
......
...@@ -398,6 +398,12 @@ TEXT runtime·atomicstorep(SB), 7, $0 ...@@ -398,6 +398,12 @@ TEXT runtime·atomicstorep(SB), 7, $0
XCHGQ AX, 0(BX) XCHGQ AX, 0(BX)
RET RET
TEXT runtime·atomicstore(SB), 7, $0
MOVQ 8(SP), BX
MOVL 16(SP), AX
XCHGL AX, 0(BX)
RET
// void jmpdefer(fn, sp); // void jmpdefer(fn, sp);
// called from deferreturn. // called from deferreturn.
// 1. pop the caller // 1. pop the caller
......
...@@ -68,3 +68,16 @@ runtime·atomicstorep(void* volatile* addr, void* v) ...@@ -68,3 +68,16 @@ runtime·atomicstorep(void* volatile* addr, void* v)
return; return;
} }
} }
#pragma textflag 7
void
runtime·atomicstore(uint32 volatile* addr, uint32 v)
{
uint32 old;
for(;;) {
old = *addr;
if(runtime·cas(addr, old, v))
return;
}
}
\ No newline at end of file
...@@ -433,6 +433,7 @@ bool runtime·casp(void**, void*, void*); ...@@ -433,6 +433,7 @@ bool runtime·casp(void**, void*, void*);
uint32 runtime·xadd(uint32 volatile*, int32); uint32 runtime·xadd(uint32 volatile*, int32);
uint32 runtime·xchg(uint32 volatile*, uint32); uint32 runtime·xchg(uint32 volatile*, uint32);
uint32 runtime·atomicload(uint32 volatile*); uint32 runtime·atomicload(uint32 volatile*);
void runtime·atomicstore(uint32 volatile*, uint32);
void* runtime·atomicloadp(void* volatile*); void* runtime·atomicloadp(void* volatile*);
void runtime·atomicstorep(void* volatile*, void*); void runtime·atomicstorep(void* volatile*, void*);
void runtime·jmpdefer(byte*, void*); void runtime·jmpdefer(byte*, void*);
......
...@@ -78,6 +78,7 @@ static int32 nfunc; ...@@ -78,6 +78,7 @@ static int32 nfunc;
static byte **fname; static byte **fname;
static int32 nfname; static int32 nfname;
static uint32 funcinit;
static Lock funclock; static Lock funclock;
static void static void
...@@ -427,10 +428,12 @@ runtime·findfunc(uintptr addr) ...@@ -427,10 +428,12 @@ runtime·findfunc(uintptr addr)
// (Before enabling the signal handler, // (Before enabling the signal handler,
// SetCPUProfileRate calls findfunc to trigger // SetCPUProfileRate calls findfunc to trigger
// the initialization outside the handler.) // the initialization outside the handler.)
if(runtime·atomicloadp(&func) == nil) { if(runtime·atomicload(&funcinit) == 0) {
runtime·lock(&funclock); runtime·lock(&funclock);
if(func == nil) if(funcinit == 0) {
buildfuncs(); buildfuncs();
runtime·atomicstore(&funcinit, 1);
}
runtime·unlock(&funclock); runtime·unlock(&funclock);
} }
......
// Copyright 2009 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.
package runtime_test
import (
"runtime"
"strings"
"testing"
)
func TestCaller(t *testing.T) {
procs := runtime.GOMAXPROCS(-1)
c := make(chan bool, procs)
for p := 0; p < procs; p++ {
go func() {
for i := 0; i < 1000; i++ {
testCallerFoo(t)
}
c <- true
}()
defer func() {
<-c
}()
}
}
func testCallerFoo(t *testing.T) {
testCallerBar(t)
}
func testCallerBar(t *testing.T) {
for i := 0; i < 2; i++ {
pc, file, line, ok := runtime.Caller(i)
f := runtime.FuncForPC(pc)
if !ok ||
!strings.HasSuffix(file, "symtab_test.go") ||
(i == 0 && !strings.HasSuffix(f.Name(), "testCallerBar")) ||
(i == 1 && !strings.HasSuffix(f.Name(), "testCallerFoo")) ||
line < 5 || line > 1000 ||
f.Entry() >= pc {
t.Errorf("incorrect symbol info %d: %t %d %d %s %s %d",
i, ok, f.Entry(), pc, f.Name(), file, line)
}
}
}
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