summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmd/5g/reg.c2
-rw-r--r--src/cmd/cgo/doc.go2
-rw-r--r--src/cmd/internal/goobj/read.go (renamed from src/debug/goobj/read.go)0
-rw-r--r--src/cmd/internal/goobj/read_test.go (renamed from src/debug/goobj/read_test.go)0
-rw-r--r--src/cmd/internal/objfile/goobj.go2
-rw-r--r--src/cmd/link/auto.go2
-rw-r--r--src/cmd/link/auto_test.go2
-rw-r--r--src/cmd/link/dead.go2
-rw-r--r--src/cmd/link/dead_test.go2
-rw-r--r--src/cmd/link/layout.go2
-rw-r--r--src/cmd/link/link_test.go2
-rw-r--r--src/cmd/link/pclntab.go2
-rw-r--r--src/cmd/link/pclntab_test.go2
-rw-r--r--src/cmd/link/prog.go2
-rw-r--r--src/cmd/link/runtime.go2
-rw-r--r--src/cmd/link/scan.go4
-rw-r--r--src/cmd/pprof/internal/report/source.go6
-rw-r--r--src/crypto/x509/root_unix.go1
-rw-r--r--src/hash/crc32/crc32.go4
-rw-r--r--src/net/http/fs.go8
-rw-r--r--src/net/url/example_test.go30
-rw-r--r--src/regexp/syntax/regexp.go2
-rwxr-xr-xsrc/run.bash36
-rw-r--r--src/runtime/chan.go1
-rw-r--r--src/runtime/heapdump.go2
-rw-r--r--src/runtime/malloc.go11
-rw-r--r--src/runtime/mgc0.go16
-rw-r--r--src/runtime/proc.go10
-rw-r--r--src/runtime/race/race_unix_test.go30
-rw-r--r--src/runtime/race1.go37
-rw-r--r--src/runtime/race_amd64.s43
-rw-r--r--src/runtime/select.go2
-rw-r--r--src/runtime/sema.go2
-rw-r--r--src/runtime/stubs.go2
-rw-r--r--src/syscall/exec_bsd.go40
-rw-r--r--src/syscall/exec_linux.go36
36 files changed, 230 insertions, 119 deletions
diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c
index 56ea7826e..611310f12 100644
--- a/src/cmd/5g/reg.c
+++ b/src/cmd/5g/reg.c
@@ -230,7 +230,7 @@ regopt(Prog *firstp)
/* the mod/div runtime routines smash R12 */
if(p->as == ADIV || p->as == ADIVU || p->as == AMOD || p->as == AMODU)
- r->set.b[z] |= RtoB(12);
+ r->set.b[0] |= RtoB(12);
}
if(firstr == R)
return;
diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go
index 69c7ce893..6179c7afd 100644
--- a/src/cmd/cgo/doc.go
+++ b/src/cmd/cgo/doc.go
@@ -152,7 +152,7 @@ In C, a function argument written as a fixed size array
actually requires a pointer to the first element of the array.
C compilers are aware of this calling convention and adjust
the call accordingly, but Go cannot. In Go, you must pass
-the pointer to the first element explicitly: C.f(&x[0]).
+the pointer to the first element explicitly: C.f(&C.x[0]).
A few special functions convert between Go and C types
by making copies of the data. In pseudo-Go definitions:
diff --git a/src/debug/goobj/read.go b/src/cmd/internal/goobj/read.go
index 79a83e59a..79a83e59a 100644
--- a/src/debug/goobj/read.go
+++ b/src/cmd/internal/goobj/read.go
diff --git a/src/debug/goobj/read_test.go b/src/cmd/internal/goobj/read_test.go
index cc991e5d9..cc991e5d9 100644
--- a/src/debug/goobj/read_test.go
+++ b/src/cmd/internal/goobj/read_test.go
diff --git a/src/cmd/internal/objfile/goobj.go b/src/cmd/internal/objfile/goobj.go
index a1d773023..6b1607a17 100644
--- a/src/cmd/internal/objfile/goobj.go
+++ b/src/cmd/internal/objfile/goobj.go
@@ -7,7 +7,7 @@
package objfile
import (
- "debug/goobj"
+ "cmd/internal/goobj"
"fmt"
"os"
)
diff --git a/src/cmd/link/auto.go b/src/cmd/link/auto.go
index f9228e8ca..21f6d6082 100644
--- a/src/cmd/link/auto.go
+++ b/src/cmd/link/auto.go
@@ -10,7 +10,7 @@
package main
import (
- "debug/goobj"
+ "cmd/internal/goobj"
"strconv"
"strings"
)
diff --git a/src/cmd/link/auto_test.go b/src/cmd/link/auto_test.go
index 27f8e2b96..f99e097a9 100644
--- a/src/cmd/link/auto_test.go
+++ b/src/cmd/link/auto_test.go
@@ -13,7 +13,7 @@ package main
import (
"bytes"
- "debug/goobj"
+ "cmd/internal/goobj"
"testing"
)
diff --git a/src/cmd/link/dead.go b/src/cmd/link/dead.go
index e1e775eb3..ee23a61f8 100644
--- a/src/cmd/link/dead.go
+++ b/src/cmd/link/dead.go
@@ -6,7 +6,7 @@
package main
-import "debug/goobj"
+import "cmd/internal/goobj"
// dead removes unreachable code and data from the program.
// It is basically a mark-sweep garbage collection: traverse all the
diff --git a/src/cmd/link/dead_test.go b/src/cmd/link/dead_test.go
index 2e179b453..eb34d0580 100644
--- a/src/cmd/link/dead_test.go
+++ b/src/cmd/link/dead_test.go
@@ -5,7 +5,7 @@
package main
import (
- "debug/goobj"
+ "cmd/internal/goobj"
"reflect"
"strings"
"testing"
diff --git a/src/cmd/link/layout.go b/src/cmd/link/layout.go
index 149ebced0..d5c291e25 100644
--- a/src/cmd/link/layout.go
+++ b/src/cmd/link/layout.go
@@ -7,7 +7,7 @@
package main
import (
- "debug/goobj"
+ "cmd/internal/goobj"
)
// A layoutSection describes a single section to add to the
diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go
index 984796784..b5ae15fc7 100644
--- a/src/cmd/link/link_test.go
+++ b/src/cmd/link/link_test.go
@@ -6,7 +6,7 @@ package main
import (
"bytes"
- "debug/goobj"
+ "cmd/internal/goobj"
"io/ioutil"
"testing"
)
diff --git a/src/cmd/link/pclntab.go b/src/cmd/link/pclntab.go
index 232d586bf..2d131781f 100644
--- a/src/cmd/link/pclntab.go
+++ b/src/cmd/link/pclntab.go
@@ -7,7 +7,7 @@
package main
import (
- "debug/goobj"
+ "cmd/internal/goobj"
"encoding/binary"
"os"
"sort"
diff --git a/src/cmd/link/pclntab_test.go b/src/cmd/link/pclntab_test.go
index 19953f579..ea8080674 100644
--- a/src/cmd/link/pclntab_test.go
+++ b/src/cmd/link/pclntab_test.go
@@ -6,7 +6,7 @@ package main
import (
"bytes"
- "debug/goobj"
+ "cmd/internal/goobj"
"fmt"
"math/rand"
"sort"
diff --git a/src/cmd/link/prog.go b/src/cmd/link/prog.go
index a52b5ff9b..77fb1ece5 100644
--- a/src/cmd/link/prog.go
+++ b/src/cmd/link/prog.go
@@ -5,7 +5,7 @@
package main
import (
- "debug/goobj"
+ "cmd/internal/goobj"
"encoding/binary"
"fmt"
"go/build"
diff --git a/src/cmd/link/runtime.go b/src/cmd/link/runtime.go
index b0c1ac98a..acda2d24d 100644
--- a/src/cmd/link/runtime.go
+++ b/src/cmd/link/runtime.go
@@ -7,7 +7,7 @@
package main
-import "debug/goobj"
+import "cmd/internal/goobj"
func (p *Prog) runtime() {
p.pclntab()
diff --git a/src/cmd/link/scan.go b/src/cmd/link/scan.go
index 0720e039b..7feb0d890 100644
--- a/src/cmd/link/scan.go
+++ b/src/cmd/link/scan.go
@@ -11,7 +11,7 @@
package main
import (
- "debug/goobj"
+ "cmd/internal/goobj"
"os"
"sort"
"strings"
@@ -69,7 +69,7 @@ func (p *Prog) scanFile(pkgpath string, file string) {
return
}
- // TODO(rsc): Change debug/goobj to record package name as gp.Name.
+ // TODO(rsc): Change cmd/internal/goobj to record package name as gp.Name.
// TODO(rsc): If pkgpath == "main", check that gp.Name == "main".
pkg.Package = gp
diff --git a/src/cmd/pprof/internal/report/source.go b/src/cmd/pprof/internal/report/source.go
index 57300dd91..73ae1b4ea 100644
--- a/src/cmd/pprof/internal/report/source.go
+++ b/src/cmd/pprof/internal/report/source.go
@@ -358,9 +358,13 @@ func getFunctionSource(fun, file string, fns nodes, start, end int) (nodes, stri
for {
line, err := buf.ReadString('\n')
if err != nil {
- if line == "" || err != io.EOF {
+ if err != io.EOF {
return nil, file, err
}
+ if line == "" {
+ // end was at or past EOF; that's okay
+ break
+ }
}
if lineno >= start {
flat, cum := sumNodes(lineNodes[lineno])
diff --git a/src/crypto/x509/root_unix.go b/src/crypto/x509/root_unix.go
index c65f626ac..f77d6c0c5 100644
--- a/src/crypto/x509/root_unix.go
+++ b/src/crypto/x509/root_unix.go
@@ -16,6 +16,7 @@ var certFiles = []string{
"/etc/ssl/cert.pem", // OpenBSD
"/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly
"/etc/pki/tls/cacert.pem", // OpenELEC
+ "/etc/certs/ca-certificates.crt", // Solaris 11.2+
}
// Possible directories with certificate files; stop after successfully
diff --git a/src/hash/crc32/crc32.go b/src/hash/crc32/crc32.go
index a2a21a06f..6a6b9473b 100644
--- a/src/hash/crc32/crc32.go
+++ b/src/hash/crc32/crc32.go
@@ -17,8 +17,8 @@ const Size = 4
// Predefined polynomials.
const (
- // Far and away the most common CRC-32 polynomial.
- // Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, mpeg-2, ...
+ // IEEE is by far and away the most common CRC-32 polynomial.
+ // Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, ...
IEEE = 0xedb88320
// Castagnoli's polynomial, used in iSCSI.
diff --git a/src/net/http/fs.go b/src/net/http/fs.go
index 7bd777b71..e322f710a 100644
--- a/src/net/http/fs.go
+++ b/src/net/http/fs.go
@@ -22,8 +22,12 @@ import (
"time"
)
-// A Dir implements http.FileSystem using the native file
-// system restricted to a specific directory tree.
+// A Dir implements FileSystem using the native file system restricted to a
+// specific directory tree.
+//
+// While the FileSystem.Open method takes '/'-separated paths, a Dir's string
+// value is a filename on the native file system, not a URL, so it is separated
+// by filepath.Separator, which isn't necessarily '/'.
//
// An empty Dir is treated as ".".
type Dir string
diff --git a/src/net/url/example_test.go b/src/net/url/example_test.go
index 56c5dc696..e55c1aa16 100644
--- a/src/net/url/example_test.go
+++ b/src/net/url/example_test.go
@@ -7,7 +7,10 @@ package url_test
import (
"fmt"
"log"
+ "net/http"
+ "net/http/httputil"
"net/url"
+ "strings"
)
func ExampleValues() {
@@ -39,3 +42,30 @@ func ExampleURL() {
fmt.Println(u)
// Output: https://google.com/search?q=golang
}
+
+func ExampleURL_opaque() {
+ // Sending a literal '%' in an HTTP request's Path
+ req := &http.Request{
+ Method: "GET",
+ Host: "example.com", // takes precendence over URL.Host
+ URL: &url.URL{
+ Host: "ignored",
+ Scheme: "https",
+ Opaque: "/%2f/",
+ },
+ Header: http.Header{
+ "User-Agent": {"godoc-example/0.1"},
+ },
+ }
+ out, err := httputil.DumpRequestOut(req, true)
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Println(strings.Replace(string(out), "\r", "", -1))
+ // Output:
+ // GET /%2f/ HTTP/1.1
+ // Host: example.com
+ // User-Agent: godoc-example/0.1
+ // Accept-Encoding: gzip
+ //
+}
diff --git a/src/regexp/syntax/regexp.go b/src/regexp/syntax/regexp.go
index 329a90e01..cea7d9e04 100644
--- a/src/regexp/syntax/regexp.go
+++ b/src/regexp/syntax/regexp.go
@@ -39,7 +39,7 @@ const (
OpEmptyMatch // matches empty string
OpLiteral // matches Runes sequence
OpCharClass // matches Runes interpreted as range pair list
- OpAnyCharNotNL // matches any character
+ OpAnyCharNotNL // matches any character except newline
OpAnyChar // matches any character
OpBeginLine // matches empty string at beginning of line
OpEndLine // matches empty string at end of line
diff --git a/src/run.bash b/src/run.bash
index d9b985fd1..6b9ecc33c 100755
--- a/src/run.bash
+++ b/src/run.bash
@@ -64,17 +64,6 @@ echo
echo '# sync -cpu=10'
go test sync -short -timeout=$(expr 120 \* $timeout_scale)s -cpu=10
-# Race detector only supported on Linux, FreeBSD and OS X,
-# and only on amd64, and only when cgo is enabled.
-case "$GOHOSTOS-$GOOS-$GOARCH-$CGO_ENABLED" in
-linux-linux-amd64-1 | freebsd-freebsd-amd64-1 | darwin-darwin-amd64-1)
- echo
- echo '# Testing race detector.'
- go test -race -i runtime/race flag
- go test -race -run=Output runtime/race
- go test -race -short flag
-esac
-
xcd() {
echo
echo '#' $1
@@ -120,6 +109,7 @@ go run $GOROOT/test/run.go - . || exit 1
[ "$CGO_ENABLED" != 1 ] ||
(xcd ../misc/cgo/test
# cgo tests inspect the traceback for runtime functions
+extlink=0
export GOTRACEBACK=2
go test -ldflags '-linkmode=auto' || exit 1
# linkmode=internal fails on dragonfly since errno is a TLS relocation.
@@ -128,19 +118,24 @@ case "$GOHOSTOS-$GOARCH" in
openbsd-386 | openbsd-amd64)
# test linkmode=external, but __thread not supported, so skip testtls.
go test -ldflags '-linkmode=external' || exit 1
+ extlink=1
;;
darwin-386 | darwin-amd64)
# linkmode=external fails on OS X 10.6 and earlier == Darwin
# 10.8 and earlier.
case $(uname -r) in
[0-9].* | 10.*) ;;
- *) go test -ldflags '-linkmode=external' || exit 1;;
+ *)
+ go test -ldflags '-linkmode=external' || exit 1
+ extlink=1
+ ;;
esac
;;
android-arm | dragonfly-386 | dragonfly-amd64 | freebsd-386 | freebsd-amd64 | freebsd-arm | linux-386 | linux-amd64 | linux-arm | netbsd-386 | netbsd-amd64)
go test -ldflags '-linkmode=external' || exit 1
go test -ldflags '-linkmode=auto' ../testtls || exit 1
go test -ldflags '-linkmode=external' ../testtls || exit 1
+ extlink=1
case "$GOHOSTOS-$GOARCH" in
netbsd-386 | netbsd-amd64) ;; # no static linking
@@ -164,6 +159,23 @@ android-arm | dragonfly-386 | dragonfly-amd64 | freebsd-386 | freebsd-amd64 | fr
esac
) || exit $?
+# Race detector only supported on Linux, FreeBSD and OS X,
+# and only on amd64, and only when cgo is enabled.
+# Delayed until here so we know whether to try external linking.
+case "$GOHOSTOS-$GOOS-$GOARCH-$CGO_ENABLED" in
+linux-linux-amd64-1 | freebsd-freebsd-amd64-1 | darwin-darwin-amd64-1)
+ echo
+ echo '# Testing race detector.'
+ go test -race -i runtime/race flag os/exec
+ go test -race -run=Output runtime/race
+ go test -race -short flag os/exec
+
+ # Test with external linking; see issue 9133.
+ if [ "$extlink" = 1 ]; then
+ go test -race -short -ldflags=-linkmode=external flag os/exec
+ fi
+esac
+
# This tests cgo -cdefs. That mode is not supported,
# so it's okay if it doesn't work on some systems.
# In particular, it works badly with clang on OS X.
diff --git a/src/runtime/chan.go b/src/runtime/chan.go
index bb0110f94..330422ad0 100644
--- a/src/runtime/chan.go
+++ b/src/runtime/chan.go
@@ -630,6 +630,7 @@ func (q *waitq) dequeue() *sudog {
return nil
}
q.first = sgp.next
+ sgp.next = nil
if q.last == sgp {
q.last = nil
}
diff --git a/src/runtime/heapdump.go b/src/runtime/heapdump.go
index c942e0163..0c1a60c8b 100644
--- a/src/runtime/heapdump.go
+++ b/src/runtime/heapdump.go
@@ -7,7 +7,7 @@
// finalizers, etc.) to a file.
// The format of the dumped file is described at
-// http://code.google.com/p/go-wiki/wiki/heapdump14
+// http://golang.org/s/go14heapdump.
package runtime
diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go
index 20cb6818d..d73d1ba6a 100644
--- a/src/runtime/malloc.go
+++ b/src/runtime/malloc.go
@@ -477,6 +477,8 @@ func GC() {
// linker-provided
var noptrdata struct{}
+var enoptrdata struct{}
+var noptrbss struct{}
var enoptrbss struct{}
// SetFinalizer sets the finalizer associated with x to f.
@@ -553,8 +555,13 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
// func main() {
// runtime.SetFinalizer(Foo, nil)
// }
- // The segments are, in order: text, rodata, noptrdata, data, bss, noptrbss.
- if uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrbss)) {
+ // The relevant segments are: noptrdata, data, bss, noptrbss.
+ // We cannot assume they are in any order or even contiguous,
+ // due to external linking.
+ if uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrdata)) ||
+ uintptr(unsafe.Pointer(&data)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&edata)) ||
+ uintptr(unsafe.Pointer(&bss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&ebss)) ||
+ uintptr(unsafe.Pointer(&noptrbss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrbss)) {
return
}
gothrow("runtime.SetFinalizer: pointer not in allocated block")
diff --git a/src/runtime/mgc0.go b/src/runtime/mgc0.go
index 6d4ae61c1..38406f33a 100644
--- a/src/runtime/mgc0.go
+++ b/src/runtime/mgc0.go
@@ -51,10 +51,26 @@ func clearpools() {
if c := p.mcache; c != nil {
c.tiny = nil
c.tinysize = 0
+
+ // disconnect cached list before dropping it on the floor,
+ // so that a dangling ref to one entry does not pin all of them.
+ var sg, sgnext *sudog
+ for sg = c.sudogcache; sg != nil; sg = sgnext {
+ sgnext = sg.next
+ sg.next = nil
+ }
c.sudogcache = nil
}
+
// clear defer pools
for i := range p.deferpool {
+ // disconnect cached list before dropping it on the floor,
+ // so that a dangling ref to one entry does not pin all of them.
+ var d, dlink *_defer
+ for d = p.deferpool[i]; d != nil; d = dlink {
+ dlink = d.link
+ d.link = nil
+ }
p.deferpool[i] = nil
}
}
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index 05ecb3d9e..50920afe8 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -165,6 +165,7 @@ func acquireSudog() *sudog {
gothrow("acquireSudog: found s.elem != nil in cache")
}
c.sudogcache = s.next
+ s.next = nil
return s
}
@@ -190,6 +191,15 @@ func releaseSudog(s *sudog) {
if s.selectdone != nil {
gothrow("runtime: sudog with non-nil selectdone")
}
+ if s.next != nil {
+ gothrow("runtime: sudog with non-nil next")
+ }
+ if s.prev != nil {
+ gothrow("runtime: sudog with non-nil prev")
+ }
+ if s.waitlink != nil {
+ gothrow("runtime: sudog with non-nil waitlink")
+ }
gp := getg()
if gp.param != nil {
gothrow("runtime: releaseSudog with non-nil gp.param")
diff --git a/src/runtime/race/race_unix_test.go b/src/runtime/race/race_unix_test.go
new file mode 100644
index 000000000..84f0acece
--- /dev/null
+++ b/src/runtime/race/race_unix_test.go
@@ -0,0 +1,30 @@
+// Copyright 2014 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.
+
+// +build race
+// +build darwin freebsd linux
+
+package race_test
+
+import (
+ "sync/atomic"
+ "syscall"
+ "testing"
+ "unsafe"
+)
+
+// Test that race detector does not crash when accessing non-Go allocated memory (issue 9136).
+func TestNonGoMemory(t *testing.T) {
+ data, err := syscall.Mmap(-1, 0, 4096, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE)
+ if err != nil {
+ t.Fatalf("failed to mmap memory: %v", err)
+ }
+ p := (*uint32)(unsafe.Pointer(&data[0]))
+ atomic.AddUint32(p, 1)
+ (*p)++
+ if *p != 2 {
+ t.Fatalf("data[0] = %v, expect 2", *p)
+ }
+ syscall.Munmap(data)
+}
diff --git a/src/runtime/race1.go b/src/runtime/race1.go
index 4c580429c..2ec2bee65 100644
--- a/src/runtime/race1.go
+++ b/src/runtime/race1.go
@@ -81,6 +81,10 @@ var __tsan_go_ignore_sync_end byte
//go:cgo_import_static __tsan_go_atomic32_compare_exchange
//go:cgo_import_static __tsan_go_atomic64_compare_exchange
+// start/end of global data (data+bss).
+var racedatastart uintptr
+var racedataend uintptr
+
// start/end of heap for race_amd64.s
var racearenastart uintptr
var racearenaend uintptr
@@ -99,7 +103,7 @@ func racecall(*byte, uintptr, uintptr, uintptr, uintptr)
//go:nosplit
func isvalidaddr(addr unsafe.Pointer) bool {
return racearenastart <= uintptr(addr) && uintptr(addr) < racearenaend ||
- uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(addr) && uintptr(addr) < uintptr(unsafe.Pointer(&enoptrbss))
+ racedatastart <= uintptr(addr) && uintptr(addr) < racedataend
}
//go:nosplit
@@ -113,9 +117,36 @@ func raceinit() uintptr {
racecall(&__tsan_init, uintptr(unsafe.Pointer(&racectx)), funcPC(racesymbolizethunk), 0, 0)
// Round data segment to page boundaries, because it's used in mmap().
- start := uintptr(unsafe.Pointer(&noptrdata)) &^ (_PageSize - 1)
- size := round(uintptr(unsafe.Pointer(&enoptrbss))-start, _PageSize)
+ start := ^uintptr(0)
+ end := uintptr(0)
+ if start > uintptr(unsafe.Pointer(&noptrdata)) {
+ start = uintptr(unsafe.Pointer(&noptrdata))
+ }
+ if start > uintptr(unsafe.Pointer(&data)) {
+ start = uintptr(unsafe.Pointer(&data))
+ }
+ if start > uintptr(unsafe.Pointer(&noptrbss)) {
+ start = uintptr(unsafe.Pointer(&noptrbss))
+ }
+ if start > uintptr(unsafe.Pointer(&bss)) {
+ start = uintptr(unsafe.Pointer(&bss))
+ }
+ if end < uintptr(unsafe.Pointer(&enoptrdata)) {
+ end = uintptr(unsafe.Pointer(&enoptrdata))
+ }
+ if end < uintptr(unsafe.Pointer(&edata)) {
+ end = uintptr(unsafe.Pointer(&edata))
+ }
+ if end < uintptr(unsafe.Pointer(&enoptrbss)) {
+ end = uintptr(unsafe.Pointer(&enoptrbss))
+ }
+ if end < uintptr(unsafe.Pointer(&ebss)) {
+ end = uintptr(unsafe.Pointer(&ebss))
+ }
+ size := round(end-start, _PageSize)
racecall(&__tsan_map_shadow, start, size, 0, 0)
+ racedatastart = start
+ racedataend = start + size
return racectx
}
diff --git a/src/runtime/race_amd64.s b/src/runtime/race_amd64.s
index a7f44870a..d54d9798f 100644
--- a/src/runtime/race_amd64.s
+++ b/src/runtime/race_amd64.s
@@ -139,17 +139,15 @@ TEXT racecalladdr<>(SB), NOSPLIT, $0-0
get_tls(R12)
MOVQ g(R12), R14
MOVQ g_racectx(R14), RARG0 // goroutine context
- // Check that addr is within [arenastart, arenaend) or within [noptrdata, enoptrbss).
+ // Check that addr is within [arenastart, arenaend) or within [racedatastart, racedataend).
CMPQ RARG1, runtime·racearenastart(SB)
JB data
CMPQ RARG1, runtime·racearenaend(SB)
JB call
data:
- MOVQ $runtime·noptrdata(SB), R13
- CMPQ RARG1, R13
+ CMPQ RARG1, runtime·racedatastart(SB)
JB ret
- MOVQ $runtime·enoptrbss(SB), R13
- CMPQ RARG1, R13
+ CMPQ RARG1, runtime·racedataend(SB)
JAE ret
call:
MOVQ AX, AX // w/o this 6a miscompiles this function
@@ -167,6 +165,7 @@ TEXT runtime·racefuncenter(SB), NOSPLIT, $0-8
MOVQ callpc+0(FP), RARG1
// void __tsan_func_enter(ThreadState *thr, void *pc);
MOVQ $__tsan_func_enter(SB), AX
+ // racecall<> preserves R15
CALL racecall<>(SB)
MOVQ R15, DX // restore function entry context
RET
@@ -307,13 +306,45 @@ TEXT sync∕atomic·CompareAndSwapPointer(SB), NOSPLIT, $0-0
TEXT racecallatomic<>(SB), NOSPLIT, $0-0
// Trigger SIGSEGV early.
MOVQ 16(SP), R12
- MOVL (R12), R12
+ MOVL (R12), R13
+ // Check that addr is within [arenastart, arenaend) or within [racedatastart, racedataend).
+ CMPQ R12, runtime·racearenastart(SB)
+ JB racecallatomic_data
+ CMPQ R12, runtime·racearenaend(SB)
+ JB racecallatomic_ok
+racecallatomic_data:
+ CMPQ R12, runtime·racedatastart(SB)
+ JB racecallatomic_ignore
+ CMPQ R12, runtime·racedataend(SB)
+ JAE racecallatomic_ignore
+racecallatomic_ok:
+ // Addr is within the good range, call the atomic function.
get_tls(R12)
MOVQ g(R12), R14
MOVQ g_racectx(R14), RARG0 // goroutine context
MOVQ 8(SP), RARG1 // caller pc
MOVQ (SP), RARG2 // pc
LEAQ 16(SP), RARG3 // arguments
+ JMP racecall<>(SB) // does not return
+racecallatomic_ignore:
+ // Addr is outside the good range.
+ // Call __tsan_go_ignore_sync_begin to ignore synchronization during the atomic op.
+ // An attempt to synchronize on the address would cause crash.
+ MOVQ AX, R15 // remember the original function
+ MOVQ $__tsan_go_ignore_sync_begin(SB), AX
+ MOVQ g(R12), R14
+ MOVQ g_racectx(R14), RARG0 // goroutine context
+ CALL racecall<>(SB)
+ MOVQ R15, AX // restore the original function
+ // Call the atomic function.
+ MOVQ g_racectx(R14), RARG0 // goroutine context
+ MOVQ 8(SP), RARG1 // caller pc
+ MOVQ (SP), RARG2 // pc
+ LEAQ 16(SP), RARG3 // arguments
+ CALL racecall<>(SB)
+ // Call __tsan_go_ignore_sync_end.
+ MOVQ $__tsan_go_ignore_sync_end(SB), AX
+ MOVQ g_racectx(R14), RARG0 // goroutine context
JMP racecall<>(SB)
// void runtime·racecall(void(*f)(...), ...)
diff --git a/src/runtime/select.go b/src/runtime/select.go
index fe9178763..6717b9395 100644
--- a/src/runtime/select.go
+++ b/src/runtime/select.go
@@ -404,6 +404,7 @@ loop:
}
}
sgnext = sglist.waitlink
+ sglist.waitlink = nil
releaseSudog(sglist)
sglist = sgnext
}
@@ -641,6 +642,7 @@ func (q *waitq) dequeueSudoG(s *sudog) {
if q.last == sgp {
q.last = prevsgp
}
+ s.next = nil
return
}
l = &sgp.next
diff --git a/src/runtime/sema.go b/src/runtime/sema.go
index d2a028c01..26dbd30ea 100644
--- a/src/runtime/sema.go
+++ b/src/runtime/sema.go
@@ -201,6 +201,7 @@ func syncsemacquire(s *syncSema) {
}
unlock(&s.lock)
if wake != nil {
+ wake.next = nil
goready(wake.g)
}
} else {
@@ -242,6 +243,7 @@ func syncsemrelease(s *syncSema, n uint32) {
if wake.releasetime != 0 {
wake.releasetime = cputicks()
}
+ wake.next = nil
goready(wake.g)
n--
}
diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go
index 217307a1e..aa7577cf9 100644
--- a/src/runtime/stubs.go
+++ b/src/runtime/stubs.go
@@ -154,7 +154,7 @@ func setcallerpc(argp unsafe.Pointer, pc uintptr)
//
// func f(arg1, arg2, arg3 int) {
// pc := getcallerpc(unsafe.Pointer(&arg1))
-// sp := getcallerpc(unsafe.Pointer(&arg2))
+// sp := getcallersp(unsafe.Pointer(&arg1))
// }
//
// These two lines find the PC and SP immediately following
diff --git a/src/syscall/exec_bsd.go b/src/syscall/exec_bsd.go
index 7c2c1f707..ff78f197f 100644
--- a/src/syscall/exec_bsd.go
+++ b/src/syscall/exec_bsd.go
@@ -19,8 +19,6 @@ type SysProcAttr struct {
Setpgid bool // Set process group ID to new pid (SYSV setpgrp)
Setctty bool // Set controlling terminal to fd 0
Noctty bool // Detach fd 0 from controlling terminal
- Foreground bool // Set foreground process group to child's pid. (Implies Setpgid. Stdin should be a TTY)
- Joinpgrp int // If != 0, child's process group ID. (Setpgid must not be set)
}
// Implemented in runtime package.
@@ -81,22 +79,7 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
if r1 != 0 {
// parent; return PID
runtime_AfterFork()
- pid = int(r1)
-
- if sys.Joinpgrp != 0 {
- // Place the child in the specified process group.
- RawSyscall(SYS_SETPGID, r1, uintptr(sys.Joinpgrp), 0)
- } else if sys.Foreground || sys.Setpgid {
- // Place the child in a new process group.
- RawSyscall(SYS_SETPGID, 0, 0, 0)
-
- if sys.Foreground {
- // Set new foreground process group.
- RawSyscall(SYS_IOCTL, uintptr(Stdin), TIOCSPGRP, uintptr(unsafe.Pointer(&pid)))
- }
- }
-
- return pid, 0
+ return int(r1), 0
}
// Fork succeeded, now in child.
@@ -118,30 +101,11 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
}
// Set process group
- if sys.Joinpgrp != 0 {
- // Place the child in the specified process group.
- _, _, err1 = RawSyscall(SYS_SETPGID, r1, uintptr(sys.Joinpgrp), 0)
- if err1 != 0 {
- goto childerror
- }
- } else if sys.Foreground || sys.Setpgid {
- // Place the child in a new process group.
+ if sys.Setpgid {
_, _, err1 = RawSyscall(SYS_SETPGID, 0, 0, 0)
if err1 != 0 {
goto childerror
}
-
- if sys.Foreground {
- r1, _, _ = RawSyscall(SYS_GETPID, 0, 0, 0)
-
- pid := int(r1)
-
- // Set new foreground process group.
- _, _, err1 = RawSyscall(SYS_IOCTL, uintptr(Stdin), TIOCSPGRP, uintptr(unsafe.Pointer(&pid)))
- if err1 != 0 {
- goto childerror
- }
- }
}
// Chroot
diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go
index 72e2f0b69..042c20a46 100644
--- a/src/syscall/exec_linux.go
+++ b/src/syscall/exec_linux.go
@@ -29,8 +29,6 @@ type SysProcAttr struct {
Ctty int // Controlling TTY fd (Linux only)
Pdeathsig Signal // Signal that the process will get when its parent dies (Linux only)
Cloneflags uintptr // Flags for clone calls (Linux only)
- Foreground bool // Set foreground process group to child's pid. (Implies Setpgid. Stdin should be a TTY)
- Joinpgrp int // If != 0, child's process group ID. (Setpgid must not be set)
UidMappings []SysProcIDMap // User ID mappings for user namespaces.
GidMappings []SysProcIDMap // Group ID mappings for user namespaces.
}
@@ -105,19 +103,6 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
Close(p[1])
}
- if sys.Joinpgrp != 0 {
- // Place the child in the specified process group.
- RawSyscall(SYS_SETPGID, r1, uintptr(sys.Joinpgrp), 0)
- } else if sys.Foreground || sys.Setpgid {
- // Place the child in a new process group.
- RawSyscall(SYS_SETPGID, 0, 0, 0)
-
- if sys.Foreground {
- // Set new foreground process group.
- RawSyscall(SYS_IOCTL, uintptr(Stdin), TIOCSPGRP, uintptr(unsafe.Pointer(&pid)))
- }
- }
-
return pid, 0
}
@@ -179,30 +164,11 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
}
// Set process group
- if sys.Joinpgrp != 0 {
- // Place the child in the specified process group.
- _, _, err1 = RawSyscall(SYS_SETPGID, r1, uintptr(sys.Joinpgrp), 0)
- if err1 != 0 {
- goto childerror
- }
- } else if sys.Foreground || sys.Setpgid {
- // Place the child in a new process group.
+ if sys.Setpgid {
_, _, err1 = RawSyscall(SYS_SETPGID, 0, 0, 0)
if err1 != 0 {
goto childerror
}
-
- if sys.Foreground {
- r1, _, _ = RawSyscall(SYS_GETPID, 0, 0, 0)
-
- pid := int(r1)
-
- // Set new foreground process group.
- _, _, err1 = RawSyscall(SYS_IOCTL, uintptr(Stdin), TIOCSPGRP, uintptr(unsafe.Pointer(&pid)))
- if err1 != 0 {
- goto childerror
- }
- }
}
// Chroot