core: add wait queue wrapper around thread flags group#21265
Open
derMihai wants to merge 1 commit intoRIOT-OS:masterfrom
Open
core: add wait queue wrapper around thread flags group#21265derMihai wants to merge 1 commit intoRIOT-OS:masterfrom
derMihai wants to merge 1 commit intoRIOT-OS:masterfrom
Conversation
320e88f to
ef2b82a
Compare
5c96ba0 to
42f01fa
Compare
Contributor
|
Now that #21254 is merged, you can rebase this. |
crasbe
reviewed
Jul 11, 2025
| * } | ||
| * ``` | ||
| * | ||
| * If you don't want to wait indefinitely, you can do it with a timeout: |
Contributor
There was a problem hiding this comment.
I think you should mention here that the ztimer has to be acquired to avoid that it's free'd somewhere else and the wait is indefinite again.
Your code currently does not acquire the ztimer.
Contributor
Author
There was a problem hiding this comment.
See the docs from ztimer_now():
* A clock is also guaranteed to be active from the time any timer is set
* (the first opportunity to get a "now" value from it is the return value of
* @ref ztimer_set) until the time the timer's callback returns.
ztimer_set_timeout_flag() will call ztimer_set() under the hood, which will acuire the timer, if required. In fact, all ztimer API which registers something is acquiring the timer, as that is trivial to do. The timer only has to be acquired if the application needs it to be running, but the clock is not aware of that (as in the case of ztimer_now()).
850eb1c to
4c07d0e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Contribution description
Note: This PR builds on top of #21254
From
core/include/wait_queue.h:This API is a thin wrapper around thread flags group and requires
"core_thread_flags_group" to be enabled in USEMODULE.
Wait queues enable lock-free, IRQ-safe condition signaling. This API is
inspired from the Linux Kernel.
Wait queues have similar semantics to condition variables, but don't require
setting the condition + signaling to be atomic, hence no mutex is needed to
function properly. In turn, one may safely call
queue_wake()from an ISR.Note, while
cond_signal()andcond_broadcast()are safe to call from an ISRcontext too, doing so will probably cause a race condition elsewhere.
Consider the following scenario using condition variables:
Note, the mutex is there only for the
cond_wait()API call, as we're notallowed to call
mutex_lock()inside the ISR. This alone is a hint thatsomething isn't right and indeed, the following sequence of events is
possible:
THRESHOLD, and is about to call cond_wait()THRESHOLDand signals the conditioncond_wait()and goes to sleep, possibly foreverUsing a wait queue, we can do this:
This is free of the race condition above because if the ISR fires between
the condition check and the
queue_wait()call, queue_wait() will returnbecause the
THREAD_FLAG_WAIT_QUEUEthread flag used in theimplementation must also have been set. In other words, if the condition is
true, then the thread flag is also set.
If you have a simple condition check expression, the waiter boiler plate
code can be eliminated by using the
QUEUE_WAIT()macro, which combinesthe join, wait, and leave operations:
If you don't want to wait indefinitely, you can do it with a timeout:
Limitations
Be aware that the condition checking is fenced but not atomic w.r. to
signaling, so you have to ensure that by other means. E.g. in the example
code above this is enforced by
atomic_load_u64().When to use?
If you know for sure you're synchronizing between threads only (no ISR),
then the condition variable has the advantage of implicit condition
setting/checking atomicity through the mutex. Otherwise go for the wait
queue, as it's more flexible by allowing the waker to be in ISR context.
Testing procedure
Run the test application on:
Issues/PRs references