diff mbox series

[9/9] wmediumd: lib: wallclock: fix timerfd handling

Message ID 20200625150754.61ba963a8ccf.I2aa70a3d80eba03d766b354a4ba05e8fb15e8287@changeid (mailing list archive)
State Not Applicable
Delegated to: Johannes Berg
Headers show
Series [1/9] wmediumd: add -lstdc++ for SANITIZE=1 | expand

Commit Message

Johannes Berg June 25, 2020, 1:08 p.m. UTC
From: Johannes Berg <johannes.berg@intel.com>

When we have a timerfd for wallclock integration, it is possible
that the following scenario happens:
 * we insert an event in to the scheduler at time T
 * some job handling handles the event loop and the fd
   becomes readable and the read is handled
 * we go back to the scheduler, now waiting for time T,
   but the fd doesn't become readable because it already
   had

This causes the scheduler to lose synchronization and nothing
really works - this manifested for example when having virtual
ethernet with a low latency, where the real processing time
may be more than the latency.

Fix this by keeping the loop entry only active when we need it,
so that the fd becomes readable we don't handle it until we're
in a situation where we actually want to.

---
 wmediumd/lib/wallclock.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/wmediumd/lib/wallclock.c b/wmediumd/lib/wallclock.c
index 4f62a5894329..3fb09accba61 100644
--- a/wmediumd/lib/wallclock.c
+++ b/wmediumd/lib/wallclock.c
@@ -56,9 +56,13 @@  void usfstl_sched_wallclock_wait(struct usfstl_scheduler *sched)
 {
 	sched->wallclock.timer_triggered = 0;
 
+	usfstl_loop_register(&sched->wallclock.entry);
+
 	while (!sched->wallclock.timer_triggered)
 		usfstl_loop_wait_and_handle();
 
+	usfstl_loop_unregister(&sched->wallclock.entry);
+
 	usfstl_sched_set_time(sched, sched->prev_external_sync);
 }
 
@@ -76,8 +80,6 @@  void usfstl_sched_wallclock_init(struct usfstl_scheduler *sched,
 	sched->wallclock.entry.handler = usfstl_sched_wallclock_handle_fd;
 
 	sched->wallclock.nsec_per_tick = ns_per_tick;
-
-	usfstl_loop_register(&sched->wallclock.entry);
 }
 
 void usfstl_sched_wallclock_exit(struct usfstl_scheduler *sched)
@@ -87,8 +89,6 @@  void usfstl_sched_wallclock_exit(struct usfstl_scheduler *sched)
 
 	sched->external_request = NULL;
 	sched->external_wait = NULL;
-
-	usfstl_loop_unregister(&sched->wallclock.entry);
 	close(sched->wallclock.entry.fd);
 }