Skip to content

Commit 729ebf1

Browse files
authored
Merge branch 'master' into windows-conin-event
2 parents a8df59a + b215a1c commit 729ebf1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+2473
-613
lines changed

README.md

+4-7
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,13 @@
55
This repository holds supplemental Go packages for low-level interactions with
66
the operating system.
77

8-
## Download/Install
9-
10-
The easiest way to install is to run `go get -u golang.org/x/sys`. You can
11-
also manually git clone the repository to `$GOPATH/src/golang.org/x/sys`.
12-
138
## Report Issues / Send Patches
149

1510
This repository uses Gerrit for code changes. To learn how to submit changes to
16-
this repository, see https://golang.org/doc/contribute.html.
11+
this repository, see https://go.dev/doc/contribute.
12+
13+
The git repository is https://go.googlesource.com/sys.
1714

1815
The main issue tracker for the sys repository is located at
19-
https://github.com/golang/go/issues. Prefix your issue with "x/sys:" in the
16+
https://go.dev/issues. Prefix your issue with "x/sys:" in the
2017
subject line, so it is easy to find.

cpu/asm_darwin_x86_gc.s

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2024 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build darwin && amd64 && gc
6+
7+
#include "textflag.h"
8+
9+
TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0
10+
JMP libc_sysctl(SB)
11+
GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8
12+
DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB)
13+
14+
TEXT libc_sysctlbyname_trampoline<>(SB),NOSPLIT,$0-0
15+
JMP libc_sysctlbyname(SB)
16+
GLOBL ·libc_sysctlbyname_trampoline_addr(SB), RODATA, $8
17+
DATA ·libc_sysctlbyname_trampoline_addr(SB)/8, $libc_sysctlbyname_trampoline<>(SB)

cpu/cpu.go

+3
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ var X86 struct {
7272
HasSSSE3 bool // Supplemental streaming SIMD extension 3
7373
HasSSE41 bool // Streaming SIMD extension 4 and 4.1
7474
HasSSE42 bool // Streaming SIMD extension 4 and 4.2
75+
HasAVXIFMA bool // Advanced vector extension Integer Fused Multiply Add
76+
HasAVXVNNI bool // Advanced vector extension Vector Neural Network Instructions
77+
HasAVXVNNIInt8 bool // Advanced vector extension Vector Neural Network Int8 instructions
7578
_ CacheLinePad
7679
}
7780

cpu/cpu_darwin_x86.go

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright 2024 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build darwin && amd64 && gc
6+
7+
package cpu
8+
9+
// darwinSupportsAVX512 checks Darwin kernel for AVX512 support via sysctl
10+
// call (see issue 43089). It also restricts AVX512 support for Darwin to
11+
// kernel version 21.3.0 (MacOS 12.2.0) or later (see issue 49233).
12+
//
13+
// Background:
14+
// Darwin implements a special mechanism to economize on thread state when
15+
// AVX512 specific registers are not in use. This scheme minimizes state when
16+
// preempting threads that haven't yet used any AVX512 instructions, but adds
17+
// special requirements to check for AVX512 hardware support at runtime (e.g.
18+
// via sysctl call or commpage inspection). See issue 43089 and link below for
19+
// full background:
20+
// https://github.com/apple-oss-distributions/xnu/blob/xnu-11215.1.10/osfmk/i386/fpu.c#L214-L240
21+
//
22+
// Additionally, all versions of the Darwin kernel from 19.6.0 through 21.2.0
23+
// (corresponding to MacOS 10.15.6 - 12.1) have a bug that can cause corruption
24+
// of the AVX512 mask registers (K0-K7) upon signal return. For this reason
25+
// AVX512 is considered unsafe to use on Darwin for kernel versions prior to
26+
// 21.3.0, where a fix has been confirmed. See issue 49233 for full background.
27+
func darwinSupportsAVX512() bool {
28+
return darwinSysctlEnabled([]byte("hw.optional.avx512f\x00")) && darwinKernelVersionCheck(21, 3, 0)
29+
}
30+
31+
// Ensure Darwin kernel version is at least major.minor.patch, avoiding dependencies
32+
func darwinKernelVersionCheck(major, minor, patch int) bool {
33+
var release [256]byte
34+
err := darwinOSRelease(&release)
35+
if err != nil {
36+
return false
37+
}
38+
39+
var mmp [3]int
40+
c := 0
41+
Loop:
42+
for _, b := range release[:] {
43+
switch {
44+
case b >= '0' && b <= '9':
45+
mmp[c] = 10*mmp[c] + int(b-'0')
46+
case b == '.':
47+
c++
48+
if c > 2 {
49+
return false
50+
}
51+
case b == 0:
52+
break Loop
53+
default:
54+
return false
55+
}
56+
}
57+
if c != 2 {
58+
return false
59+
}
60+
return mmp[0] > major || mmp[0] == major && (mmp[1] > minor || mmp[1] == minor && mmp[2] >= patch)
61+
}

cpu/cpu_gc_x86.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66

77
package cpu
88

9-
// cpuid is implemented in cpu_x86.s for gc compiler
9+
// cpuid is implemented in cpu_gc_x86.s for gc compiler
1010
// and in cpu_gccgo.c for gccgo.
1111
func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32)
1212

13-
// xgetbv with ecx = 0 is implemented in cpu_x86.s for gc compiler
13+
// xgetbv with ecx = 0 is implemented in cpu_gc_x86.s for gc compiler
1414
// and in cpu_gccgo.c for gccgo.
1515
func xgetbv() (eax, edx uint32)

cpu/cpu_x86.s renamed to cpu/cpu_gc_x86.s

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ TEXT ·cpuid(SB), NOSPLIT, $0-24
1818
RET
1919

2020
// func xgetbv() (eax, edx uint32)
21-
TEXT ·xgetbv(SB),NOSPLIT,$0-8
21+
TEXT ·xgetbv(SB), NOSPLIT, $0-8
2222
MOVL $0, CX
2323
XGETBV
2424
MOVL AX, eax+0(FP)

cpu/cpu_gccgo_x86.go

-6
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,3 @@ func xgetbv() (eax, edx uint32) {
2323
gccgoXgetbv(&a, &d)
2424
return a, d
2525
}
26-
27-
// gccgo doesn't build on Darwin, per:
28-
// https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/gcc.rb#L76
29-
func darwinSupportsAVX512() bool {
30-
return false
31-
}

cpu/cpu_other_x86.go

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright 2024 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build 386 || amd64p32 || (amd64 && (!darwin || !gc))
6+
7+
package cpu
8+
9+
func darwinSupportsAVX512() bool {
10+
panic("only implemented for gc && amd64 && darwin")
11+
}

cpu/cpu_test.go

+34
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,40 @@ func TestAVX512HasAVX2AndAVX(t *testing.T) {
4141
}
4242
}
4343

44+
func TestAVX512BF16HasAVX512(t *testing.T) {
45+
if runtime.GOARCH == "amd64" {
46+
if cpu.X86.HasAVX512BF16 && !cpu.X86.HasAVX512 {
47+
t.Fatal("HasAVX512 expected true, got false")
48+
}
49+
}
50+
}
51+
52+
func TestAVXVNNIHasAVX(t *testing.T) {
53+
if cpu.X86.HasAVXVNNI && !cpu.X86.HasAVX {
54+
t.Fatal("HasAVX expected true, got false")
55+
}
56+
}
57+
58+
func TestAVXIFMAHasAVXVNNIAndAVX(t *testing.T) {
59+
if cpu.X86.HasAVXIFMA && !cpu.X86.HasAVX {
60+
t.Fatal("HasAVX expected true, got false")
61+
}
62+
63+
if cpu.X86.HasAVXIFMA && !cpu.X86.HasAVXVNNI {
64+
t.Fatal("HasAVXVNNI expected true, got false")
65+
}
66+
}
67+
68+
func TestAVXVNNIInt8HasAVXVNNIAndAVX(t *testing.T) {
69+
if cpu.X86.HasAVXVNNIInt8 && !cpu.X86.HasAVXVNNI {
70+
t.Fatal("HasAVXVNNI expected true, got false")
71+
}
72+
73+
if cpu.X86.HasAVXVNNIInt8 && !cpu.X86.HasAVX {
74+
t.Fatal("HasAVX expected true, got false")
75+
}
76+
}
77+
4478
func TestARM64minimalFeatures(t *testing.T) {
4579
if runtime.GOARCH != "arm64" || runtime.GOOS == "ios" {
4680
return

cpu/cpu_x86.go

+19-8
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ func initOptions() {
5353
{Name: "sse41", Feature: &X86.HasSSE41},
5454
{Name: "sse42", Feature: &X86.HasSSE42},
5555
{Name: "ssse3", Feature: &X86.HasSSSE3},
56+
{Name: "avxifma", Feature: &X86.HasAVXIFMA},
57+
{Name: "avxvnni", Feature: &X86.HasAVXVNNI},
58+
{Name: "avxvnniint8", Feature: &X86.HasAVXVNNIInt8},
5659

5760
// These capabilities should always be enabled on amd64:
5861
{Name: "sse2", Feature: &X86.HasSSE2, Required: runtime.GOARCH == "amd64"},
@@ -92,10 +95,8 @@ func archInit() {
9295
osSupportsAVX = isSet(1, eax) && isSet(2, eax)
9396

9497
if runtime.GOOS == "darwin" {
95-
// Darwin doesn't save/restore AVX-512 mask registers correctly across signal handlers.
96-
// Since users can't rely on mask register contents, let's not advertise AVX-512 support.
97-
// See issue 49233.
98-
osSupportsAVX512 = false
98+
// Darwin requires special AVX512 checks, see cpu_darwin_x86.go
99+
osSupportsAVX512 = osSupportsAVX && darwinSupportsAVX512()
99100
} else {
100101
// Check if OPMASK and ZMM registers have OS support.
101102
osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax)
@@ -108,7 +109,7 @@ func archInit() {
108109
return
109110
}
110111

111-
_, ebx7, ecx7, edx7 := cpuid(7, 0)
112+
eax7, ebx7, ecx7, edx7 := cpuid(7, 0)
112113
X86.HasBMI1 = isSet(3, ebx7)
113114
X86.HasAVX2 = isSet(5, ebx7) && osSupportsAVX
114115
X86.HasBMI2 = isSet(8, ebx7)
@@ -136,14 +137,24 @@ func archInit() {
136137
X86.HasAVX512VAES = isSet(9, ecx7)
137138
X86.HasAVX512VBMI2 = isSet(6, ecx7)
138139
X86.HasAVX512BITALG = isSet(12, ecx7)
139-
140-
eax71, _, _, _ := cpuid(7, 1)
141-
X86.HasAVX512BF16 = isSet(5, eax71)
142140
}
143141

144142
X86.HasAMXTile = isSet(24, edx7)
145143
X86.HasAMXInt8 = isSet(25, edx7)
146144
X86.HasAMXBF16 = isSet(22, edx7)
145+
146+
// These features depend on the second level of extended features.
147+
if eax7 >= 1 {
148+
eax71, _, _, edx71 := cpuid(7, 1)
149+
if X86.HasAVX512 {
150+
X86.HasAVX512BF16 = isSet(5, eax71)
151+
}
152+
if X86.HasAVX {
153+
X86.HasAVXIFMA = isSet(23, eax71)
154+
X86.HasAVXVNNI = isSet(4, eax71)
155+
X86.HasAVXVNNIInt8 = isSet(4, edx71)
156+
}
157+
}
147158
}
148159

149160
func isSet(bitpos uint, value uint32) bool {

cpu/syscall_darwin_x86_gc.go

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Copyright 2024 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Minimal copy of x/sys/unix so the cpu package can make a
6+
// system call on Darwin without depending on x/sys/unix.
7+
8+
//go:build darwin && amd64 && gc
9+
10+
package cpu
11+
12+
import (
13+
"syscall"
14+
"unsafe"
15+
)
16+
17+
type _C_int int32
18+
19+
// adapted from unix.Uname() at x/sys/unix/syscall_darwin.go L419
20+
func darwinOSRelease(release *[256]byte) error {
21+
// from x/sys/unix/zerrors_openbsd_amd64.go
22+
const (
23+
CTL_KERN = 0x1
24+
KERN_OSRELEASE = 0x2
25+
)
26+
27+
mib := []_C_int{CTL_KERN, KERN_OSRELEASE}
28+
n := unsafe.Sizeof(*release)
29+
30+
return sysctl(mib, &release[0], &n, nil, 0)
31+
}
32+
33+
type Errno = syscall.Errno
34+
35+
var _zero uintptr // Single-word zero for use when we need a valid pointer to 0 bytes.
36+
37+
// from x/sys/unix/zsyscall_darwin_amd64.go L791-807
38+
func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error {
39+
var _p0 unsafe.Pointer
40+
if len(mib) > 0 {
41+
_p0 = unsafe.Pointer(&mib[0])
42+
} else {
43+
_p0 = unsafe.Pointer(&_zero)
44+
}
45+
if _, _, err := syscall_syscall6(
46+
libc_sysctl_trampoline_addr,
47+
uintptr(_p0),
48+
uintptr(len(mib)),
49+
uintptr(unsafe.Pointer(old)),
50+
uintptr(unsafe.Pointer(oldlen)),
51+
uintptr(unsafe.Pointer(new)),
52+
uintptr(newlen),
53+
); err != 0 {
54+
return err
55+
}
56+
57+
return nil
58+
}
59+
60+
var libc_sysctl_trampoline_addr uintptr
61+
62+
// adapted from internal/cpu/cpu_arm64_darwin.go
63+
func darwinSysctlEnabled(name []byte) bool {
64+
out := int32(0)
65+
nout := unsafe.Sizeof(out)
66+
if ret := sysctlbyname(&name[0], (*byte)(unsafe.Pointer(&out)), &nout, nil, 0); ret != nil {
67+
return false
68+
}
69+
return out > 0
70+
}
71+
72+
//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib"
73+
74+
var libc_sysctlbyname_trampoline_addr uintptr
75+
76+
// adapted from runtime/sys_darwin.go in the pattern of sysctl() above, as defined in x/sys/unix
77+
func sysctlbyname(name *byte, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error {
78+
if _, _, err := syscall_syscall6(
79+
libc_sysctlbyname_trampoline_addr,
80+
uintptr(unsafe.Pointer(name)),
81+
uintptr(unsafe.Pointer(old)),
82+
uintptr(unsafe.Pointer(oldlen)),
83+
uintptr(unsafe.Pointer(new)),
84+
uintptr(newlen),
85+
0,
86+
); err != 0 {
87+
return err
88+
}
89+
90+
return nil
91+
}
92+
93+
//go:cgo_import_dynamic libc_sysctlbyname sysctlbyname "/usr/lib/libSystem.B.dylib"
94+
95+
// Implemented in the runtime package (runtime/sys_darwin.go)
96+
func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
97+
98+
//go:linkname syscall_syscall6 syscall.syscall6

unix/dup3_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
//go:build freebsd || linux || netbsd || openbsd
5+
//go:build dragonfly || freebsd || linux || netbsd || openbsd
66

77
package unix_test
88

@@ -16,7 +16,7 @@ import (
1616
)
1717

1818
func TestDup3(t *testing.T) {
19-
tempFile, err := os.Create(filepath.Join(t.TempDir(), "TestDup"))
19+
tempFile, err := os.Create(filepath.Join(t.TempDir(), "TestDup3"))
2020
if err != nil {
2121
t.Fatal(err)
2222
}

0 commit comments

Comments
 (0)