mirror of
https://github.com/micropython/micropython.git
synced 2025-07-21 21:11:12 +02:00
py/scheduler: Only run scheduler callbacks queued before run started.
Without this change, a scheduler callback which itself queues a new callback will have that callback executed as part of the same scheduler run. Where a callback may re-queue itself, this can lead to an infinite loop. With this change, each call to mp_handle_pending() will only service the callbacks which were queued when the scheduler pass started - any callbacks added during the run are serviced on the next mp_handle_pending(). This does mean some interrupts may have higher latency (as callback is deferred until next scheduler run), but the worst-case latency should stay very similar. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
This commit is contained in:
committed by
Damien George
parent
b15348415e
commit
7f274c7550
@@ -88,17 +88,21 @@ static inline void mp_sched_run_pending(void) {
|
|||||||
|
|
||||||
#if MICROPY_SCHEDULER_STATIC_NODES
|
#if MICROPY_SCHEDULER_STATIC_NODES
|
||||||
// Run all pending C callbacks.
|
// Run all pending C callbacks.
|
||||||
while (MP_STATE_VM(sched_head) != NULL) {
|
mp_sched_node_t *original_tail = MP_STATE_VM(sched_tail);
|
||||||
mp_sched_node_t *node = MP_STATE_VM(sched_head);
|
if (original_tail != NULL) {
|
||||||
MP_STATE_VM(sched_head) = node->next;
|
mp_sched_node_t *node;
|
||||||
if (MP_STATE_VM(sched_head) == NULL) {
|
do {
|
||||||
MP_STATE_VM(sched_tail) = NULL;
|
node = MP_STATE_VM(sched_head);
|
||||||
}
|
MP_STATE_VM(sched_head) = node->next;
|
||||||
mp_sched_callback_t callback = node->callback;
|
if (MP_STATE_VM(sched_head) == NULL) {
|
||||||
node->callback = NULL;
|
MP_STATE_VM(sched_tail) = NULL;
|
||||||
MICROPY_END_ATOMIC_SECTION(atomic_state);
|
}
|
||||||
callback(node);
|
mp_sched_callback_t callback = node->callback;
|
||||||
atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
|
node->callback = NULL;
|
||||||
|
MICROPY_END_ATOMIC_SECTION(atomic_state);
|
||||||
|
callback(node);
|
||||||
|
atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
|
||||||
|
} while (node != original_tail); // Don't execute any callbacks scheduled during this run
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user