From: Andrei Tatar Date: Wed, 22 Jan 2025 22:16:37 +0000 (+0100) Subject: lib/posix-timerfd: Output correct old_value on set X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=a81f9ec3c91971109b2bc498ccc2fb80c9e5d4f2;p=unikraft%2Funikraft.git lib/posix-timerfd: Output correct old_value on set Previously settime() would output the old timerfd setting verbatim, as an absolute deadline; this contradicts timerfd_settime(2) which clearly states that old_value should be output with the same semantics as gettime() -- relative time remaining until the next expiration. This change makes settime() calculate and output this time correctly. Signed-off-by: Andrei Tatar Approved-by: Sergiu Moga Reviewed-by: Sergiu Moga GitHub-Closes: #1568 --- diff --git a/lib/posix-timerfd/timerfd.c b/lib/posix-timerfd/timerfd.c index 1e1b32719..b9b2fb661 100644 --- a/lib/posix-timerfd/timerfd.c +++ b/lib/posix-timerfd/timerfd.c @@ -329,8 +329,10 @@ int uk_sys_timerfd_settime(const struct uk_file *f, int flags, struct timerfd_node *d; const struct itimerspec *set; struct itimerspec absset; + struct timespec t; const int disarm = !new_value->it_value.tv_sec && !new_value->it_value.tv_nsec; + const int abstime = !!(flags & TFD_TIMER_ABSTIME); if (unlikely(flags & ~TFD_TIMER_ABSTIME)) return -EINVAL; @@ -341,18 +343,22 @@ int uk_sys_timerfd_settime(const struct uk_file *f, int flags, d = f->node; uk_file_wlock(f); - if (disarm || flags & TFD_TIMER_ABSTIME) { + if (old_value || !(disarm || abstime)) + uk_sys_clock_gettime(d->clkid, &t); + + if (disarm || abstime) { set = new_value; } else { - struct timespec t; - - uk_sys_clock_gettime(d->clkid, &t); absset.it_interval = new_value->it_interval; absset.it_value = uk_time_spec_sum(&new_value->it_value, &t); set = &absset; } - if (old_value) - *old_value = d->set; + if (old_value) { + struct timerfd_status st = _timerfd_valnext(&d->set, &t); + + old_value->it_interval = d->set.it_interval; + old_value->it_value = uk_time_spec_from_nsec(st.next); + } _timerfd_set(d, set); (void)_timerfd_update(f); uk_file_wunlock(f);