fix(core): remove unnecessary delays during event polling
What changed, and why it matters
This small firmware change prevents the Trezor device from going to sleep or adding artificial delays when event pollers are still active. Previously, the code always paused after each polling loop, even if it had just woken up a task. Now it only pauses when no task was actually woken. The main practical effect is better responsiveness and lower latency, not a security fix.
No security action required. Treat as a normal performance/efficiency improvement. If reviewing for side effects, verify that skipping `__WFI()` when events are processed does not cause excessive power draw or scheduler starvation under sustained I/O load.
Security signals we found
No security-relevant keywords in commit title or message
No input validation, buffer, or cryptographic changes
Change is purely timing/scheduler behavior in event-polling loop
No changelog entry suggests routine optimization
Evidence from the diff
In sysevents_poll(), the polling loop iterates over registered event pollers and wakes any task whose file descriptor is ready or whose timeout has expired. Before the patch, the loop unconditionally executed a delay/sleep (systick_delay_ms(1) on emulator, __WFI() on device) after every iteration. The patch tracks whether any poller was actually serviced via a new events_processed flag and skips the delay/sleep when a task was woken. This removes unnecessary latency between consecutive event-driven operations but does not change access control, trust boundaries, or cryptographic handling.
Changed components
core/embed/sys/task/sysevent.cTrezor Core event polling dispatcherInspect captured patch +9 / −4
diff --git a/core/embed/sys/task/sysevent.c b/core/embed/sys/task/sysevent.c
index ad88b09df..c3f9ae934 100644
--- a/core/embed/sys/task/sysevent.c
+++ b/core/embed/sys/task/sysevent.c
@@ -258,6 +258,8 @@ void sysevents_poll(const sysevents_t *awaited, sysevents_t *signalled,
uint32_t now = systick_ms();
+ bool events_processed = false;
+
// Choose the next task to run
for (size_t prio = 0; prio < dispatcher->pollers_count; prio++) {
sysevent_poller_t *poller = &dispatcher->pollers[prio];
@@ -265,6 +267,7 @@ void sysevents_poll(const sysevents_t *awaited, sysevents_t *signalled,
bool ready = (poller->signalled.read_ready != 0) ||
(poller->signalled.write_ready != 0);
if (ready || timed_out) {
+ events_processed = true;
systask_t *task = poller->task;
#if defined(KERNEL) && !defined(TREZOR_EMULATOR)
if (task->applet != NULL) {
@@ -283,13 +286,15 @@ void sysevents_poll(const sysevents_t *awaited, sysevents_t *signalled,
}
}
+ if (!events_processed) {
#ifdef TREZOR_EMULATOR
- // Wait a bit to not consume 100% CPU
- systick_delay_ms(1);
+ // Wait a bit to not consume 100% CPU
+ systick_delay_ms(1);
#else
- // Wait for the next event
- __WFI();
+ // Wait for the next event
+ __WFI();
#endif
+ }
}
}
Why this scored 11/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.