clock_settime: don't block when up_rtc_settime is called#18816
clock_settime: don't block when up_rtc_settime is called#18816linguini1 merged 1 commit intoapache:masterfrom
Conversation
Setting the current time in RTC may be a blocking operation (driver needs to wait for oscillator stabilization after reset and so on). This may cause the unwanted effect of clock_settime blocking the code execution for a considerable amount of time. The solution is to plan a low priority work that takes care of setting the time in RTC and let clock_settime continue. We don't have to check if the work is available, just cancel it if there is a new time set request. This is used only if CONFIG_SCHED_LPWORK is enabled. Signed-off-by: Michal Lenc <michallenc@seznam.cz>
|
Seems fine! Would this cause issues with getting the clock time after the set though? Where the caller might expect the time to be set correctly once the caller returns? Can this issue be fixed by performing the call in a worker thread at the application level, instead of in the kernel? |
You still get the correct time after the set, because the read with The entire RTC clock setting is unfortunately not standardized and platform specific. Linux for example has a specific IOCTL or you can configure periodic writes to RTC if I remember it correctly, but it doesn't change it on It can be fixed at the application level, but that is fixing the kernel problem from the app instead of fixing it in the kernel. And I think this is kernel issue because |
This explanation makes a lot of sense, I think that fixing in the kernel and having it as default behavior is fine! |
cederom
left a comment
There was a problem hiding this comment.
Thank you @michallenc :-)
| */ | ||
|
|
||
| g_rtc_to_set = *tp; | ||
| work_queue(LPWORK, &g_rtc_work, rtc_worker, |
There was a problem hiding this comment.
but in a busy system, lp work mayn't schedule for while, how to handle the time drift. @michallenc
if caller really care the blocking, it's better let caller call clock_settime in the background thread.
There was a problem hiding this comment.
True, but blocking for 30 ms is also not correct. The user can choose higher priority for lp work if the system is really busy and preempt other not so important tasks. Most RTCs store time in seconds, so the write would have to be significantly delayed to show any time drift.
I don't really see other good solution here, except from removing RTC set from clock_settime and having a separate API like Linux.
There was a problem hiding this comment.
True, but blocking for 30 ms is also not correct. The user can choose higher priority for lp work if the system is really busy and preempt other not so important tasks. Most RTCs store time in seconds, so the write would have to be significantly delayed to show any time drift.
it's depends on hardware, nuttx even has the code to support the high res RTC(CONFIG_RTC_HIRES).
I don't really see other good solution here, except from removing RTC set from
clock_settimeand having a separate API like Linux.
you can update RTC through /dev/rtcx.
BT, timespec has two fields, the second clock_settime may corrupt the setting in the work thread.
There was a problem hiding this comment.
you can update RTC through /dev/rtcx.
That's what I would prefer in a long term, but that would mean removing up_rtc_settime from clock_settime, which would break many applications that rely on this behavior. And we would have to rewrite some RTC drivers to actually register a device driver.
There was a problem hiding this comment.
you can update RTC through /dev/rtcx.
That's what I would prefer in a long term, but that would mean removing
up_rtc_settimefromclock_settime, which would break many applications that rely on this behavior.
And we would have to rewrite some RTC drivers to actually register a device driver.
you can utilize arch_rtc which could simplify the code a lot:
https://github.com/apache/nuttx/blob/master/drivers/timers/arch_rtc.c
Summary
Setting the current time in RTC may be a blocking operation (driver needs to wait for oscillator stabilization after reset and so on). This may cause the unwanted effect of
clock_settimeblocking the code execution for a considerable amount of time.The solution is to plan a low priority work that takes care of setting the time in RTC and let
clock_settimecontinue. We don't have to check if the work is available, just cancel it if there is a new time set request.This is used only if
CONFIG_SCHED_LPWORKis enabled. I was thinking about putting this under a special separate config option, but it seems like something you always want if you have LPWORK - but feel free to suggest otherwise, I am not against creating an option solely for this.Impact
clock_settimenow shouldn't block the code execution.Testing
We encountered this with
mcp794xxRTC - the controller waits until the oscillator is started, which may take tens of milliseconds (we measured up to ~40 ms on oscilloscope delay). This caused issue in a customer's custom protocol implementation - we receive the current time, set it and response with status message - but there were timeouts in the communication if time was set.The issue no longer occurs if RTC set time is done in a separate work thread as
clock_settimedoesn't block.