Enable free-threading support #472
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Add support for free-threaded Python (PEP 703).
The significant change here is the use of thread local instead of a volatile
global for the switching_thread_state global (which is otherwise protected
by the GIL). There's some overhead to using a thread local, so only do this
in the free-threaded build.
The only other two bits of shared mutable data are G_TOTAL_MAIN_GREENLETS
and ThreadState::clocks_used_during_gc. Modify the latter to use a
std::atomic with relaxed memory order, which should be good enough, and
performance probably matters for those updates.
For G_TOTAL_MAIN_GREENLETS, switch to a std::atomic without changing the
inc/dec operations (which means they use sequential consistency), because
they're rare enough that performance doesn't really matter.
Also mark the main extension modules and the two test extensions as
supporting free-threading (without switching to multi-phase init). The GIL
will still temporarily be enabled during module import, but that probably
won't matter (modules are usually imported before starting threads). If it
does, switching to multi-phase init is always an option.
The existing test suite cover threads extensively enough that no extra tests
are necessary. There is an intermittent failure (<0.2% of runs) that shows
up when running the testsuite in a tight loop, but this happens in regular
Python builds (and before 3.14) too. ThreadSanitizer can't be used on
greenlet, from what I can tell because of how it gets confused by the stack
switching. This is the case for GILful Python builds as well.