mirror of
https://github.com/golang/go.git
synced 2025-10-19 11:03:18 +00:00
runtime: use futexes with 64-bit time on Linux
Linux introduced new syscalls to fix the year 2038 issue. To still be able to use the old ones, the Kconfig option COMPAT_32BIT_TIME would be necessary. Use the new syscall with 64-bit values for futexwakeup by default. Define _ENOSYS for detecting if it's not available. Add a fallback to use the older syscall in case the new one is not available, since Go runs on Linux from 2.6.32 on, per https://go.dev/wiki/MinimumRequirements. Fixes #75133
This commit is contained in:
parent
ef05b66d61
commit
96dd1bd84b
19 changed files with 186 additions and 22 deletions
|
@ -48,6 +48,7 @@ const (
|
||||||
EINTR = C.EINTR
|
EINTR = C.EINTR
|
||||||
EAGAIN = C.EAGAIN
|
EAGAIN = C.EAGAIN
|
||||||
ENOMEM = C.ENOMEM
|
ENOMEM = C.ENOMEM
|
||||||
|
ENOSYS = C.ENOSYS
|
||||||
|
|
||||||
PROT_NONE = C.PROT_NONE
|
PROT_NONE = C.PROT_NONE
|
||||||
PROT_READ = C.PROT_READ
|
PROT_READ = C.PROT_READ
|
||||||
|
|
|
@ -37,6 +37,7 @@ const (
|
||||||
EINTR = C.EINTR
|
EINTR = C.EINTR
|
||||||
EAGAIN = C.EAGAIN
|
EAGAIN = C.EAGAIN
|
||||||
ENOMEM = C.ENOMEM
|
ENOMEM = C.ENOMEM
|
||||||
|
ENOSYS = C.ENOSYS
|
||||||
|
|
||||||
PROT_NONE = C.PROT_NONE
|
PROT_NONE = C.PROT_NONE
|
||||||
PROT_READ = C.PROT_READ
|
PROT_READ = C.PROT_READ
|
||||||
|
|
|
@ -9,6 +9,7 @@ const (
|
||||||
_EINTR = 0x4
|
_EINTR = 0x4
|
||||||
_EAGAIN = 0xb
|
_EAGAIN = 0xb
|
||||||
_ENOMEM = 0xc
|
_ENOMEM = 0xc
|
||||||
|
_ENOSYS = 0x26
|
||||||
|
|
||||||
_PROT_NONE = 0x0
|
_PROT_NONE = 0x0
|
||||||
_PROT_READ = 0x1
|
_PROT_READ = 0x1
|
||||||
|
@ -136,16 +137,30 @@ type fpstate struct {
|
||||||
anon0 [48]byte
|
anon0 [48]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type timespec struct {
|
// The timespec structs and types are defined in Linux in
|
||||||
|
// include/uapi/linux/time_types.h and include/uapi/asm-generic/posix_types.h.
|
||||||
|
type timespec32 struct {
|
||||||
tv_sec int32
|
tv_sec int32
|
||||||
tv_nsec int32
|
tv_nsec int32
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func (ts *timespec) setNsec(ns int64) {
|
func (ts *timespec32) setNsec(ns int64) {
|
||||||
ts.tv_sec = timediv(ns, 1e9, &ts.tv_nsec)
|
ts.tv_sec = timediv(ns, 1e9, &ts.tv_nsec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type timespec struct {
|
||||||
|
tv_sec int64
|
||||||
|
tv_nsec int64
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
func (ts *timespec) setNsec(ns int64) {
|
||||||
|
var newNS int32
|
||||||
|
ts.tv_sec = int64(timediv(ns, 1e9, &newNS))
|
||||||
|
ts.tv_nsec = int64(newNS)
|
||||||
|
}
|
||||||
|
|
||||||
type timeval struct {
|
type timeval struct {
|
||||||
tv_sec int32
|
tv_sec int32
|
||||||
tv_usec int32
|
tv_usec int32
|
||||||
|
@ -223,8 +238,8 @@ type ucontext struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type itimerspec struct {
|
type itimerspec struct {
|
||||||
it_interval timespec
|
it_interval timespec32
|
||||||
it_value timespec
|
it_value timespec32
|
||||||
}
|
}
|
||||||
|
|
||||||
type itimerval struct {
|
type itimerval struct {
|
||||||
|
|
|
@ -9,6 +9,7 @@ const (
|
||||||
_EINTR = 0x4
|
_EINTR = 0x4
|
||||||
_EAGAIN = 0xb
|
_EAGAIN = 0xb
|
||||||
_ENOMEM = 0xc
|
_ENOMEM = 0xc
|
||||||
|
_ENOSYS = 0x26
|
||||||
|
|
||||||
_PROT_NONE = 0x0
|
_PROT_NONE = 0x0
|
||||||
_PROT_READ = 0x1
|
_PROT_READ = 0x1
|
||||||
|
|
|
@ -11,6 +11,7 @@ const (
|
||||||
_EINTR = 0x4
|
_EINTR = 0x4
|
||||||
_ENOMEM = 0xc
|
_ENOMEM = 0xc
|
||||||
_EAGAIN = 0xb
|
_EAGAIN = 0xb
|
||||||
|
_ENOSYS = 0x26
|
||||||
|
|
||||||
_PROT_NONE = 0
|
_PROT_NONE = 0
|
||||||
_PROT_READ = 0x1
|
_PROT_READ = 0x1
|
||||||
|
@ -95,16 +96,30 @@ const (
|
||||||
_SOCK_DGRAM = 0x2
|
_SOCK_DGRAM = 0x2
|
||||||
)
|
)
|
||||||
|
|
||||||
type timespec struct {
|
// The timespec structs and types are defined in Linux in
|
||||||
|
// include/uapi/linux/time_types.h and include/uapi/asm-generic/posix_types.h.
|
||||||
|
type timespec32 struct {
|
||||||
tv_sec int32
|
tv_sec int32
|
||||||
tv_nsec int32
|
tv_nsec int32
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func (ts *timespec) setNsec(ns int64) {
|
func (ts *timespec32) setNsec(ns int64) {
|
||||||
ts.tv_sec = timediv(ns, 1e9, &ts.tv_nsec)
|
ts.tv_sec = timediv(ns, 1e9, &ts.tv_nsec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type timespec struct {
|
||||||
|
tv_sec int64
|
||||||
|
tv_nsec int64
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
func (ts *timespec) setNsec(ns int64) {
|
||||||
|
var newNS int32
|
||||||
|
ts.tv_sec = int64(timediv(ns, 1e9, &newNS))
|
||||||
|
ts.tv_nsec = int64(newNS)
|
||||||
|
}
|
||||||
|
|
||||||
type stackt struct {
|
type stackt struct {
|
||||||
ss_sp *byte
|
ss_sp *byte
|
||||||
ss_flags int32
|
ss_flags int32
|
||||||
|
@ -155,8 +170,8 @@ func (tv *timeval) set_usec(x int32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type itimerspec struct {
|
type itimerspec struct {
|
||||||
it_interval timespec
|
it_interval timespec32
|
||||||
it_value timespec
|
it_value timespec32
|
||||||
}
|
}
|
||||||
|
|
||||||
type itimerval struct {
|
type itimerval struct {
|
||||||
|
|
|
@ -9,6 +9,7 @@ const (
|
||||||
_EINTR = 0x4
|
_EINTR = 0x4
|
||||||
_EAGAIN = 0xb
|
_EAGAIN = 0xb
|
||||||
_ENOMEM = 0xc
|
_ENOMEM = 0xc
|
||||||
|
_ENOSYS = 0x26
|
||||||
|
|
||||||
_PROT_NONE = 0x0
|
_PROT_NONE = 0x0
|
||||||
_PROT_READ = 0x1
|
_PROT_READ = 0x1
|
||||||
|
|
|
@ -10,6 +10,7 @@ const (
|
||||||
_EINTR = 0x4
|
_EINTR = 0x4
|
||||||
_EAGAIN = 0xb
|
_EAGAIN = 0xb
|
||||||
_ENOMEM = 0xc
|
_ENOMEM = 0xc
|
||||||
|
_ENOSYS = 0x26
|
||||||
|
|
||||||
_PROT_NONE = 0x0
|
_PROT_NONE = 0x0
|
||||||
_PROT_READ = 0x1
|
_PROT_READ = 0x1
|
||||||
|
|
|
@ -12,6 +12,7 @@ const (
|
||||||
_EINTR = 0x4
|
_EINTR = 0x4
|
||||||
_EAGAIN = 0xb
|
_EAGAIN = 0xb
|
||||||
_ENOMEM = 0xc
|
_ENOMEM = 0xc
|
||||||
|
_ENOSYS = 0x26
|
||||||
|
|
||||||
_PROT_NONE = 0x0
|
_PROT_NONE = 0x0
|
||||||
_PROT_READ = 0x1
|
_PROT_READ = 0x1
|
||||||
|
|
|
@ -12,6 +12,7 @@ const (
|
||||||
_EINTR = 0x4
|
_EINTR = 0x4
|
||||||
_EAGAIN = 0xb
|
_EAGAIN = 0xb
|
||||||
_ENOMEM = 0xc
|
_ENOMEM = 0xc
|
||||||
|
_ENOSYS = 0x26
|
||||||
|
|
||||||
_PROT_NONE = 0x0
|
_PROT_NONE = 0x0
|
||||||
_PROT_READ = 0x1
|
_PROT_READ = 0x1
|
||||||
|
@ -93,16 +94,30 @@ const (
|
||||||
_SIGEV_THREAD_ID = 0x4
|
_SIGEV_THREAD_ID = 0x4
|
||||||
)
|
)
|
||||||
|
|
||||||
type timespec struct {
|
// The timespec structs and types are defined in Linux in
|
||||||
|
// include/uapi/linux/time_types.h and include/uapi/asm-generic/posix_types.h.
|
||||||
|
type timespec32 struct {
|
||||||
tv_sec int32
|
tv_sec int32
|
||||||
tv_nsec int32
|
tv_nsec int32
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func (ts *timespec) setNsec(ns int64) {
|
func (ts *timespec32) setNsec(ns int64) {
|
||||||
ts.tv_sec = timediv(ns, 1e9, &ts.tv_nsec)
|
ts.tv_sec = timediv(ns, 1e9, &ts.tv_nsec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type timespec struct {
|
||||||
|
tv_sec int64
|
||||||
|
tv_nsec int64
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
func (ts *timespec) setNsec(ns int64) {
|
||||||
|
var newNS int32
|
||||||
|
ts.tv_sec = int64(timediv(ns, 1e9, &newNS))
|
||||||
|
ts.tv_nsec = int64(newNS)
|
||||||
|
}
|
||||||
|
|
||||||
type timeval struct {
|
type timeval struct {
|
||||||
tv_sec int32
|
tv_sec int32
|
||||||
tv_usec int32
|
tv_usec int32
|
||||||
|
@ -138,8 +153,8 @@ type siginfo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type itimerspec struct {
|
type itimerspec struct {
|
||||||
it_interval timespec
|
it_interval timespec32
|
||||||
it_value timespec
|
it_value timespec32
|
||||||
}
|
}
|
||||||
|
|
||||||
type itimerval struct {
|
type itimerval struct {
|
||||||
|
|
|
@ -9,6 +9,7 @@ const (
|
||||||
_EINTR = 0x4
|
_EINTR = 0x4
|
||||||
_EAGAIN = 0xb
|
_EAGAIN = 0xb
|
||||||
_ENOMEM = 0xc
|
_ENOMEM = 0xc
|
||||||
|
_ENOSYS = 0x26
|
||||||
|
|
||||||
_PROT_NONE = 0x0
|
_PROT_NONE = 0x0
|
||||||
_PROT_READ = 0x1
|
_PROT_READ = 0x1
|
||||||
|
|
|
@ -9,6 +9,7 @@ const (
|
||||||
_EINTR = 0x4
|
_EINTR = 0x4
|
||||||
_EAGAIN = 0xb
|
_EAGAIN = 0xb
|
||||||
_ENOMEM = 0xc
|
_ENOMEM = 0xc
|
||||||
|
_ENOSYS = 0x26
|
||||||
|
|
||||||
_PROT_NONE = 0x0
|
_PROT_NONE = 0x0
|
||||||
_PROT_READ = 0x1
|
_PROT_READ = 0x1
|
||||||
|
|
|
@ -10,6 +10,7 @@ const (
|
||||||
_EINTR = 0x4
|
_EINTR = 0x4
|
||||||
_EAGAIN = 0xb
|
_EAGAIN = 0xb
|
||||||
_ENOMEM = 0xc
|
_ENOMEM = 0xc
|
||||||
|
_ENOSYS = 0x26
|
||||||
|
|
||||||
_PROT_NONE = 0x0
|
_PROT_NONE = 0x0
|
||||||
_PROT_READ = 0x1
|
_PROT_READ = 0x1
|
||||||
|
|
|
@ -10,6 +10,7 @@ const (
|
||||||
_EINTR = 0x4
|
_EINTR = 0x4
|
||||||
_EAGAIN = 0xb
|
_EAGAIN = 0xb
|
||||||
_ENOMEM = 0xc
|
_ENOMEM = 0xc
|
||||||
|
_ENOSYS = 0x26
|
||||||
|
|
||||||
_PROT_NONE = 0x0
|
_PROT_NONE = 0x0
|
||||||
_PROT_READ = 0x1
|
_PROT_READ = 0x1
|
||||||
|
|
|
@ -40,9 +40,6 @@ type mOS struct {
|
||||||
waitsema uint32 // semaphore for parking on locks
|
waitsema uint32 // semaphore for parking on locks
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
func futex(addr unsafe.Pointer, op int32, val uint32, ts, addr2 unsafe.Pointer, val3 uint32) int32
|
|
||||||
|
|
||||||
// Linux futex.
|
// Linux futex.
|
||||||
//
|
//
|
||||||
// futexsleep(uint32 *addr, uint32 val)
|
// futexsleep(uint32 *addr, uint32 val)
|
||||||
|
@ -79,7 +76,7 @@ func futexsleep(addr *uint32, val uint32, ns int64) {
|
||||||
|
|
||||||
var ts timespec
|
var ts timespec
|
||||||
ts.setNsec(ns)
|
ts.setNsec(ns)
|
||||||
futex(unsafe.Pointer(addr), _FUTEX_WAIT_PRIVATE, val, unsafe.Pointer(&ts), nil, 0)
|
futex(unsafe.Pointer(addr), _FUTEX_WAIT_PRIVATE, val, &ts, nil, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If any procs are sleeping on addr, wake up at most cnt.
|
// If any procs are sleeping on addr, wake up at most cnt.
|
||||||
|
|
40
src/runtime/os_linux_futex32.go
Normal file
40
src/runtime/os_linux_futex32.go
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
// Copyright 2025 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.
|
||||||
|
|
||||||
|
//go:build linux && (386 || arm || mips || mipsle || ppc)
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"internal/runtime/atomic"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
//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 is32bitOnly atomic.Bool
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
func futex(addr unsafe.Pointer, op int32, val uint32, ts *timespec, addr2 unsafe.Pointer, val3 uint32) int32 {
|
||||||
|
if !is32bitOnly.Load() {
|
||||||
|
ret := futex_time64(addr, op, val, ts, addr2, val3)
|
||||||
|
// futex_time64 is only supported on Linux 5.0+
|
||||||
|
if ret != -_ENOSYS {
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
is32bitOnly.Store(true)
|
||||||
|
}
|
||||||
|
// Downgrade ts.
|
||||||
|
var ts32 timespec32
|
||||||
|
var pts32 *timespec32
|
||||||
|
if ts != nil {
|
||||||
|
ts32.setNsec(ts.tv_sec*1e9 + ts.tv_nsec)
|
||||||
|
pts32 = &ts32
|
||||||
|
}
|
||||||
|
return futex_time32(addr, op, val, pts32, addr2, val3)
|
||||||
|
}
|
14
src/runtime/os_linux_futex64.go
Normal file
14
src/runtime/os_linux_futex64.go
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// Copyright 2025 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.
|
||||||
|
|
||||||
|
//go:build linux && !(386 || arm || mips || mipsle || ppc || s390)
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func futex(addr unsafe.Pointer, op int32, val uint32, ts *timespec, addr2 unsafe.Pointer, val3 uint32) int32
|
|
@ -48,6 +48,7 @@
|
||||||
#define SYS_madvise 219
|
#define SYS_madvise 219
|
||||||
#define SYS_gettid 224
|
#define SYS_gettid 224
|
||||||
#define SYS_futex 240
|
#define SYS_futex 240
|
||||||
|
#define SYS_futex_time64 422
|
||||||
#define SYS_sched_getaffinity 242
|
#define SYS_sched_getaffinity 242
|
||||||
#define SYS_set_thread_area 243
|
#define SYS_set_thread_area 243
|
||||||
#define SYS_exit_group 252
|
#define SYS_exit_group 252
|
||||||
|
@ -532,10 +533,26 @@ TEXT runtime·madvise(SB),NOSPLIT,$0
|
||||||
MOVL AX, ret+12(FP)
|
MOVL AX, ret+12(FP)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
// Linux: kernel/futex/syscalls.c, requiring COMPAT_32BIT_TIME
|
||||||
|
// int32 futex(int32 *uaddr, int32 op, int32 val,
|
||||||
|
// struct old_timespec32 *timeout, int32 *uaddr2, int32 val2);
|
||||||
|
TEXT runtime·futex_time32(SB),NOSPLIT,$0
|
||||||
|
MOVL $SYS_futex, AX
|
||||||
|
MOVL addr+0(FP), BX
|
||||||
|
MOVL op+4(FP), CX
|
||||||
|
MOVL val+8(FP), DX
|
||||||
|
MOVL ts+12(FP), SI
|
||||||
|
MOVL addr2+16(FP), DI
|
||||||
|
MOVL val3+20(FP), BP
|
||||||
|
INVOKE_SYSCALL
|
||||||
|
MOVL AX, ret+24(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
// Linux: kernel/futex/syscalls.c
|
||||||
// int32 futex(int32 *uaddr, int32 op, int32 val,
|
// int32 futex(int32 *uaddr, int32 op, int32 val,
|
||||||
// struct timespec *timeout, int32 *uaddr2, int32 val2);
|
// struct timespec *timeout, int32 *uaddr2, int32 val2);
|
||||||
TEXT runtime·futex(SB),NOSPLIT,$0
|
TEXT runtime·futex_time64(SB),NOSPLIT,$0
|
||||||
MOVL $SYS_futex, AX
|
MOVL $SYS_futex_time64, AX
|
||||||
MOVL addr+0(FP), BX
|
MOVL addr+0(FP), BX
|
||||||
MOVL op+4(FP), CX
|
MOVL op+4(FP), CX
|
||||||
MOVL val+8(FP), DX
|
MOVL val+8(FP), DX
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#define SYS_sigaltstack (SYS_BASE + 186)
|
#define SYS_sigaltstack (SYS_BASE + 186)
|
||||||
#define SYS_mmap2 (SYS_BASE + 192)
|
#define SYS_mmap2 (SYS_BASE + 192)
|
||||||
#define SYS_futex (SYS_BASE + 240)
|
#define SYS_futex (SYS_BASE + 240)
|
||||||
|
#define SYS_futex_time64 (SYS_BASE + 422)
|
||||||
#define SYS_exit_group (SYS_BASE + 248)
|
#define SYS_exit_group (SYS_BASE + 248)
|
||||||
#define SYS_munmap (SYS_BASE + 91)
|
#define SYS_munmap (SYS_BASE + 91)
|
||||||
#define SYS_madvise (SYS_BASE + 220)
|
#define SYS_madvise (SYS_BASE + 220)
|
||||||
|
@ -403,9 +404,10 @@ finish:
|
||||||
|
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
// Linux: kernel/futex/syscalls.c, requiring COMPAT_32BIT_TIME
|
||||||
// int32 futex(int32 *uaddr, int32 op, int32 val,
|
// int32 futex(int32 *uaddr, int32 op, int32 val,
|
||||||
// struct timespec *timeout, int32 *uaddr2, int32 val2);
|
// struct old_timespec32 *timeout, int32 *uaddr2, int32 val2);
|
||||||
TEXT runtime·futex(SB),NOSPLIT,$0
|
TEXT runtime·futex_time32(SB),NOSPLIT,$0
|
||||||
MOVW addr+0(FP), R0
|
MOVW addr+0(FP), R0
|
||||||
MOVW op+4(FP), R1
|
MOVW op+4(FP), R1
|
||||||
MOVW val+8(FP), R2
|
MOVW val+8(FP), R2
|
||||||
|
@ -417,6 +419,21 @@ TEXT runtime·futex(SB),NOSPLIT,$0
|
||||||
MOVW R0, ret+24(FP)
|
MOVW R0, ret+24(FP)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
// Linux: kernel/futex/syscalls.c
|
||||||
|
// int32 futex(int32 *uaddr, int32 op, int32 val,
|
||||||
|
// struct timespec *timeout, int32 *uaddr2, int32 val2);
|
||||||
|
TEXT runtime·futex_time64(SB),NOSPLIT,$0
|
||||||
|
MOVW addr+0(FP), R0
|
||||||
|
MOVW op+4(FP), R1
|
||||||
|
MOVW val+8(FP), R2
|
||||||
|
MOVW ts+12(FP), R3
|
||||||
|
MOVW addr2+16(FP), R4
|
||||||
|
MOVW val3+20(FP), R5
|
||||||
|
MOVW $SYS_futex_time64, R7
|
||||||
|
SWI $0
|
||||||
|
MOVW R0, ret+24(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
// int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void));
|
// int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void));
|
||||||
TEXT runtime·clone(SB),NOSPLIT,$0
|
TEXT runtime·clone(SB),NOSPLIT,$0
|
||||||
MOVW flags+0(FP), R0
|
MOVW flags+0(FP), R0
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#define SYS_mincore 4217
|
#define SYS_mincore 4217
|
||||||
#define SYS_gettid 4222
|
#define SYS_gettid 4222
|
||||||
#define SYS_futex 4238
|
#define SYS_futex 4238
|
||||||
|
#define SYS_futex_time64 4422
|
||||||
#define SYS_sched_getaffinity 4240
|
#define SYS_sched_getaffinity 4240
|
||||||
#define SYS_exit_group 4246
|
#define SYS_exit_group 4246
|
||||||
#define SYS_timer_create 4257
|
#define SYS_timer_create 4257
|
||||||
|
@ -362,8 +363,10 @@ TEXT runtime·madvise(SB),NOSPLIT,$0-16
|
||||||
MOVW R2, ret+12(FP)
|
MOVW R2, ret+12(FP)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// int32 futex(int32 *uaddr, int32 op, int32 val, struct timespec *timeout, int32 *uaddr2, int32 val2);
|
// Linux: kernel/futex/syscalls.c, requiring COMPAT_32BIT_TIME
|
||||||
TEXT runtime·futex(SB),NOSPLIT,$20-28
|
// int32 futex(int32 *uaddr, int32 op, int32 val,
|
||||||
|
// struct old_timespec32 *timeout, int32 *uaddr2, int32 val2);
|
||||||
|
TEXT runtime·futex_time32(SB),NOSPLIT,$20-28
|
||||||
MOVW addr+0(FP), R4
|
MOVW addr+0(FP), R4
|
||||||
MOVW op+4(FP), R5
|
MOVW op+4(FP), R5
|
||||||
MOVW val+8(FP), R6
|
MOVW val+8(FP), R6
|
||||||
|
@ -382,6 +385,27 @@ TEXT runtime·futex(SB),NOSPLIT,$20-28
|
||||||
MOVW R2, ret+24(FP)
|
MOVW R2, ret+24(FP)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
// Linux: kernel/futex/syscalls.c
|
||||||
|
// int32 futex(int32 *uaddr, int32 op, int32 val,
|
||||||
|
// struct timespec *timeout, int32 *uaddr2, int32 val2);
|
||||||
|
TEXT runtime·futex_time64(SB),NOSPLIT,$20-28
|
||||||
|
MOVW addr+0(FP), R4
|
||||||
|
MOVW op+4(FP), R5
|
||||||
|
MOVW val+8(FP), R6
|
||||||
|
MOVW ts+12(FP), R7
|
||||||
|
|
||||||
|
MOVW addr2+16(FP), R8
|
||||||
|
MOVW val3+20(FP), R9
|
||||||
|
|
||||||
|
MOVW R8, 16(R29)
|
||||||
|
MOVW R9, 20(R29)
|
||||||
|
|
||||||
|
MOVW $SYS_futex_time64, R2
|
||||||
|
SYSCALL
|
||||||
|
BEQ R7, 2(PC)
|
||||||
|
SUBU R2, R0, R2 // caller expects negative errno
|
||||||
|
MOVW R2, ret+24(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
// int32 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
|
// int32 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
|
||||||
TEXT runtime·clone(SB),NOSPLIT|NOFRAME,$0-24
|
TEXT runtime·clone(SB),NOSPLIT|NOFRAME,$0-24
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue