diff --git a/cpu/cpu.go b/cpu/cpu.go index ec07aab057..02609d5b21 100644 --- a/cpu/cpu.go +++ b/cpu/cpu.go @@ -201,6 +201,25 @@ var S390X struct { _ CacheLinePad } +// RISCV64 contains the supported CPU features and performance characteristics for riscv64 +// platforms. The booleans in RISCV64, with the exception of HasFastMisaligned, indicate +// the presence of RISC-V extensions. +// +// It is safe to assume that all the RV64G extensions are supported and so they are omitted from +// this structure. As riscv64 Go programs require at least RV64G, the code that populates +// this structure cannot run successfully if some of the RV64G extensions are missing. +// The struct is padded to avoid false sharing. +var RISCV64 struct { + _ CacheLinePad + HasFastMisaligned bool // Fast misaligned accesses + HasC bool // Compressed instruction-set extension + HasV bool // Vector extension compatible with RVV 1.0 + HasZba bool // Address generation instructions extension + HasZbb bool // Basic bit-manipulation extension + HasZbs bool // Single-bit instructions extension + _ CacheLinePad +} + func init() { archInit() initOptions() diff --git a/cpu/cpu_linux_noinit.go b/cpu/cpu_linux_noinit.go index cd63e73355..7d902b6847 100644 --- a/cpu/cpu_linux_noinit.go +++ b/cpu/cpu_linux_noinit.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. -//go:build linux && !arm && !arm64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !s390x +//go:build linux && !arm && !arm64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !s390x && !riscv64 package cpu diff --git a/cpu/cpu_linux_riscv64.go b/cpu/cpu_linux_riscv64.go new file mode 100644 index 0000000000..cb4a0c5728 --- /dev/null +++ b/cpu/cpu_linux_riscv64.go @@ -0,0 +1,137 @@ +// Copyright 2024 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 cpu + +import ( + "syscall" + "unsafe" +) + +// RISC-V extension discovery code for Linux. The approach here is to first try the riscv_hwprobe +// syscall falling back to HWCAP to check for the C extension if riscv_hwprobe is not available. +// +// A note on detection of the Vector extension using HWCAP. +// +// Support for the Vector extension version 1.0 was added to the Linux kernel in release 6.5. +// Support for the riscv_hwprobe syscall was added in 6.4. It follows that if the riscv_hwprobe +// syscall is not available then neither is the Vector extension (which needs kernel support). +// The riscv_hwprobe syscall should then be all we need to detect the Vector extension. +// However, some RISC-V board manufacturers ship boards with an older kernel on top of which +// they have back-ported various versions of the Vector extension patches but not the riscv_hwprobe +// patches. These kernels advertise support for the Vector extension using HWCAP. Falling +// back to HWCAP to detect the Vector extension, if riscv_hwprobe is not available, or simply not +// bothering with riscv_hwprobe at all and just using HWCAP may then seem like an attractive option. +// +// Unfortunately, simply checking the 'V' bit in AT_HWCAP will not work as this bit is used by +// RISC-V board and cloud instance providers to mean different things. The Lichee Pi 4A board +// and the Scaleway RV1 cloud instances use the 'V' bit to advertise their support for the unratified +// 0.7.1 version of the Vector Specification. The Banana Pi BPI-F3 and the CanMV-K230 board use +// it to advertise support for 1.0 of the Vector extension. Versions 0.7.1 and 1.0 of the Vector +// extension are binary incompatible. HWCAP can then not be used in isolation to populate the +// HasV field as this field indicates that the underlying CPU is compatible with RVV 1.0. +// +// There is a way at runtime to distinguish between versions 0.7.1 and 1.0 of the Vector +// specification by issuing a RVV 1.0 vsetvli instruction and checking the vill bit of the vtype +// register. This check would allow us to safely detect version 1.0 of the Vector extension +// with HWCAP, if riscv_hwprobe were not available. However, the check cannot +// be added until the assembler supports the Vector instructions. +// +// Note the riscv_hwprobe syscall does not suffer from these ambiguities by design as all of the +// extensions it advertises support for are explicitly versioned. It's also worth noting that +// the riscv_hwprobe syscall is the only way to detect multi-letter RISC-V extensions, e.g., Zba. +// These cannot be detected using HWCAP and so riscv_hwprobe must be used to detect the majority +// of RISC-V extensions. +// +// Please see https://docs.kernel.org/arch/riscv/hwprobe.html for more information. + +// golang.org/x/sys/cpu is not allowed to depend on golang.org/x/sys/unix so we must +// reproduce the constants, types and functions needed to make the riscv_hwprobe syscall +// here. + +const ( + // Copied from golang.org/x/sys/unix/ztypes_linux_riscv64.go. + riscv_HWPROBE_KEY_IMA_EXT_0 = 0x4 + riscv_HWPROBE_IMA_C = 0x2 + riscv_HWPROBE_IMA_V = 0x4 + riscv_HWPROBE_EXT_ZBA = 0x8 + riscv_HWPROBE_EXT_ZBB = 0x10 + riscv_HWPROBE_EXT_ZBS = 0x20 + riscv_HWPROBE_KEY_CPUPERF_0 = 0x5 + riscv_HWPROBE_MISALIGNED_FAST = 0x3 + riscv_HWPROBE_MISALIGNED_MASK = 0x7 +) + +const ( + // sys_RISCV_HWPROBE is copied from golang.org/x/sys/unix/zsysnum_linux_riscv64.go. + sys_RISCV_HWPROBE = 258 +) + +// riscvHWProbePairs is copied from golang.org/x/sys/unix/ztypes_linux_riscv64.go. +type riscvHWProbePairs struct { + key int64 + value uint64 +} + +const ( + // CPU features + hwcap_RISCV_ISA_C = 1 << ('C' - 'A') +) + +func doinit() { + // A slice of key/value pair structures is passed to the RISCVHWProbe syscall. The key + // field should be initialised with one of the key constants defined above, e.g., + // RISCV_HWPROBE_KEY_IMA_EXT_0. The syscall will set the value field to the appropriate value. + // If the kernel does not recognise a key it will set the key field to -1 and the value field to 0. + + pairs := []riscvHWProbePairs{ + {riscv_HWPROBE_KEY_IMA_EXT_0, 0}, + {riscv_HWPROBE_KEY_CPUPERF_0, 0}, + } + + // This call only indicates that extensions are supported if they are implemented on all cores. + if riscvHWProbe(pairs, 0) { + if pairs[0].key != -1 { + v := uint(pairs[0].value) + RISCV64.HasC = isSet(v, riscv_HWPROBE_IMA_C) + RISCV64.HasV = isSet(v, riscv_HWPROBE_IMA_V) + RISCV64.HasZba = isSet(v, riscv_HWPROBE_EXT_ZBA) + RISCV64.HasZbb = isSet(v, riscv_HWPROBE_EXT_ZBB) + RISCV64.HasZbs = isSet(v, riscv_HWPROBE_EXT_ZBS) + } + if pairs[1].key != -1 { + v := pairs[1].value & riscv_HWPROBE_MISALIGNED_MASK + RISCV64.HasFastMisaligned = v == riscv_HWPROBE_MISALIGNED_FAST + } + } + + // Let's double check with HWCAP if the C extension does not appear to be supported. + // This may happen if we're running on a kernel older than 6.4. + + if !RISCV64.HasC { + RISCV64.HasC = isSet(hwCap, hwcap_RISCV_ISA_C) + } +} + +func isSet(hwc uint, value uint) bool { + return hwc&value != 0 +} + +// riscvHWProbe is a simplified version of the generated wrapper function found in +// golang.org/x/sys/unix/zsyscall_linux_riscv64.go. We simplify it by removing the +// cpuCount and cpus parameters which we do not need. We always want to pass 0 for +// these parameters here so the kernel only reports the extensions that are present +// on all cores. +func riscvHWProbe(pairs []riscvHWProbePairs, flags uint) bool { + var _zero uintptr + var p0 unsafe.Pointer + if len(pairs) > 0 { + p0 = unsafe.Pointer(&pairs[0]) + } else { + p0 = unsafe.Pointer(&_zero) + } + + _, _, e1 := syscall.Syscall6(sys_RISCV_HWPROBE, uintptr(p0), uintptr(len(pairs)), uintptr(0), uintptr(0), uintptr(flags), 0) + return e1 == 0 +} diff --git a/cpu/cpu_riscv64.go b/cpu/cpu_riscv64.go index 7f0c79c004..aca3199c91 100644 --- a/cpu/cpu_riscv64.go +++ b/cpu/cpu_riscv64.go @@ -8,4 +8,13 @@ package cpu const cacheLineSize = 64 -func initOptions() {} +func initOptions() { + options = []option{ + {Name: "fastmisaligned", Feature: &RISCV64.HasFastMisaligned}, + {Name: "c", Feature: &RISCV64.HasC}, + {Name: "v", Feature: &RISCV64.HasV}, + {Name: "zba", Feature: &RISCV64.HasZba}, + {Name: "zbb", Feature: &RISCV64.HasZbb}, + {Name: "zbs", Feature: &RISCV64.HasZbs}, + } +} diff --git a/cpu/cpu_test.go b/cpu/cpu_test.go index ba25551509..7a9bac7e5d 100644 --- a/cpu/cpu_test.go +++ b/cpu/cpu_test.go @@ -61,6 +61,14 @@ func TestMIPS64Initialized(t *testing.T) { } } +func TestRISCV64Initialized(t *testing.T) { + if runtime.GOARCH == "riscv64" { + if !cpu.Initialized { + t.Fatal("Initialized expected true, got false") + } + } +} + // On ppc64x, the ISA bit for POWER8 should always be set on POWER8 and beyond. func TestPPC64minimalFeatures(t *testing.T) { // Do not run this with gccgo on ppc64, as it doesn't have POWER8 as a minimum diff --git a/unix/darwin_amd64_test.go b/unix/darwin_amd64_test.go index b6dac524c4..f89b50e717 100644 --- a/unix/darwin_amd64_test.go +++ b/unix/darwin_amd64_test.go @@ -22,6 +22,7 @@ var darwinTests = [...]darwinTest{ {"close", libc_close_trampoline_addr}, {"closedir", libc_closedir_trampoline_addr}, {"connect", libc_connect_trampoline_addr}, + {"connectx", libc_connectx_trampoline_addr}, {"dup", libc_dup_trampoline_addr}, {"dup2", libc_dup2_trampoline_addr}, {"exchangedata", libc_exchangedata_trampoline_addr}, diff --git a/unix/darwin_arm64_test.go b/unix/darwin_arm64_test.go index 5a310de020..5fc4feb44b 100644 --- a/unix/darwin_arm64_test.go +++ b/unix/darwin_arm64_test.go @@ -22,6 +22,7 @@ var darwinTests = [...]darwinTest{ {"close", libc_close_trampoline_addr}, {"closedir", libc_closedir_trampoline_addr}, {"connect", libc_connect_trampoline_addr}, + {"connectx", libc_connectx_trampoline_addr}, {"dup", libc_dup_trampoline_addr}, {"dup2", libc_dup2_trampoline_addr}, {"exchangedata", libc_exchangedata_trampoline_addr}, diff --git a/unix/darwin_test.go b/unix/darwin_test.go index 8edde104b1..f8fea55f1e 100644 --- a/unix/darwin_test.go +++ b/unix/darwin_test.go @@ -35,10 +35,14 @@ func TestDarwinLoader(t *testing.T) { // // In an ideal world each syscall would have its own test, so this test // would be unnecessary. Unfortunately, we do not live in that world. + exe, err := os.Executable() + if err != nil { + t.Fatal(err) + } for _, test := range darwinTests { // Call the test binary recursively, giving it a magic argument // (see init below) and the name of the test to run. - cmd := exec.Command(os.Args[0], "testDarwinLoader", test.name) + cmd := exec.Command(exe, "testDarwinLoader", test.name) // Run subprocess, collect results. Note that we expect the subprocess // to fail somehow, so the error is irrelevant. diff --git a/unix/linux/mkall.go b/unix/linux/mkall.go index ae159148b2..d78109261c 100644 --- a/unix/linux/mkall.go +++ b/unix/linux/mkall.go @@ -40,7 +40,7 @@ const TempDir = "/tmp" const GOOS = "linux" // Only for Linux targets const BuildArch = "amd64" // Must be built on this architecture -const MinKernel = "2.6.23" // https://golang.org/doc/install#requirements +const MinKernel = "2.6.32" // https://go.dev/wiki/MinimumRequirements#linuxlinux type target struct { GoArch string // Architecture name according to Go diff --git a/unix/linux/types.go b/unix/linux/types.go index 27b56486c4..75acaec896 100644 --- a/unix/linux/types.go +++ b/unix/linux/types.go @@ -451,6 +451,37 @@ struct my_can_bittiming_const { #define RISCV_HWPROBE_EXT_ZBA (1 << 3) #define RISCV_HWPROBE_EXT_ZBB (1 << 4) #define RISCV_HWPROBE_EXT_ZBS (1 << 5) +#define RISCV_HWPROBE_EXT_ZICBOZ (1 << 6) +#define RISCV_HWPROBE_EXT_ZBC (1 << 7) +#define RISCV_HWPROBE_EXT_ZBKB (1 << 8) +#define RISCV_HWPROBE_EXT_ZBKC (1 << 9) +#define RISCV_HWPROBE_EXT_ZBKX (1 << 10) +#define RISCV_HWPROBE_EXT_ZKND (1 << 11) +#define RISCV_HWPROBE_EXT_ZKNE (1 << 12) +#define RISCV_HWPROBE_EXT_ZKNH (1 << 13) +#define RISCV_HWPROBE_EXT_ZKSED (1 << 14) +#define RISCV_HWPROBE_EXT_ZKSH (1 << 15) +#define RISCV_HWPROBE_EXT_ZKT (1 << 16) +#define RISCV_HWPROBE_EXT_ZVBB (1 << 17) +#define RISCV_HWPROBE_EXT_ZVBC (1 << 18) +#define RISCV_HWPROBE_EXT_ZVKB (1 << 19) +#define RISCV_HWPROBE_EXT_ZVKG (1 << 20) +#define RISCV_HWPROBE_EXT_ZVKNED (1 << 21) +#define RISCV_HWPROBE_EXT_ZVKNHA (1 << 22) +#define RISCV_HWPROBE_EXT_ZVKNHB (1 << 23) +#define RISCV_HWPROBE_EXT_ZVKSED (1 << 24) +#define RISCV_HWPROBE_EXT_ZVKSH (1 << 25) +#define RISCV_HWPROBE_EXT_ZVKT (1 << 26) +#define RISCV_HWPROBE_EXT_ZFH (1 << 27) +#define RISCV_HWPROBE_EXT_ZFHMIN (1 << 28) +#define RISCV_HWPROBE_EXT_ZIHINTNTL (1 << 29) +#define RISCV_HWPROBE_EXT_ZVFH (1 << 30) +#define RISCV_HWPROBE_EXT_ZVFHMIN (1ULL << 31) +#define RISCV_HWPROBE_EXT_ZFA (1ULL << 32) +#define RISCV_HWPROBE_EXT_ZTSO (1ULL << 33) +#define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34) +#define RISCV_HWPROBE_EXT_ZICOND (1ULL << 35) +#define RISCV_HWPROBE_EXT_ZIHINTPAUSE (1ULL << 36) #define RISCV_HWPROBE_KEY_CPUPERF_0 5 #define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0) #define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0) @@ -458,6 +489,8 @@ struct my_can_bittiming_const { #define RISCV_HWPROBE_MISALIGNED_FAST (3 << 0) #define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0) #define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0) +#define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6 +#define RISCV_HWPROBE_WHICH_CPUS (1 << 0) struct riscv_hwprobe {}; #endif @@ -5906,6 +5939,37 @@ const ( RISCV_HWPROBE_EXT_ZBA = C.RISCV_HWPROBE_EXT_ZBA RISCV_HWPROBE_EXT_ZBB = C.RISCV_HWPROBE_EXT_ZBB RISCV_HWPROBE_EXT_ZBS = C.RISCV_HWPROBE_EXT_ZBS + RISCV_HWPROBE_EXT_ZICBOZ = C.RISCV_HWPROBE_EXT_ZICBOZ + RISCV_HWPROBE_EXT_ZBC = C.RISCV_HWPROBE_EXT_ZBC + RISCV_HWPROBE_EXT_ZBKB = C.RISCV_HWPROBE_EXT_ZBKB + RISCV_HWPROBE_EXT_ZBKC = C.RISCV_HWPROBE_EXT_ZBKC + RISCV_HWPROBE_EXT_ZBKX = C.RISCV_HWPROBE_EXT_ZBKX + RISCV_HWPROBE_EXT_ZKND = C.RISCV_HWPROBE_EXT_ZKND + RISCV_HWPROBE_EXT_ZKNE = C.RISCV_HWPROBE_EXT_ZKNE + RISCV_HWPROBE_EXT_ZKNH = C.RISCV_HWPROBE_EXT_ZKNH + RISCV_HWPROBE_EXT_ZKSED = C.RISCV_HWPROBE_EXT_ZKSED + RISCV_HWPROBE_EXT_ZKSH = C.RISCV_HWPROBE_EXT_ZKSH + RISCV_HWPROBE_EXT_ZKT = C.RISCV_HWPROBE_EXT_ZKT + RISCV_HWPROBE_EXT_ZVBB = C.RISCV_HWPROBE_EXT_ZVBB + RISCV_HWPROBE_EXT_ZVBC = C.RISCV_HWPROBE_EXT_ZVBC + RISCV_HWPROBE_EXT_ZVKB = C.RISCV_HWPROBE_EXT_ZVKB + RISCV_HWPROBE_EXT_ZVKG = C.RISCV_HWPROBE_EXT_ZVKG + RISCV_HWPROBE_EXT_ZVKNED = C.RISCV_HWPROBE_EXT_ZVKNED + RISCV_HWPROBE_EXT_ZVKNHA = C.RISCV_HWPROBE_EXT_ZVKNHA + RISCV_HWPROBE_EXT_ZVKNHB = C.RISCV_HWPROBE_EXT_ZVKNHB + RISCV_HWPROBE_EXT_ZVKSED = C.RISCV_HWPROBE_EXT_ZVKSED + RISCV_HWPROBE_EXT_ZVKSH = C.RISCV_HWPROBE_EXT_ZVKSH + RISCV_HWPROBE_EXT_ZVKT = C.RISCV_HWPROBE_EXT_ZVKT + RISCV_HWPROBE_EXT_ZFH = C.RISCV_HWPROBE_EXT_ZFH + RISCV_HWPROBE_EXT_ZFHMIN = C.RISCV_HWPROBE_EXT_ZFHMIN + RISCV_HWPROBE_EXT_ZIHINTNTL = C.RISCV_HWPROBE_EXT_ZIHINTNTL + RISCV_HWPROBE_EXT_ZVFH = C.RISCV_HWPROBE_EXT_ZVFH + RISCV_HWPROBE_EXT_ZVFHMIN = C.RISCV_HWPROBE_EXT_ZVFHMIN + RISCV_HWPROBE_EXT_ZFA = C.RISCV_HWPROBE_EXT_ZFA + RISCV_HWPROBE_EXT_ZTSO = C.RISCV_HWPROBE_EXT_ZTSO + RISCV_HWPROBE_EXT_ZACAS = C.RISCV_HWPROBE_EXT_ZACAS + RISCV_HWPROBE_EXT_ZICOND = C.RISCV_HWPROBE_EXT_ZICOND + RISCV_HWPROBE_EXT_ZIHINTPAUSE = C.RISCV_HWPROBE_EXT_ZIHINTPAUSE RISCV_HWPROBE_KEY_CPUPERF_0 = C.RISCV_HWPROBE_KEY_CPUPERF_0 RISCV_HWPROBE_MISALIGNED_UNKNOWN = C.RISCV_HWPROBE_MISALIGNED_UNKNOWN RISCV_HWPROBE_MISALIGNED_EMULATED = C.RISCV_HWPROBE_MISALIGNED_EMULATED @@ -5913,6 +5977,8 @@ const ( RISCV_HWPROBE_MISALIGNED_FAST = C.RISCV_HWPROBE_MISALIGNED_FAST RISCV_HWPROBE_MISALIGNED_UNSUPPORTED = C.RISCV_HWPROBE_MISALIGNED_UNSUPPORTED RISCV_HWPROBE_MISALIGNED_MASK = C.RISCV_HWPROBE_MISALIGNED_MASK + RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE = C.RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE + RISCV_HWPROBE_WHICH_CPUS = C.RISCV_HWPROBE_WHICH_CPUS ) type SchedAttr C.struct_sched_attr diff --git a/unix/mkerrors.sh b/unix/mkerrors.sh index d07dd09eb5..e14b766a32 100755 --- a/unix/mkerrors.sh +++ b/unix/mkerrors.sh @@ -552,6 +552,7 @@ ccflags="$@" $2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ && $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ || $2 ~ /^SOCK_|SK_DIAG_|SKNLGRP_$/ || + $2 ~ /^(CONNECT|SAE)_/ || $2 ~ /^FIORDCHK$/ || $2 ~ /^SIOC/ || $2 ~ /^TIOC/ || diff --git a/unix/mkpost.go b/unix/mkpost.go index 5dc2a2b92c..c98a77d7f6 100644 --- a/unix/mkpost.go +++ b/unix/mkpost.go @@ -202,6 +202,20 @@ func main() { spareFieldsRegex := regexp.MustCompile(`X__spare\S*`) b = spareFieldsRegex.ReplaceAll(b, []byte("_")) + // Rename chunk_size field in XDPUmemReg. + // When the struct was originally added (CL 136695) the only + // field with a prefix was chunk_size, so cgo rewrote the + // field to Size. Later Linux added a tx_metadata_len field, + // so cgo left chunk_size as Chunk_size (CL 577975). + // Go back to Size so that packages like gvisor don't have + // to adjust. + xdpUmemRegType := regexp.MustCompile(`type XDPUmemReg struct {[^}]*}`) + xdpUmemRegStructs := xdpUmemRegType.FindAll(b, -1) + for _, s := range xdpUmemRegStructs { + newName := bytes.Replace(s, []byte("Chunk_size"), []byte("Size"), 1) + b = bytes.Replace(b, s, newName, 1) + } + // Remove cgo padding fields removePaddingFieldsRegex := regexp.MustCompile(`Pad_cgo_\d+`) b = removePaddingFieldsRegex.ReplaceAll(b, []byte("_")) diff --git a/unix/openbsd_test.go b/unix/openbsd_test.go index 8ca05245d7..cd36c43755 100644 --- a/unix/openbsd_test.go +++ b/unix/openbsd_test.go @@ -43,7 +43,7 @@ func init() { // testCmd generates a proper command that, when executed, runs the test // corresponding to the given key. func testCmd(procName string) (*exec.Cmd, error) { - exe, err := filepath.Abs(os.Args[0]) + exe, err := os.Executable() if err != nil { return nil, err } diff --git a/unix/syscall_darwin.go b/unix/syscall_darwin.go index 2d15200adb..099867deed 100644 --- a/unix/syscall_darwin.go +++ b/unix/syscall_darwin.go @@ -566,6 +566,43 @@ func PthreadFchdir(fd int) (err error) { return pthread_fchdir_np(fd) } +// Connectx calls connectx(2) to initiate a connection on a socket. +// +// srcIf, srcAddr, and dstAddr are filled into a [SaEndpoints] struct and passed as the endpoints argument. +// +// - srcIf is the optional source interface index. 0 means unspecified. +// - srcAddr is the optional source address. nil means unspecified. +// - dstAddr is the destination address. +// +// On success, Connectx returns the number of bytes enqueued for transmission. +func Connectx(fd int, srcIf uint32, srcAddr, dstAddr Sockaddr, associd SaeAssocID, flags uint32, iov []Iovec, connid *SaeConnID) (n uintptr, err error) { + endpoints := SaEndpoints{ + Srcif: srcIf, + } + + if srcAddr != nil { + addrp, addrlen, err := srcAddr.sockaddr() + if err != nil { + return 0, err + } + endpoints.Srcaddr = (*RawSockaddr)(addrp) + endpoints.Srcaddrlen = uint32(addrlen) + } + + if dstAddr != nil { + addrp, addrlen, err := dstAddr.sockaddr() + if err != nil { + return 0, err + } + endpoints.Dstaddr = (*RawSockaddr)(addrp) + endpoints.Dstaddrlen = uint32(addrlen) + } + + err = connectx(fd, &endpoints, associd, flags, iov, &n, connid) + return +} + +//sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) //sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) diff --git a/unix/syscall_freebsd_test.go b/unix/syscall_freebsd_test.go index cbe3d36696..46b48d6f37 100644 --- a/unix/syscall_freebsd_test.go +++ b/unix/syscall_freebsd_test.go @@ -53,7 +53,7 @@ func init() { } func testCmd(procName string, procArg string) (*exec.Cmd, error) { - exe, err := filepath.Abs(os.Args[0]) + exe, err := os.Executable() if err != nil { return nil, err } diff --git a/unix/syscall_hurd.go b/unix/syscall_hurd.go index ba46651f8e..a6a2d2fc2b 100644 --- a/unix/syscall_hurd.go +++ b/unix/syscall_hurd.go @@ -11,6 +11,7 @@ package unix int ioctl(int, unsigned long int, uintptr_t); */ import "C" +import "unsafe" func ioctl(fd int, req uint, arg uintptr) (err error) { r0, er := C.ioctl(C.int(fd), C.ulong(req), C.uintptr_t(arg)) diff --git a/unix/syscall_unix_test.go b/unix/syscall_unix_test.go index 29c158fbab..3bb5c7a10a 100644 --- a/unix/syscall_unix_test.go +++ b/unix/syscall_unix_test.go @@ -205,7 +205,11 @@ func TestPassFD(t *testing.T) { defer writeFile.Close() defer readFile.Close() - cmd := exec.Command(os.Args[0], "-test.run=^TestPassFD$", "--", t.TempDir()) + exe, err := os.Executable() + if err != nil { + t.Fatal(err) + } + cmd := exec.Command(exe, "-test.run=^TestPassFD$", "--", t.TempDir()) cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"} if lp := os.Getenv("LD_LIBRARY_PATH"); lp != "" { cmd.Env = append(cmd.Env, "LD_LIBRARY_PATH="+lp) diff --git a/unix/types_darwin.go b/unix/types_darwin.go index 7ed32a1a5f..36e2f045da 100644 --- a/unix/types_darwin.go +++ b/unix/types_darwin.go @@ -177,6 +177,12 @@ type XVSockPgen C.struct_xvsockpgen type _Socklen C.socklen_t +type SaeAssocID C.sae_associd_t + +type SaeConnID C.sae_connid_t + +type SaEndpoints C.struct_sa_endpoints + type Xucred C.struct_xucred type Linger C.struct_linger diff --git a/unix/types_freebsd.go b/unix/types_freebsd.go index 23e3a026af..601096ee5f 100644 --- a/unix/types_freebsd.go +++ b/unix/types_freebsd.go @@ -356,6 +356,7 @@ const ( POLLRDNORM = C.POLLRDNORM POLLWRBAND = C.POLLWRBAND POLLWRNORM = C.POLLWRNORM + POLLRDHUP = C.POLLRDHUP ) // Capabilities diff --git a/unix/zerrors_darwin_amd64.go b/unix/zerrors_darwin_amd64.go index 4308ac1772..d73c4652e6 100644 --- a/unix/zerrors_darwin_amd64.go +++ b/unix/zerrors_darwin_amd64.go @@ -237,6 +237,9 @@ const ( CLOCK_UPTIME_RAW_APPROX = 0x9 CLONE_NOFOLLOW = 0x1 CLONE_NOOWNERCOPY = 0x2 + CONNECT_DATA_AUTHENTICATED = 0x4 + CONNECT_DATA_IDEMPOTENT = 0x2 + CONNECT_RESUME_ON_READ_WRITE = 0x1 CR0 = 0x0 CR1 = 0x1000 CR2 = 0x2000 @@ -1265,6 +1268,10 @@ const ( RTV_SSTHRESH = 0x20 RUSAGE_CHILDREN = -0x1 RUSAGE_SELF = 0x0 + SAE_ASSOCID_ALL = 0xffffffff + SAE_ASSOCID_ANY = 0x0 + SAE_CONNID_ALL = 0xffffffff + SAE_CONNID_ANY = 0x0 SCM_CREDS = 0x3 SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x2 diff --git a/unix/zerrors_darwin_arm64.go b/unix/zerrors_darwin_arm64.go index c8068a7a16..4a55a40058 100644 --- a/unix/zerrors_darwin_arm64.go +++ b/unix/zerrors_darwin_arm64.go @@ -237,6 +237,9 @@ const ( CLOCK_UPTIME_RAW_APPROX = 0x9 CLONE_NOFOLLOW = 0x1 CLONE_NOOWNERCOPY = 0x2 + CONNECT_DATA_AUTHENTICATED = 0x4 + CONNECT_DATA_IDEMPOTENT = 0x2 + CONNECT_RESUME_ON_READ_WRITE = 0x1 CR0 = 0x0 CR1 = 0x1000 CR2 = 0x2000 @@ -1265,6 +1268,10 @@ const ( RTV_SSTHRESH = 0x20 RUSAGE_CHILDREN = -0x1 RUSAGE_SELF = 0x0 + SAE_ASSOCID_ALL = 0xffffffff + SAE_ASSOCID_ANY = 0x0 + SAE_CONNID_ALL = 0xffffffff + SAE_CONNID_ANY = 0x0 SCM_CREDS = 0x3 SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x2 diff --git a/unix/zerrors_zos_s390x.go b/unix/zerrors_zos_s390x.go index da08b2ab3d..1ec2b1407b 100644 --- a/unix/zerrors_zos_s390x.go +++ b/unix/zerrors_zos_s390x.go @@ -581,6 +581,8 @@ const ( AT_EMPTY_PATH = 0x1000 AT_REMOVEDIR = 0x200 RENAME_NOREPLACE = 1 << 0 + ST_RDONLY = 1 + ST_NOSUID = 2 ) const ( diff --git a/unix/zsyscall_darwin_amd64.go b/unix/zsyscall_darwin_amd64.go index b622533ef2..24b346e1a3 100644 --- a/unix/zsyscall_darwin_amd64.go +++ b/unix/zsyscall_darwin_amd64.go @@ -841,6 +841,26 @@ var libc_pthread_fchdir_np_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) { + var _p0 unsafe.Pointer + if len(iov) > 0 { + _p0 = unsafe.Pointer(&iov[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall9(libc_connectx_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(endpoints)), uintptr(associd), uintptr(flags), uintptr(_p0), uintptr(len(iov)), uintptr(unsafe.Pointer(n)), uintptr(unsafe.Pointer(connid)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_connectx_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_connectx connectx "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { _, _, e1 := syscall_syscall6(libc_sendfile_trampoline_addr, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) if e1 != 0 { diff --git a/unix/zsyscall_darwin_amd64.s b/unix/zsyscall_darwin_amd64.s index cfe6646baf..ebd213100b 100644 --- a/unix/zsyscall_darwin_amd64.s +++ b/unix/zsyscall_darwin_amd64.s @@ -248,6 +248,11 @@ TEXT libc_pthread_fchdir_np_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_pthread_fchdir_np_trampoline_addr(SB), RODATA, $8 DATA ·libc_pthread_fchdir_np_trampoline_addr(SB)/8, $libc_pthread_fchdir_np_trampoline<>(SB) +TEXT libc_connectx_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_connectx(SB) +GLOBL ·libc_connectx_trampoline_addr(SB), RODATA, $8 +DATA ·libc_connectx_trampoline_addr(SB)/8, $libc_connectx_trampoline<>(SB) + TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sendfile(SB) GLOBL ·libc_sendfile_trampoline_addr(SB), RODATA, $8 diff --git a/unix/zsyscall_darwin_arm64.go b/unix/zsyscall_darwin_arm64.go index 13f624f69f..824b9c2d5e 100644 --- a/unix/zsyscall_darwin_arm64.go +++ b/unix/zsyscall_darwin_arm64.go @@ -841,6 +841,26 @@ var libc_pthread_fchdir_np_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) { + var _p0 unsafe.Pointer + if len(iov) > 0 { + _p0 = unsafe.Pointer(&iov[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall9(libc_connectx_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(endpoints)), uintptr(associd), uintptr(flags), uintptr(_p0), uintptr(len(iov)), uintptr(unsafe.Pointer(n)), uintptr(unsafe.Pointer(connid)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_connectx_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_connectx connectx "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { _, _, e1 := syscall_syscall6(libc_sendfile_trampoline_addr, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) if e1 != 0 { diff --git a/unix/zsyscall_darwin_arm64.s b/unix/zsyscall_darwin_arm64.s index fe222b75df..4f178a2293 100644 --- a/unix/zsyscall_darwin_arm64.s +++ b/unix/zsyscall_darwin_arm64.s @@ -248,6 +248,11 @@ TEXT libc_pthread_fchdir_np_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_pthread_fchdir_np_trampoline_addr(SB), RODATA, $8 DATA ·libc_pthread_fchdir_np_trampoline_addr(SB)/8, $libc_pthread_fchdir_np_trampoline<>(SB) +TEXT libc_connectx_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_connectx(SB) +GLOBL ·libc_connectx_trampoline_addr(SB), RODATA, $8 +DATA ·libc_connectx_trampoline_addr(SB)/8, $libc_connectx_trampoline<>(SB) + TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sendfile(SB) GLOBL ·libc_sendfile_trampoline_addr(SB), RODATA, $8 diff --git a/unix/ztypes_darwin_amd64.go b/unix/ztypes_darwin_amd64.go index 091d107f3a..d003c3d437 100644 --- a/unix/ztypes_darwin_amd64.go +++ b/unix/ztypes_darwin_amd64.go @@ -306,6 +306,19 @@ type XVSockPgen struct { type _Socklen uint32 +type SaeAssocID uint32 + +type SaeConnID uint32 + +type SaEndpoints struct { + Srcif uint32 + Srcaddr *RawSockaddr + Srcaddrlen uint32 + Dstaddr *RawSockaddr + Dstaddrlen uint32 + _ [4]byte +} + type Xucred struct { Version uint32 Uid uint32 diff --git a/unix/ztypes_darwin_arm64.go b/unix/ztypes_darwin_arm64.go index 28ff4ef74d..0d45a941aa 100644 --- a/unix/ztypes_darwin_arm64.go +++ b/unix/ztypes_darwin_arm64.go @@ -306,6 +306,19 @@ type XVSockPgen struct { type _Socklen uint32 +type SaeAssocID uint32 + +type SaeConnID uint32 + +type SaEndpoints struct { + Srcif uint32 + Srcaddr *RawSockaddr + Srcaddrlen uint32 + Dstaddr *RawSockaddr + Dstaddrlen uint32 + _ [4]byte +} + type Xucred struct { Version uint32 Uid uint32 diff --git a/unix/ztypes_freebsd_386.go b/unix/ztypes_freebsd_386.go index 6cbd094a3a..51e13eb055 100644 --- a/unix/ztypes_freebsd_386.go +++ b/unix/ztypes_freebsd_386.go @@ -625,6 +625,7 @@ const ( POLLRDNORM = 0x40 POLLWRBAND = 0x100 POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 ) type CapRights struct { diff --git a/unix/ztypes_freebsd_amd64.go b/unix/ztypes_freebsd_amd64.go index 7c03b6ee77..d002d8ef3c 100644 --- a/unix/ztypes_freebsd_amd64.go +++ b/unix/ztypes_freebsd_amd64.go @@ -630,6 +630,7 @@ const ( POLLRDNORM = 0x40 POLLWRBAND = 0x100 POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 ) type CapRights struct { diff --git a/unix/ztypes_freebsd_arm.go b/unix/ztypes_freebsd_arm.go index 422107ee8b..3f863d898d 100644 --- a/unix/ztypes_freebsd_arm.go +++ b/unix/ztypes_freebsd_arm.go @@ -616,6 +616,7 @@ const ( POLLRDNORM = 0x40 POLLWRBAND = 0x100 POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 ) type CapRights struct { diff --git a/unix/ztypes_freebsd_arm64.go b/unix/ztypes_freebsd_arm64.go index 505a12acfd..61c7293106 100644 --- a/unix/ztypes_freebsd_arm64.go +++ b/unix/ztypes_freebsd_arm64.go @@ -610,6 +610,7 @@ const ( POLLRDNORM = 0x40 POLLWRBAND = 0x100 POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 ) type CapRights struct { diff --git a/unix/ztypes_freebsd_riscv64.go b/unix/ztypes_freebsd_riscv64.go index cc986c7900..b5d17414f0 100644 --- a/unix/ztypes_freebsd_riscv64.go +++ b/unix/ztypes_freebsd_riscv64.go @@ -612,6 +612,7 @@ const ( POLLRDNORM = 0x40 POLLWRBAND = 0x100 POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 ) type CapRights struct { diff --git a/unix/ztypes_linux.go b/unix/ztypes_linux.go index 7f1961b907..9f2550dc31 100644 --- a/unix/ztypes_linux.go +++ b/unix/ztypes_linux.go @@ -2486,7 +2486,7 @@ type XDPMmapOffsets struct { type XDPUmemReg struct { Addr uint64 Len uint64 - Chunk_size uint32 + Size uint32 Headroom uint32 Flags uint32 Tx_metadata_len uint32 diff --git a/unix/ztypes_linux_riscv64.go b/unix/ztypes_linux_riscv64.go index 15adc04142..ad05b51a60 100644 --- a/unix/ztypes_linux_riscv64.go +++ b/unix/ztypes_linux_riscv64.go @@ -727,6 +727,37 @@ const ( RISCV_HWPROBE_EXT_ZBA = 0x8 RISCV_HWPROBE_EXT_ZBB = 0x10 RISCV_HWPROBE_EXT_ZBS = 0x20 + RISCV_HWPROBE_EXT_ZICBOZ = 0x40 + RISCV_HWPROBE_EXT_ZBC = 0x80 + RISCV_HWPROBE_EXT_ZBKB = 0x100 + RISCV_HWPROBE_EXT_ZBKC = 0x200 + RISCV_HWPROBE_EXT_ZBKX = 0x400 + RISCV_HWPROBE_EXT_ZKND = 0x800 + RISCV_HWPROBE_EXT_ZKNE = 0x1000 + RISCV_HWPROBE_EXT_ZKNH = 0x2000 + RISCV_HWPROBE_EXT_ZKSED = 0x4000 + RISCV_HWPROBE_EXT_ZKSH = 0x8000 + RISCV_HWPROBE_EXT_ZKT = 0x10000 + RISCV_HWPROBE_EXT_ZVBB = 0x20000 + RISCV_HWPROBE_EXT_ZVBC = 0x40000 + RISCV_HWPROBE_EXT_ZVKB = 0x80000 + RISCV_HWPROBE_EXT_ZVKG = 0x100000 + RISCV_HWPROBE_EXT_ZVKNED = 0x200000 + RISCV_HWPROBE_EXT_ZVKNHA = 0x400000 + RISCV_HWPROBE_EXT_ZVKNHB = 0x800000 + RISCV_HWPROBE_EXT_ZVKSED = 0x1000000 + RISCV_HWPROBE_EXT_ZVKSH = 0x2000000 + RISCV_HWPROBE_EXT_ZVKT = 0x4000000 + RISCV_HWPROBE_EXT_ZFH = 0x8000000 + RISCV_HWPROBE_EXT_ZFHMIN = 0x10000000 + RISCV_HWPROBE_EXT_ZIHINTNTL = 0x20000000 + RISCV_HWPROBE_EXT_ZVFH = 0x40000000 + RISCV_HWPROBE_EXT_ZVFHMIN = 0x80000000 + RISCV_HWPROBE_EXT_ZFA = 0x100000000 + RISCV_HWPROBE_EXT_ZTSO = 0x200000000 + RISCV_HWPROBE_EXT_ZACAS = 0x400000000 + RISCV_HWPROBE_EXT_ZICOND = 0x800000000 + RISCV_HWPROBE_EXT_ZIHINTPAUSE = 0x1000000000 RISCV_HWPROBE_KEY_CPUPERF_0 = 0x5 RISCV_HWPROBE_MISALIGNED_UNKNOWN = 0x0 RISCV_HWPROBE_MISALIGNED_EMULATED = 0x1 @@ -734,4 +765,6 @@ const ( RISCV_HWPROBE_MISALIGNED_FAST = 0x3 RISCV_HWPROBE_MISALIGNED_UNSUPPORTED = 0x4 RISCV_HWPROBE_MISALIGNED_MASK = 0x7 + RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE = 0x6 + RISCV_HWPROBE_WHICH_CPUS = 0x1 ) diff --git a/windows/syscall_windows.go b/windows/syscall_windows.go index 1fa34fd17c..5cee9a3143 100644 --- a/windows/syscall_windows.go +++ b/windows/syscall_windows.go @@ -313,6 +313,10 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys SetConsoleMode(console Handle, mode uint32) (err error) = kernel32.SetConsoleMode //sys GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) (err error) = kernel32.GetConsoleScreenBufferInfo //sys setConsoleCursorPosition(console Handle, position uint32) (err error) = kernel32.SetConsoleCursorPosition +//sys GetConsoleCP() (cp uint32, err error) = kernel32.GetConsoleCP +//sys GetConsoleOutputCP() (cp uint32, err error) = kernel32.GetConsoleOutputCP +//sys SetConsoleCP(cp uint32) (err error) = kernel32.SetConsoleCP +//sys SetConsoleOutputCP(cp uint32) (err error) = kernel32.SetConsoleOutputCP //sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW //sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW //sys resizePseudoConsole(pconsole Handle, size uint32) (hr error) = kernel32.ResizePseudoConsole diff --git a/windows/types_windows.go b/windows/types_windows.go index 3f03b3d57c..7b97a154c9 100644 --- a/windows/types_windows.go +++ b/windows/types_windows.go @@ -1060,6 +1060,7 @@ const ( SIO_GET_EXTENSION_FUNCTION_POINTER = IOC_INOUT | IOC_WS2 | 6 SIO_KEEPALIVE_VALS = IOC_IN | IOC_VENDOR | 4 SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12 + SIO_UDP_NETRESET = IOC_IN | IOC_VENDOR | 15 // cf. http://support.microsoft.com/default.aspx?scid=kb;en-us;257460 diff --git a/windows/zsyscall_windows.go b/windows/zsyscall_windows.go index 9bb979a3e4..4c2e1bdc01 100644 --- a/windows/zsyscall_windows.go +++ b/windows/zsyscall_windows.go @@ -247,7 +247,9 @@ var ( procGetCommandLineW = modkernel32.NewProc("GetCommandLineW") procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW") procGetComputerNameW = modkernel32.NewProc("GetComputerNameW") + procGetConsoleCP = modkernel32.NewProc("GetConsoleCP") procGetConsoleMode = modkernel32.NewProc("GetConsoleMode") + procGetConsoleOutputCP = modkernel32.NewProc("GetConsoleOutputCP") procGetConsoleScreenBufferInfo = modkernel32.NewProc("GetConsoleScreenBufferInfo") procGetCurrentDirectoryW = modkernel32.NewProc("GetCurrentDirectoryW") procGetCurrentProcessId = modkernel32.NewProc("GetCurrentProcessId") @@ -347,8 +349,10 @@ var ( procSetCommMask = modkernel32.NewProc("SetCommMask") procSetCommState = modkernel32.NewProc("SetCommState") procSetCommTimeouts = modkernel32.NewProc("SetCommTimeouts") + procSetConsoleCP = modkernel32.NewProc("SetConsoleCP") procSetConsoleCursorPosition = modkernel32.NewProc("SetConsoleCursorPosition") procSetConsoleMode = modkernel32.NewProc("SetConsoleMode") + procSetConsoleOutputCP = modkernel32.NewProc("SetConsoleOutputCP") procSetCurrentDirectoryW = modkernel32.NewProc("SetCurrentDirectoryW") procSetDefaultDllDirectories = modkernel32.NewProc("SetDefaultDllDirectories") procSetDllDirectoryW = modkernel32.NewProc("SetDllDirectoryW") @@ -2162,6 +2166,15 @@ func GetComputerName(buf *uint16, n *uint32) (err error) { return } +func GetConsoleCP() (cp uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetConsoleCP.Addr(), 0, 0, 0, 0) + cp = uint32(r0) + if cp == 0 { + err = errnoErr(e1) + } + return +} + func GetConsoleMode(console Handle, mode *uint32) (err error) { r1, _, e1 := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(mode)), 0) if r1 == 0 { @@ -2170,6 +2183,15 @@ func GetConsoleMode(console Handle, mode *uint32) (err error) { return } +func GetConsoleOutputCP() (cp uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetConsoleOutputCP.Addr(), 0, 0, 0, 0) + cp = uint32(r0) + if cp == 0 { + err = errnoErr(e1) + } + return +} + func GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) (err error) { r1, _, e1 := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(info)), 0) if r1 == 0 { @@ -3038,6 +3060,14 @@ func SetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) { return } +func SetConsoleCP(cp uint32) (err error) { + r1, _, e1 := syscall.Syscall(procSetConsoleCP.Addr(), 1, uintptr(cp), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func setConsoleCursorPosition(console Handle, position uint32) (err error) { r1, _, e1 := syscall.Syscall(procSetConsoleCursorPosition.Addr(), 2, uintptr(console), uintptr(position), 0) if r1 == 0 { @@ -3054,6 +3084,14 @@ func SetConsoleMode(console Handle, mode uint32) (err error) { return } +func SetConsoleOutputCP(cp uint32) (err error) { + r1, _, e1 := syscall.Syscall(procSetConsoleOutputCP.Addr(), 1, uintptr(cp), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func SetCurrentDirectory(path *uint16) (err error) { r1, _, e1 := syscall.Syscall(procSetCurrentDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) if r1 == 0 {