-
Notifications
You must be signed in to change notification settings - Fork 2k
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
WIP/POC: start a test where xtimer uses a fake 'periph_timer' mock implementation #10321
base: master
Are you sure you want to change the base?
Conversation
@Josar I managed to show some issues by using mocks. As I started after your PR was merged, I focused on the remarks I did in the comments section of your PR. That is using your new documentation that I found all these issues so +1 for writing it :) |
Nice! Tests for stuff like that should have been there before. Thanks for providing this mock test.
I think most of the involved people actually agreed that there are more problems that aren't fixed by the provided PR. The intention for moving forward quickly with this wasn't to ignore/disagree with remaining critics. AIUI the requirements for the _xtimer_set_absolute parameters didn't change - but they are now stated explicitly. Nonetheless you are absolutely right about these requirements being hard (or in some cases impossible) to ensure - and we need to address that. Just a few comments:
Sounds reasonable to hand over this information.
I'm not sure on what other problems this may create and how this would change the performance.
What is "past" from the context of the spin call? From the function I'd expect that it spins until this value is reached - without handling stuff like that. In general, spin should only be used for very short periods of time where timer setup and callback overhead is too heavy i.e. cases where another thread being scheduled in between will likely break what the spin is used for anyway (e.g. timing sensitive bitbanging). For that reason I think that spinning (if impossible to avoid) should only be used with interrupts disabled - because otherwise it probably won't work for the intended use case anyway. |
|
||
/* | ||
* Set the internal timer without handling any callbacks | ||
* Should fit the internal precisiong |
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.
I know it's still WIP, but there's a typo here
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.
Fixed
… mock implementation Change that the 'post' callback so it is done after 'timer_read' only.
…mock implementation
I said I was writing it and provided a first skeleton, but it was merged before I could provide a test. The principle is quite easy, you define macros to redirect function calls to the mocks and include the
Yes but the documentation also says "this prerequisite is verified" when it is wrong. In the same time, the requirements/behavior changed a little bit, as this line in the changeset, which did not solve the main bug, would make more easily /* backoff */
- xtimer_spin_until(target + XTIMER_BACKOFF);
+ xtimer_spin_until(target);
_shoot(timer);
return 0;
https://github.com/RIOT-OS/RIOT/pull/9211/files#diff-5371c49e6244a42b30cd3a714c0e9aacR203 And all the changes, documentation, fix and unrelated were in a single commit.
I will try to show with tests too, but I will need to mock The goal is to have a deterministic time between calling The performance should only be that we spend the time taken to call They can be restored before doing
Spin is an The As said there are many things with this one that are together and did not listed all of them yet. I do not know how timing sensitive they are, but with two applications you could overshoot by the de-schedule time anyway if another application de-schedules you before you enter the function with A de-scheduler thread could de-schedule you by The problem here, is not that you overshoot by the de-schedule time which would be normal but by a full loop of the low level timer. |
I was more referring to the fact that stuff like that should have been tested way earlier - preferably even before merging xtimer...
Right, this comment should be removed.
This shows one of the general problems quite well: no static offset value will be correct as long as the time it tries to compensate for is non-deterministic.
👍
Sure, what I meant is: "past" is hard to define if your time, like in the current spin implementation, is running in a circle ;)
👍
I guess we can agree that delaying a higher prio thread is far from optimal and should be avoided - but your point on performance vs. actually working should be also considered here. A general thing that always comes to my mind regarding xtimer: currently it is really hard to quantify and compare performance of the implementation and show effects of changes as comparable numbers. |
Question for the Does it trigger immediately as the value is elapsed, or does it ignore I need to know to implement the mock properly. |
@cladmi the target should end up (timer max value) into the future |
I think as it is implemented There is no Context is only available within xtimer. |
The ztimer mock module (WIP) might be interesting here. |
So we should be really really extra careful to not put a timer in the past as it would basically also ignore one timer overflow: Lines 477 to 486 in 8de5ba2
I think it deserves a test to show this in one of I think in my mock I would more put it more as an "assert it should not be in the past" as it is something that should not happen within xtimer. @gebart I will take a look at your mock, it took me some time to understand that |
There's also a backend (hack) for xtimer so it can be used on top of any ztimer, e.g., the ztimer_mock. |
@MichelRottleuthner any next steps here? |
Converted to draft. There has been no activity for a long time but it does provide a POC. |
Contribution description
This is more an issue with code than a pull request
The newly added documentation by #9211 explains the requirement of
_xtimer_set_absolute
, which is great as they are now explicit.But the requirement are impossible to guarantee in the current implementation.
I provide unittests using a mock highly wip implementation of
periph_timer
to show cases where the prerequisites and stated conditions are not met.Idea for a solution
Ideas I see to handle this
now
from the caller for_xtimer_set_absolute
and change it to takenow
+offset
.irq_disable
before calling_xtimer_now
in the functionxtimer_spin_until
resistant to being called in the past and correctly defines its requirementsThere is a lot to say on this one and it would require specific definition of how long a process is allowed to be de-scheduled. Right now, if a process is de-scheduled for more than
(1 << XTIMER_WITDH) / XTIMER_HZ
it would not be detected by this function. This is65ms
on theiotlab-m3
board, and it may even require stricter constraints.De-scheduled in _xtimer_set
xtimer_core.c
As
_xtimer_set
is executed without masked interrupt, the thread could be de-scheduled forXTIMER_BACKOFF +1
ticks between these two lines:RIOT/sys/xtimer/xtimer_core.c
Lines 152 to 153 in 1d95da0
Which could make
_xtimer_set_absolute
called with a time in the past.So no
_xtimer_set
does not "ensure this".Test provided for this one.
De-scheduled in _xtimer_set_absolute just after
_xtimer_now
RIOT/sys/xtimer/xtimer_core.c
Lines 180 to 203 in 1d95da0
The thread could be de-scheduled for
XTIMER_BACKOFF +1
before callingxtimer_spin_until
which would make it called with a time already elapsed, and so do a full loop around.Test provided for this one.
De-scheduled in _xtimer_set_absolute before
irq_disable
RIOT/sys/xtimer/xtimer_core.c
Lines 216 to 222 in 1d95da0
This could be show by de-scheduling before
irq_disable
, but the test does not shows this for the moment.Testing procedure
Run the example in
tests/xtimer_mocked_periph_timer
with a board using a 1Mhz timer for xtimer (test implementation limitation) I tested it withsamr21-xpro
oriotlab-m3
.A test is provided for the first two cases.
The implementation uses a WIP mocked
periph_timer
implementation to allow simulating descheduling at certain times by increasing the low level timer.It is based on the number of call to _xtimer_now, so it breaks with
DEBUG
in xtimer.Issues/PRs references
Mention of the real issues in this comment https://github.com/RIOT-OS/RIOT/pull/9211/files#r229728883