From 6c3d62d60e5ff02ebe61e56e06d6365e530ec39e Mon Sep 17 00:00:00 2001 From: abdullahkiani007 Date: Wed, 15 Oct 2025 16:32:23 +0500 Subject: [PATCH] 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 64-bit version returns _ENOSYS. Fixes #75133 --- src/runtime/defs_linux_386.go | 6 +++- src/runtime/defs_linux_arm.go | 7 ++++- src/runtime/defs_linux_mipsx.go | 7 ++++- src/runtime/os_linux.go | 3 -- src/runtime/os_linux_settime32.go | 47 +++++++++++++++++++++++++++++++ src/runtime/os_linux_settime64.go | 10 +++++++ src/runtime/sys_linux_386.s | 14 ++++++++- src/runtime/sys_linux_arm.s | 15 ++++++++-- src/runtime/sys_linux_mipsx.s | 14 ++++++++- 9 files changed, 113 insertions(+), 10 deletions(-) create mode 100644 src/runtime/os_linux_settime32.go create mode 100644 src/runtime/os_linux_settime64.go diff --git a/src/runtime/defs_linux_386.go b/src/runtime/defs_linux_386.go index e902d8175c3b0d..c6c7d7d6d880c0 100644 --- a/src/runtime/defs_linux_386.go +++ b/src/runtime/defs_linux_386.go @@ -237,10 +237,14 @@ type ucontext struct { uc_sigmask uint32 } -type itimerspec struct { +type itimerspec32 struct { it_interval timespec32 it_value timespec32 } +type itimerspec struct { + it_interval timespec + it_value timespec +} type itimerval struct { it_interval timeval diff --git a/src/runtime/defs_linux_arm.go b/src/runtime/defs_linux_arm.go index 35c4faf96405d3..ff879fad89faa1 100644 --- a/src/runtime/defs_linux_arm.go +++ b/src/runtime/defs_linux_arm.go @@ -169,11 +169,16 @@ func (tv *timeval) set_usec(x int32) { tv.tv_usec = x } -type itimerspec struct { +type itimerspec32 struct { it_interval timespec32 it_value timespec32 } +type itimerspec struct { + it_interval timespec + it_value timespec +} + type itimerval struct { it_interval timeval it_value timeval diff --git a/src/runtime/defs_linux_mipsx.go b/src/runtime/defs_linux_mipsx.go index cec504c885662b..5b10b910dbebf2 100644 --- a/src/runtime/defs_linux_mipsx.go +++ b/src/runtime/defs_linux_mipsx.go @@ -152,11 +152,16 @@ type siginfo struct { _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte } -type itimerspec struct { +type itimerspec32 struct { it_interval timespec32 it_value timespec32 } +type itimerspec struct { + it_interval timespec + it_value timespec +} + type itimerval struct { it_interval timeval it_value timeval diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go index 080dd9653232ed..1b7d5731cc32ab 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -435,9 +435,6 @@ func setitimer(mode int32, new, old *itimerval) //go:noescape 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 func timer_delete(timerid int32) int32 diff --git a/src/runtime/os_linux_settime32.go b/src/runtime/os_linux_settime32.go new file mode 100644 index 00000000000000..6df7f21dc9ce71 --- /dev/null +++ b/src/runtime/os_linux_settime32.go @@ -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) +} diff --git a/src/runtime/os_linux_settime64.go b/src/runtime/os_linux_settime64.go new file mode 100644 index 00000000000000..60650da33fb990 --- /dev/null +++ b/src/runtime/os_linux_settime64.go @@ -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 diff --git a/src/runtime/sys_linux_386.s b/src/runtime/sys_linux_386.s index 1c3f1ff3e6e575..f664d8ace7f997 100644 --- a/src/runtime/sys_linux_386.s +++ b/src/runtime/sys_linux_386.s @@ -54,6 +54,7 @@ #define SYS_exit_group 252 #define SYS_timer_create 259 #define SYS_timer_settime 260 +#define SYS_timer_settime64 409 #define SYS_timer_delete 263 #define SYS_clock_gettime 265 #define SYS_tgkill 270 @@ -209,7 +210,8 @@ TEXT runtime·timer_create(SB),NOSPLIT,$0-16 MOVL AX, ret+12(FP) 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 timerid+0(FP), BX MOVL flags+4(FP), CX @@ -219,6 +221,16 @@ TEXT runtime·timer_settime(SB),NOSPLIT,$0-20 MOVL AX, ret+16(FP) 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 MOVL $SYS_timer_delete, AX MOVL timerid+0(FP), BX diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s index 44b56ccb9f0094..f19e293d0fc3e0 100644 --- a/src/runtime/sys_linux_arm.s +++ b/src/runtime/sys_linux_arm.s @@ -44,6 +44,7 @@ #define SYS_clock_gettime (SYS_BASE + 263) #define SYS_timer_create (SYS_BASE + 257) #define SYS_timer_settime (SYS_BASE + 258) +#define SYS_timer_settime64 (SYS_BASE + 409) #define SYS_timer_delete (SYS_BASE + 261) #define SYS_pipe2 (SYS_BASE + 359) #define SYS_access (SYS_BASE + 33) @@ -231,8 +232,8 @@ TEXT runtime·timer_create(SB),NOSPLIT,$0-16 SWI $0 MOVW R0, ret+12(FP) 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), R0 MOVW flags+4(FP), R1 MOVW new+8(FP), R2 @@ -242,6 +243,16 @@ TEXT runtime·timer_settime(SB),NOSPLIT,$0-20 MOVW R0, ret+16(FP) 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 MOVW timerid+0(FP), R0 MOVW $SYS_timer_delete, R7 diff --git a/src/runtime/sys_linux_mipsx.s b/src/runtime/sys_linux_mipsx.s index 6f11841efc73e2..bc3f84fbb9591e 100644 --- a/src/runtime/sys_linux_mipsx.s +++ b/src/runtime/sys_linux_mipsx.s @@ -39,6 +39,7 @@ #define SYS_exit_group 4246 #define SYS_timer_create 4257 #define SYS_timer_settime 4258 +#define SYS_timer_settime64 4409 #define SYS_timer_delete 4261 #define SYS_clock_gettime 4263 #define SYS_tgkill 4266 @@ -197,7 +198,8 @@ TEXT runtime·timer_create(SB),NOSPLIT,$0-16 MOVW R2, ret+12(FP) 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 flags+4(FP), R5 MOVW new+8(FP), R6 @@ -207,6 +209,16 @@ TEXT runtime·timer_settime(SB),NOSPLIT,$0-20 MOVW R2, ret+16(FP) 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 MOVW timerid+0(FP), R4 MOVW $SYS_timer_delete, R2