]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
lib/posix-timerfd: Output correct old_value on set
authorAndrei Tatar <andrei@unikraft.io>
Wed, 22 Jan 2025 22:16:37 +0000 (23:16 +0100)
committerUnikraft Bot <monkey@unikraft.io>
Tue, 25 Feb 2025 08:02:29 +0000 (08:02 +0000)
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 <andrei@unikraft.io>
Approved-by: Sergiu Moga <sergiu@unikraft.io>
Reviewed-by: Sergiu Moga <sergiu@unikraft.io>
GitHub-Closes: #1568

lib/posix-timerfd/timerfd.c

index 1e1b3271944f90a2f009877622af1de25c773792..b9b2fb6610002b7013c6525ed07324ca350772ee 100644 (file)
@@ -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);