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.
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.
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.
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.
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.
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.
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.
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.
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.
|
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.
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 |
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.
Why this? evp is used just in the line below.
There was a problem hiding this comment.
Ah, leftover from shuffling around the #ifdefs, 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 |
| 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.
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.
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.
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.
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.
sys/net/gnrc/netif/gnrc_netif.c
Outdated
| 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.
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.
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 <koen@bergzand.net>
bd4b45d to
2013ac7
Compare
|
Squashed! I've also removed the "REMOVEME" commit that added the event module to gnrc_networking. |
|
@jia200x Ping! |
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