Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/internal/runtime/syscall/linux/defs_linux_386.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const (
SYS_OPENAT = 295
SYS_PREAD64 = 180
SYS_READ = 3
SYS_UNAME = 122

EFD_NONBLOCK = 0x800

Expand Down
1 change: 1 addition & 0 deletions src/internal/runtime/syscall/linux/defs_linux_amd64.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const (
SYS_OPENAT = 257
SYS_PREAD64 = 17
SYS_READ = 0
SYS_UNAME = 63

EFD_NONBLOCK = 0x800

Expand Down
1 change: 1 addition & 0 deletions src/internal/runtime/syscall/linux/defs_linux_arm.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const (
SYS_OPENAT = 322
SYS_PREAD64 = 180
SYS_READ = 3
SYS_UNAME = 122

EFD_NONBLOCK = 0x800

Expand Down
1 change: 1 addition & 0 deletions src/internal/runtime/syscall/linux/defs_linux_arm64.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const (
SYS_OPENAT = 56
SYS_PREAD64 = 67
SYS_READ = 63
SYS_UNAME = 160

EFD_NONBLOCK = 0x800

Expand Down
1 change: 1 addition & 0 deletions src/internal/runtime/syscall/linux/defs_linux_loong64.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const (
SYS_OPENAT = 56
SYS_PREAD64 = 67
SYS_READ = 63
SYS_UNAME = 160

EFD_NONBLOCK = 0x800

Expand Down
1 change: 1 addition & 0 deletions src/internal/runtime/syscall/linux/defs_linux_mips64x.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const (
SYS_OPENAT = 5247
SYS_PREAD64 = 5016
SYS_READ = 5000
SYS_UNAME = 5061

EFD_NONBLOCK = 0x80

Expand Down
1 change: 1 addition & 0 deletions src/internal/runtime/syscall/linux/defs_linux_mipsx.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const (
SYS_OPENAT = 4288
SYS_PREAD64 = 4200
SYS_READ = 4003
SYS_UNAME = 4122

EFD_NONBLOCK = 0x80

Expand Down
1 change: 1 addition & 0 deletions src/internal/runtime/syscall/linux/defs_linux_ppc64x.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const (
SYS_OPENAT = 286
SYS_PREAD64 = 179
SYS_READ = 3
SYS_UNAME = 122

EFD_NONBLOCK = 0x800

Expand Down
1 change: 1 addition & 0 deletions src/internal/runtime/syscall/linux/defs_linux_riscv64.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const (
SYS_OPENAT = 56
SYS_PREAD64 = 67
SYS_READ = 63
SYS_UNAME = 160

EFD_NONBLOCK = 0x800

Expand Down
1 change: 1 addition & 0 deletions src/internal/runtime/syscall/linux/defs_linux_s390x.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const (
SYS_OPENAT = 288
SYS_PREAD64 = 180
SYS_READ = 3
SYS_UNAME = 122

EFD_NONBLOCK = 0x800

Expand Down
14 changes: 14 additions & 0 deletions src/internal/runtime/syscall/linux/syscall_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,17 @@ func Pread(fd int, p []byte, offset int64) (n int, errno uintptr) {
}
return int(r1), e
}

type Utsname struct {
Sysname [65]byte
Nodename [65]byte
Release [65]byte
Version [65]byte
Machine [65]byte
Domainname [65]byte
}

func Uname(buf *Utsname) (errno uintptr) {
_, _, e := Syscall6(SYS_UNAME, uintptr(unsafe.Pointer(buf)), 0, 0, 0, 0, 0)
return e
}
62 changes: 62 additions & 0 deletions src/runtime/os_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ func osinit() {
numCPUStartup = getCPUCount()
physHugePageSize = getHugePageSize()
vgetrandomInit()
configure64bitsTimeOn32BitsArchitectures()
}

var urandom_dev = []byte("/dev/urandom\x00")
Expand Down Expand Up @@ -935,3 +936,64 @@ func mprotect(addr unsafe.Pointer, n uintptr, prot int32) (ret int32, errno int3
r, _, err := linux.Syscall6(linux.SYS_MPROTECT, uintptr(addr), n, uintptr(prot), 0, 0, 0)
return int32(r), int32(err)
}

type kernelVersion struct {
major int
minor int
}

// getKernelVersion returns major and minor kernel version numbers
// parsed from the uname release field.
func getKernelVersion() kernelVersion {
var buf linux.Utsname
if e := linux.Uname(&buf); e != 0 {
throw("uname failed")
}

rel := gostringnocopy(&buf.Release[0])
major, minor, _, ok := parseRelease(rel)
if !ok {
throw("failed to parse kernel version from uname")
}
return kernelVersion{major: major, minor: minor}
}

// parseRelease parses a dot-separated version number. It follows the
// semver syntax, but allows the minor and patch versions to be
// elided.
func parseRelease(rel string) (major, minor, patch int, ok bool) {
// Strip anything after a dash or plus.
for i := 0; i < len(rel); i++ {
if rel[i] == '-' || rel[i] == '+' {
rel = rel[:i]
break
}
}

next := func() (int, bool) {
for i := 0; i < len(rel); i++ {
if rel[i] == '.' {
ver, err := strconv.Atoi(rel[:i])
rel = rel[i+1:]
return ver, err == nil
}
}
ver, err := strconv.Atoi(rel)
rel = ""
return ver, err == nil
}
if major, ok = next(); !ok || rel == "" {
return
}
if minor, ok = next(); !ok || rel == "" {
return
}
patch, ok = next()
return
}

// GE checks if the running kernel version
// is greater than or equal to the provided version.
func (kv kernelVersion) GE(x, y int) bool {
return kv.major > x || (kv.major == x && kv.minor >= y)
}
28 changes: 9 additions & 19 deletions src/runtime/os_linux32.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,25 @@
package runtime

import (
"internal/runtime/atomic"
"unsafe"
)

func configure64bitsTimeOn32BitsArchitectures() {
use64bitsTimeOn32bits = getKernelVersion().GE(5, 1)
}

//go:noescape
func futex_time32(addr unsafe.Pointer, op int32, val uint32, ts *timespec32, addr2 unsafe.Pointer, val3 uint32) int32

//go:noescape
func futex_time64(addr unsafe.Pointer, op int32, val uint32, ts *timespec, addr2 unsafe.Pointer, val3 uint32) int32

var isFutexTime32bitOnly atomic.Bool
var use64bitsTimeOn32bits bool

//go:nosplit
func futex(addr unsafe.Pointer, op int32, val uint32, ts *timespec, addr2 unsafe.Pointer, val3 uint32) int32 {
if !isFutexTime32bitOnly.Load() {
ret := futex_time64(addr, op, val, ts, addr2, val3)
// futex_time64 is only supported on Linux 5.0+
if ret != -_ENOSYS {
return ret
}
isFutexTime32bitOnly.Store(true)
if use64bitsTimeOn32bits {
return futex_time64(addr, op, val, ts, addr2, val3)
}
// Downgrade ts.
var ts32 timespec32
Expand All @@ -45,17 +43,10 @@ func timer_settime32(timerid int32, flags int32, new, old *itimerspec32) int32
//go:noescape
func timer_settime64(timerid int32, flags int32, new, old *itimerspec) int32

var isSetTime32bitOnly atomic.Bool

//go:nosplit
func timer_settime(timerid int32, flags int32, new, old *itimerspec) int32 {
if !isSetTime32bitOnly.Load() {
ret := timer_settime64(timerid, flags, new, old)
// timer_settime64 is only supported on Linux 5.0+
if ret != -_ENOSYS {
return ret
}
isSetTime32bitOnly.Store(true)
if use64bitsTimeOn32bits {
return timer_settime64(timerid, flags, new, old)
}

var newts, oldts itimerspec32
Expand All @@ -73,6 +64,5 @@ func timer_settime(timerid int32, flags int32, new, old *itimerspec) int32 {
old32 = &oldts
}

// Fall back to 32-bit timer
return timer_settime32(timerid, flags, new32, old32)
}
2 changes: 2 additions & 0 deletions src/runtime/os_linux64.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"unsafe"
)

func configure64bitsTimeOn32BitsArchitectures() {}

//go:noescape
func futex(addr unsafe.Pointer, op int32, val uint32, ts *timespec, addr2 unsafe.Pointer, val3 uint32) int32

Expand Down
Loading