Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

py/scheduler: Allow C scheduler callbacks to re-queue themselves.#17347

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
projectgus wants to merge2 commits intomicropython:master
base:master
Choose a base branch
Loading
fromprojectgus:feature/c-scheduler-recurse

Conversation

projectgus
Copy link
Contributor

@projectgusprojectgus commentedMay 23, 2025
edited
Loading

Summary

Currently if a scheduler callbacks queues a new C scheduled callback, that callback will run in the same schedule pass. This means if a scheduler callback re-queues itself, it can "infinite loop" inside the scheduler.

This change means that any call tomp_handle_pending() will only process the callbacks which were queued whenmp_handle_pending() started running. Therefore any callback which re-queues itself should have that callback handled the next timemp_handle_pending() is called.

This is an alternative to#17248 and should remove the need for#17264. Probable fix for#17246.

This does create potential for some additional callback latency (i.e. if an interrupt fires while a different scheduler callback is running, the interrupt callback is now deferred until the next scheduler run). However the worst-case scheduler latency remains similar (interrupt fires at end of one scheduler pass, has to wait until the next one). I think most MicroPython systems only sparsely call C scheduler callbacks, so this shouldn't be noticeable in most cases.

There is also potential for a misbehaving callback that re-schedules itself continuously to degrade performance of MicroPython (as the callback runs continuously with some allowance for Python code to run), whereas before it would have locked up MicroPython entirely which is more obviously broken.

This work was funded through GitHub Sponsors.

Testing

  • I adapted the test case@andrewleech added inpy/scheduler: warning about C callbacks scheduling new tasks. #17248 for the new behaviour and resubmitted here, so coverage test now includes C scheduler callbacks (testing the new logic).
  • Manually ran the rp2 unit tests on RP2_PICO board. As this is a tickless port I felt it had the most potential for an interrupt timing bug to surface due to this change. All passed.

Trade-offs and Alternatives

projectgusand others added2 commitsMay 23, 2025 14:43
Without this change, a scheduler callback which itself queues a newcallback will have that callback executed as part of the same schedulerrun. Where a callback may re-queue itself, this can lead to an infiniteloop.With this change, each call to mp_handle_pending() will only service thecallbacks which were queued when the scheduler pass started - any callbacksadded during the run are serviced on the next mp_handle_pending().This does mean some interrupts may have higher latency (as callback isdeferred until next scheduler run), but the worst-case latency should stayvery similar.This work was funded through GitHub Sponsors.Signed-off-by: Angus Gratton <angus@redyak.com.au>
Test modified to reschedule itself based on a flag setting. Without thechange in the parent commit, this test executes the callback indefinitelyand hangs but with the change it runs only once each timemp_handle_pending() is called.Modified-by: Angus Gratton <angus@redyak.com.au>Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
@projectgusprojectgus added the py-coreRelates to py/ directory in source labelMay 23, 2025
@projectgus
Copy link
ContributorAuthor

@andrewleech Are you able to easily reproduce the issue that#17264 is fixing? Am interested to know if this fixes it OK, I noticed just now that PR links to your commitaf4a8e9 which implies the problem is actually with recursive calls tomp_handle_pending() itself rather than callbacks re-adding themselves, so that might need a different fix...

@codecovCodecov
Copy link

codecovbot commentedMay 23, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 98.54%. Comparing base(49f81d5) to head(8b14be1).

Additional details and impacted files
@@            Coverage Diff             @@##           master   #17347      +/-   ##==========================================- Coverage   98.54%   98.54%   -0.01%==========================================  Files         169      169                Lines       21898    21929      +31     ==========================================+ Hits        21579    21609      +30- Misses        319      320       +1

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report?Share it here.

🚀 New features to boost your workflow:
  • ❄️Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actionsGitHub Actions
Copy link

Code size report:

   bare-arm:    +0 +0.000% minimal x86:    +0 +0.000%    unix x64:    +0 +0.000% standard      stm32:    +8 +0.002% PYBV10     mimxrt:    +8 +0.002% TEENSY40        rp2:    +8 +0.001% RPI_PICO_W       samd:    +8 +0.003% ADAFRUIT_ITSYBITSY_M4_EXPRESS  qemu rv32:    +0 +0.000% VIRT_RV32

@andrewleech
Copy link
Contributor

Thanks for this@projectgus yes it's easy to reproduce with a stm32wb55 that's had its rfcore firmware wiped, when trying to start BLE it gets stuck trying to init forever in a loop, the higher level timeout code never runs.
I'll get a unit set up to test the change.

@@ -99,6 +100,9 @@ static inline void mp_sched_run_pending(void) {
MICROPY_END_ATOMIC_SECTION(atomic_state);
callback(node);
atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
if (node == original_tail) {
break; // Don't execute any callbacks scheduled during this run
}
Copy link
Member

Choose a reason for hiding this comment

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

Can this be rewritten as:

mp_sched_node_t*original_tail=MP_STATE_VM(sched_tail);while (MP_STATE_VM(sched_head)!=original_tail) {    ...}

?

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@dpgeorgedpgeorgedpgeorge left review comments

@andrewleechandrewleechAwaiting requested review from andrewleech

Assignees
No one assigned
Labels
py-coreRelates to py/ directory in source
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

4 participants
@projectgus@andrewleech@dpgeorge@pi-anl

[8]ページ先頭

©2009-2025 Movatter.jp