-
Notifications
You must be signed in to change notification settings - Fork 758
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
Initial free threaded bindings #4421
Merged
Merged
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
2685691
add support in pyo3-build-config for free-threaded python
ngoldbaum e8613d5
update object.h bindings for free-threaded build
ngoldbaum eeac20c
Add PyMutex bindings
ngoldbaum 8eebe43
fix po3-ffi-check with free-threaded build
ngoldbaum 9e9d77e
error when building with limited api and Py_GIL_DISABLED
ngoldbaum 79dd1a7
Add CI job for free-threaded build
ngoldbaum 5aaa03a
fix issues building on older pythons
ngoldbaum f4219b3
ci config fixup
ngoldbaum 4ff9a62
fix clippy on gil-enabled 3.13 build
ngoldbaum 57e7e3d
Apply suggestions from code review
ngoldbaum a042e56
make PyMutex and PyObject refcounting fields atomics
ngoldbaum 7c493eb
add new field on PyConfig in 3.13 debug ABI
ngoldbaum da3e50c
warn and disable abi3 on gil-disabled build
ngoldbaum 77b4d96
fix conditional compilation for PyMutex usage
ngoldbaum 96dd13e
temporarily skip test that deadlocks
ngoldbaum dbcb9d2
remove Py_GIL_DISABLED from py_sys_config cfg options
ngoldbaum d9dac3c
only expose PyMutex in 3.13
ngoldbaum 9b70b07
make PyObject_HEAD_INIT a function
ngoldbaum 3e03dd1
intialize ob_ref_local to _Py_IMMORTAL_REFCNT_LOCAL in HEAD_INIT
ngoldbaum f695203
Fix clippy lint about static with interior mutability
ngoldbaum 848c793
add TODO comments about INCREF and DECREF in free-threaded build
ngoldbaum 6e66cb0
make the _bits field of PyMutex pub(crate)
ngoldbaum 126c97b
refactor so HEAD_INIT remains a constant
ngoldbaum 162a65e
ignore clippy lint about interior mutability
ngoldbaum 6103d26
revert unnecessary changes to pyo3-build-config
ngoldbaum 8a9ef2d
add changelog entries
ngoldbaum e1ddd01
use derive(Debug) for PyMutex
ngoldbaum 1a088ea
Add PhantomPinned field to PyMutex bindings
ngoldbaum 38bc492
Update pyo3-build-config/src/impl_.rs
ngoldbaum a85fa4c
Update pyo3-ffi/src/object.rs
ngoldbaum 60c26c4
fix build config again
ngoldbaum File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
* Added bindings for PyMutex. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
* Updated FFI bindings for free-threaded CPython 3.13 ABI |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
use std::marker::PhantomPinned; | ||
use std::sync::atomic::AtomicU8; | ||
|
||
#[repr(transparent)] | ||
#[derive(Debug)] | ||
pub struct PyMutex { | ||
ngoldbaum marked this conversation as resolved.
Show resolved
Hide resolved
|
||
pub(crate) _bits: AtomicU8, | ||
pub(crate) _pin: PhantomPinned, | ||
} | ||
|
||
extern "C" { | ||
pub fn PyMutex_Lock(m: *mut PyMutex); | ||
pub fn PyMutex_UnLock(m: *mut PyMutex); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,13 @@ | ||
use crate::pyport::{Py_hash_t, Py_ssize_t}; | ||
#[cfg(Py_GIL_DISABLED)] | ||
use crate::PyMutex; | ||
#[cfg(Py_GIL_DISABLED)] | ||
use std::marker::PhantomPinned; | ||
use std::mem; | ||
use std::os::raw::{c_char, c_int, c_uint, c_ulong, c_void}; | ||
use std::ptr; | ||
#[cfg(Py_GIL_DISABLED)] | ||
use std::sync::atomic::{AtomicIsize, AtomicU32, AtomicU8, Ordering::Relaxed}; | ||
|
||
#[cfg(Py_LIMITED_API)] | ||
opaque_struct!(PyTypeObject); | ||
|
@@ -22,12 +28,33 @@ pub const _Py_IMMORTAL_REFCNT: Py_ssize_t = { | |
} | ||
}; | ||
|
||
#[cfg(Py_GIL_DISABLED)] | ||
pub const _Py_IMMORTAL_REFCNT_LOCAL: u32 = u32::MAX; | ||
#[cfg(Py_GIL_DISABLED)] | ||
pub const _Py_REF_SHARED_SHIFT: isize = 2; | ||
|
||
#[allow(clippy::declare_interior_mutable_const)] | ||
pub const PyObject_HEAD_INIT: PyObject = PyObject { | ||
#[cfg(py_sys_config = "Py_TRACE_REFS")] | ||
_ob_next: std::ptr::null_mut(), | ||
#[cfg(py_sys_config = "Py_TRACE_REFS")] | ||
_ob_prev: std::ptr::null_mut(), | ||
#[cfg(Py_3_12)] | ||
#[cfg(Py_GIL_DISABLED)] | ||
ob_tid: 0, | ||
#[cfg(Py_GIL_DISABLED)] | ||
_padding: 0, | ||
#[cfg(Py_GIL_DISABLED)] | ||
ob_mutex: PyMutex { | ||
_bits: AtomicU8::new(0), | ||
_pin: PhantomPinned, | ||
}, | ||
#[cfg(Py_GIL_DISABLED)] | ||
ob_gc_bits: 0, | ||
#[cfg(Py_GIL_DISABLED)] | ||
ob_ref_local: AtomicU32::new(_Py_IMMORTAL_REFCNT_LOCAL), | ||
#[cfg(Py_GIL_DISABLED)] | ||
ob_ref_shared: AtomicIsize::new(0), | ||
#[cfg(all(not(Py_GIL_DISABLED), Py_3_12))] | ||
ob_refcnt: PyObjectObRefcnt { ob_refcnt: 1 }, | ||
#[cfg(not(Py_3_12))] | ||
ob_refcnt: 1, | ||
|
@@ -67,6 +94,19 @@ pub struct PyObject { | |
pub _ob_next: *mut PyObject, | ||
#[cfg(py_sys_config = "Py_TRACE_REFS")] | ||
pub _ob_prev: *mut PyObject, | ||
#[cfg(Py_GIL_DISABLED)] | ||
pub ob_tid: libc::uintptr_t, | ||
#[cfg(Py_GIL_DISABLED)] | ||
pub _padding: u16, | ||
#[cfg(Py_GIL_DISABLED)] | ||
pub ob_mutex: PyMutex, // per-object lock | ||
#[cfg(Py_GIL_DISABLED)] | ||
pub ob_gc_bits: u8, // gc-related state | ||
#[cfg(Py_GIL_DISABLED)] | ||
pub ob_ref_local: AtomicU32, // local reference count | ||
#[cfg(Py_GIL_DISABLED)] | ||
pub ob_ref_shared: AtomicIsize, // shared reference count | ||
#[cfg(not(Py_GIL_DISABLED))] | ||
pub ob_refcnt: PyObjectObRefcnt, | ||
#[cfg(PyPy)] | ||
pub ob_pypy_link: Py_ssize_t, | ||
|
@@ -91,6 +131,18 @@ pub unsafe fn Py_Is(x: *mut PyObject, y: *mut PyObject) -> c_int { | |
} | ||
|
||
#[inline] | ||
#[cfg(Py_GIL_DISABLED)] | ||
pub unsafe fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t { | ||
let local = (*ob).ob_ref_local.load(Relaxed); | ||
if local == _Py_IMMORTAL_REFCNT_LOCAL { | ||
return _Py_IMMORTAL_REFCNT; | ||
} | ||
let shared = (*ob).ob_ref_shared.load(Relaxed); | ||
Comment on lines
+136
to
+140
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I checked the CPython source to verify these are indeed relaxed loads 👍 |
||
local as Py_ssize_t + Py_ssize_t::from(shared >> _Py_REF_SHARED_SHIFT) | ||
davidhewitt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
#[inline] | ||
#[cfg(not(Py_GIL_DISABLED))] | ||
#[cfg(Py_3_12)] | ||
pub unsafe fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t { | ||
(*ob).ob_refcnt.ob_refcnt | ||
|
@@ -134,7 +186,7 @@ pub unsafe fn Py_IS_TYPE(ob: *mut PyObject, tp: *mut PyTypeObject) -> c_int { | |
} | ||
|
||
#[inline(always)] | ||
#[cfg(all(Py_3_12, target_pointer_width = "64"))] | ||
#[cfg(all(not(Py_GIL_DISABLED), Py_3_12, target_pointer_width = "64"))] | ||
pub unsafe fn _Py_IsImmortal(op: *mut PyObject) -> c_int { | ||
(((*op).ob_refcnt.ob_refcnt as crate::PY_INT32_T) < 0) as c_int | ||
} | ||
|
@@ -507,8 +559,14 @@ extern "C" { | |
|
||
#[inline(always)] | ||
pub unsafe fn Py_INCREF(op: *mut PyObject) { | ||
ngoldbaum marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// On limited API or with refcount debugging, let the interpreter do refcounting | ||
#[cfg(any(Py_LIMITED_API, py_sys_config = "Py_REF_DEBUG", GraalPy))] | ||
// On limited API, the free-threaded build, or with refcount debugging, let the interpreter do refcounting | ||
// TODO: reimplement the logic in the header in the free-threaded build, for a little bit of performance. | ||
#[cfg(any( | ||
Py_GIL_DISABLED, | ||
Py_LIMITED_API, | ||
py_sys_config = "Py_REF_DEBUG", | ||
GraalPy | ||
))] | ||
{ | ||
// _Py_IncRef was added to the ABI in 3.10; skips null checks | ||
#[cfg(all(Py_3_10, not(PyPy)))] | ||
|
@@ -523,7 +581,12 @@ pub unsafe fn Py_INCREF(op: *mut PyObject) { | |
} | ||
|
||
// version-specific builds are allowed to directly manipulate the reference count | ||
#[cfg(not(any(any(Py_LIMITED_API, py_sys_config = "Py_REF_DEBUG", GraalPy))))] | ||
#[cfg(not(any( | ||
Py_GIL_DISABLED, | ||
Py_LIMITED_API, | ||
py_sys_config = "Py_REF_DEBUG", | ||
GraalPy | ||
)))] | ||
{ | ||
#[cfg(all(Py_3_12, target_pointer_width = "64"))] | ||
{ | ||
|
@@ -559,9 +622,11 @@ pub unsafe fn Py_INCREF(op: *mut PyObject) { | |
track_caller | ||
)] | ||
pub unsafe fn Py_DECREF(op: *mut PyObject) { | ||
// On limited API or with refcount debugging, let the interpreter do refcounting | ||
// On limited API, the free-threaded build, or with refcount debugging, let the interpreter do refcounting | ||
// On 3.12+ we implement refcount debugging to get better assertion locations on negative refcounts | ||
// TODO: reimplement the logic in the header in the free-threaded build, for a little bit of performance. | ||
#[cfg(any( | ||
Py_GIL_DISABLED, | ||
Py_LIMITED_API, | ||
all(py_sys_config = "Py_REF_DEBUG", not(Py_3_12)), | ||
GraalPy | ||
|
@@ -580,6 +645,7 @@ pub unsafe fn Py_DECREF(op: *mut PyObject) { | |
} | ||
|
||
#[cfg(not(any( | ||
Py_GIL_DISABLED, | ||
Py_LIMITED_API, | ||
all(py_sys_config = "Py_REF_DEBUG", not(Py_3_12)), | ||
GraalPy | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very cool to see this job running, thanks 🙏