Page MenuHomeFreeBSD

D55790.id173514.diff
No OneTemporary

D55790.id173514.diff

diff --git a/sys/kern/sys_timerfd.c b/sys/kern/sys_timerfd.c
--- a/sys/kern/sys_timerfd.c
+++ b/sys/kern/sys_timerfd.c
@@ -393,23 +393,25 @@
timerfd_expire(void *arg)
{
struct timerfd *tfd = (struct timerfd *)arg;
- struct timespec uptime;
+ sbintime_t exp, interval, now, next, diff;
++tfd->tfd_count;
tfd->tfd_expired = true;
if (timespecisset(&tfd->tfd_time.it_interval)) {
+ exp = tstosbt(tfd->tfd_time.it_value);
+ interval = tstosbt(tfd->tfd_time.it_interval);
+ now = sbinuptime();
+ next = now + interval;
+
/* Count missed events. */
- nanouptime(&uptime);
- if (timespeccmp(&uptime, &tfd->tfd_time.it_value, >)) {
- timespecsub(&uptime, &tfd->tfd_time.it_value, &uptime);
- tfd->tfd_count += tstosbt(uptime) /
- tstosbt(tfd->tfd_time.it_interval);
+ if (now > exp) {
+ diff = now - exp;
+ tfd->tfd_count += diff / interval;
+ next -= diff % interval;
}
- timespecadd(&tfd->tfd_time.it_value,
- &tfd->tfd_time.it_interval, &tfd->tfd_time.it_value);
- callout_schedule_sbt(&tfd->tfd_callout,
- tstosbt(tfd->tfd_time.it_value),
- 0, C_ABSOLUTE);
+
+ callout_schedule_sbt(&tfd->tfd_callout, next, 0, C_ABSOLUTE);
+ tfd->tfd_time.it_value = sbttots(next);
} else {
/* Single shot timer. */
callout_deactivate(&tfd->tfd_callout);
diff --git a/tests/sys/kern/timerfd.c b/tests/sys/kern/timerfd.c
--- a/tests/sys/kern/timerfd.c
+++ b/tests/sys/kern/timerfd.c
@@ -981,6 +981,34 @@
ATF_REQUIRE(errno == EAGAIN);
}
+ATF_TC_WITHOUT_HEAD(timerfd__missed_events);
+ATF_TC_BODY_FD_LEAKCHECK(timerfd__missed_events, tc)
+{
+ struct itimerspec its = { };
+ uint64_t timeouts;
+ int timerfd;
+
+ timerfd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
+ ATF_REQUIRE(timerfd >= 0);
+
+ ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &its.it_value) == 0);
+ its.it_value.tv_sec -= 1000;
+ its.it_interval.tv_sec = 1;
+
+ ATF_REQUIRE(timerfd_settime(timerfd, TFD_TIMER_ABSTIME, &its,
+ NULL) == 0);
+
+ ATF_REQUIRE(read(timerfd, &timeouts, sizeof(timeouts)) ==
+ sizeof(timeouts));
+ ATF_REQUIRE_MSG(timeouts == 1001, "%ld", (long)timeouts);
+
+ ATF_REQUIRE(read(timerfd, &timeouts, sizeof(timeouts)) ==
+ sizeof(timeouts));
+ ATF_REQUIRE_MSG(timeouts == 1, "%ld", (long)timeouts);
+
+ ATF_REQUIRE(close(timerfd) == 0);
+}
+
/*
* Tests requiring root (clock_settime on CLOCK_REALTIME).
* Tests gracefully skip if not running as root.
@@ -1338,6 +1366,7 @@
ATF_TP_ADD_TC(tp, timerfd__short_evfilt_timer_timeout);
ATF_TP_ADD_TC(tp, timerfd__unmodified_errno);
ATF_TP_ADD_TC(tp, timerfd__reset_to_very_long);
+ ATF_TP_ADD_TC(tp, timerfd__missed_events);
ATF_TP_ADD_TC(tp, timerfd_root__zero_read_on_abs_realtime);
ATF_TP_ADD_TC(tp, timerfd_root__read_on_abs_realtime_no_interval);

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 4, 1:56 PM (4 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30822282
Default Alt Text
D55790.id173514.diff (2 KB)

Event Timeline