Skip to content

Commit 57b0939

Browse files
authored
[libc] Fix alarm layout mismatch on 32-bit time64 (#201276)
Fixed alarm implementation on 32-bit architectures with 64-bit time_t (like RISC-V 32-bit). The SYS_setitimer syscall on these platforms expects the legacy 32-bit struct itimerval (with 32-bit tv_sec and tv_usec). Convert the arguments to this layout before invoking the syscall to avoid the kernel misinterpreting the timeout. Assisted-by: Automated tooling, human reviewed.
1 parent 9bb17a0 commit 57b0939

1 file changed

Lines changed: 23 additions & 10 deletions

File tree

libc/src/unistd/linux/alarm.cpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,29 @@ LLVM_LIBC_FUNCTION(unsigned int, alarm, (unsigned int seconds)) {
3030
return static_cast<unsigned int>(
3131
LIBC_NAMESPACE::syscall_impl<long>(SYS_alarm, seconds));
3232
#elif defined(SYS_setitimer)
33-
struct itimerval itv, old_itv;
34-
itv.it_interval.tv_sec = 0;
35-
itv.it_interval.tv_usec = 0;
36-
itv.it_value.tv_sec = seconds;
37-
itv.it_value.tv_usec = 0;
38-
if (LIBC_NAMESPACE::syscall_impl<int>(SYS_setitimer, 0 /* ITIMER_REAL */,
39-
&itv, &old_itv) < 0)
40-
return 0;
41-
return static_cast<unsigned int>(old_itv.it_value.tv_sec +
42-
(old_itv.it_value.tv_usec > 0 ? 1 : 0));
33+
// On 32-bit architectures with 64-bit time_t, SYS_setitimer still expects
34+
// 32-bit fields. We must convert itimerval to use 32-bit fields.
35+
if constexpr (sizeof(time_t) > sizeof(long)) {
36+
long itv32[4] = {0, 0, static_cast<long>(seconds), 0};
37+
long old_itv32[4];
38+
long ret = LIBC_NAMESPACE::syscall_impl<long>(
39+
SYS_setitimer, 0 /* ITIMER_REAL */, itv32, old_itv32);
40+
if (ret < 0)
41+
return 0;
42+
return static_cast<unsigned int>(old_itv32[2] + (old_itv32[3] > 0 ? 1 : 0));
43+
} else {
44+
struct itimerval itv, old_itv;
45+
itv.it_interval.tv_sec = 0;
46+
itv.it_interval.tv_usec = 0;
47+
itv.it_value.tv_sec = seconds;
48+
itv.it_value.tv_usec = 0;
49+
long ret = LIBC_NAMESPACE::syscall_impl<long>(
50+
SYS_setitimer, 0 /* ITIMER_REAL */, &itv, &old_itv);
51+
if (ret < 0)
52+
return 0;
53+
return static_cast<unsigned int>(old_itv.it_value.tv_sec +
54+
(old_itv.it_value.tv_usec > 0 ? 1 : 0));
55+
}
4356
#else
4457
#error "alarm implementation not available for this architecture"
4558
#endif

0 commit comments

Comments
 (0)