From: Johannes Berg <johannes.berg@xxxxxxxxx> 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 --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); } -- 2.26.2