Skip to content

Conversation

kaspar030
Copy link
Contributor

Contribution description

This changes xtimer_msg_receive_timeout() to use thread flags instead of a canary message, for the timeout. This is one way to fix the issue found in #13345.

It does add a dependency to "core_thread_flags", adding ~200b code on ARM, if thread flags are otherwise unused.

Testing procedure

Fixes 13345.

Issues/PRs references

@kaspar030 kaspar030 added Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) Area: core Area: RIOT kernel. Handle PRs marked with this with care! CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Feb 21, 2020
Copy link
Contributor

@MichelRottleuthner MichelRottleuthner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be possible to do this with a mutex so we don't require the thread flags feature?

res = -1;
}

if (! (flags & THREAD_FLAG_TIMEOUT)) {
xtimer_remove(t);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm.. the timer could fire between the check and calling the remove, leaving a TIMEOUT flag set.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure that matters, as the "timeout set" functions always clear that flag at the beginning. I'll clear it anyways.

@kaspar030
Copy link
Contributor Author

Wouldn't it be possible to do this with a mutex so we don't require the thread flags feature?

I think not without going into the guts of the message receive code. thread flags already have special handling in there, that's why I've re-used it.

@MichelRottleuthner
Copy link
Contributor

I wonder how safe is it to assume that the timeout thread flag is not used by any other callback/interrupt?

An alternative to this solution could be adding a mutex that is (try_)locked either from _xtimer_msg_receive_timeout or the timer callback.
The callback would then only send the timeout message if it was able to lock the mutex.
The receiving function then still receives either the timeout message or the proper message and can then decide if it needs to cancel the timer or throw away the unneeded timeout message.
What do you think?

@@ -128,47 +128,44 @@ void _xtimer_set_msg64(xtimer_t *timer, uint64_t offset, msg_t *msg, kernel_pid_
_xtimer_set64(timer, offset, offset >> 32);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is:
_callback_msg
_setup_msg
_xtimer_set_msg
_xtimer_set_msg64
still needed?

@kaspar030
Copy link
Contributor Author

Wouldn't it be possible to do this with a mutex so we don't require the thread flags feature?

It would then require the mutex feature. That isn't optional, but still quite large and not necesarily used (linked in).

@kaspar030
Copy link
Contributor Author

I wonder how safe is it to assume that the timeout thread flag is not used by any other callback/interrupt?

That is actually a feature, and a matter of documentation.
Currently, in RIOT, only the xtimer function sets that timeout.
That can be used to set up higher-level timeouts, e.g.,

xtimer_set_timeout_flag(10s);
// dop stuff
xtimer_msg_receive_timeout(foo, 5s);
if timeout: abort
xtimer_msg_receive_timeout(foo, 5s);
if timeout: abort
xtimer_msg_receive_timeout(foo, 5s);
if timeout: abort
// ...

Now the xtimer_msg_receive calls can each take up to 5s, but with the timeout flag based implementation, the whole block cannot take longer than 10s.

But yeah, for that to work the timeout flag shouldn't be reset in xtimer_set_timeout_flag().

@MichelRottleuthner
Copy link
Contributor

How to continue with this one?
Upside: simple solution, no additional mutex handling or other fancy mechanisms needed.
Downside: if any part of the application calls xtimer_set_timeout_flag in a way that overlaps with xtimer_msg_receive_timeout this will cause trouble.
It would be hard (impossible?) to cover just by documentation: yes we can add a statement to both functions, explaining the constraints. But how is the user supposed to know if a module uses xtimer_set_timeout_flag internally?

This solution is better than what we have now but I have the strong feeling someone will be bitten by this again If we try to "fix" the corner cases by documentation.
@kaspar030 what do you think?

@MrKevinWeiss MrKevinWeiss added this to the Release 2021.07 milestone Jun 21, 2021
@MrKevinWeiss
Copy link
Contributor

This is also pretty old, is it still a problem now?

@MrKevinWeiss MrKevinWeiss removed this from the Release 2021.07 milestone Jul 15, 2021
@kaspar030
Copy link
Contributor Author

closing as xtimer is deprecated

@kaspar030 kaspar030 closed this May 31, 2022
@kaspar030 kaspar030 deleted the msg_receive_timeout_use_thread_flag branch May 31, 2022 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: core Area: RIOT kernel. Handle PRs marked with this with care! CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants