Skip to content
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

uORB add WorkItem callbacks on publication #12159

Closed
wants to merge 1 commit into from

Conversation

dagar
Copy link
Member

@dagar dagar commented Jun 3, 2019

This PR adds a simple callback mechanism to uORB on publication that schedules a cycle of a WorkItem in the new PX4 work queue.

This is effectively an alternative to the typical PX4 pattern of a task per module with a main loop polling a single topic.

Coupling uORB to WorkItems wasn't my first choice, but after experimenting with various c++ delegate options the simplicity of this with the intended usage is appealing. I'm certainly open to suggestions though.

Copy link
Member

@davids5 davids5 left a comment

Choose a reason for hiding this comment

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

@dagar How are the items removed from the notification list when a workItem is deleted?

@dagar dagar force-pushed the pr-orb_wq_schedule_callback branch from cabe881 to f8bdacb Compare June 3, 2019 20:53
@dagar
Copy link
Member Author

dagar commented Jun 3, 2019

@dagar How are the items removed from the notification list when a workItem is deleted?

They're responsible for removing (unregister) themselves when stopping. For most usage I anticipate this would be rolled into a module base class. At that point simple modules will effectively be actors/active objects.

@dagar dagar force-pushed the pr-orb_wq_schedule_callback branch from f8bdacb to 38b7b87 Compare June 3, 2019 21:07
@jkflying
Copy link
Contributor

jkflying commented Jun 4, 2019

Just from a super high level, I'd love it if the interface was the same as regular subscription to a topic, but with an enum to specify the priority. So iif there is something super critical you just use the MAX_PRIORITY enum and it calls back directly from the publisher, not even going to the work queue. But if you use the HIGH/MEDIUM/LOW_PRIORITY it schedules it through the work queue, rather than having an entirely different interface to subscribe with.

Not sure if that is the direction this is going, maybe just laying the foundations for something like that here?

julianoes
julianoes previously approved these changes Jun 4, 2019
Copy link
Contributor

@julianoes julianoes left a comment

Choose a reason for hiding this comment

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

Looks correct from what I can tell.

@dagar
Copy link
Member Author

dagar commented Jun 4, 2019

Just from a super high level, I'd love it if the interface was the same as regular subscription to a topic, but with an enum to specify the priority. So iif there is something super critical you just use the MAX_PRIORITY enum and it calls back directly from the publisher, not even going to the work queue. But if you use the HIGH/MEDIUM/LOW_PRIORITY it schedules it through the work queue, rather than having an entirely different interface to subscribe with.

Not sure if that is the direction this is going, maybe just laying the foundations for something like that here?

Actually that's part of why it's tightly integrated with the WQ, where the priority is set ahead of time for the specific thread.

https://github.com/PX4/Firmware/blob/6f9598c76aeb229178ad67367ce7196609b21c38/src/platforms/common/px4_work_queue/WorkQueueManager.hpp#L51-L66

I did actually consider the direct callback, but it gets questionable with the different publication contexts and stack size concerns. For example, up until recently a huge portion of publications were happening from interrupts.

I should mention the high level idea here is that several of the "hot paths" involving chains of multiple modules will now actually be able to share a single WQ thread.

Example:

IMU select/filter -> rate controller -> output module (fmu)

Publishing data is what queues the next module to run. If those modules are in the same WQ they'll run back to back without even a context switch.

@dagar dagar force-pushed the pr-orb_wq_schedule_callback branch from 38b7b87 to 63db265 Compare June 4, 2019 14:09
Copy link
Member

@bkueng bkueng left a comment

Choose a reason for hiding this comment

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

The biggest danger I see, as well as @davids5, is dangling pointers if orb_unregister_work_callback is forgotten. If wrapped accordingly into objects, it will work though.

@dagar I see various people (including myself) having questions around the more high-level overall design. Is there a document where you outline your vision, discuss alternative solutions, compare to the current state, and pros/cons of each?
I think that would be helpful.

uORB::Manager::orb_register_work_callback(px4::WorkItem *item, const orb_metadata *meta, int instance)
{
// find node and insert callback (like pollset)
if ((item != nullptr) && (meta != nullptr)) {
Copy link
Member

Choose a reason for hiding this comment

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

I prefer early returns here, it will be more readable.

// prevent duplicate registrations
for (auto existing_item : _registered_work_items) {
if (item == existing_item) {
PX4_ERR("work item already registered, skipping");
Copy link
Member

Choose a reason for hiding this comment

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

This needs to go after ATOMIC_LEAVE.

Also such low-level methods should return an appropriate error code instead of using printf.

#include <px4_defines.h>
#include <drivers/drv_hrt.h>

namespace px4
{

class WorkItem : public IntrusiveQueueNode<WorkItem *>
class WorkItem : public IntrusiveQueueNode<WorkItem *>, public ListNode<WorkItem *>
Copy link
Member

Choose a reason for hiding this comment

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

Can you document the purpose of IntrusiveQueueNode and ListNode?

@dagar
Copy link
Member Author

dagar commented Jun 7, 2019

@dagar I see various people (including myself) having questions around the more high-level overall design. Is there a document where you outline your vision, discuss alternative solutions, compare to the current state, and pros/cons of each?
I think that would be helpful.

Continued in #12207 with some background and example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants