diff options
author | Ian Lance Taylor <iant@golang.org> | 2020-02-05 14:33:27 -0800 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2020-02-15 09:14:10 -0800 |
commit | 0b3c2eed35d608d6541ecf004a9576b4eae0b4ef (patch) | |
tree | c92c05d53eb054d8085d069800f4e9b586fef5a3 /libgo/go/runtime/memmove_test.go | |
parent | 17edb3310d8ce9d5f6c9e53f6c1f7d611c2a5a41 (diff) | |
download | gcc-0b3c2eed35d608d6541ecf004a9576b4eae0b4ef.zip gcc-0b3c2eed35d608d6541ecf004a9576b4eae0b4ef.tar.gz gcc-0b3c2eed35d608d6541ecf004a9576b4eae0b4ef.tar.bz2 |
libgo: update to Go1.14rc1 release
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/218017
Diffstat (limited to 'libgo/go/runtime/memmove_test.go')
-rw-r--r-- | libgo/go/runtime/memmove_test.go | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/libgo/go/runtime/memmove_test.go b/libgo/go/runtime/memmove_test.go index 0b2e191..396c130 100644 --- a/libgo/go/runtime/memmove_test.go +++ b/libgo/go/runtime/memmove_test.go @@ -11,7 +11,9 @@ import ( "internal/race" "internal/testenv" . "runtime" + "sync/atomic" "testing" + "unsafe" ) func TestMemmove(t *testing.T) { @@ -206,6 +208,71 @@ func cmpb(a, b []byte) int { return l } +// Ensure that memmove writes pointers atomically, so the GC won't +// observe a partially updated pointer. +func TestMemmoveAtomicity(t *testing.T) { + if race.Enabled { + t.Skip("skip under the race detector -- this test is intentionally racy") + } + + var x int + + for _, backward := range []bool{true, false} { + for _, n := range []int{3, 4, 5, 6, 7, 8, 9, 10, 15, 25, 49} { + n := n + + // test copying [N]*int. + sz := uintptr(n * PtrSize) + name := fmt.Sprint(sz) + if backward { + name += "-backward" + } else { + name += "-forward" + } + t.Run(name, func(t *testing.T) { + // Use overlapping src and dst to force forward/backward copy. + var s [100]*int + src := s[n-1 : 2*n-1] + dst := s[:n] + if backward { + src, dst = dst, src + } + for i := range src { + src[i] = &x + } + for i := range dst { + dst[i] = nil + } + + var ready uint32 + go func() { + sp := unsafe.Pointer(&src[0]) + dp := unsafe.Pointer(&dst[0]) + atomic.StoreUint32(&ready, 1) + for i := 0; i < 10000; i++ { + Memmove(dp, sp, sz) + MemclrNoHeapPointers(dp, sz) + } + atomic.StoreUint32(&ready, 2) + }() + + for atomic.LoadUint32(&ready) == 0 { + Gosched() + } + + for atomic.LoadUint32(&ready) != 2 { + for i := range dst { + p := dst[i] + if p != nil && p != &x { + t.Fatalf("got partially updated pointer %p at dst[%d], want either nil or %p", p, i, &x) + } + } + } + }) + } + } +} + func benchmarkSizes(b *testing.B, sizes []int, fn func(b *testing.B, n int)) { for _, n := range sizes { b.Run(fmt.Sprint(n), func(b *testing.B) { |