-
Notifications
You must be signed in to change notification settings - Fork 79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Skip task/timer updated if late for more than a few periods #129
Conversation
When the system time is changed ahead due to ntp/time zone/daylight/etc changed, it's better to skip updates than to run all the activities and timers continuously to catch up all the missing updates.
Just for the record: There are plans to rewrite the Thread and Timer classes to not depend on real-time clock (system time) anymore, but to use condition variables and monotonic clock sources instead whenever applicable. This would also solve the problem that periodic tasks cannot be stopped before the current waiting period expired. But as long as we do not have that patch, this PR is a step in the right direction. Nevertheless it should be considered as a workaround. Thanks for the effort! |
Skip task/timer updated if late for more than a few periods
Skip task/timer updated if late for more than a few periods
int maxDelayInPeriods = 4; | ||
NANO_TIME period = task->period; | ||
if (now - wake > maxDelayInPeriods*period) { | ||
period = period * ((now - wake) / period); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually this should have been
period += period * ((now - wake) / period);
because we always want to add at least one period (line 260) plus eventually the additional ones, like in Timer.cpp:108.
I am thinking about reverting this patch for toolchain-2.9 in favor of #138. #138 only provides a solution for the Also it should be noted that both patches, #129 and #138, are not effective anymore for periodic components in connection with #91. So actually we would need a clean solution for all these cases of interruptible, perodic waiting by adding an OS abstraction of condition variables which support waiting based on a steady clock source. For gnulinux/pthread that would be using pthread_condattr_setclock with |
The absolute time returned by rtos_get_time_ns() or RTT::os::TimeService::getNSecs() was generated from a wall clock (time of day), which is not monotonic and can jump in certain cases, e.g. due to an NTP update. This time is used in several internal and public API functions to implement timers or to wait on a condition variable, mutex or semaphore with a timeout. In all these cases non-steady system time can have undesirable side effects, which are not expected in a Real-Time Toolkit. There have been several attempts to fix or at least mitigate that problem: - http://bugs.orocos.org/show_bug.cgi?id=735 - orocos-toolchain#129 - orocos-toolchain#138 This patch introduces some potentially breaking changes: - Use clock_gettime(CLOCK_MONOTONIC, ...) to implement rtos_get_time_ns() for the gnulinux target. This change has a major impact on all usages of that method, rtos_get_ticks() or the higher-level methods RTT::os::TimeService::getNSecs() and RTT::os::TimeService::getTicks(), whose return values cannot be interpreted as wall time anymore. - Consequently remove the rtos_get_time_monotonic-ns() function introduced in orocos-toolchain#138. - Drop RTT::os::Semaphore::waitUntil() and the underlying OS abstraction functions. The only usage within the RTT core was in RTT::os::Timer, which can easily be rewritten using condition variables. POSIX semaphores do not support waiting with an absolute timeout from the monotonic clock. - Added new OS abstraction functions for waiting on a mutex lock with a relative timeout. POSIX does not provide a pthread_mutexattr_setclock() method similar to pthread_condattr_setclock(). For that reason rtos_mutex_lock_until() and rtos_mutex_trylock_for() are currently falling back to CLOCK_REALTIME.
The absolute time returned by rtos_get_time_ns() or RTT::os::TimeService::getNSecs() was generated from a wall clock (time of day), which is not monotonic and can jump in certain cases, e.g. due to an NTP update. This time is used in several internal and public API functions to implement timers or to wait on a condition variable, mutex or semaphore with a timeout. In all these cases non-steady system time can have undesirable side effects, which are not expected in a Real-Time Toolkit. There have been several attempts to fix or at least mitigate that problem: - http://bugs.orocos.org/show_bug.cgi?id=735 - orocos-toolchain#129 - orocos-toolchain#138 This patch introduces some potentially breaking changes: - Use clock_gettime(CLOCK_MONOTONIC, ...) to implement rtos_get_time_ns() for the gnulinux target. This change has a major impact on all usages of that method, rtos_get_ticks() or the higher-level methods RTT::os::TimeService::getNSecs() and RTT::os::TimeService::getTicks(), whose return values cannot be interpreted as wall time anymore. - Consequently remove the rtos_get_time_monotonic-ns() function introduced in orocos-toolchain#138. - Drop RTT::os::Semaphore::waitUntil() and the underlying OS abstraction functions. The only usage within the RTT core was in RTT::os::Timer, which can easily be rewritten using condition variables. POSIX semaphores do not support waiting with an absolute timeout from the monotonic clock. - Added new OS abstraction functions for waiting on a mutex lock with a relative timeout. POSIX does not provide a pthread_mutexattr_setclock() method similar to pthread_condattr_setclock(). For that reason rtos_mutex_lock_until() and rtos_mutex_trylock_for() are currently falling back to CLOCK_REALTIME. Signed-off-by: Johannes Meyer <johannes@intermodalics.eu>
The absolute time returned by rtos_get_time_ns() or RTT::os::TimeService::getNSecs() was generated from a wall clock (time of day), which is not monotonic and can jump in certain cases, e.g. due to an NTP update. This time source is used in several internal and public API functions to implement timers or to wait on a condition variable, mutex or semaphore with a timeout. In all these cases non-steady system time can have undesirable side effects, which are not expected in a Real-Time Toolkit. There have been several attempts to fix or at least mitigate that problem: - http://bugs.orocos.org/show_bug.cgi?id=735 - orocos-toolchain#129 - orocos-toolchain#138 This patch introduces some potentially breaking semantic changes, with only minimal changes to the public API: - Use clock_gettime(CLOCK_MONOTONIC, ...) to implement rtos_get_time_ns() for the gnulinux target. This change has a major impact on all usages of that method, rtos_get_ticks() or the higher-level methods RTT::os::TimeService::getNSecs() and RTT::os::TimeService::getTicks(), whose return values cannot be interpreted as wall time anymore. - Consequently remove the rtos_get_time_monotonic_ns() function introduced in orocos-toolchain#138. - Drop RTT::os::Semaphore::waitUntil() and the underlying OS abstraction functions. The only usage within the RTT core was in RTT::os::Timer, which can be rewritten using a condition variable. POSIX semaphores do not support waiting with an absolute timeout from the monotonic clock. - Add new OS abstraction functions for waiting on a mutex lock with a relative timeout and use them to implement RTT::os::Mutex::timedlock(). POSIX does not provide a pthread_mutexattr_setclock() method similar to pthread_condattr_setclock(). For that reason rtos_mutex_lock_until() and rtos_mutex_trylock_for() have to fall back to CLOCK_REALTIME and may still be affected by time adjustments while waiting. Signed-off-by: Johannes Meyer <johannes@intermodalics.eu>
The absolute time returned by rtos_get_time_ns() or RTT::os::TimeService::getNSecs() was generated from a wall clock (time of day), which is not monotonic and can jump in certain cases, e.g. due to an NTP update. This time source is used in several internal and public API functions to implement timers or to wait on a condition variable, mutex or semaphore with a timeout. In all these cases non-steady system time can have undesirable side effects, which are not expected in a Real-Time Toolkit. There have been several attempts to fix or at least mitigate that problem: - http://bugs.orocos.org/show_bug.cgi?id=735 - orocos-toolchain#129 - orocos-toolchain#138 This patch introduces some potentially breaking semantic changes, with only minimal changes to the public API: - Use clock_gettime(CLOCK_MONOTONIC, ...) to implement rtos_get_time_ns() for the gnulinux target. This change has a major impact on all usages of that method, rtos_get_ticks() or the higher-level methods RTT::os::TimeService::getNSecs() and RTT::os::TimeService::getTicks(), whose return values cannot be interpreted as wall time anymore. - Consequently remove the rtos_get_time_monotonic_ns() function introduced in orocos-toolchain#138. - Drop RTT::os::Semaphore::waitUntil() and the underlying OS abstraction functions. The only usage within the RTT core was in RTT::os::Timer, which can be rewritten using a condition variable. POSIX semaphores do not support waiting with an absolute timeout from the monotonic clock. - Add new OS abstraction functions for waiting on a mutex lock with a relative timeout and use them to implement RTT::os::Mutex::timedlock(). POSIX does not provide a pthread_mutexattr_setclock() method similar to pthread_condattr_setclock(). For that reason rtos_mutex_lock_until() and rtos_mutex_trylock_for() have to fall back to CLOCK_REALTIME and may still be affected by time adjustments while waiting. Signed-off-by: Johannes Meyer <johannes@intermodalics.eu>
I'm not confident the proposed behavior is desired, I'm looking for comments/feedback.
I had the case with system time changed after rtt started, it caused all the periodic activities and timer to
run continuously to catch up all the missing updates since 1970.
I think the similar situation may happen when the system clock changed for other reasons like
daylight or time zone changes.
The better solution would be to use monotonic clocks, but as I understand it can't be used with sem_timedwait.