-
Notifications
You must be signed in to change notification settings - Fork 6.5k
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
kernel: Introduce k_triggered_work #14041
kernel: Introduce k_triggered_work #14041
Conversation
All checks are passing now. Review history of this comment for details about previous failed status. |
685cad3
to
c312e15
Compare
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.
Maybe it would be a little more general to have a callback-based API where a kernel function can be registered on a pollable object that gets called on event state changes, then implement k_triggered_work() in terms of that? That strikes me as useful too, and that way we won't have to implement it as two separate subsystems.
@BFrog and @microbuilder might be able to provide feedback as to whether this feature would help solve sensor notification problems where #13718 (comment) suggested that callbacks are problematic but we still want to get rid of coupling sensor drivers to a specific thread hand-off solution. I don't fully understand @andyross's suggestion but if its intent is to support immediate execution of specific actions ("kernel function") on event notifications, where one of the available actions is submitting work to a queue, I could see that being more general. Examples of other useful triggers would help motivate the generalization. |
I am not sure this would work well. If state change happens from atomic context (e.g. interrupt) some API (e.g. mutex) would be unusable. Triggering work with pollable objects makes code executed from workq thread which has fewer limitations. Triggered work should work in userspace. As an alternative I was also thinking about creating callback manager that would have its own thread and poll on behalf of others. This is however more expressive from the RAM perspective as you have to create yet another thread and yet another stack. |
c312e15
to
bd752ce
Compare
I have updated the PR introducing a callback into I have kept the callback internal to the polling code, as exporting it to the user might create a lot of trouble: It is called with interupts disabled from various contexts. |
1403599
to
f7b2c12
Compare
To be clear: my thinking here is targetted more at how to evolve poll instead of bolting things onto it. IMHO poll (not really the subject of this patch per se) is implemented at the wrong level of abstraction. Threads that wait for something, in Zephyr, are always waiting on a wait_q. So the wait_q should be 1:1 with our "signalable event" thing. But that's not the way poll works, so everything needs to be special cased ("Oh, you're waiting on a semaphore, that's different than being pended on a fifo and I'm going to handle them with a big switch statement"). I'd like to get those switches and special cases out of poll, and make "signal interest in multiple wait_q's" a single lower level operation. In that world, having special cases on what to do after the signal (i.e. ready the thread vs. add a work item) has all the same problems and I'd like to have the low level operation be as decoupled from the API as possible. |
@andyross: What you propose will not work with the k_triggered_work interface introduced here. I simply do not have a thread which I could put in the wait_q. |
f7b2c12
to
a3a4c34
Compare
ae27adb
to
ff8809c
Compare
kernel/poll.c
Outdated
|
||
int _impl_k_poll(struct k_poll_event *events, int num_events, s32_t timeout) | ||
{ | ||
__ASSERT(!_is_in_isr(), ""); |
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.
asserts after the variable declarations
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.
ff8809c
to
2eeeeb3
Compare
@pabigot: I added basic tests for the new functionality. |
299f11e
to
cb606a0
Compare
dfe2d56
to
34ae8c3
Compare
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.
This seems ok. There's enough that I'm not entirely happy about that I don't want to go ahead and approve it. There's nothing here that I would, at this moment, insist be changed, but I don't think there's been enough eyes on it from a functional perspective to just merge it.
I'd still like to see it named k_work_poll
since it's essentially a threadless k_poll
.
Also the timeout addition should be squashed into the commit that adds the new API.
When a work item timeout occurs I believe it would be better to delay disabling the poller until the wrapper work handler clears the event registry. That would require separate tracking of whether the timeout fired and whether events were discovered; e.g. add to struct k_work_triggered
a signaled
flag that gets set in k_work_triggered_poller_cb
just as expired
is set in triggered_work_expiration_handler
. Then the consumer can optimally handle any events that occur between the timeout and the point where the work handler gets invoked rather than assuming there's nothing to do except timeout activity.
@andyross or somebody from the kernel team should determine whether the addition of CONFIG_POLL=y
to tests/kernel/workq/work_queue
is appropriate, since that eliminates the former use of that test when CONFIG_POLL
is not selected.
@@ -1,3 +1,4 @@ | |||
CONFIG_ZTEST=y | |||
CONFIG_QEMU_TICKLESS_WORKAROUND=y | |||
CONFIG_POLL=y |
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.
With this addition please remove the section of testcase.yaml
that runs this test with CONFIG_POLL=y
.
Or it may be that the new API needs to be in a separate test so the behavior of workq
without CONFIG_POLL
continues to be tested. For that we need input from a kernel maintainer.
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.
Done
kernel/poll.c
Outdated
k_work_submit_to_queue(work_q, &twork->work); | ||
} | ||
|
||
static int k_work_triggered_poller_cb(struct k_poll_event *event, u32_t status) |
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.
For consistency with other internal functions this should be triggered_work_poller_cb
. The k_
prefix makes it look like public API.
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.
Done
kernel/poll.c
Outdated
struct _poller *poller = event->poller; | ||
|
||
if (poller->is_polling && poller->thread) { | ||
struct k_work_triggered *work = |
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.
In at least one other function (the expiration handler above) this variable is twork
to distinguish it from the contained struct k_work
member. Consistent naming that indicates the type of the pointed-to value would be nice.
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.
Done
82d3518
to
b1cadc1
Compare
I think that it is possible now:
|
Yes, but it's more accurate to say that the application must scan the events, as once the timeout occurs nothing outside the event array records the fact of a subsequent signal. In I had proposed:
Switching from Again I'm not requesting that you do this; I still want other eyes on it before approving. As is it's a nice feature (though with surprisingly little interest); it could just have better compatibility with existing API, IMO. |
requested by @pizi-nordic for API meeting: provide input on #14041 (comment) i.e. whether API should follow Prototype in last commits of https://github.com/pabigot/zephyr/commits/pr/14041 attn @carlescufi |
Added to dev-review since #14041 (comment) didn't get time in API telecon. @pizi-nordic would really like to get the API settled so this can be merged. |
dev-review: meeting consensus was to go with @pabigot proposal and rename to |
This commit separates k_poll() infrastructure from k_poll() API implementation, allowing other (future) API calls to use the same framework. Signed-off-by: Piotr Zięcik <piotr.ziecik@nordicsemi.no>
76ed74c
to
fb81402
Compare
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.
Two small documentation changes (fix link, mention submit on timeout).
The :cpp:func:`k_work_poll()` interface schedules a triggered work | ||
item in response to a **poll event** (see :ref:`polling_v2`), that will | ||
call a user-defined function when the monitored resource becomes available | ||
or a poll signal is raised. In contrast to :cpp:func:`k_poll()`, |
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.
" the a monitored resource becomes available or a poll signal is raised, or a timeout occurs."
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
Triggered Work | ||
************** | ||
|
||
The :cpp:func:`k_work_poll()` interface schedules a triggered work |
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.
This needs to be k_work_poll_submit()
for the documentation link to work.
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
kernel/poll.c
Outdated
.thread = _current, | ||
.cb = k_poll_poller_cb }; | ||
|
||
__ASSERT(!z_is_in_isr(), ""); |
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.
Sorry, didn't run it first: this needs to be z_arch_is_in_isr()
(upstream rename).
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.
This commit adds new k_work_poll interface. It allows to submit given work to a workqueue automatically when one of the watched pollable objects changes its state. Signed-off-by: Piotr Zięcik <piotr.ziecik@nordicsemi.no> Signed-off-by: Peter A. Bigot <pab@pabigot.com>
fb81402
to
687f290
Compare
This PR introduces triggered work. The triggered work is submitted to workqueue when one of watched events happen. Such mechanism allows to eliminate costly dedicated threads to execute something when data is available or some resource become ready.
The work is driven mostly by device power management (details: #13382 (comment)) and @pdunaj needs.
Fixes: #10748