-
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
gnrc_netif: Add support for internal event loop #13669
Conversation
sys/net/gnrc/netif/gnrc_netif.c
Outdated
*/ | ||
static void _process_events_await_msg(gnrc_netif_t *netif, msg_t *msg) | ||
{ | ||
#ifdef MODULE_GNRC_NETIF_EVENTS |
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 suggest to change this to a regular if-else chain (with IS_ACTIVE). Then we get compile checks for free
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.
That's not possible, some members of gnrc_netif_t
are only available when this module is enabled. Modifying this to IS_ACTIVE
will result in compilation failures when GNRC_NETIF_EVENTS
is not enabled.
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.
you can simply define a static inline function:
static inline _get_evq(netif_t *netif)
{
#if IS_ACTIVE(MODULE_GNRC_NETIF_EVENTS)
return netif->evq;
#else
return NULL;
#endif
}
Then you call that function in the while loop.
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 function does not compile when evq
is not a member of gnrc_netif_t
, which is the case when MODULE_GNRC_NETIF_EVENTS
because of the ifdef
guards 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.
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.
Then it should still work with @jia200x's last proposal.
Oh, of course, I misread his last suggestion.
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.
Okay, while this is possible, it is starting to become more and more messy. For the solution posted by @jia200x I have to include both event.h
and thread_flags.h
. For thread_flags.h
to be included it is required to enable MODULE_CORE_THREAD_FLAGS
increasing the build size whether we're using MODULE_GNRC_NETIF_EVENTS
or not.
Conditionally including event.h
and thread_flags.h
doesn't work because the code between the regular if-else chain (with IS_ACTIVE) requires those for one of the branches to compile.
Am I missing something silly here that allows me to get this to work or is the current #ifdef
really the only way out here? I honestly don't want to start guarding every individual troublesome call in this snippet if we can avoid it.
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.
It should be IS_USED()
btw not, IS_ACTIVE()
. If you use #if
(not if ()
it should work even if you #ifdef
the calls above. Let me give you some suggestions.
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 root of the problem here is the #error in thread_flags header. It's misplaced IMO. It should be in the C file that defines the thread flags function.
I can open a PR to move it (unless you are faster :), it should be a low hanging fruit.
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.
codewise looks fine, just some minor comments above |
sys/net/gnrc/netif/gnrc_netif.c
Outdated
*/ | ||
static void _process_events_await_msg(gnrc_netif_t *netif, msg_t *msg) | ||
{ | ||
#ifdef MODULE_GNRC_NETIF_EVENTS |
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.
It should be IS_USED()
btw not, IS_ACTIVE()
. If you use #if
(not if ()
it should work even if you #ifdef
the calls above. Let me give you some suggestions.
ddcd163
to
1c0ab40
Compare
Reworked, comments should be addressed with this. |
Great! I will give it a deeper look in a few hours |
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.
One minor thing ;-)
sys/net/gnrc/netif/gnrc_netif.c
Outdated
*/ | ||
static void _event_handler_isr(event_t *evp) | ||
{ | ||
(void)evp; |
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.
Why this? evp
is used just in the line below.
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.
Ah, leftover from shuffling around the #ifdef
s, will remove
This compiles for me and would result in less diff --git a/sys/net/gnrc/netif/gnrc_netif.c b/sys/net/gnrc/netif/gnrc_netif.c
index 34f7c5f5c..ad62a6ac1 100644
--- a/sys/net/gnrc/netif/gnrc_netif.c
+++ b/sys/net/gnrc/netif/gnrc_netif.c
@@ -1359,7 +1359,6 @@ void gnrc_netif_default_init(gnrc_netif_t *netif)
#endif
}
-#if IS_USED(MODULE_GNRC_NETIF_EVENTS)
/**
* @brief Call the ISR handler from an event
*
@@ -1367,11 +1366,13 @@ void gnrc_netif_default_init(gnrc_netif_t *netif)
*/
static void _event_handler_isr(event_t *evp)
{
- (void)evp;
+#if IS_USED(MODULE_GNRC_NETIF_EVENTS)
gnrc_netif_t *netif = container_of(evp, gnrc_netif_t, event_isr);
netif->dev->driver->isr(netif->dev);
-}
+#else
+ (void)evp;
#endif
+}
/**
* @brief Retrieve the netif event queue if enabled
@@ -1452,11 +1453,11 @@ static void *_gnrc_netif_thread(void *args)
gnrc_netif_acquire(netif);
dev = netif->dev;
netif->pid = sched_active_pid;
-#if IS_USED(MODULE_GNRC_NETIF_EVENTS)
- netif->event_isr.handler = _event_handler_isr,
- /* set up the event queue */
- event_queue_init(&netif->evq);
-#endif /* MODULE_GNRC_NETIF_EVENTS */
+ if (IS_USED(MODULE_GNRC_NETIF_EVENTS)) {
+ netif->event_isr.handler = _event_handler_isr,
+ /* set up the event queue */
+ event_queue_init(&netif->evq);
+ }
/* setup the link-layer's message queue */
msg_init_queue(msg_queue, CONFIG_GNRC_NETIF_MSG_QUEUE_SIZE);
/* register the event callback with the device driver */ |
This doesn't compile for me if I don't compile with |
I might have forgotten, that |
Tested on |
|
||
DEBUG("gnrc_netif: starting thread %i\n", sched_active_pid); | ||
netif = args; | ||
gnrc_netif_acquire(netif); | ||
dev = netif->dev; | ||
netif->pid = sched_active_pid; | ||
#if IS_USED(MODULE_GNRC_NETIF_EVENTS) |
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.
Just nitpick comment, this could be moved to it's own function (e.g gnrc_netif_events_init()
). Then you remove the #ifdef
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.
That's just shuffling around #ifdef
's right? Instead of the #ifdef
in the init function they are moved to the new function. Do you think this makes the code more readable?
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 mean:
if (IS_USED(MODULE_GNRC_NETIF_EVENTS)) {
gnrc_netif_events_init();
}
Might be a matter of personal taste here, so I'm OK with what you decide. But in the other comment the msg_t
logic is guarded
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 prefer to leave this as is for now, it keeps the initialization code in one place as much as possible and I don't think the ifdef decreases readability much in this case.
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.
ok! np
sys/net/gnrc/netif/gnrc_netif.c
Outdated
@@ -1487,12 +1585,16 @@ static void _event_cb(netdev_t *dev, netdev_event_t event) | |||
gnrc_netif_t *netif = (gnrc_netif_t *) dev->context; | |||
|
|||
if (event == NETDEV_EVENT_ISR) { | |||
#if IS_USED(MODULE_GNRC_NETIF_EVENTS) |
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.
Same here. What speaks againts:
static inline gnrc_netif_events_post(gnrc_netif_t *netif)
{
#if IS_USED(GNRC_NETIF_EVENTS)
event_post(&netif->evq, &netif->event_isr);
#else
(void) netif;
#endif
}
?
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.
Nothing, implemented this in the latest fixup
please squash |
Enabled by the gnrc_netif_events pseudo module. Using an internal event loop within the gnrc_netif thread eliminates the risk of lost interrupts and lets ISR events always be handled before any send/receive requests from other threads are processed. The events in the event loop is also a potential hook for MAC layers and other link layer modules which may need to inject and process events before any external IPC messages are handled. Co-Authored-By: Koen Zandberg <[email protected]>
bd4b45d
to
2013ac7
Compare
Squashed! I've also removed the "REMOVEME" commit that added the event module to gnrc_networking. |
@jia200x Ping! |
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.
Ok, it looks good to me! ACK
Adapted from #9326
Contribution description
From #9326:
Enabled by the gnrc_netif_events pseudo module. Using an internal event loop eliminates the risk of lost interrupts and lets ISR events always be handled before any send/receive requests from other threads are processed.
The events in the event loop is also a potential hook for MAC layers and other link layer modules which may need a way to inject and process events before any external IPC messages are handled.
Testing procedure
There is an extra commit in the PR to add the pseudomodule to
examples/gnrc_networking
. The example should still function as before.Issues/PRs references
Adapted from #9326