aboutsummaryrefslogtreecommitdiff
path: root/src/internal
diff options
context:
space:
mode:
Diffstat (limited to 'src/internal')
-rw-r--r--src/internal/bytealg/bytealg.go4
-rw-r--r--src/internal/bytealg/count_generic.go2
-rw-r--r--src/internal/bytealg/count_native.go2
-rw-r--r--src/internal/bytealg/count_riscv64.s44
-rw-r--r--src/internal/bytealg/equal_mips64x.s72
-rw-r--r--src/internal/bytealg/index_generic.go38
-rw-r--r--src/internal/cfg/cfg.go1
-rw-r--r--src/internal/cpu/cpu.go37
-rw-r--r--src/internal/cpu/cpu.s6
-rw-r--r--src/internal/cpu/cpu_arm64.go88
-rw-r--r--src/internal/cpu/cpu_arm64.s18
-rw-r--r--src/internal/cpu/cpu_arm64_android.go11
-rw-r--r--src/internal/cpu/cpu_arm64_darwin.go34
-rw-r--r--src/internal/cpu/cpu_arm64_freebsd.go45
-rw-r--r--src/internal/cpu/cpu_arm64_hwcap.go63
-rw-r--r--src/internal/cpu/cpu_arm64_linux.go13
-rw-r--r--src/internal/cpu/cpu_arm64_other.go17
-rw-r--r--src/internal/cpu/cpu_mips.go3
-rw-r--r--src/internal/cpu/cpu_mipsle.go3
-rw-r--r--src/internal/cpu/cpu_no_init.go18
-rw-r--r--src/internal/cpu/cpu_no_name.go19
-rw-r--r--src/internal/cpu/cpu_ppc64x.go27
-rw-r--r--src/internal/cpu/cpu_ppc64x_aix.go21
-rw-r--r--src/internal/cpu/cpu_ppc64x_linux.go29
-rw-r--r--src/internal/cpu/cpu_riscv64.go3
-rw-r--r--src/internal/cpu/cpu_s390x.go15
-rw-r--r--src/internal/cpu/cpu_s390x_test.go4
-rw-r--r--src/internal/cpu/cpu_test.go8
-rw-r--r--src/internal/cpu/cpu_wasm.go3
-rw-r--r--src/internal/cpu/cpu_x86.go60
-rw-r--r--src/internal/fmtsort/sort.go2
-rw-r--r--src/internal/fmtsort/sort_test.go22
-rw-r--r--src/internal/obscuretestdata/obscuretestdata.go5
-rw-r--r--src/internal/poll/copy_file_range_linux.go55
-rw-r--r--src/internal/poll/error_test.go3
-rw-r--r--src/internal/poll/fd_fsync_darwin.go7
-rw-r--r--src/internal/poll/fd_posix.go11
-rw-r--r--src/internal/poll/fd_unix.go18
-rw-r--r--src/internal/poll/fd_windows.go27
-rw-r--r--src/internal/poll/fd_writev_illumos.go16
-rw-r--r--src/internal/poll/hook_cloexec.go2
-rw-r--r--src/internal/poll/iovec_illumos.go16
-rw-r--r--src/internal/poll/iovec_unix.go13
-rw-r--r--src/internal/poll/read_test.go5
-rw-r--r--src/internal/poll/sock_cloexec.go2
-rw-r--r--src/internal/poll/sys_cloexec.go2
-rw-r--r--src/internal/poll/writev.go4
-rw-r--r--src/internal/profile/profile.go5
-rw-r--r--src/internal/reflectlite/reflect_mirror_test.go3
-rw-r--r--src/internal/reflectlite/type.go38
-rw-r--r--src/internal/reflectlite/value.go5
-rw-r--r--src/internal/syscall/unix/pipe2_illumos.go34
-rw-r--r--src/internal/syscall/unix/writev_illumos.go30
-rw-r--r--src/internal/syscall/windows/mksyscall.go2
-rw-r--r--src/internal/syscall/windows/registry/key.go17
-rw-r--r--src/internal/syscall/windows/registry/mksyscall.go2
-rw-r--r--src/internal/syscall/windows/registry/registry_test.go6
-rw-r--r--src/internal/syscall/windows/registry/value.go13
-rw-r--r--src/internal/syscall/windows/registry/zsyscall_windows.go25
-rw-r--r--src/internal/syscall/windows/syscall_windows.go9
-rw-r--r--src/internal/syscall/windows/zsyscall_windows.go352
-rw-r--r--src/internal/sysinfo/sysinfo.go31
-rw-r--r--src/internal/testenv/testenv.go64
-rw-r--r--src/internal/testenv/testenv_windows.go3
-rw-r--r--src/internal/trace/gc_test.go6
-rw-r--r--src/internal/trace/parser_test.go9
66 files changed, 1050 insertions, 522 deletions
diff --git a/src/internal/bytealg/bytealg.go b/src/internal/bytealg/bytealg.go
index 6fd9308369..b30c234436 100644
--- a/src/internal/bytealg/bytealg.go
+++ b/src/internal/bytealg/bytealg.go
@@ -99,7 +99,7 @@ func HashStrRev(sep string) (uint32, uint32) {
}
// IndexRabinKarpBytes uses the Rabin-Karp search algorithm to return the index of the
-// first occurence of substr in s, or -1 if not present.
+// first occurrence of substr in s, or -1 if not present.
func IndexRabinKarpBytes(s, sep []byte) int {
// Rabin-Karp search
hashsep, pow := HashStrBytes(sep)
@@ -124,7 +124,7 @@ func IndexRabinKarpBytes(s, sep []byte) int {
}
// IndexRabinKarp uses the Rabin-Karp search algorithm to return the index of the
-// first occurence of substr in s, or -1 if not present.
+// first occurrence of substr in s, or -1 if not present.
func IndexRabinKarp(s, substr string) int {
// Rabin-Karp search
hashss, pow := HashStr(substr)
diff --git a/src/internal/bytealg/count_generic.go b/src/internal/bytealg/count_generic.go
index 7cc1d50312..5575e81ab8 100644
--- a/src/internal/bytealg/count_generic.go
+++ b/src/internal/bytealg/count_generic.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !amd64,!arm,!arm64,!ppc64le,!ppc64,!s390x
+// +build !amd64,!arm,!arm64,!ppc64le,!ppc64,!riscv64,!s390x
package bytealg
diff --git a/src/internal/bytealg/count_native.go b/src/internal/bytealg/count_native.go
index 0448fca9e8..b1ff1d265a 100644
--- a/src/internal/bytealg/count_native.go
+++ b/src/internal/bytealg/count_native.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build amd64 arm arm64 ppc64le ppc64 s390x
+// +build amd64 arm arm64 ppc64le ppc64 riscv64 s390x
package bytealg
diff --git a/src/internal/bytealg/count_riscv64.s b/src/internal/bytealg/count_riscv64.s
new file mode 100644
index 0000000000..3f4eb23286
--- /dev/null
+++ b/src/internal/bytealg/count_riscv64.s
@@ -0,0 +1,44 @@
+// Copyright 2020 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.
+
+#include "go_asm.h"
+#include "textflag.h"
+
+TEXT ·Count(SB),NOSPLIT,$0-40
+ MOV b_base+0(FP), A1
+ MOV b_len+8(FP), A2
+ MOVBU c+24(FP), A3 // byte to count
+ MOV ZERO, A4 // count
+ ADD A1, A2 // end
+
+loop:
+ BEQ A1, A2, done
+ MOVBU (A1), A5
+ ADD $1, A1
+ BNE A3, A5, loop
+ ADD $1, A4
+ JMP loop
+
+done:
+ MOV A4, ret+32(FP)
+ RET
+
+TEXT ·CountString(SB),NOSPLIT,$0-32
+ MOV s_base+0(FP), A1
+ MOV s_len+8(FP), A2
+ MOVBU c+16(FP), A3 // byte to count
+ MOV ZERO, A4 // count
+ ADD A1, A2 // end
+
+loop:
+ BEQ A1, A2, done
+ MOVBU (A1), A5
+ ADD $1, A1
+ BNE A3, A5, loop
+ ADD $1, A4
+ JMP loop
+
+done:
+ MOV A4, ret+24(FP)
+ RET
diff --git a/src/internal/bytealg/equal_mips64x.s b/src/internal/bytealg/equal_mips64x.s
index 58dc4303b4..641e3ff06c 100644
--- a/src/internal/bytealg/equal_mips64x.s
+++ b/src/internal/bytealg/equal_mips64x.s
@@ -16,18 +16,82 @@ TEXT runtime·memequal(SB),NOSPLIT|NOFRAME,$0-25
BEQ R1, R2, eq
MOVV size+16(FP), R3
ADDV R1, R3, R4
-loop:
- BNE R1, R4, test
+
+ // chunk size is 16
+ SGTU $16, R3, R8
+ BEQ R0, R8, chunk_entry
+
+byte_loop:
+ BNE R1, R4, byte_test
MOVV $1, R1
MOVB R1, ret+24(FP)
RET
-test:
+byte_test:
MOVBU (R1), R6
ADDV $1, R1
MOVBU (R2), R7
ADDV $1, R2
- BEQ R6, R7, loop
+ BEQ R6, R7, byte_loop
+ JMP not_eq
+
+chunk_entry:
+ // make sure both a and b are aligned
+ OR R1, R2, R9
+ AND $0x7, R9
+ BNE R0, R9, byte_loop
+ JMP chunk_loop_1
+
+chunk_loop:
+ // chunk size is 16
+ SGTU $16, R3, R8
+ BNE R0, R8, chunk_tail_8
+chunk_loop_1:
+ MOVV (R1), R6
+ MOVV (R2), R7
+ BNE R6, R7, not_eq
+ MOVV 8(R1), R12
+ MOVV 8(R2), R13
+ ADDV $16, R1
+ ADDV $16, R2
+ SUBV $16, R3
+ BEQ R12, R13, chunk_loop
+ JMP not_eq
+
+chunk_tail_8:
+ AND $8, R3, R14
+ BEQ R0, R14, chunk_tail_4
+ MOVV (R1), R6
+ MOVV (R2), R7
+ BNE R6, R7, not_eq
+ ADDV $8, R1
+ ADDV $8, R2
+
+chunk_tail_4:
+ AND $4, R3, R14
+ BEQ R0, R14, chunk_tail_2
+ MOVWU (R1), R6
+ MOVWU (R2), R7
+ BNE R6, R7, not_eq
+ ADDV $4, R1
+ ADDV $4, R2
+
+chunk_tail_2:
+ AND $2, R3, R14
+ BEQ R0, R14, chunk_tail_1
+ MOVHU (R1), R6
+ MOVHU (R2), R7
+ BNE R6, R7, not_eq
+ ADDV $2, R1
+ ADDV $2, R2
+
+chunk_tail_1:
+ AND $1, R3, R14
+ BEQ R0, R14, eq
+ MOVBU (R1), R6
+ MOVBU (R2), R7
+ BEQ R6, R7, eq
+not_eq:
MOVB R0, ret+24(FP)
RET
eq:
diff --git a/src/internal/bytealg/index_generic.go b/src/internal/bytealg/index_generic.go
index 83345f1013..98e859f925 100644
--- a/src/internal/bytealg/index_generic.go
+++ b/src/internal/bytealg/index_generic.go
@@ -16,42 +16,8 @@ func Index(a, b []byte) int {
// IndexString returns the index of the first instance of b in a, or -1 if b is not present in a.
// Requires 2 <= len(b) <= MaxLen.
-func IndexString(s, substr string) int {
- // This is a partial copy of strings.Index, here because bytes.IndexAny and bytes.LastIndexAny
- // call bytealg.IndexString. Some platforms have an optimized assembly version of this function.
- // This implementation is used for those that do not. Although the pure Go implementation here
- // works for the case of len(b) > MaxLen, we do not require that its assembly implementation also
- // supports the case of len(b) > MaxLen. And we do not guarantee that this function supports the
- // case of len(b) > MaxLen.
- n := len(substr)
- c0 := substr[0]
- c1 := substr[1]
- i := 0
- t := len(s) - n + 1
- fails := 0
- for i < t {
- if s[i] != c0 {
- o := IndexByteString(s[i:t], c0)
- if o < 0 {
- return -1
- }
- i += o
- }
- if s[i+1] == c1 && s[i:i+n] == substr {
- return i
- }
- i++
- fails++
- if fails >= 4+i>>4 && i < t {
- // See comment in src/bytes/bytes.go.
- j := IndexRabinKarp(s[i:], substr)
- if j < 0 {
- return -1
- }
- return i + j
- }
- }
- return -1
+func IndexString(a, b string) int {
+ panic("unimplemented")
}
// Cutover reports the number of failures of IndexByte we should tolerate
diff --git a/src/internal/cfg/cfg.go b/src/internal/cfg/cfg.go
index bdbe9df3e7..553021374d 100644
--- a/src/internal/cfg/cfg.go
+++ b/src/internal/cfg/cfg.go
@@ -58,6 +58,7 @@ const KnownEnv = `
GOSUMDB
GOTMPDIR
GOTOOLDIR
+ GOVCS
GOWASM
GO_EXTLINK_ENABLED
PKG_CONFIG
diff --git a/src/internal/cpu/cpu.go b/src/internal/cpu/cpu.go
index 2829945af0..dab5d068ef 100644
--- a/src/internal/cpu/cpu.go
+++ b/src/internal/cpu/cpu.go
@@ -56,32 +56,17 @@ var ARM struct {
// The booleans in ARM64 contain the correspondingly named cpu feature bit.
// The struct is padded to avoid false sharing.
var ARM64 struct {
- _ CacheLinePad
- HasFP bool
- HasASIMD bool
- HasEVTSTRM bool
- HasAES bool
- HasPMULL bool
- HasSHA1 bool
- HasSHA2 bool
- HasCRC32 bool
- HasATOMICS bool
- HasFPHP bool
- HasASIMDHP bool
- HasCPUID bool
- HasASIMDRDM bool
- HasJSCVT bool
- HasFCMA bool
- HasLRCPC bool
- HasDCPOP bool
- HasSHA3 bool
- HasSM3 bool
- HasSM4 bool
- HasASIMDDP bool
- HasSHA512 bool
- HasSVE bool
- HasASIMDFHM bool
- _ CacheLinePad
+ _ CacheLinePad
+ HasAES bool
+ HasPMULL bool
+ HasSHA1 bool
+ HasSHA2 bool
+ HasCRC32 bool
+ HasATOMICS bool
+ HasCPUID bool
+ IsNeoverseN1 bool
+ IsZeus bool
+ _ CacheLinePad
}
var MIPS64X struct {
diff --git a/src/internal/cpu/cpu.s b/src/internal/cpu/cpu.s
new file mode 100644
index 0000000000..3c770c132d
--- /dev/null
+++ b/src/internal/cpu/cpu.s
@@ -0,0 +1,6 @@
+// Copyright 2020 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.
+
+// This assembly file exists to allow internal/cpu to call
+// non-exported runtime functions that use "go:linkname". \ No newline at end of file
diff --git a/src/internal/cpu/cpu_arm64.go b/src/internal/cpu/cpu_arm64.go
index efdb3b9e33..f64d9e4dd3 100644
--- a/src/internal/cpu/cpu_arm64.go
+++ b/src/internal/cpu/cpu_arm64.go
@@ -6,97 +6,23 @@ package cpu
const CacheLinePadSize = 64
-// arm64 doesn't have a 'cpuid' equivalent, so we rely on HWCAP/HWCAP2.
-// These are initialized by archauxv and should not be changed after they are
-// initialized.
-var HWCap uint
-var HWCap2 uint
-
-// HWCAP/HWCAP2 bits. These are exposed by Linux.
-const (
- hwcap_FP = 1 << 0
- hwcap_ASIMD = 1 << 1
- hwcap_EVTSTRM = 1 << 2
- hwcap_AES = 1 << 3
- hwcap_PMULL = 1 << 4
- hwcap_SHA1 = 1 << 5
- hwcap_SHA2 = 1 << 6
- hwcap_CRC32 = 1 << 7
- hwcap_ATOMICS = 1 << 8
- hwcap_FPHP = 1 << 9
- hwcap_ASIMDHP = 1 << 10
- hwcap_CPUID = 1 << 11
- hwcap_ASIMDRDM = 1 << 12
- hwcap_JSCVT = 1 << 13
- hwcap_FCMA = 1 << 14
- hwcap_LRCPC = 1 << 15
- hwcap_DCPOP = 1 << 16
- hwcap_SHA3 = 1 << 17
- hwcap_SM3 = 1 << 18
- hwcap_SM4 = 1 << 19
- hwcap_ASIMDDP = 1 << 20
- hwcap_SHA512 = 1 << 21
- hwcap_SVE = 1 << 22
- hwcap_ASIMDFHM = 1 << 23
-)
-
func doinit() {
options = []option{
- {Name: "evtstrm", Feature: &ARM64.HasEVTSTRM},
{Name: "aes", Feature: &ARM64.HasAES},
{Name: "pmull", Feature: &ARM64.HasPMULL},
{Name: "sha1", Feature: &ARM64.HasSHA1},
{Name: "sha2", Feature: &ARM64.HasSHA2},
{Name: "crc32", Feature: &ARM64.HasCRC32},
{Name: "atomics", Feature: &ARM64.HasATOMICS},
- {Name: "fphp", Feature: &ARM64.HasFPHP},
- {Name: "asimdhp", Feature: &ARM64.HasASIMDHP},
{Name: "cpuid", Feature: &ARM64.HasCPUID},
- {Name: "asimdrdm", Feature: &ARM64.HasASIMDRDM},
- {Name: "jscvt", Feature: &ARM64.HasJSCVT},
- {Name: "fcma", Feature: &ARM64.HasFCMA},
- {Name: "lrcpc", Feature: &ARM64.HasLRCPC},
- {Name: "dcpop", Feature: &ARM64.HasDCPOP},
- {Name: "sha3", Feature: &ARM64.HasSHA3},
- {Name: "sm3", Feature: &ARM64.HasSM3},
- {Name: "sm4", Feature: &ARM64.HasSM4},
- {Name: "asimddp", Feature: &ARM64.HasASIMDDP},
- {Name: "sha512", Feature: &ARM64.HasSHA512},
- {Name: "sve", Feature: &ARM64.HasSVE},
- {Name: "asimdfhm", Feature: &ARM64.HasASIMDFHM},
-
- // These capabilities should always be enabled on arm64:
- {Name: "fp", Feature: &ARM64.HasFP, Required: true},
- {Name: "asimd", Feature: &ARM64.HasASIMD, Required: true},
+ {Name: "isNeoverseN1", Feature: &ARM64.IsNeoverseN1},
+ {Name: "isZeus", Feature: &ARM64.IsZeus},
}
- // HWCAP feature bits
- ARM64.HasFP = isSet(HWCap, hwcap_FP)
- ARM64.HasASIMD = isSet(HWCap, hwcap_ASIMD)
- ARM64.HasEVTSTRM = isSet(HWCap, hwcap_EVTSTRM)
- ARM64.HasAES = isSet(HWCap, hwcap_AES)
- ARM64.HasPMULL = isSet(HWCap, hwcap_PMULL)
- ARM64.HasSHA1 = isSet(HWCap, hwcap_SHA1)
- ARM64.HasSHA2 = isSet(HWCap, hwcap_SHA2)
- ARM64.HasCRC32 = isSet(HWCap, hwcap_CRC32)
- ARM64.HasATOMICS = isSet(HWCap, hwcap_ATOMICS)
- ARM64.HasFPHP = isSet(HWCap, hwcap_FPHP)
- ARM64.HasASIMDHP = isSet(HWCap, hwcap_ASIMDHP)
- ARM64.HasCPUID = isSet(HWCap, hwcap_CPUID)
- ARM64.HasASIMDRDM = isSet(HWCap, hwcap_ASIMDRDM)
- ARM64.HasJSCVT = isSet(HWCap, hwcap_JSCVT)
- ARM64.HasFCMA = isSet(HWCap, hwcap_FCMA)
- ARM64.HasLRCPC = isSet(HWCap, hwcap_LRCPC)
- ARM64.HasDCPOP = isSet(HWCap, hwcap_DCPOP)
- ARM64.HasSHA3 = isSet(HWCap, hwcap_SHA3)
- ARM64.HasSM3 = isSet(HWCap, hwcap_SM3)
- ARM64.HasSM4 = isSet(HWCap, hwcap_SM4)
- ARM64.HasASIMDDP = isSet(HWCap, hwcap_ASIMDDP)
- ARM64.HasSHA512 = isSet(HWCap, hwcap_SHA512)
- ARM64.HasSVE = isSet(HWCap, hwcap_SVE)
- ARM64.HasASIMDFHM = isSet(HWCap, hwcap_ASIMDFHM)
+ // arm64 uses different ways to detect CPU features at runtime depending on the operating system.
+ osInit()
}
-func isSet(hwc uint, value uint) bool {
- return hwc&value != 0
-}
+func getisar0() uint64
+
+func getMIDR() uint64
diff --git a/src/internal/cpu/cpu_arm64.s b/src/internal/cpu/cpu_arm64.s
new file mode 100644
index 0000000000..d6e7f44373
--- /dev/null
+++ b/src/internal/cpu/cpu_arm64.s
@@ -0,0 +1,18 @@
+// Copyright 2020 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.
+
+#include "textflag.h"
+
+// func getisar0() uint64
+TEXT ·getisar0(SB),NOSPLIT,$0
+ // get Instruction Set Attributes 0 into R0
+ MRS ID_AA64ISAR0_EL1, R0
+ MOVD R0, ret+0(FP)
+ RET
+
+// func getMIDR() uint64
+TEXT ·getMIDR(SB), NOSPLIT, $0-8
+ MRS MIDR_EL1, R0
+ MOVD R0, ret+0(FP)
+ RET
diff --git a/src/internal/cpu/cpu_arm64_android.go b/src/internal/cpu/cpu_arm64_android.go
new file mode 100644
index 0000000000..3c9e57c52a
--- /dev/null
+++ b/src/internal/cpu/cpu_arm64_android.go
@@ -0,0 +1,11 @@
+// Copyright 2020 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 arm64
+
+package cpu
+
+func osInit() {
+ hwcapInit("android")
+}
diff --git a/src/internal/cpu/cpu_arm64_darwin.go b/src/internal/cpu/cpu_arm64_darwin.go
new file mode 100644
index 0000000000..e094b97f97
--- /dev/null
+++ b/src/internal/cpu/cpu_arm64_darwin.go
@@ -0,0 +1,34 @@
+// Copyright 2020 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 arm64
+// +build darwin
+// +build !ios
+
+package cpu
+
+func osInit() {
+ ARM64.HasATOMICS = sysctlEnabled([]byte("hw.optional.armv8_1_atomics\x00"))
+ ARM64.HasCRC32 = sysctlEnabled([]byte("hw.optional.armv8_crc32\x00"))
+
+ // There are no hw.optional sysctl values for the below features on Mac OS 11.0
+ // to detect their supported state dynamically. Assume the CPU features that
+ // Apple Silicon M1 supports to be available as a minimal set of features
+ // to all Go programs running on darwin/arm64.
+ ARM64.HasAES = true
+ ARM64.HasPMULL = true
+ ARM64.HasSHA1 = true
+ ARM64.HasSHA2 = true
+}
+
+//go:noescape
+func getsysctlbyname(name []byte) (int32, int32)
+
+func sysctlEnabled(name []byte) bool {
+ ret, value := getsysctlbyname(name)
+ if ret < 0 {
+ return false
+ }
+ return value > 0
+}
diff --git a/src/internal/cpu/cpu_arm64_freebsd.go b/src/internal/cpu/cpu_arm64_freebsd.go
new file mode 100644
index 0000000000..9de2005c2e
--- /dev/null
+++ b/src/internal/cpu/cpu_arm64_freebsd.go
@@ -0,0 +1,45 @@
+// Copyright 2020 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 arm64
+
+package cpu
+
+func osInit() {
+ // Retrieve info from system register ID_AA64ISAR0_EL1.
+ isar0 := getisar0()
+
+ // ID_AA64ISAR0_EL1
+ switch extractBits(isar0, 4, 7) {
+ case 1:
+ ARM64.HasAES = true
+ case 2:
+ ARM64.HasAES = true
+ ARM64.HasPMULL = true
+ }
+
+ switch extractBits(isar0, 8, 11) {
+ case 1:
+ ARM64.HasSHA1 = true
+ }
+
+ switch extractBits(isar0, 12, 15) {
+ case 1, 2:
+ ARM64.HasSHA2 = true
+ }
+
+ switch extractBits(isar0, 16, 19) {
+ case 1:
+ ARM64.HasCRC32 = true
+ }
+
+ switch extractBits(isar0, 20, 23) {
+ case 2:
+ ARM64.HasATOMICS = true
+ }
+}
+
+func extractBits(data uint64, start, end uint) uint {
+ return (uint)(data>>start) & ((1 << (end - start + 1)) - 1)
+}
diff --git a/src/internal/cpu/cpu_arm64_hwcap.go b/src/internal/cpu/cpu_arm64_hwcap.go
new file mode 100644
index 0000000000..fdaf43e1a2
--- /dev/null
+++ b/src/internal/cpu/cpu_arm64_hwcap.go
@@ -0,0 +1,63 @@
+// Copyright 2020 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 arm64
+// +build linux
+
+package cpu
+
+// HWCap may be initialized by archauxv and
+// should not be changed after it was initialized.
+var HWCap uint
+
+// HWCAP bits. These are exposed by Linux.
+const (
+ hwcap_AES = 1 << 3
+ hwcap_PMULL = 1 << 4
+ hwcap_SHA1 = 1 << 5
+ hwcap_SHA2 = 1 << 6
+ hwcap_CRC32 = 1 << 7
+ hwcap_ATOMICS = 1 << 8
+ hwcap_CPUID = 1 << 11
+)
+
+func hwcapInit(os string) {
+ // HWCap was populated by the runtime from the auxiliary vector.
+ // Use HWCap information since reading aarch64 system registers
+ // is not supported in user space on older linux kernels.
+ ARM64.HasAES = isSet(HWCap, hwcap_AES)
+ ARM64.HasPMULL = isSet(HWCap, hwcap_PMULL)
+ ARM64.HasSHA1 = isSet(HWCap, hwcap_SHA1)
+ ARM64.HasSHA2 = isSet(HWCap, hwcap_SHA2)
+ ARM64.HasCRC32 = isSet(HWCap, hwcap_CRC32)
+ ARM64.HasCPUID = isSet(HWCap, hwcap_CPUID)
+
+ // The Samsung S9+ kernel reports support for atomics, but not all cores
+ // actually support them, resulting in SIGILL. See issue #28431.
+ // TODO(elias.naur): Only disable the optimization on bad chipsets on android.
+ ARM64.HasATOMICS = isSet(HWCap, hwcap_ATOMICS) && os != "android"
+
+ // Check to see if executing on a NeoverseN1 and in order to do that,
+ // check the AUXV for the CPUID bit. The getMIDR function executes an
+ // instruction which would normally be an illegal instruction, but it's
+ // trapped by the kernel, the value sanitized and then returned. Without
+ // the CPUID bit the kernel will not trap the instruction and the process
+ // will be terminated with SIGILL.
+ if ARM64.HasCPUID {
+ midr := getMIDR()
+ part_num := uint16((midr >> 4) & 0xfff)
+ implementor := byte((midr >> 24) & 0xff)
+
+ if implementor == 'A' && part_num == 0xd0c {
+ ARM64.IsNeoverseN1 = true
+ }
+ if implementor == 'A' && part_num == 0xd40 {
+ ARM64.IsZeus = true
+ }
+ }
+}
+
+func isSet(hwc uint, value uint) bool {
+ return hwc&value != 0
+}
diff --git a/src/internal/cpu/cpu_arm64_linux.go b/src/internal/cpu/cpu_arm64_linux.go
new file mode 100644
index 0000000000..2f7411ff1e
--- /dev/null
+++ b/src/internal/cpu/cpu_arm64_linux.go
@@ -0,0 +1,13 @@
+// Copyright 2020 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 arm64
+// +build linux
+// +build !android
+
+package cpu
+
+func osInit() {
+ hwcapInit("linux")
+}
diff --git a/src/internal/cpu/cpu_arm64_other.go b/src/internal/cpu/cpu_arm64_other.go
new file mode 100644
index 0000000000..f191db28d2
--- /dev/null
+++ b/src/internal/cpu/cpu_arm64_other.go
@@ -0,0 +1,17 @@
+// Copyright 2020 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 arm64
+// +build !linux
+// +build !freebsd
+// +build !android
+// +build !darwin ios
+
+package cpu
+
+func osInit() {
+ // Other operating systems do not support reading HWCap from auxiliary vector,
+ // reading privileged aarch64 system registers or sysctl in user space to detect
+ // CPU features at runtime.
+}
diff --git a/src/internal/cpu/cpu_mips.go b/src/internal/cpu/cpu_mips.go
index 0f821e44e7..14a9c975ea 100644
--- a/src/internal/cpu/cpu_mips.go
+++ b/src/internal/cpu/cpu_mips.go
@@ -5,3 +5,6 @@
package cpu
const CacheLinePadSize = 32
+
+func doinit() {
+}
diff --git a/src/internal/cpu/cpu_mipsle.go b/src/internal/cpu/cpu_mipsle.go
index 0f821e44e7..14a9c975ea 100644
--- a/src/internal/cpu/cpu_mipsle.go
+++ b/src/internal/cpu/cpu_mipsle.go
@@ -5,3 +5,6 @@
package cpu
const CacheLinePadSize = 32
+
+func doinit() {
+}
diff --git a/src/internal/cpu/cpu_no_init.go b/src/internal/cpu/cpu_no_init.go
deleted file mode 100644
index fb381e1ce2..0000000000
--- a/src/internal/cpu/cpu_no_init.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2018 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 !386
-// +build !amd64
-// +build !arm
-// +build !arm64
-// +build !ppc64
-// +build !ppc64le
-// +build !s390x
-// +build !mips64
-// +build !mips64le
-
-package cpu
-
-func doinit() {
-}
diff --git a/src/internal/cpu/cpu_no_name.go b/src/internal/cpu/cpu_no_name.go
new file mode 100644
index 0000000000..ce1c37a3c7
--- /dev/null
+++ b/src/internal/cpu/cpu_no_name.go
@@ -0,0 +1,19 @@
+// Copyright 2020 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 !386
+// +build !amd64
+
+package cpu
+
+// Name returns the CPU name given by the vendor
+// if it can be read directly from memory or by CPU instructions.
+// If the CPU name can not be determined an empty string is returned.
+//
+// Implementations that use the Operating System (e.g. sysctl or /sys/)
+// to gather CPU information for display should be placed in internal/sysinfo.
+func Name() string {
+ // "A CPU has no name".
+ return ""
+}
diff --git a/src/internal/cpu/cpu_ppc64x.go b/src/internal/cpu/cpu_ppc64x.go
index 2487879c46..beb1765427 100644
--- a/src/internal/cpu/cpu_ppc64x.go
+++ b/src/internal/cpu/cpu_ppc64x.go
@@ -8,39 +8,14 @@ package cpu
const CacheLinePadSize = 128
-// ppc64x doesn't have a 'cpuid' equivalent, so we rely on HWCAP/HWCAP2.
-// These are initialized by archauxv and should not be changed after they are
-// initialized.
-// On aix/ppc64, these values are initialized early in the runtime in runtime/os_aix.go.
-var HWCap uint
-var HWCap2 uint
-
-// HWCAP/HWCAP2 bits. These are exposed by the kernel.
-const (
- // ISA Level
- PPC_FEATURE2_ARCH_2_07 = 0x80000000
- PPC_FEATURE2_ARCH_3_00 = 0x00800000
-
- // CPU features
- PPC_FEATURE2_DARN = 0x00200000
- PPC_FEATURE2_SCV = 0x00100000
-)
-
func doinit() {
options = []option{
{Name: "darn", Feature: &PPC64.HasDARN},
{Name: "scv", Feature: &PPC64.HasSCV},
{Name: "power9", Feature: &PPC64.IsPOWER9},
-
- // These capabilities should always be enabled on ppc64 and ppc64le:
- {Name: "power8", Feature: &PPC64.IsPOWER8, Required: true},
}
- // HWCAP2 feature bits
- PPC64.IsPOWER8 = isSet(HWCap2, PPC_FEATURE2_ARCH_2_07)
- PPC64.IsPOWER9 = isSet(HWCap2, PPC_FEATURE2_ARCH_3_00)
- PPC64.HasDARN = isSet(HWCap2, PPC_FEATURE2_DARN)
- PPC64.HasSCV = isSet(HWCap2, PPC_FEATURE2_SCV)
+ osinit()
}
func isSet(hwc uint, value uint) bool {
diff --git a/src/internal/cpu/cpu_ppc64x_aix.go b/src/internal/cpu/cpu_ppc64x_aix.go
new file mode 100644
index 0000000000..b840b823ba
--- /dev/null
+++ b/src/internal/cpu/cpu_ppc64x_aix.go
@@ -0,0 +1,21 @@
+// Copyright 2020 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 ppc64 ppc64le
+
+package cpu
+
+const (
+ // getsystemcfg constants
+ _SC_IMPL = 2
+ _IMPL_POWER9 = 0x20000
+)
+
+func osinit() {
+ impl := getsystemcfg(_SC_IMPL)
+ PPC64.IsPOWER9 = isSet(impl, _IMPL_POWER9)
+}
+
+// getsystemcfg is defined in runtime/os2_aix.go
+func getsystemcfg(label uint) uint
diff --git a/src/internal/cpu/cpu_ppc64x_linux.go b/src/internal/cpu/cpu_ppc64x_linux.go
new file mode 100644
index 0000000000..73b191436d
--- /dev/null
+++ b/src/internal/cpu/cpu_ppc64x_linux.go
@@ -0,0 +1,29 @@
+// Copyright 2020 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 ppc64 ppc64le
+
+package cpu
+
+// ppc64 doesn't have a 'cpuid' equivalent, so we rely on HWCAP/HWCAP2.
+// These are initialized by archauxv and should not be changed after they are
+// initialized.
+var HWCap uint
+var HWCap2 uint
+
+// HWCAP bits. These are exposed by Linux.
+const (
+ // ISA Level
+ hwcap2_ARCH_3_00 = 0x00800000
+
+ // CPU features
+ hwcap2_DARN = 0x00200000
+ hwcap2_SCV = 0x00100000
+)
+
+func osinit() {
+ PPC64.IsPOWER9 = isSet(HWCap2, hwcap2_ARCH_3_00)
+ PPC64.HasDARN = isSet(HWCap2, hwcap2_DARN)
+ PPC64.HasSCV = isSet(HWCap2, hwcap2_SCV)
+}
diff --git a/src/internal/cpu/cpu_riscv64.go b/src/internal/cpu/cpu_riscv64.go
index c49cab79fd..54b8c3378b 100644
--- a/src/internal/cpu/cpu_riscv64.go
+++ b/src/internal/cpu/cpu_riscv64.go
@@ -5,3 +5,6 @@
package cpu
const CacheLinePadSize = 32
+
+func doinit() {
+}
diff --git a/src/internal/cpu/cpu_s390x.go b/src/internal/cpu/cpu_s390x.go
index 526e074225..45d8ed27f0 100644
--- a/src/internal/cpu/cpu_s390x.go
+++ b/src/internal/cpu/cpu_s390x.go
@@ -6,6 +6,8 @@ package cpu
const CacheLinePadSize = 256
+var HWCap uint
+
// bitIsSet reports whether the bit at index is set. The bit index
// is in big endian order, so bit index 0 is the leftmost bit.
func bitIsSet(bits []uint64, index uint) bool {
@@ -95,8 +97,10 @@ const (
// vector facilities
vxe facility = 135 // vector-enhancements 1
- // Note: vx and highgprs are excluded because they require
- // kernel support and so must be fetched from HWCAP.
+ // Note: vx requires kernel support
+ // and so must be fetched from HWCAP.
+
+ hwcap_VX = 1 << 11 // vector facility
)
// facilityList contains the result of an STFLE call.
@@ -188,7 +192,14 @@ func doinit() {
S390X.HasEDDSA = kdsa.Has(eddsaVerifyEd25519, eddsaSignEd25519, eddsaVerifyEd448, eddsaSignEd448)
}
}
+
+ S390X.HasVX = isSet(HWCap, hwcap_VX)
+
if S390X.HasVX {
S390X.HasVXE = facilities.Has(vxe)
}
}
+
+func isSet(hwc uint, value uint) bool {
+ return hwc&value != 0
+}
diff --git a/src/internal/cpu/cpu_s390x_test.go b/src/internal/cpu/cpu_s390x_test.go
index d910bbe695..ad86858db0 100644
--- a/src/internal/cpu/cpu_s390x_test.go
+++ b/src/internal/cpu/cpu_s390x_test.go
@@ -7,13 +7,13 @@ package cpu_test
import (
"errors"
. "internal/cpu"
- "io/ioutil"
+ "os"
"regexp"
"testing"
)
func getFeatureList() ([]string, error) {
- cpuinfo, err := ioutil.ReadFile("/proc/cpuinfo")
+ cpuinfo, err := os.ReadFile("/proc/cpuinfo")
if err != nil {
return nil, err
}
diff --git a/src/internal/cpu/cpu_test.go b/src/internal/cpu/cpu_test.go
index e09bd2d8b9..2de7365732 100644
--- a/src/internal/cpu/cpu_test.go
+++ b/src/internal/cpu/cpu_test.go
@@ -15,9 +15,10 @@ import (
)
func TestMinimalFeatures(t *testing.T) {
+ // TODO: maybe do MustSupportFeatureDectection(t) ?
if runtime.GOARCH == "arm64" {
switch runtime.GOOS {
- case "linux", "android":
+ case "linux", "android", "darwin":
default:
t.Skipf("%s/%s is not supported", runtime.GOOS, runtime.GOARCH)
}
@@ -36,6 +37,10 @@ func MustHaveDebugOptionsSupport(t *testing.T) {
}
}
+func MustSupportFeatureDectection(t *testing.T) {
+ // TODO: add platforms that do not have CPU feature detection support.
+}
+
func runDebugOptionsTest(t *testing.T, test string, options string) {
MustHaveDebugOptionsSupport(t)
@@ -58,6 +63,7 @@ func runDebugOptionsTest(t *testing.T, test string, options string) {
}
func TestDisableAllCapabilities(t *testing.T) {
+ MustSupportFeatureDectection(t)
runDebugOptionsTest(t, "TestAllCapabilitiesDisabled", "cpu.all=off")
}
diff --git a/src/internal/cpu/cpu_wasm.go b/src/internal/cpu/cpu_wasm.go
index b459738770..2310ad6a48 100644
--- a/src/internal/cpu/cpu_wasm.go
+++ b/src/internal/cpu/cpu_wasm.go
@@ -5,3 +5,6 @@
package cpu
const CacheLinePadSize = 64
+
+func doinit() {
+}
diff --git a/src/internal/cpu/cpu_x86.go b/src/internal/cpu/cpu_x86.go
index da6cf67258..ba6bf69034 100644
--- a/src/internal/cpu/cpu_x86.go
+++ b/src/internal/cpu/cpu_x86.go
@@ -38,6 +38,8 @@ const (
cpuid_ADX = 1 << 19
)
+var maxExtendedFunctionInformation uint32
+
func doinit() {
options = []option{
{Name: "adx", Feature: &X86.HasADX},
@@ -65,19 +67,30 @@ func doinit() {
return
}
+ maxExtendedFunctionInformation, _, _, _ = cpuid(0x80000000, 0)
+
_, _, ecx1, edx1 := cpuid(1, 0)
X86.HasSSE2 = isSet(edx1, cpuid_SSE2)
X86.HasSSE3 = isSet(ecx1, cpuid_SSE3)
X86.HasPCLMULQDQ = isSet(ecx1, cpuid_PCLMULQDQ)
X86.HasSSSE3 = isSet(ecx1, cpuid_SSSE3)
- X86.HasFMA = isSet(ecx1, cpuid_FMA)
X86.HasSSE41 = isSet(ecx1, cpuid_SSE41)
X86.HasSSE42 = isSet(ecx1, cpuid_SSE42)
X86.HasPOPCNT = isSet(ecx1, cpuid_POPCNT)
X86.HasAES = isSet(ecx1, cpuid_AES)
+
+ // OSXSAVE can be false when using older Operating Systems
+ // or when explicitly disabled on newer Operating Systems by
+ // e.g. setting the xsavedisable boot option on Windows 10.
X86.HasOSXSAVE = isSet(ecx1, cpuid_OSXSAVE)
+ // The FMA instruction set extension only has VEX prefixed instructions.
+ // VEX prefixed instructions require OSXSAVE to be enabled.
+ // See Intel 64 and IA-32 Architecture Software Developer’s Manual Volume 2
+ // Section 2.4 "AVX and SSE Instruction Exception Specification"
+ X86.HasFMA = isSet(ecx1, cpuid_FMA) && X86.HasOSXSAVE
+
osSupportsAVX := false
// For XGETBV, OSXSAVE bit is required and sufficient.
if X86.HasOSXSAVE {
@@ -103,3 +116,48 @@ func doinit() {
func isSet(hwc uint32, value uint32) bool {
return hwc&value != 0
}
+
+// Name returns the CPU name given by the vendor.
+// If the CPU name can not be determined an
+// empty string is returned.
+func Name() string {
+ if maxExtendedFunctionInformation < 0x80000004 {
+ return ""
+ }
+
+ data := make([]byte, 0, 3*4*4)
+
+ var eax, ebx, ecx, edx uint32
+ eax, ebx, ecx, edx = cpuid(0x80000002, 0)
+ data = appendBytes(data, eax, ebx, ecx, edx)
+ eax, ebx, ecx, edx = cpuid(0x80000003, 0)
+ data = appendBytes(data, eax, ebx, ecx, edx)
+ eax, ebx, ecx, edx = cpuid(0x80000004, 0)
+ data = appendBytes(data, eax, ebx, ecx, edx)
+
+ // Trim leading spaces.
+ for len(data) > 0 && data[0] == ' ' {
+ data = data[1:]
+ }
+
+ // Trim tail after and including the first null byte.
+ for i, c := range data {
+ if c == '\x00' {
+ data = data[:i]
+ break
+ }
+ }
+
+ return string(data)
+}
+
+func appendBytes(b []byte, args ...uint32) []byte {
+ for _, arg := range args {
+ b = append(b,
+ byte((arg >> 0)),
+ byte((arg >> 8)),
+ byte((arg >> 16)),
+ byte((arg >> 24)))
+ }
+ return b
+}
diff --git a/src/internal/fmtsort/sort.go b/src/internal/fmtsort/sort.go
index b01229bd06..7127ba6ac3 100644
--- a/src/internal/fmtsort/sort.go
+++ b/src/internal/fmtsort/sort.go
@@ -130,7 +130,7 @@ func compare(aVal, bVal reflect.Value) int {
default:
return -1
}
- case reflect.Ptr:
+ case reflect.Ptr, reflect.UnsafePointer:
a, b := aVal.Pointer(), bVal.Pointer()
switch {
case a < b:
diff --git a/src/internal/fmtsort/sort_test.go b/src/internal/fmtsort/sort_test.go
index aaa0004666..5c4db1c5fa 100644
--- a/src/internal/fmtsort/sort_test.go
+++ b/src/internal/fmtsort/sort_test.go
@@ -11,6 +11,7 @@ import (
"reflect"
"strings"
"testing"
+ "unsafe"
)
var compareTests = [][]reflect.Value{
@@ -32,6 +33,7 @@ var compareTests = [][]reflect.Value{
ct(reflect.TypeOf(complex128(0+1i)), -1-1i, -1+0i, -1+1i, 0-1i, 0+0i, 0+1i, 1-1i, 1+0i, 1+1i),
ct(reflect.TypeOf(false), false, true),
ct(reflect.TypeOf(&ints[0]), &ints[0], &ints[1], &ints[2]),
+ ct(reflect.TypeOf(unsafe.Pointer(&ints[0])), unsafe.Pointer(&ints[0]), unsafe.Pointer(&ints[1]), unsafe.Pointer(&ints[2])),
ct(reflect.TypeOf(chans[0]), chans[0], chans[1], chans[2]),
ct(reflect.TypeOf(toy{}), toy{0, 1}, toy{0, 2}, toy{1, -1}, toy{1, 1}),
ct(reflect.TypeOf([2]int{}), [2]int{1, 1}, [2]int{1, 2}, [2]int{2, 0}),
@@ -119,6 +121,10 @@ var sortTests = []sortTest{
"PTR0:0 PTR1:1 PTR2:2",
},
{
+ unsafePointerMap(),
+ "UNSAFEPTR0:0 UNSAFEPTR1:1 UNSAFEPTR2:2",
+ },
+ {
map[toy]string{{7, 2}: "72", {7, 1}: "71", {3, 4}: "34"},
"{3 4}:34 {7 1}:71 {7 2}:72",
},
@@ -159,6 +165,14 @@ func sprintKey(key reflect.Value) string {
}
}
return "PTR???"
+ case "unsafe.Pointer":
+ ptr := key.Interface().(unsafe.Pointer)
+ for i := range ints {
+ if ptr == unsafe.Pointer(&ints[i]) {
+ return fmt.Sprintf("UNSAFEPTR%d", i)
+ }
+ }
+ return "UNSAFEPTR???"
case "chan int":
c := key.Interface().(chan int)
for i := range chans {
@@ -185,6 +199,14 @@ func pointerMap() map[*int]string {
return m
}
+func unsafePointerMap() map[unsafe.Pointer]string {
+ m := make(map[unsafe.Pointer]string)
+ for i := 2; i >= 0; i-- {
+ m[unsafe.Pointer(&ints[i])] = fmt.Sprint(i)
+ }
+ return m
+}
+
func chanMap() map[chan int]string {
m := make(map[chan int]string)
for i := 2; i >= 0; i-- {
diff --git a/src/internal/obscuretestdata/obscuretestdata.go b/src/internal/obscuretestdata/obscuretestdata.go
index 512f3759b4..5ea2cdf5d1 100644
--- a/src/internal/obscuretestdata/obscuretestdata.go
+++ b/src/internal/obscuretestdata/obscuretestdata.go
@@ -10,7 +10,6 @@ package obscuretestdata
import (
"encoding/base64"
"io"
- "io/ioutil"
"os"
)
@@ -24,7 +23,7 @@ func DecodeToTempFile(name string) (path string, err error) {
}
defer f.Close()
- tmp, err := ioutil.TempFile("", "obscuretestdata-decoded-")
+ tmp, err := os.CreateTemp("", "obscuretestdata-decoded-")
if err != nil {
return "", err
}
@@ -47,5 +46,5 @@ func ReadFile(name string) ([]byte, error) {
return nil, err
}
defer f.Close()
- return ioutil.ReadAll(base64.NewDecoder(base64.StdEncoding, f))
+ return io.ReadAll(base64.NewDecoder(base64.StdEncoding, f))
}
diff --git a/src/internal/poll/copy_file_range_linux.go b/src/internal/poll/copy_file_range_linux.go
index 09de299ff7..fc34aef4cb 100644
--- a/src/internal/poll/copy_file_range_linux.go
+++ b/src/internal/poll/copy_file_range_linux.go
@@ -10,15 +10,61 @@ import (
"syscall"
)
-var copyFileRangeSupported int32 = 1 // accessed atomically
+var copyFileRangeSupported int32 = -1 // accessed atomically
const maxCopyFileRangeRound = 1 << 30
+func kernelVersion() (major int, minor int) {
+ var uname syscall.Utsname
+ if err := syscall.Uname(&uname); err != nil {
+ return
+ }
+
+ rl := uname.Release
+ var values [2]int
+ vi := 0
+ value := 0
+ for _, c := range rl {
+ if '0' <= c && c <= '9' {
+ value = (value * 10) + int(c-'0')
+ } else {
+ // Note that we're assuming N.N.N here. If we see anything else we are likely to
+ // mis-parse it.
+ values[vi] = value
+ vi++
+ if vi >= len(values) {
+ break
+ }
+ value = 0
+ }
+ }
+ switch vi {
+ case 0:
+ return 0, 0
+ case 1:
+ return values[0], 0
+ case 2:
+ return values[0], values[1]
+ }
+ return
+}
+
// CopyFileRange copies at most remain bytes of data from src to dst, using
// the copy_file_range system call. dst and src must refer to regular files.
func CopyFileRange(dst, src *FD, remain int64) (written int64, handled bool, err error) {
- if atomic.LoadInt32(&copyFileRangeSupported) == 0 {
+ if supported := atomic.LoadInt32(&copyFileRangeSupported); supported == 0 {
return 0, false, nil
+ } else if supported == -1 {
+ major, minor := kernelVersion()
+ if major > 5 || (major == 5 && minor >= 3) {
+ atomic.StoreInt32(&copyFileRangeSupported, 1)
+ } else {
+ // copy_file_range(2) is broken in various ways on kernels older than 5.3,
+ // see issue #42400 and
+ // https://man7.org/linux/man-pages/man2/copy_file_range.2.html#VERSIONS
+ atomic.StoreInt32(&copyFileRangeSupported, 0)
+ return 0, false, nil
+ }
}
for remain > 0 {
max := remain
@@ -41,7 +87,7 @@ func CopyFileRange(dst, src *FD, remain int64) (written int64, handled bool, err
// use copy_file_range(2) again.
atomic.StoreInt32(&copyFileRangeSupported, 0)
return 0, false, nil
- case syscall.EXDEV, syscall.EINVAL, syscall.EOPNOTSUPP, syscall.EPERM:
+ case syscall.EXDEV, syscall.EINVAL, syscall.EIO, syscall.EOPNOTSUPP, syscall.EPERM:
// Prior to Linux 5.3, it was not possible to
// copy_file_range across file systems. Similarly to
// the ENOSYS case above, if we see EXDEV, we have
@@ -53,6 +99,9 @@ func CopyFileRange(dst, src *FD, remain int64) (written int64, handled bool, err
// file. This is another case where no data has been
// transfered, so we consider it unhandled.
//
+ // If src and dst are on CIFS, we can see EIO.
+ // See issue #42334.
+ //
// If the file is on NFS, we can see EOPNOTSUPP.
// See issue #40731.
//
diff --git a/src/internal/poll/error_test.go b/src/internal/poll/error_test.go
index 06b96f635a..abc8b1684f 100644
--- a/src/internal/poll/error_test.go
+++ b/src/internal/poll/error_test.go
@@ -6,6 +6,7 @@ package poll_test
import (
"fmt"
+ "io/fs"
"net"
"os"
"testing"
@@ -37,7 +38,7 @@ func parseReadError(nestedErr error, verify func(error) (string, bool)) error {
if nerr, ok := err.(*net.OpError); ok {
err = nerr.Err
}
- if nerr, ok := err.(*os.PathError); ok {
+ if nerr, ok := err.(*fs.PathError); ok {
err = nerr.Err
}
if nerr, ok := err.(*os.SyscallError); ok {
diff --git a/src/internal/poll/fd_fsync_darwin.go b/src/internal/poll/fd_fsync_darwin.go
index 91751496a4..48e7596922 100644
--- a/src/internal/poll/fd_fsync_darwin.go
+++ b/src/internal/poll/fd_fsync_darwin.go
@@ -14,7 +14,8 @@ func (fd *FD) Fsync() error {
return err
}
defer fd.decref()
-
- _, e1 := fcntl(fd.Sysfd, syscall.F_FULLFSYNC, 0)
- return e1
+ return ignoringEINTR(func() error {
+ _, err := fcntl(fd.Sysfd, syscall.F_FULLFSYNC, 0)
+ return err
+ })
}
diff --git a/src/internal/poll/fd_posix.go b/src/internal/poll/fd_posix.go
index e5fb05c9c2..4edfa953a4 100644
--- a/src/internal/poll/fd_posix.go
+++ b/src/internal/poll/fd_posix.go
@@ -29,17 +29,6 @@ func (fd *FD) Shutdown(how int) error {
return syscall.Shutdown(fd.Sysfd, how)
}
-// Fchmod wraps syscall.Fchmod.
-func (fd *FD) Fchmod(mode uint32) error {
- if err := fd.incref(); err != nil {
- return err
- }
- defer fd.decref()
- return ignoringEINTR(func() error {
- return syscall.Fchmod(fd.Sysfd, mode)
- })
-}
-
// Fchown wraps syscall.Fchown.
func (fd *FD) Fchown(uid, gid int) error {
if err := fd.incref(); err != nil {
diff --git a/src/internal/poll/fd_unix.go b/src/internal/poll/fd_unix.go
index 1d5101eac3..2e77e76c87 100644
--- a/src/internal/poll/fd_unix.go
+++ b/src/internal/poll/fd_unix.go
@@ -74,7 +74,14 @@ func (fd *FD) destroy() error {
// Poller may want to unregister fd in readiness notification mechanism,
// so this must be executed before CloseFunc.
fd.pd.close()
+
+ // We don't use ignoringEINTR here because POSIX does not define
+ // whether the descriptor is closed if close returns EINTR.
+ // If the descriptor is indeed closed, using a loop would race
+ // with some other goroutine opening a new descriptor.
+ // (The Linux kernel guarantees that it is closed on an EINTR error.)
err := CloseFunc(fd.Sysfd)
+
fd.Sysfd = -1
runtime_Semrelease(&fd.csema)
return err
@@ -437,6 +444,17 @@ func (fd *FD) ReadDirent(buf []byte) (int, error) {
}
}
+// Fchmod wraps syscall.Fchmod.
+func (fd *FD) Fchmod(mode uint32) error {
+ if err := fd.incref(); err != nil {
+ return err
+ }
+ defer fd.decref()
+ return ignoringEINTR(func() error {
+ return syscall.Fchmod(fd.Sysfd, mode)
+ })
+}
+
// Fchdir wraps syscall.Fchdir.
func (fd *FD) Fchdir() error {
if err := fd.incref(); err != nil {
diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go
index e1ef6199b3..d8c834f929 100644
--- a/src/internal/poll/fd_windows.go
+++ b/src/internal/poll/fd_windows.go
@@ -886,6 +886,33 @@ func (fd *FD) FindNextFile(data *syscall.Win32finddata) error {
return syscall.FindNextFile(fd.Sysfd, data)
}
+// Fchmod updates syscall.ByHandleFileInformation.Fileattributes when needed.
+func (fd *FD) Fchmod(mode uint32) error {
+ if err := fd.incref(); err != nil {
+ return err
+ }
+ defer fd.decref()
+
+ var d syscall.ByHandleFileInformation
+ if err := syscall.GetFileInformationByHandle(fd.Sysfd, &d); err != nil {
+ return err
+ }
+ attrs := d.FileAttributes
+ if mode&syscall.S_IWRITE != 0 {
+ attrs &^= syscall.FILE_ATTRIBUTE_READONLY
+ } else {
+ attrs |= syscall.FILE_ATTRIBUTE_READONLY
+ }
+ if attrs == d.FileAttributes {
+ return nil
+ }
+
+ var du windows.FILE_BASIC_INFO
+ du.FileAttributes = attrs
+ l := uint32(unsafe.Sizeof(d))
+ return windows.SetFileInformationByHandle(fd.Sysfd, windows.FileBasicInfo, uintptr(unsafe.Pointer(&du)), l)
+}
+
// Fchdir wraps syscall.Fchdir.
func (fd *FD) Fchdir() error {
if err := fd.incref(); err != nil {
diff --git a/src/internal/poll/fd_writev_illumos.go b/src/internal/poll/fd_writev_illumos.go
new file mode 100644
index 0000000000..1fa47ab1a3
--- /dev/null
+++ b/src/internal/poll/fd_writev_illumos.go
@@ -0,0 +1,16 @@
+// Copyright 2020 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 illumos
+
+package poll
+
+import (
+ "internal/syscall/unix"
+ "syscall"
+)
+
+func writev(fd int, iovecs []syscall.Iovec) (uintptr, error) {
+ return unix.Writev(fd, iovecs)
+}
diff --git a/src/internal/poll/hook_cloexec.go b/src/internal/poll/hook_cloexec.go
index 5c93bdaf6c..5fd5449bb0 100644
--- a/src/internal/poll/hook_cloexec.go
+++ b/src/internal/poll/hook_cloexec.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build dragonfly freebsd linux netbsd openbsd
+// +build dragonfly freebsd illumos linux netbsd openbsd
package poll
diff --git a/src/internal/poll/iovec_illumos.go b/src/internal/poll/iovec_illumos.go
new file mode 100644
index 0000000000..057067465b
--- /dev/null
+++ b/src/internal/poll/iovec_illumos.go
@@ -0,0 +1,16 @@
+// Copyright 2020 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 illumos
+
+package poll
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+func newIovecWithBase(base *byte) syscall.Iovec {
+ return syscall.Iovec{Base: (*int8)(unsafe.Pointer(base))}
+}
diff --git a/src/internal/poll/iovec_unix.go b/src/internal/poll/iovec_unix.go
new file mode 100644
index 0000000000..6f98947866
--- /dev/null
+++ b/src/internal/poll/iovec_unix.go
@@ -0,0 +1,13 @@
+// Copyright 2020 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 darwin dragonfly freebsd linux netbsd openbsd
+
+package poll
+
+import "syscall"
+
+func newIovecWithBase(base *byte) syscall.Iovec {
+ return syscall.Iovec{Base: base}
+}
diff --git a/src/internal/poll/read_test.go b/src/internal/poll/read_test.go
index b4f5236d3e..598a52ee44 100644
--- a/src/internal/poll/read_test.go
+++ b/src/internal/poll/read_test.go
@@ -5,7 +5,6 @@
package poll_test
import (
- "io/ioutil"
"os"
"runtime"
"sync"
@@ -22,7 +21,7 @@ func TestRead(t *testing.T) {
go func(p string) {
defer wg.Done()
for i := 0; i < 100; i++ {
- if _, err := ioutil.ReadFile(p); err != nil {
+ if _, err := os.ReadFile(p); err != nil {
t.Error(err)
return
}
@@ -38,7 +37,7 @@ func TestRead(t *testing.T) {
func specialFiles() []string {
var ps []string
switch runtime.GOOS {
- case "darwin", "dragonfly", "freebsd", "netbsd", "openbsd":
+ case "darwin", "ios", "dragonfly", "freebsd", "netbsd", "openbsd":
ps = []string{
"/dev/null",
}
diff --git a/src/internal/poll/sock_cloexec.go b/src/internal/poll/sock_cloexec.go
index 691cb8e36f..ff7982ca9e 100644
--- a/src/internal/poll/sock_cloexec.go
+++ b/src/internal/poll/sock_cloexec.go
@@ -5,7 +5,7 @@
// This file implements sysSocket and accept for platforms that
// provide a fast path for setting SetNonblock and CloseOnExec.
-// +build dragonfly freebsd linux netbsd openbsd
+// +build dragonfly freebsd illumos linux netbsd openbsd
package poll
diff --git a/src/internal/poll/sys_cloexec.go b/src/internal/poll/sys_cloexec.go
index 7b87f136df..4b3c642173 100644
--- a/src/internal/poll/sys_cloexec.go
+++ b/src/internal/poll/sys_cloexec.go
@@ -5,7 +5,7 @@
// This file implements sysSocket and accept for platforms that do not
// provide a fast path for setting SetNonblock and CloseOnExec.
-// +build aix darwin js,wasm solaris
+// +build aix darwin js,wasm solaris,!illumos
package poll
diff --git a/src/internal/poll/writev.go b/src/internal/poll/writev.go
index 305e2fd209..0123fc33de 100644
--- a/src/internal/poll/writev.go
+++ b/src/internal/poll/writev.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd illumos linux netbsd openbsd
package poll
@@ -38,7 +38,7 @@ func (fd *FD) Writev(v *[][]byte) (int64, error) {
if len(chunk) == 0 {
continue
}
- iovecs = append(iovecs, syscall.Iovec{Base: &chunk[0]})
+ iovecs = append(iovecs, newIovecWithBase(&chunk[0]))
if fd.IsStream && len(chunk) > 1<<30 {
iovecs[len(iovecs)-1].SetLen(1 << 30)
break // continue chunk on next writev
diff --git a/src/internal/profile/profile.go b/src/internal/profile/profile.go
index a6275bc6de..29568aa4b5 100644
--- a/src/internal/profile/profile.go
+++ b/src/internal/profile/profile.go
@@ -12,7 +12,6 @@ import (
"compress/gzip"
"fmt"
"io"
- "io/ioutil"
"regexp"
"strings"
"time"
@@ -125,7 +124,7 @@ type Function struct {
// may be a gzip-compressed encoded protobuf or one of many legacy
// profile formats which may be unsupported in the future.
func Parse(r io.Reader) (*Profile, error) {
- orig, err := ioutil.ReadAll(r)
+ orig, err := io.ReadAll(r)
if err != nil {
return nil, err
}
@@ -136,7 +135,7 @@ func Parse(r io.Reader) (*Profile, error) {
if err != nil {
return nil, fmt.Errorf("decompressing profile: %v", err)
}
- data, err := ioutil.ReadAll(gz)
+ data, err := io.ReadAll(gz)
if err != nil {
return nil, fmt.Errorf("decompressing profile: %v", err)
}
diff --git a/src/internal/reflectlite/reflect_mirror_test.go b/src/internal/reflectlite/reflect_mirror_test.go
index fbb6fb397e..9b28b13550 100644
--- a/src/internal/reflectlite/reflect_mirror_test.go
+++ b/src/internal/reflectlite/reflect_mirror_test.go
@@ -9,6 +9,7 @@ import (
"go/ast"
"go/parser"
"go/token"
+ "io/fs"
"os"
"path/filepath"
"runtime"
@@ -71,7 +72,7 @@ func (v visitor) Visit(n ast.Node) ast.Visitor {
func loadTypes(path, pkgName string, v visitor) {
fset := token.NewFileSet()
- filter := func(fi os.FileInfo) bool {
+ filter := func(fi fs.FileInfo) bool {
return strings.HasSuffix(fi.Name(), ".go")
}
pkgs, err := parser.ParseDir(fset, path, filter, 0)
diff --git a/src/internal/reflectlite/type.go b/src/internal/reflectlite/type.go
index eb7f1a4b78..15ba30da36 100644
--- a/src/internal/reflectlite/type.go
+++ b/src/internal/reflectlite/type.go
@@ -384,6 +384,44 @@ const (
kindMask = (1 << 5) - 1
)
+// String returns the name of k.
+func (k Kind) String() string {
+ if int(k) < len(kindNames) {
+ return kindNames[k]
+ }
+ return kindNames[0]
+}
+
+var kindNames = []string{
+ Invalid: "invalid",
+ Bool: "bool",
+ Int: "int",
+ Int8: "int8",
+ Int16: "int16",
+ Int32: "int32",
+ Int64: "int64",
+ Uint: "uint",
+ Uint8: "uint8",
+ Uint16: "uint16",
+ Uint32: "uint32",
+ Uint64: "uint64",
+ Uintptr: "uintptr",
+ Float32: "float32",
+ Float64: "float64",
+ Complex64: "complex64",
+ Complex128: "complex128",
+ Array: "array",
+ Chan: "chan",
+ Func: "func",
+ Interface: "interface",
+ Map: "map",
+ Ptr: "ptr",
+ Slice: "slice",
+ String: "string",
+ Struct: "struct",
+ UnsafePointer: "unsafe.Pointer",
+}
+
func (t *uncommonType) methods() []method {
if t.mcount == 0 {
return nil
diff --git a/src/internal/reflectlite/value.go b/src/internal/reflectlite/value.go
index 85beea606c..0365eeeabf 100644
--- a/src/internal/reflectlite/value.go
+++ b/src/internal/reflectlite/value.go
@@ -160,7 +160,10 @@ type ValueError struct {
}
func (e *ValueError) Error() string {
- return "reflect: call of " + e.Method + " on zero Value"
+ if e.Kind == 0 {
+ return "reflect: call of " + e.Method + " on zero Value"
+ }
+ return "reflect: call of " + e.Method + " on " + e.Kind.String() + " Value"
}
// methodName returns the name of the calling method,
diff --git a/src/internal/syscall/unix/pipe2_illumos.go b/src/internal/syscall/unix/pipe2_illumos.go
new file mode 100644
index 0000000000..f3ac8d29df
--- /dev/null
+++ b/src/internal/syscall/unix/pipe2_illumos.go
@@ -0,0 +1,34 @@
+// Copyright 2020 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 illumos
+
+package unix
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+//go:cgo_import_dynamic libc_pipe2 pipe2 "libc.so"
+
+//go:linkname procpipe2 libc_pipe2
+
+var procpipe2 uintptr
+
+type _C_int int32
+
+func Pipe2(p []int, flags int) error {
+ if len(p) != 2 {
+ return syscall.EINVAL
+ }
+ var pp [2]_C_int
+ _, _, errno := syscall6(uintptr(unsafe.Pointer(&procpipe2)), 2, uintptr(unsafe.Pointer(&pp)), uintptr(flags), 0, 0, 0, 0)
+ if errno != 0 {
+ return errno
+ }
+ p[0] = int(pp[0])
+ p[1] = int(pp[1])
+ return nil
+}
diff --git a/src/internal/syscall/unix/writev_illumos.go b/src/internal/syscall/unix/writev_illumos.go
new file mode 100644
index 0000000000..eb7973d65b
--- /dev/null
+++ b/src/internal/syscall/unix/writev_illumos.go
@@ -0,0 +1,30 @@
+// Copyright 2020 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 illumos
+
+package unix
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+//go:cgo_import_dynamic libc_writev writev "libc.so"
+
+//go:linkname procwritev libc_writev
+
+var procwritev uintptr
+
+func Writev(fd int, iovs []syscall.Iovec) (uintptr, error) {
+ var p *syscall.Iovec
+ if len(iovs) > 0 {
+ p = &iovs[0]
+ }
+ n, _, errno := syscall6(uintptr(unsafe.Pointer(&procwritev)), 3, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(len(iovs)), 0, 0, 0)
+ if errno != 0 {
+ return 0, errno
+ }
+ return n, nil
+}
diff --git a/src/internal/syscall/windows/mksyscall.go b/src/internal/syscall/windows/mksyscall.go
index 95e36f7aa3..599f07601b 100644
--- a/src/internal/syscall/windows/mksyscall.go
+++ b/src/internal/syscall/windows/mksyscall.go
@@ -6,4 +6,4 @@
package windows
-//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go syscall_windows.go security_windows.go psapi_windows.go symlink_windows.go
+//go:generate go run ../../../syscall/mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go security_windows.go psapi_windows.go symlink_windows.go
diff --git a/src/internal/syscall/windows/registry/key.go b/src/internal/syscall/windows/registry/key.go
index cc3d0c774b..612c48f084 100644
--- a/src/internal/syscall/windows/registry/key.go
+++ b/src/internal/syscall/windows/registry/key.go
@@ -25,10 +25,7 @@
//
package registry
-import (
- "io"
- "syscall"
-)
+import "syscall"
const (
// Registry key security and access rights.
@@ -90,20 +87,13 @@ func OpenKey(k Key, path string, access uint32) (Key, error) {
}
// ReadSubKeyNames returns the names of subkeys of key k.
-// The parameter n controls the number of returned names,
-// analogous to the way os.File.Readdirnames works.
-func (k Key) ReadSubKeyNames(n int) ([]string, error) {
+func (k Key) ReadSubKeyNames() ([]string, error) {
names := make([]string, 0)
// Registry key size limit is 255 bytes and described there:
// https://msdn.microsoft.com/library/windows/desktop/ms724872.aspx
buf := make([]uint16, 256) //plus extra room for terminating zero byte
loopItems:
for i := uint32(0); ; i++ {
- if n > 0 {
- if len(names) == n {
- return names, nil
- }
- }
l := uint32(len(buf))
for {
err := syscall.RegEnumKeyEx(syscall.Handle(k), i, &buf[0], &l, nil, nil, nil, nil)
@@ -123,9 +113,6 @@ loopItems:
}
names = append(names, syscall.UTF16ToString(buf[:l]))
}
- if n > len(names) {
- return names, io.EOF
- }
return names, nil
}
diff --git a/src/internal/syscall/windows/registry/mksyscall.go b/src/internal/syscall/windows/registry/mksyscall.go
index cb4906a7b2..320abf7fc6 100644
--- a/src/internal/syscall/windows/registry/mksyscall.go
+++ b/src/internal/syscall/windows/registry/mksyscall.go
@@ -6,4 +6,4 @@
package registry
-//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go syscall.go
+//go:generate go run ../../../../syscall/mksyscall_windows.go -output zsyscall_windows.go syscall.go
diff --git a/src/internal/syscall/windows/registry/registry_test.go b/src/internal/syscall/windows/registry/registry_test.go
index 8227232c70..5797162900 100644
--- a/src/internal/syscall/windows/registry/registry_test.go
+++ b/src/internal/syscall/windows/registry/registry_test.go
@@ -34,7 +34,7 @@ func TestReadSubKeyNames(t *testing.T) {
}
defer k.Close()
- names, err := k.ReadSubKeyNames(-1)
+ names, err := k.ReadSubKeyNames()
if err != nil {
t.Fatal(err)
}
@@ -190,7 +190,7 @@ func setValues(t *testing.T, k registry.Key) {
}
func enumerateValues(t *testing.T, k registry.Key) {
- names, err := k.ReadValueNames(-1)
+ names, err := k.ReadValueNames()
if err != nil {
t.Error(err)
return
@@ -480,7 +480,7 @@ func deleteValues(t *testing.T, k registry.Key) {
continue
}
}
- names, err := k.ReadValueNames(-1)
+ names, err := k.ReadValueNames()
if err != nil {
t.Error(err)
return
diff --git a/src/internal/syscall/windows/registry/value.go b/src/internal/syscall/windows/registry/value.go
index bf8ab00759..dc3930a6bc 100644
--- a/src/internal/syscall/windows/registry/value.go
+++ b/src/internal/syscall/windows/registry/value.go
@@ -8,7 +8,6 @@ package registry
import (
"errors"
- "io"
"syscall"
"unicode/utf16"
"unsafe"
@@ -341,9 +340,7 @@ func (k Key) DeleteValue(name string) error {
}
// ReadValueNames returns the value names of key k.
-// The parameter n controls the number of returned names,
-// analogous to the way os.File.Readdirnames works.
-func (k Key) ReadValueNames(n int) ([]string, error) {
+func (k Key) ReadValueNames() ([]string, error) {
ki, err := k.Stat()
if err != nil {
return nil, err
@@ -352,11 +349,6 @@ func (k Key) ReadValueNames(n int) ([]string, error) {
buf := make([]uint16, ki.MaxValueNameLen+1) // extra room for terminating null character
loopItems:
for i := uint32(0); ; i++ {
- if n > 0 {
- if len(names) == n {
- return names, nil
- }
- }
l := uint32(len(buf))
for {
err := regEnumValue(syscall.Handle(k), i, &buf[0], &l, nil, nil, nil, nil)
@@ -376,8 +368,5 @@ loopItems:
}
names = append(names, syscall.UTF16ToString(buf[:l]))
}
- if n > len(names) {
- return names, io.EOF
- }
return names, nil
}
diff --git a/src/internal/syscall/windows/registry/zsyscall_windows.go b/src/internal/syscall/windows/registry/zsyscall_windows.go
index c3f3a8a215..cab1319374 100644
--- a/src/internal/syscall/windows/registry/zsyscall_windows.go
+++ b/src/internal/syscall/windows/registry/zsyscall_windows.go
@@ -18,6 +18,7 @@ const (
var (
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
+ errERROR_EINVAL error = syscall.EINVAL
)
// errnoErr returns common boxed Errno values, to prevent
@@ -25,7 +26,7 @@ var (
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
- return nil
+ return errERROR_EINVAL
case errnoERROR_IO_PENDING:
return errERROR_IO_PENDING
}
@@ -41,10 +42,10 @@ var (
procRegCreateKeyExW = modadvapi32.NewProc("RegCreateKeyExW")
procRegDeleteKeyW = modadvapi32.NewProc("RegDeleteKeyW")
- procRegSetValueExW = modadvapi32.NewProc("RegSetValueExW")
- procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW")
procRegDeleteValueW = modadvapi32.NewProc("RegDeleteValueW")
+ procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW")
procRegLoadMUIStringW = modadvapi32.NewProc("RegLoadMUIStringW")
+ procRegSetValueExW = modadvapi32.NewProc("RegSetValueExW")
procExpandEnvironmentStringsW = modkernel32.NewProc("ExpandEnvironmentStringsW")
)
@@ -64,8 +65,8 @@ func regDeleteKey(key syscall.Handle, subkey *uint16) (regerrno error) {
return
}
-func regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) {
- r0, _, _ := syscall.Syscall6(procRegSetValueExW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(valueName)), uintptr(reserved), uintptr(vtype), uintptr(unsafe.Pointer(buf)), uintptr(bufsize))
+func regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) {
+ r0, _, _ := syscall.Syscall(procRegDeleteValueW.Addr(), 2, uintptr(key), uintptr(unsafe.Pointer(name)), 0)
if r0 != 0 {
regerrno = syscall.Errno(r0)
}
@@ -80,16 +81,16 @@ func regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint3
return
}
-func regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) {
- r0, _, _ := syscall.Syscall(procRegDeleteValueW.Addr(), 2, uintptr(key), uintptr(unsafe.Pointer(name)), 0)
+func regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint32, buflenCopied *uint32, flags uint32, dir *uint16) (regerrno error) {
+ r0, _, _ := syscall.Syscall9(procRegLoadMUIStringW.Addr(), 7, uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(unsafe.Pointer(buflenCopied)), uintptr(flags), uintptr(unsafe.Pointer(dir)), 0, 0)
if r0 != 0 {
regerrno = syscall.Errno(r0)
}
return
}
-func regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint32, buflenCopied *uint32, flags uint32, dir *uint16) (regerrno error) {
- r0, _, _ := syscall.Syscall9(procRegLoadMUIStringW.Addr(), 7, uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(unsafe.Pointer(buflenCopied)), uintptr(flags), uintptr(unsafe.Pointer(dir)), 0, 0)
+func regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) {
+ r0, _, _ := syscall.Syscall6(procRegSetValueExW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(valueName)), uintptr(reserved), uintptr(vtype), uintptr(unsafe.Pointer(buf)), uintptr(bufsize))
if r0 != 0 {
regerrno = syscall.Errno(r0)
}
@@ -100,11 +101,7 @@ func expandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32,
r0, _, e1 := syscall.Syscall(procExpandEnvironmentStringsW.Addr(), 3, uintptr(unsafe.Pointer(src)), uintptr(unsafe.Pointer(dst)), uintptr(size))
n = uint32(r0)
if n == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+ err = errnoErr(e1)
}
return
}
diff --git a/src/internal/syscall/windows/syscall_windows.go b/src/internal/syscall/windows/syscall_windows.go
index edf0b5a40b..1f40c11820 100644
--- a/src/internal/syscall/windows/syscall_windows.go
+++ b/src/internal/syscall/windows/syscall_windows.go
@@ -131,6 +131,14 @@ type IpAdapterAddresses struct {
/* more fields might be present here. */
}
+type FILE_BASIC_INFO struct {
+ CreationTime syscall.Filetime
+ LastAccessTime syscall.Filetime
+ LastWriteTime syscall.Filetime
+ ChangedTime syscall.Filetime
+ FileAttributes uint32
+}
+
const (
IfOperStatusUp = 1
IfOperStatusDown = 2
@@ -145,6 +153,7 @@ const (
//sys GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW
//sys MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW
//sys GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32, err error) = kernel32.GetModuleFileNameW
+//sys SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf uintptr, bufsize uint32) (err error) = kernel32.SetFileInformationByHandle
const (
WSA_FLAG_OVERLAPPED = 0x01
diff --git a/src/internal/syscall/windows/zsyscall_windows.go b/src/internal/syscall/windows/zsyscall_windows.go
index ca5b4e6f16..170b239486 100644
--- a/src/internal/syscall/windows/zsyscall_windows.go
+++ b/src/internal/syscall/windows/zsyscall_windows.go
@@ -18,6 +18,7 @@ const (
var (
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
+ errERROR_EINVAL error = syscall.EINVAL
)
// errnoErr returns common boxed Errno values, to prevent
@@ -25,7 +26,7 @@ var (
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
- return nil
+ return errERROR_EINVAL
case errnoERROR_IO_PENDING:
return errERROR_IO_PENDING
}
@@ -36,121 +37,113 @@ func errnoErr(e syscall.Errno) error {
}
var (
+ modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll"))
modiphlpapi = syscall.NewLazyDLL(sysdll.Add("iphlpapi.dll"))
modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll"))
- modws2_32 = syscall.NewLazyDLL(sysdll.Add("ws2_32.dll"))
modnetapi32 = syscall.NewLazyDLL(sysdll.Add("netapi32.dll"))
- modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll"))
- moduserenv = syscall.NewLazyDLL(sysdll.Add("userenv.dll"))
modpsapi = syscall.NewLazyDLL(sysdll.Add("psapi.dll"))
+ moduserenv = syscall.NewLazyDLL(sysdll.Add("userenv.dll"))
+ modws2_32 = syscall.NewLazyDLL(sysdll.Add("ws2_32.dll"))
+ procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges")
+ procDuplicateTokenEx = modadvapi32.NewProc("DuplicateTokenEx")
+ procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf")
+ procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW")
+ procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken")
+ procRevertToSelf = modadvapi32.NewProc("RevertToSelf")
+ procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation")
procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses")
+ procGetACP = modkernel32.NewProc("GetACP")
procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW")
- procMoveFileExW = modkernel32.NewProc("MoveFileExW")
+ procGetConsoleCP = modkernel32.NewProc("GetConsoleCP")
+ procGetCurrentThread = modkernel32.NewProc("GetCurrentThread")
+ procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx")
+ procGetFinalPathNameByHandleW = modkernel32.NewProc("GetFinalPathNameByHandleW")
procGetModuleFileNameW = modkernel32.NewProc("GetModuleFileNameW")
- procWSASocketW = modws2_32.NewProc("WSASocketW")
procLockFileEx = modkernel32.NewProc("LockFileEx")
- procUnlockFileEx = modkernel32.NewProc("UnlockFileEx")
- procGetACP = modkernel32.NewProc("GetACP")
- procGetConsoleCP = modkernel32.NewProc("GetConsoleCP")
+ procMoveFileExW = modkernel32.NewProc("MoveFileExW")
procMultiByteToWideChar = modkernel32.NewProc("MultiByteToWideChar")
- procGetCurrentThread = modkernel32.NewProc("GetCurrentThread")
+ procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle")
+ procUnlockFileEx = modkernel32.NewProc("UnlockFileEx")
procNetShareAdd = modnetapi32.NewProc("NetShareAdd")
procNetShareDel = modnetapi32.NewProc("NetShareDel")
- procGetFinalPathNameByHandleW = modkernel32.NewProc("GetFinalPathNameByHandleW")
+ procNetUserGetLocalGroups = modnetapi32.NewProc("NetUserGetLocalGroups")
+ procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock")
procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock")
- procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf")
- procRevertToSelf = modadvapi32.NewProc("RevertToSelf")
- procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken")
- procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW")
- procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges")
- procDuplicateTokenEx = modadvapi32.NewProc("DuplicateTokenEx")
- procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation")
procGetProfilesDirectoryW = moduserenv.NewProc("GetProfilesDirectoryW")
- procNetUserGetLocalGroups = modnetapi32.NewProc("NetUserGetLocalGroups")
- procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
- procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx")
+ procWSASocketW = modws2_32.NewProc("WSASocketW")
)
-func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) {
- r0, _, _ := syscall.Syscall6(procGetAdaptersAddresses.Addr(), 5, uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizePointer)), 0)
- if r0 != 0 {
- errcode = syscall.Errno(r0)
+func adjustTokenPrivileges(token syscall.Token, disableAllPrivileges bool, newstate *TOKEN_PRIVILEGES, buflen uint32, prevstate *TOKEN_PRIVILEGES, returnlen *uint32) (ret uint32, err error) {
+ var _p0 uint32
+ if disableAllPrivileges {
+ _p0 = 1
+ }
+ r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen)))
+ ret = uint32(r0)
+ if true {
+ err = errnoErr(e1)
}
return
}
-func GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) {
- r1, _, e1 := syscall.Syscall(procGetComputerNameExW.Addr(), 3, uintptr(nameformat), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n)))
+func DuplicateTokenEx(hExistingToken syscall.Token, dwDesiredAccess uint32, lpTokenAttributes *syscall.SecurityAttributes, impersonationLevel uint32, tokenType TokenType, phNewToken *syscall.Token) (err error) {
+ r1, _, e1 := syscall.Syscall6(procDuplicateTokenEx.Addr(), 6, uintptr(hExistingToken), uintptr(dwDesiredAccess), uintptr(unsafe.Pointer(lpTokenAttributes)), uintptr(impersonationLevel), uintptr(tokenType), uintptr(unsafe.Pointer(phNewToken)))
if r1 == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+ err = errnoErr(e1)
}
return
}
-func MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) {
- r1, _, e1 := syscall.Syscall(procMoveFileExW.Addr(), 3, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), uintptr(flags))
+func ImpersonateSelf(impersonationlevel uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(impersonationlevel), 0, 0)
if r1 == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+ err = errnoErr(e1)
}
return
}
-func GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32, err error) {
- r0, _, e1 := syscall.Syscall(procGetModuleFileNameW.Addr(), 3, uintptr(module), uintptr(unsafe.Pointer(fn)), uintptr(len))
- n = uint32(r0)
- if n == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+func LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) {
+ r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemname)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid)))
+ if r1 == 0 {
+ err = errnoErr(e1)
}
return
}
-func WSASocket(af int32, typ int32, protocol int32, protinfo *syscall.WSAProtocolInfo, group uint32, flags uint32) (handle syscall.Handle, err error) {
- r0, _, e1 := syscall.Syscall6(procWSASocketW.Addr(), 6, uintptr(af), uintptr(typ), uintptr(protocol), uintptr(unsafe.Pointer(protinfo)), uintptr(group), uintptr(flags))
- handle = syscall.Handle(r0)
- if handle == syscall.InvalidHandle {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+func OpenThreadToken(h syscall.Handle, access uint32, openasself bool, token *syscall.Token) (err error) {
+ var _p0 uint32
+ if openasself {
+ _p0 = 1
+ }
+ r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(h), uintptr(access), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
}
return
}
-func LockFileEx(file syscall.Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) {
- r1, _, e1 := syscall.Syscall6(procLockFileEx.Addr(), 6, uintptr(file), uintptr(flags), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped)))
+func RevertToSelf() (err error) {
+ r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0)
if r1 == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+ err = errnoErr(e1)
}
return
}
-func UnlockFileEx(file syscall.Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) {
- r1, _, e1 := syscall.Syscall6(procUnlockFileEx.Addr(), 5, uintptr(file), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped)), 0)
+func SetTokenInformation(tokenHandle syscall.Token, tokenInformationClass uint32, tokenInformation uintptr, tokenInformationLength uint32) (err error) {
+ r1, _, e1 := syscall.Syscall6(procSetTokenInformation.Addr(), 4, uintptr(tokenHandle), uintptr(tokenInformationClass), uintptr(tokenInformation), uintptr(tokenInformationLength), 0, 0)
if r1 == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+ err = errnoErr(e1)
+ }
+ return
+}
+
+func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) {
+ r0, _, _ := syscall.Syscall6(procGetAdaptersAddresses.Addr(), 5, uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizePointer)), 0)
+ if r0 != 0 {
+ errcode = syscall.Errno(r0)
}
return
}
@@ -161,22 +154,17 @@ func GetACP() (acp uint32) {
return
}
-func GetConsoleCP() (ccp uint32) {
- r0, _, _ := syscall.Syscall(procGetConsoleCP.Addr(), 0, 0, 0, 0)
- ccp = uint32(r0)
+func GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procGetComputerNameExW.Addr(), 3, uintptr(nameformat), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n)))
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
return
}
-func MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) {
- r0, _, e1 := syscall.Syscall6(procMultiByteToWideChar.Addr(), 6, uintptr(codePage), uintptr(dwFlags), uintptr(unsafe.Pointer(str)), uintptr(nstr), uintptr(unsafe.Pointer(wchar)), uintptr(nwchar))
- nwrite = int32(r0)
- if nwrite == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
- }
+func GetConsoleCP() (ccp uint32) {
+ r0, _, _ := syscall.Syscall(procGetConsoleCP.Addr(), 0, 0, 0, 0)
+ ccp = uint32(r0)
return
}
@@ -184,211 +172,143 @@ func GetCurrentThread() (pseudoHandle syscall.Handle, err error) {
r0, _, e1 := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0)
pseudoHandle = syscall.Handle(r0)
if pseudoHandle == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+ err = errnoErr(e1)
}
return
}
-func NetShareAdd(serverName *uint16, level uint32, buf *byte, parmErr *uint16) (neterr error) {
- r0, _, _ := syscall.Syscall6(procNetShareAdd.Addr(), 4, uintptr(unsafe.Pointer(serverName)), uintptr(level), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(parmErr)), 0, 0)
- if r0 != 0 {
- neterr = syscall.Errno(r0)
+func GetFileInformationByHandleEx(handle syscall.Handle, class uint32, info *byte, bufsize uint32) (err error) {
+ r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(handle), uintptr(class), uintptr(unsafe.Pointer(info)), uintptr(bufsize), 0, 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
}
return
}
-func NetShareDel(serverName *uint16, netName *uint16, reserved uint32) (neterr error) {
- r0, _, _ := syscall.Syscall(procNetShareDel.Addr(), 3, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(netName)), uintptr(reserved))
- if r0 != 0 {
- neterr = syscall.Errno(r0)
+func GetFinalPathNameByHandle(file syscall.Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) {
+ r0, _, e1 := syscall.Syscall6(procGetFinalPathNameByHandleW.Addr(), 4, uintptr(file), uintptr(unsafe.Pointer(filePath)), uintptr(filePathSize), uintptr(flags), 0, 0)
+ n = uint32(r0)
+ if n == 0 {
+ err = errnoErr(e1)
}
return
}
-func GetFinalPathNameByHandle(file syscall.Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) {
- r0, _, e1 := syscall.Syscall6(procGetFinalPathNameByHandleW.Addr(), 4, uintptr(file), uintptr(unsafe.Pointer(filePath)), uintptr(filePathSize), uintptr(flags), 0, 0)
+func GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32, err error) {
+ r0, _, e1 := syscall.Syscall(procGetModuleFileNameW.Addr(), 3, uintptr(module), uintptr(unsafe.Pointer(fn)), uintptr(len))
n = uint32(r0)
if n == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+ err = errnoErr(e1)
}
return
}
-func CreateEnvironmentBlock(block **uint16, token syscall.Token, inheritExisting bool) (err error) {
- var _p0 uint32
- if inheritExisting {
- _p0 = 1
- } else {
- _p0 = 0
- }
- r1, _, e1 := syscall.Syscall(procCreateEnvironmentBlock.Addr(), 3, uintptr(unsafe.Pointer(block)), uintptr(token), uintptr(_p0))
+func LockFileEx(file syscall.Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) {
+ r1, _, e1 := syscall.Syscall6(procLockFileEx.Addr(), 6, uintptr(file), uintptr(flags), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped)))
if r1 == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+ err = errnoErr(e1)
}
return
}
-func DestroyEnvironmentBlock(block *uint16) (err error) {
- r1, _, e1 := syscall.Syscall(procDestroyEnvironmentBlock.Addr(), 1, uintptr(unsafe.Pointer(block)), 0, 0)
+func MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procMoveFileExW.Addr(), 3, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), uintptr(flags))
if r1 == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+ err = errnoErr(e1)
}
return
}
-func ImpersonateSelf(impersonationlevel uint32) (err error) {
- r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(impersonationlevel), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+func MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) {
+ r0, _, e1 := syscall.Syscall6(procMultiByteToWideChar.Addr(), 6, uintptr(codePage), uintptr(dwFlags), uintptr(unsafe.Pointer(str)), uintptr(nstr), uintptr(unsafe.Pointer(wchar)), uintptr(nwchar))
+ nwrite = int32(r0)
+ if nwrite == 0 {
+ err = errnoErr(e1)
}
return
}
-func RevertToSelf() (err error) {
- r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0)
+func SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf uintptr, bufsize uint32) (err error) {
+ r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(handle), uintptr(fileInformationClass), uintptr(buf), uintptr(bufsize), 0, 0)
if r1 == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+ err = errnoErr(e1)
}
return
}
-func OpenThreadToken(h syscall.Handle, access uint32, openasself bool, token *syscall.Token) (err error) {
- var _p0 uint32
- if openasself {
- _p0 = 1
- } else {
- _p0 = 0
- }
- r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(h), uintptr(access), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0)
+func UnlockFileEx(file syscall.Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) {
+ r1, _, e1 := syscall.Syscall6(procUnlockFileEx.Addr(), 5, uintptr(file), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped)), 0)
if r1 == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+ err = errnoErr(e1)
}
return
}
-func LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) {
- r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemname)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid)))
- if r1 == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+func NetShareAdd(serverName *uint16, level uint32, buf *byte, parmErr *uint16) (neterr error) {
+ r0, _, _ := syscall.Syscall6(procNetShareAdd.Addr(), 4, uintptr(unsafe.Pointer(serverName)), uintptr(level), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(parmErr)), 0, 0)
+ if r0 != 0 {
+ neterr = syscall.Errno(r0)
}
return
}
-func adjustTokenPrivileges(token syscall.Token, disableAllPrivileges bool, newstate *TOKEN_PRIVILEGES, buflen uint32, prevstate *TOKEN_PRIVILEGES, returnlen *uint32) (ret uint32, err error) {
- var _p0 uint32
- if disableAllPrivileges {
- _p0 = 1
- } else {
- _p0 = 0
- }
- r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen)))
- ret = uint32(r0)
- if true {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+func NetShareDel(serverName *uint16, netName *uint16, reserved uint32) (neterr error) {
+ r0, _, _ := syscall.Syscall(procNetShareDel.Addr(), 3, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(netName)), uintptr(reserved))
+ if r0 != 0 {
+ neterr = syscall.Errno(r0)
}
return
}
-func DuplicateTokenEx(hExistingToken syscall.Token, dwDesiredAccess uint32, lpTokenAttributes *syscall.SecurityAttributes, impersonationLevel uint32, tokenType TokenType, phNewToken *syscall.Token) (err error) {
- r1, _, e1 := syscall.Syscall6(procDuplicateTokenEx.Addr(), 6, uintptr(hExistingToken), uintptr(dwDesiredAccess), uintptr(unsafe.Pointer(lpTokenAttributes)), uintptr(impersonationLevel), uintptr(tokenType), uintptr(unsafe.Pointer(phNewToken)))
- if r1 == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+func NetUserGetLocalGroups(serverName *uint16, userName *uint16, level uint32, flags uint32, buf **byte, prefMaxLen uint32, entriesRead *uint32, totalEntries *uint32) (neterr error) {
+ r0, _, _ := syscall.Syscall9(procNetUserGetLocalGroups.Addr(), 8, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(userName)), uintptr(level), uintptr(flags), uintptr(unsafe.Pointer(buf)), uintptr(prefMaxLen), uintptr(unsafe.Pointer(entriesRead)), uintptr(unsafe.Pointer(totalEntries)), 0)
+ if r0 != 0 {
+ neterr = syscall.Errno(r0)
}
return
}
-func SetTokenInformation(tokenHandle syscall.Token, tokenInformationClass uint32, tokenInformation uintptr, tokenInformationLength uint32) (err error) {
- r1, _, e1 := syscall.Syscall6(procSetTokenInformation.Addr(), 4, uintptr(tokenHandle), uintptr(tokenInformationClass), uintptr(tokenInformation), uintptr(tokenInformationLength), 0, 0)
+func GetProcessMemoryInfo(handle syscall.Handle, memCounters *PROCESS_MEMORY_COUNTERS, cb uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procGetProcessMemoryInfo.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(memCounters)), uintptr(cb))
if r1 == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+ err = errnoErr(e1)
}
return
}
-func GetProfilesDirectory(dir *uint16, dirLen *uint32) (err error) {
- r1, _, e1 := syscall.Syscall(procGetProfilesDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(unsafe.Pointer(dirLen)), 0)
+func CreateEnvironmentBlock(block **uint16, token syscall.Token, inheritExisting bool) (err error) {
+ var _p0 uint32
+ if inheritExisting {
+ _p0 = 1
+ }
+ r1, _, e1 := syscall.Syscall(procCreateEnvironmentBlock.Addr(), 3, uintptr(unsafe.Pointer(block)), uintptr(token), uintptr(_p0))
if r1 == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+ err = errnoErr(e1)
}
return
}
-func NetUserGetLocalGroups(serverName *uint16, userName *uint16, level uint32, flags uint32, buf **byte, prefMaxLen uint32, entriesRead *uint32, totalEntries *uint32) (neterr error) {
- r0, _, _ := syscall.Syscall9(procNetUserGetLocalGroups.Addr(), 8, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(userName)), uintptr(level), uintptr(flags), uintptr(unsafe.Pointer(buf)), uintptr(prefMaxLen), uintptr(unsafe.Pointer(entriesRead)), uintptr(unsafe.Pointer(totalEntries)), 0)
- if r0 != 0 {
- neterr = syscall.Errno(r0)
+func DestroyEnvironmentBlock(block *uint16) (err error) {
+ r1, _, e1 := syscall.Syscall(procDestroyEnvironmentBlock.Addr(), 1, uintptr(unsafe.Pointer(block)), 0, 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
}
return
}
-func GetProcessMemoryInfo(handle syscall.Handle, memCounters *PROCESS_MEMORY_COUNTERS, cb uint32) (err error) {
- r1, _, e1 := syscall.Syscall(procGetProcessMemoryInfo.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(memCounters)), uintptr(cb))
+func GetProfilesDirectory(dir *uint16, dirLen *uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procGetProfilesDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(unsafe.Pointer(dirLen)), 0)
if r1 == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+ err = errnoErr(e1)
}
return
}
-func GetFileInformationByHandleEx(handle syscall.Handle, class uint32, info *byte, bufsize uint32) (err error) {
- r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(handle), uintptr(class), uintptr(unsafe.Pointer(info)), uintptr(bufsize), 0, 0)
- if r1 == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
+func WSASocket(af int32, typ int32, protocol int32, protinfo *syscall.WSAProtocolInfo, group uint32, flags uint32) (handle syscall.Handle, err error) {
+ r0, _, e1 := syscall.Syscall6(procWSASocketW.Addr(), 6, uintptr(af), uintptr(typ), uintptr(protocol), uintptr(unsafe.Pointer(protinfo)), uintptr(group), uintptr(flags))
+ handle = syscall.Handle(r0)
+ if handle == syscall.InvalidHandle {
+ err = errnoErr(e1)
}
return
}
diff --git a/src/internal/sysinfo/sysinfo.go b/src/internal/sysinfo/sysinfo.go
new file mode 100644
index 0000000000..961be7abae
--- /dev/null
+++ b/src/internal/sysinfo/sysinfo.go
@@ -0,0 +1,31 @@
+// Copyright 2020 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 sysinfo implements high level hardware information gathering
+// that can be used for debugging or information purposes.
+package sysinfo
+
+import (
+ internalcpu "internal/cpu"
+ "sync"
+)
+
+type cpuInfo struct {
+ once sync.Once
+ name string
+}
+
+var CPU cpuInfo
+
+func (cpu *cpuInfo) Name() string {
+ cpu.once.Do(func() {
+ // Try to get the information from internal/cpu.
+ if name := internalcpu.Name(); name != "" {
+ cpu.name = name
+ return
+ }
+ // TODO(martisch): use /proc/cpuinfo and /sys/devices/system/cpu/ on Linux as fallback.
+ })
+ return cpu.name
+}
diff --git a/src/internal/testenv/testenv.go b/src/internal/testenv/testenv.go
index 309b2702ed..c902b1404f 100644
--- a/src/internal/testenv/testenv.go
+++ b/src/internal/testenv/testenv.go
@@ -43,12 +43,8 @@ func HasGoBuild() bool {
return false
}
switch runtime.GOOS {
- case "android", "js":
+ case "android", "js", "ios":
return false
- case "darwin":
- if runtime.GOARCH == "arm64" {
- return false
- }
}
return true
}
@@ -122,12 +118,8 @@ func GoTool() (string, error) {
// using os.StartProcess or (more commonly) exec.Command.
func HasExec() bool {
switch runtime.GOOS {
- case "js":
+ case "js", "ios":
return false
- case "darwin":
- if runtime.GOARCH == "arm64" {
- return false
- }
}
return true
}
@@ -135,10 +127,8 @@ func HasExec() bool {
// HasSrc reports whether the entire source tree is available under GOROOT.
func HasSrc() bool {
switch runtime.GOOS {
- case "darwin":
- if runtime.GOARCH == "arm64" {
- return false
- }
+ case "ios":
+ return false
}
return true
}
@@ -202,6 +192,32 @@ func MustHaveCGO(t testing.TB) {
}
}
+// CanInternalLink reports whether the current system can link programs with
+// internal linking.
+// (This is the opposite of cmd/internal/sys.MustLinkExternal. Keep them in sync.)
+func CanInternalLink() bool {
+ switch runtime.GOOS {
+ case "android":
+ if runtime.GOARCH != "arm64" {
+ return false
+ }
+ case "ios":
+ if runtime.GOARCH == "arm64" {
+ return false
+ }
+ }
+ return true
+}
+
+// MustInternalLink checks that the current system can link programs with internal
+// linking.
+// If not, MustInternalLink calls t.Skip with an explanation.
+func MustInternalLink(t testing.TB) {
+ if !CanInternalLink() {
+ t.Skipf("skipping test: internal linking on %s/%s is not supported", runtime.GOOS, runtime.GOARCH)
+ }
+}
+
// HasSymlink reports whether the current system can use os.Symlink.
func HasSymlink() bool {
ok, _ := hasSymlink()
@@ -270,3 +286,23 @@ func CleanCmdEnv(cmd *exec.Cmd) *exec.Cmd {
}
return cmd
}
+
+// CPUIsSlow reports whether the CPU running the test is suspected to be slow.
+func CPUIsSlow() bool {
+ switch runtime.GOARCH {
+ case "arm", "mips", "mipsle", "mips64", "mips64le":
+ return true
+ }
+ return false
+}
+
+// SkipIfShortAndSlow skips t if -short is set and the CPU running the test is
+// suspected to be slow.
+//
+// (This is useful for CPU-intensive tests that otherwise complete quickly.)
+func SkipIfShortAndSlow(t testing.TB) {
+ if testing.Short() && CPUIsSlow() {
+ t.Helper()
+ t.Skipf("skipping test in -short mode on %s", runtime.GOARCH)
+ }
+}
diff --git a/src/internal/testenv/testenv_windows.go b/src/internal/testenv/testenv_windows.go
index eb8d6ac165..4802b13951 100644
--- a/src/internal/testenv/testenv_windows.go
+++ b/src/internal/testenv/testenv_windows.go
@@ -5,7 +5,6 @@
package testenv
import (
- "io/ioutil"
"os"
"path/filepath"
"sync"
@@ -16,7 +15,7 @@ var symlinkOnce sync.Once
var winSymlinkErr error
func initWinHasSymlink() {
- tmpdir, err := ioutil.TempDir("", "symtest")
+ tmpdir, err := os.MkdirTemp("", "symtest")
if err != nil {
panic("failed to create temp directory: " + err.Error())
}
diff --git a/src/internal/trace/gc_test.go b/src/internal/trace/gc_test.go
index 4f9c77041a..9b9771e7b0 100644
--- a/src/internal/trace/gc_test.go
+++ b/src/internal/trace/gc_test.go
@@ -6,8 +6,8 @@ package trace
import (
"bytes"
- "io/ioutil"
"math"
+ "os"
"testing"
"time"
)
@@ -84,7 +84,7 @@ func TestMMUTrace(t *testing.T) {
t.Skip("skipping in -short mode")
}
- data, err := ioutil.ReadFile("testdata/stress_1_10_good")
+ data, err := os.ReadFile("testdata/stress_1_10_good")
if err != nil {
t.Fatalf("failed to read input file: %v", err)
}
@@ -126,7 +126,7 @@ func TestMMUTrace(t *testing.T) {
}
func BenchmarkMMU(b *testing.B) {
- data, err := ioutil.ReadFile("testdata/stress_1_10_good")
+ data, err := os.ReadFile("testdata/stress_1_10_good")
if err != nil {
b.Fatalf("failed to read input file: %v", err)
}
diff --git a/src/internal/trace/parser_test.go b/src/internal/trace/parser_test.go
index 6d87970157..cdab95a59e 100644
--- a/src/internal/trace/parser_test.go
+++ b/src/internal/trace/parser_test.go
@@ -6,7 +6,6 @@ package trace
import (
"bytes"
- "io/ioutil"
"os"
"path/filepath"
"strings"
@@ -34,20 +33,20 @@ func TestCorruptedInputs(t *testing.T) {
}
func TestParseCanned(t *testing.T) {
- files, err := ioutil.ReadDir("./testdata")
+ files, err := os.ReadDir("./testdata")
if err != nil {
t.Fatalf("failed to read ./testdata: %v", err)
}
for _, f := range files {
- name := filepath.Join("./testdata", f.Name())
- info, err := os.Stat(name)
+ info, err := f.Info()
if err != nil {
t.Fatal(err)
}
if testing.Short() && info.Size() > 10000 {
continue
}
- data, err := ioutil.ReadFile(name)
+ name := filepath.Join("./testdata", f.Name())
+ data, err := os.ReadFile(name)
if err != nil {
t.Fatal(err)
}