runtime: use timer_settime64 on 32-bit 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 64-bit syscall for timer_settime by default.
Add a fallback to use the 32-bit syscall when the
64-bit version returns _ENOSYS.

Fixes #75133

Change-Id: Iccb8831b67f665067ee526e93c3ff2f4f5392edf
GitHub-Last-Rev: 6c3d62d60e
GitHub-Pull-Request: golang/go#75957
Reviewed-on: https://go-review.googlesource.com/c/go/+/712642
Reviewed-by: Jorropo <jorropo.pgm@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Jorropo <jorropo.pgm@gmail.com>
This commit is contained in:
abdullahkiani007 2025-10-18 14:43:53 +00:00 committed by Gopher Robot
parent b31dc77cea
commit 4620db72d2
9 changed files with 113 additions and 10 deletions

View file

@ -237,10 +237,14 @@ type ucontext struct {
uc_sigmask uint32 uc_sigmask uint32
} }
type itimerspec struct { type itimerspec32 struct {
it_interval timespec32 it_interval timespec32
it_value timespec32 it_value timespec32
} }
type itimerspec struct {
it_interval timespec
it_value timespec
}
type itimerval struct { type itimerval struct {
it_interval timeval it_interval timeval

View file

@ -169,11 +169,16 @@ func (tv *timeval) set_usec(x int32) {
tv.tv_usec = x tv.tv_usec = x
} }
type itimerspec struct { type itimerspec32 struct {
it_interval timespec32 it_interval timespec32
it_value timespec32 it_value timespec32
} }
type itimerspec struct {
it_interval timespec
it_value timespec
}
type itimerval struct { type itimerval struct {
it_interval timeval it_interval timeval
it_value timeval it_value timeval

View file

@ -152,11 +152,16 @@ type siginfo struct {
_ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte
} }
type itimerspec struct { type itimerspec32 struct {
it_interval timespec32 it_interval timespec32
it_value timespec32 it_value timespec32
} }
type itimerspec struct {
it_interval timespec
it_value timespec
}
type itimerval struct { type itimerval struct {
it_interval timeval it_interval timeval
it_value timeval it_value timeval

View file

@ -435,9 +435,6 @@ func setitimer(mode int32, new, old *itimerval)
//go:noescape //go:noescape
func timer_create(clockid int32, sevp *sigevent, timerid *int32) int32 func timer_create(clockid int32, sevp *sigevent, timerid *int32) int32
//go:noescape
func timer_settime(timerid int32, flags int32, new, old *itimerspec) int32
//go:noescape //go:noescape
func timer_delete(timerid int32) int32 func timer_delete(timerid int32) int32

View file

@ -0,0 +1,47 @@
// 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)
package runtime
import "internal/runtime/atomic"
var timer32bitOnly atomic.Bool
//go:noescape
func timer_settime32(timerid int32, flags int32, new, old *itimerspec32) int32
//go:noescape
func timer_settime64(timerid int32, flags int32, new, old *itimerspec) int32
//go:nosplit
func timer_settime(timerid int32, flags int32, new, old *itimerspec) int32 {
if !timer32bitOnly.Load() {
ret := timer_settime64(timerid, flags, new, old)
// timer_settime64 is only supported on Linux 5.0+
if ret != -_ENOSYS {
return ret
}
timer32bitOnly.Store(true)
}
var newts,oldts itimerspec32
var new32,old32 *itimerspec32
if new != nil {
newts.it_interval.setNsec(new.it_interval.tv_sec*1e9 + new.it_interval.tv_nsec)
newts.it_value.setNsec(new.it_value.tv_sec*1e9 + new.it_value.tv_nsec)
new32 = &newts
}
if old != nil {
oldts.it_interval.setNsec(old.it_interval.tv_sec*1e9 + old.it_interval.tv_nsec)
oldts.it_value.setNsec(old.it_value.tv_sec*1e9 + old.it_value.tv_nsec)
old32 = &oldts
}
// Fall back to 32-bit timer
return timer_settime32(timerid, flags, new32, old32)
}

View file

@ -0,0 +1,10 @@
// 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)
package runtime
//go:noescape
func timer_settime(timerid int32, flags int32, new, old *itimerspec) int32

View file

@ -54,6 +54,7 @@
#define SYS_exit_group 252 #define SYS_exit_group 252
#define SYS_timer_create 259 #define SYS_timer_create 259
#define SYS_timer_settime 260 #define SYS_timer_settime 260
#define SYS_timer_settime64 409
#define SYS_timer_delete 263 #define SYS_timer_delete 263
#define SYS_clock_gettime 265 #define SYS_clock_gettime 265
#define SYS_tgkill 270 #define SYS_tgkill 270
@ -209,7 +210,8 @@ TEXT runtime·timer_create(SB),NOSPLIT,$0-16
MOVL AX, ret+12(FP) MOVL AX, ret+12(FP)
RET RET
TEXT runtime·timer_settime(SB),NOSPLIT,$0-20 // Linux: kernel/time/posix-timer.c, requiring COMPAT_32BIT_TIME
TEXT runtime·timer_settime32(SB),NOSPLIT,$0-20
MOVL $SYS_timer_settime, AX MOVL $SYS_timer_settime, AX
MOVL timerid+0(FP), BX MOVL timerid+0(FP), BX
MOVL flags+4(FP), CX MOVL flags+4(FP), CX
@ -219,6 +221,16 @@ TEXT runtime·timer_settime(SB),NOSPLIT,$0-20
MOVL AX, ret+16(FP) MOVL AX, ret+16(FP)
RET RET
TEXT runtime·timer_settime64(SB),NOSPLIT,$0-20
MOVL $SYS_timer_settime64, AX
MOVL timerid+0(FP), BX
MOVL flags+4(FP), CX
MOVL new+8(FP), DX
MOVL old+12(FP), SI
INVOKE_SYSCALL
MOVL AX, ret+16(FP)
RET
TEXT runtime·timer_delete(SB),NOSPLIT,$0-8 TEXT runtime·timer_delete(SB),NOSPLIT,$0-8
MOVL $SYS_timer_delete, AX MOVL $SYS_timer_delete, AX
MOVL timerid+0(FP), BX MOVL timerid+0(FP), BX

View file

@ -44,6 +44,7 @@
#define SYS_clock_gettime (SYS_BASE + 263) #define SYS_clock_gettime (SYS_BASE + 263)
#define SYS_timer_create (SYS_BASE + 257) #define SYS_timer_create (SYS_BASE + 257)
#define SYS_timer_settime (SYS_BASE + 258) #define SYS_timer_settime (SYS_BASE + 258)
#define SYS_timer_settime64 (SYS_BASE + 409)
#define SYS_timer_delete (SYS_BASE + 261) #define SYS_timer_delete (SYS_BASE + 261)
#define SYS_pipe2 (SYS_BASE + 359) #define SYS_pipe2 (SYS_BASE + 359)
#define SYS_access (SYS_BASE + 33) #define SYS_access (SYS_BASE + 33)
@ -231,8 +232,8 @@ TEXT runtime·timer_create(SB),NOSPLIT,$0-16
SWI $0 SWI $0
MOVW R0, ret+12(FP) MOVW R0, ret+12(FP)
RET RET
// Linux: kernel/time/posix-timer.c, requiring COMPAT_32BIT_TIME.
TEXT runtime·timer_settime(SB),NOSPLIT,$0-20 TEXT runtime·timer_settime32(SB),NOSPLIT,$0-20
MOVW timerid+0(FP), R0 MOVW timerid+0(FP), R0
MOVW flags+4(FP), R1 MOVW flags+4(FP), R1
MOVW new+8(FP), R2 MOVW new+8(FP), R2
@ -242,6 +243,16 @@ TEXT runtime·timer_settime(SB),NOSPLIT,$0-20
MOVW R0, ret+16(FP) MOVW R0, ret+16(FP)
RET RET
TEXT runtime·timer_settime64(SB),NOSPLIT,$0-20
MOVW timerid+0(FP), R0
MOVW flags+4(FP), R1
MOVW new+8(FP), R2
MOVW old+12(FP), R3
MOVW $SYS_timer_settime64, R7
SWI $0
MOVW R0, ret+16(FP)
RET
TEXT runtime·timer_delete(SB),NOSPLIT,$0-8 TEXT runtime·timer_delete(SB),NOSPLIT,$0-8
MOVW timerid+0(FP), R0 MOVW timerid+0(FP), R0
MOVW $SYS_timer_delete, R7 MOVW $SYS_timer_delete, R7

View file

@ -39,6 +39,7 @@
#define SYS_exit_group 4246 #define SYS_exit_group 4246
#define SYS_timer_create 4257 #define SYS_timer_create 4257
#define SYS_timer_settime 4258 #define SYS_timer_settime 4258
#define SYS_timer_settime64 4409
#define SYS_timer_delete 4261 #define SYS_timer_delete 4261
#define SYS_clock_gettime 4263 #define SYS_clock_gettime 4263
#define SYS_tgkill 4266 #define SYS_tgkill 4266
@ -197,7 +198,8 @@ TEXT runtime·timer_create(SB),NOSPLIT,$0-16
MOVW R2, ret+12(FP) MOVW R2, ret+12(FP)
RET RET
TEXT runtime·timer_settime(SB),NOSPLIT,$0-20 // Linux: kernel/time/posix-timer.c, requiring COMPAT_32BIT_TIME
TEXT runtime·timer_settime32(SB),NOSPLIT,$0-20
MOVW timerid+0(FP), R4 MOVW timerid+0(FP), R4
MOVW flags+4(FP), R5 MOVW flags+4(FP), R5
MOVW new+8(FP), R6 MOVW new+8(FP), R6
@ -207,6 +209,16 @@ TEXT runtime·timer_settime(SB),NOSPLIT,$0-20
MOVW R2, ret+16(FP) MOVW R2, ret+16(FP)
RET RET
TEXT runtime·timer_settime64(SB),NOSPLIT,$0-20
MOVW timerid+0(FP), R4
MOVW flags+4(FP), R5
MOVW new+8(FP), R6
MOVW old+12(FP), R7
MOVW $SYS_timer_settime64, R2
SYSCALL
MOVW R2, ret+16(FP)
RET
TEXT runtime·timer_delete(SB),NOSPLIT,$0-8 TEXT runtime·timer_delete(SB),NOSPLIT,$0-8
MOVW timerid+0(FP), R4 MOVW timerid+0(FP), R4
MOVW $SYS_timer_delete, R2 MOVW $SYS_timer_delete, R2