Skip to content

Allow the GIL to be enabled on the unix port, and add a CI job to test this configuration #17668

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

Open
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

dpgeorge
Copy link
Member

@dpgeorge dpgeorge commented Jul 13, 2025

Summary

Up until now, thread tests have only been run (under CI at least) on a small number of build configurations. PR #17655 enables the thread tests on a lot more of the existing builds, and this PR adds a new job which builds and tests the unix port with the GIL enabled.

(This PR builds on #17655 and includes all the commits from that PR.)

Running tests with the GIL enabled will help to test the esp32 port's threading implementation, which also uses the GIL.

Edit: updated some thread tests to add time.sleep(0) to the busy-wait loop, so that they pass when used with the native emitter.

Testing

Will be tested by CI.

Edit: new CI job runs correctly, and takes 1 minute 55 seconds. It runs the thread tests in bytecode and native emitter mode.

Trade-offs and Alternatives

Adds a new CI job which adds to the CI time, but it should only be a couple of minutes, and run in parallel.

@dpgeorge dpgeorge added port-unix tests Relates to tests/ directory in source labels Jul 13, 2025
Copy link

Code size report:

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

Copy link

codecov bot commented Jul 13, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 98.41%. Comparing base (0b698b8) to head (13aae9e).
Report is 2 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #17668      +/-   ##
==========================================
- Coverage   98.44%   98.41%   -0.04%     
==========================================
  Files         171      171              
  Lines       22208    22208              
==========================================
- Hits        21863    21855       -8     
- Misses        345      353       +8     

☔ 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.

@dpgeorge dpgeorge added this to the release-1.26.0 milestone Jul 13, 2025
@@ -36,7 +37,7 @@ def th(n, lo, hi):

# busy wait for threads to finish
Copy link
Contributor

Choose a reason for hiding this comment

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

Missed one.

But, TBH, I would still call all of them busy waits since the arg to sleep() is 0.

Copy link
Member Author

Choose a reason for hiding this comment

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

OK, I've reverted the change to the comment and just left them all as "busy wait for threads to finish".

try:
import _thread

have_thread = "thread"
Copy link
Contributor

Choose a reason for hiding this comment

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

I was going to suggest to just make this "yes" here, but I see run-tests.py changes in a later commit, so it doesn't really matter.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, it's changed later to be GIL or no-GIL.

@dpgeorge dpgeorge force-pushed the tests-add-unix-gil-build branch from 526493b to 62f720f Compare July 14, 2025 12:23
@dpgeorge dpgeorge requested a review from projectgus July 14, 2025 23:29
Copy link
Contributor

@projectgus projectgus left a comment

Choose a reason for hiding this comment

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

Changes look good to me. Suggest as part of this PR we also add some brief docs about the native emitter thread/scheduler starvation issue, and the sleep(0) workaround. I think the appropriate place is the dot point list in reference/speed_python.rst?

(While looking for that I also noticed that refernece/micropython.rst doesn't document the native annotation at all - it should probably have a short entry that links to the explanatory section in speed_python.rst? I can submit this in a follow-up, though.)

dpgeorge added 11 commits July 17, 2025 14:39
This is a workaround for the case where threading is enabled without a GIL.
In such a configuration, creating a new global variable is not atomic and
threads have race conditions resizing/accessing the global dict.

Signed-off-by: Damien George <damien@micropython.org>
Builds with stackless enabled are slower than non-stackless, and this test
takes around 2 minutes on the unix port of MicroPython with the standard
unix parameters.  So detect stackless mode and reduce the time of the test.

Signed-off-by: Damien George <damien@micropython.org>
When detecting the target platform, check if the `_thread` module is
available.  If so, add the thread tests to the set of tests to run (unless
the set of tests is explicitly given).

With this change, the unix port no longer needs to explicitly run the set
of thread tests, so that line has been removed from the Makefile.

This change will make sure thread tests are run with other testing
combinations.  In particular, thread tests are now run:
- on the unix port with the native emitter
- on macOS builds
- on unix qemu, the architectures MIPS, ARM and RISCV-64

Signed-off-by: Damien George <damien@micropython.org>
This commit adds a feature check to the test runner to detect if the target
has the GIL or not.

Currently this information is hard-coded: unix/PC targets and the rp2 port
are considered to be GIL-less, and all other targets have the GIL enabled
(if they have threading enabled).

With the change here, some code is run to detect the GIL.  That uses the
fact that native code won't bounce the GIL and can hog it, and times how
long code runs.

Signed-off-by: Damien George <damien@micropython.org>
The qemu emulation introduces enough overhead that the
`tests/thread/stress_aes.py` test overruns the default timeout.  So
increase it to allow this test to pass.

Signed-off-by: Damien George <damien@micropython.org>
This test passes sometimes and fails other times.  Eventually that should
be fixed, but for now just skip this test.

Signed-off-by: Damien George <damien@micropython.org>
This test passes sometimes and fails other times.  Eventually that should
be fixed, but for now just skip this test.

Signed-off-by: Damien George <damien@micropython.org>
The unix port can now be built with the GIL enabled, by passing
MICROPY_PY_THREAD_GIL=1 on the make command line.

Signed-off-by: Damien George <damien@micropython.org>
Signed-off-by: Damien George <damien@micropython.org>
The native emitter will not release/bounce the GIL when running code, so
if it runs tight loops then no other threads get a chance to run (if the
GIL is enabled).  So for the thread tests, explicitly include a call to
`time.sleep(0)` (or equivalent) to bounce the GIL and give other threads a
chance to run.

For some tests (eg `thread_coop.py`) the whole point of the test is to test
that the GIL is correctly bounced.  So for those cases for the use of the
bytecode emitter for the busy functions.

Signed-off-by: Damien George <damien@micropython.org>
Signed-off-by: Damien George <damien@micropython.org>
@dpgeorge dpgeorge force-pushed the tests-add-unix-gil-build branch from 62f720f to 13aae9e Compare July 17, 2025 05:05
@dpgeorge
Copy link
Member Author

Suggest as part of this PR we also add some brief docs about the native emitter thread/scheduler starvation issue, and the sleep(0) workaround.

I've now added this in the last commit.

While looking for that I also noticed that refernece/micropython.rst doesn't document the native annotation at all - it should probably have a short entry that links to the explanatory section in speed_python.rst?

Yes, would be good to document bytecode/native/viper decorators in docs/library/micropython.rst. Feel free to do that (but not urgent).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
port-unix tests Relates to tests/ directory in source
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy