aboutsummaryrefslogtreecommitdiff
path: root/src/internal
diff options
context:
space:
mode:
Diffstat (limited to 'src/internal')
-rw-r--r--src/internal/abi/abi.go28
-rw-r--r--src/internal/buildcfg/cfg.go16
-rw-r--r--src/internal/buildcfg/cfg_test.go25
-rw-r--r--src/internal/cfg/cfg.go1
-rw-r--r--src/internal/poll/splice_linux_test.go53
5 files changed, 85 insertions, 38 deletions
diff --git a/src/internal/abi/abi.go b/src/internal/abi/abi.go
index eadff248d9..46dc593bd7 100644
--- a/src/internal/abi/abi.go
+++ b/src/internal/abi/abi.go
@@ -19,6 +19,14 @@ import (
// when it may not be safe to keep them only in the integer
// register space otherwise.
type RegArgs struct {
+ // Values in these slots should be precisely the bit-by-bit
+ // representation of how they would appear in a register.
+ //
+ // This means that on big endian arches, integer values should
+ // be in the top bits of the slot. Floats are usually just
+ // directly represented, but some architectures treat narrow
+ // width floating point values specially (e.g. they're promoted
+ // first, or they need to be NaN-boxed).
Ints [IntArgRegs]uintptr // untyped integer registers
Floats [FloatArgRegs]uint64 // untyped float registers
@@ -56,26 +64,6 @@ func (r *RegArgs) IntRegArgAddr(reg int, argSize uintptr) unsafe.Pointer {
return unsafe.Pointer(uintptr(unsafe.Pointer(&r.Ints[reg])) + offset)
}
-// FloatRegArgAddr returns a pointer inside of r.Floats[reg] that is appropriately
-// offset for an argument of size argSize.
-//
-// argSize must be non-zero, fit in a register, and a power-of-two.
-//
-// This method is a helper for dealing with the endianness of different CPU
-// architectures, since sub-word-sized arguments in big endian architectures
-// need to be "aligned" to the upper edge of the register to be interpreted
-// by the CPU correctly.
-func (r *RegArgs) FloatRegArgAddr(reg int, argSize uintptr) unsafe.Pointer {
- if argSize > EffectiveFloatRegSize || argSize == 0 || argSize&(argSize-1) != 0 {
- panic("invalid argSize")
- }
- offset := uintptr(0)
- if goarch.BigEndian {
- offset = EffectiveFloatRegSize - argSize
- }
- return unsafe.Pointer(uintptr(unsafe.Pointer(&r.Floats[reg])) + offset)
-}
-
// IntArgRegBitmap is a bitmap large enough to hold one bit per
// integer argument/return register.
type IntArgRegBitmap [(IntArgRegs + 7) / 8]uint8
diff --git a/src/internal/buildcfg/cfg.go b/src/internal/buildcfg/cfg.go
index 9fe7f211fb..68c10a2824 100644
--- a/src/internal/buildcfg/cfg.go
+++ b/src/internal/buildcfg/cfg.go
@@ -25,6 +25,7 @@ var (
GOARCH = envOr("GOARCH", defaultGOARCH)
GOOS = envOr("GOOS", defaultGOOS)
GO386 = envOr("GO386", defaultGO386)
+ GOAMD64 = goamd64()
GOARM = goarm()
GOMIPS = gomips()
GOMIPS64 = gomips64()
@@ -52,6 +53,21 @@ func envOr(key, value string) string {
return value
}
+func goamd64() int {
+ switch v := envOr("GOAMD64", defaultGOAMD64); v {
+ case "v1":
+ return 1
+ case "v2":
+ return 2
+ case "v3":
+ return 3
+ case "v4":
+ return 4
+ }
+ Error = fmt.Errorf("invalid GOAMD64: must be v1, v2, v3, v4")
+ return int(defaultGOAMD64[len("v")] - '0')
+}
+
func goarm() int {
def := defaultGOARM
if GOOS == "android" && GOARCH == "arm" {
diff --git a/src/internal/buildcfg/cfg_test.go b/src/internal/buildcfg/cfg_test.go
new file mode 100644
index 0000000000..9180441c28
--- /dev/null
+++ b/src/internal/buildcfg/cfg_test.go
@@ -0,0 +1,25 @@
+// Copyright 2021 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 buildcfg
+
+import (
+ "os"
+ "testing"
+)
+
+func TestConfigFlags(t *testing.T) {
+ os.Setenv("GOAMD64", "v1")
+ if goamd64() != 1 {
+ t.Errorf("Wrong parsing of GOAMD64=v1")
+ }
+ os.Setenv("GOAMD64", "v4")
+ if goamd64() != 4 {
+ t.Errorf("Wrong parsing of GOAMD64=v4")
+ }
+ os.Setenv("GOAMD64", "1")
+ if goamd64() != 1 {
+ t.Errorf("Wrong parsing of GOAMD64=1")
+ }
+}
diff --git a/src/internal/cfg/cfg.go b/src/internal/cfg/cfg.go
index 815994b679..4cb3fbd4f3 100644
--- a/src/internal/cfg/cfg.go
+++ b/src/internal/cfg/cfg.go
@@ -33,6 +33,7 @@ const KnownEnv = `
GCCGO
GO111MODULE
GO386
+ GOAMD64
GOARCH
GOARM
GOBIN
diff --git a/src/internal/poll/splice_linux_test.go b/src/internal/poll/splice_linux_test.go
index 280468c7e7..8c4363886e 100644
--- a/src/internal/poll/splice_linux_test.go
+++ b/src/internal/poll/splice_linux_test.go
@@ -6,40 +6,48 @@ package poll_test
import (
"internal/poll"
- "internal/syscall/unix"
"runtime"
- "syscall"
+ "sync"
+ "sync/atomic"
"testing"
"time"
)
-// checkPipes returns true if all pipes are closed properly, false otherwise.
-func checkPipes(fds []int) bool {
- for _, fd := range fds {
- // Check if each pipe fd has been closed.
- _, _, errno := syscall.Syscall(unix.FcntlSyscall, uintptr(fd), syscall.F_GETPIPE_SZ, 0)
- if errno == 0 {
- return false
+var closeHook atomic.Value // func(fd int)
+
+func init() {
+ closeFunc := poll.CloseFunc
+ poll.CloseFunc = func(fd int) (err error) {
+ if v := closeHook.Load(); v != nil {
+ if hook := v.(func(int)); hook != nil {
+ hook(fd)
+ }
}
+ return closeFunc(fd)
}
- return true
}
func TestSplicePipePool(t *testing.T) {
const N = 64
var (
- p *poll.SplicePipe
- ps []*poll.SplicePipe
- fds []int
- err error
+ p *poll.SplicePipe
+ ps []*poll.SplicePipe
+ allFDs []int
+ pendingFDs sync.Map // fd → struct{}{}
+ err error
)
+
+ closeHook.Store(func(fd int) { pendingFDs.Delete(fd) })
+ t.Cleanup(func() { closeHook.Store((func(int))(nil)) })
+
for i := 0; i < N; i++ {
p, _, err = poll.GetPipe()
if err != nil {
- t.Skip("failed to create pipe, skip this test")
+ t.Skipf("failed to create pipe due to error(%v), skip this test", err)
}
_, pwfd := poll.GetPipeFds(p)
- fds = append(fds, pwfd)
+ allFDs = append(allFDs, pwfd)
+ pendingFDs.Store(pwfd, struct{}{})
ps = append(ps, p)
}
for _, p = range ps {
@@ -62,12 +70,21 @@ func TestSplicePipePool(t *testing.T) {
for {
runtime.GC()
time.Sleep(10 * time.Millisecond)
- if checkPipes(fds) {
+
+ // Detect whether all pipes are closed properly.
+ var leakedFDs []int
+ pendingFDs.Range(func(k, v interface{}) bool {
+ leakedFDs = append(leakedFDs, k.(int))
+ return true
+ })
+ if len(leakedFDs) == 0 {
break
}
+
select {
case <-expiredTime.C:
- t.Fatal("at least one pipe is still open")
+ t.Logf("all descriptors: %v", allFDs)
+ t.Fatalf("leaked descriptors: %v", leakedFDs)
default:
}
}