From d2ccaafb18665ff1ce046cfcba5071d086b38f72 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sun, 8 Jun 2025 04:15:47 +0200 Subject: [PATCH 1/6] CI: Start out with a separate test --- .github/workflows/freethreading_tests.yml | 45 +++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 .github/workflows/freethreading_tests.yml diff --git a/.github/workflows/freethreading_tests.yml b/.github/workflows/freethreading_tests.yml new file mode 100644 index 000000000..059f39412 --- /dev/null +++ b/.github/workflows/freethreading_tests.yml @@ -0,0 +1,45 @@ +name: Free Threading Tests +on: [push, pull_request] +jobs: + freethreading_tests: + name: Free Threaded Build ${{ matrix.os.emoji }} ${{ matrix.os.name }} ${{ matrix.python }} + runs-on: ${{ matrix.os.runs-on }} + strategy: + fail-fast: false + matrix: + os: + - name: Linux + matrix: linux + emoji: 🐧 + runs-on: [ubuntu-latest] + - name: macOS intel + matrix: macos + emoji: 🍎 + runs-on: [macos-13] + - name: macOS silicon + matrix: macos + emoji: 🍎 + runs-on: [macos-14] + - name: Windows + matrix: windows + emoji: 🪟 + runs-on: [windows-latest] + steps: + - uses: actions/checkout@v4 + - name: Install uv and set the python version + uses: astral-sh/setup-uv@v5 + with: + version: "0.7.2" + python-version: 3.13t + enable-cache: false + - name: Set up Python + run: uv python install + - name: Install Dependencies + run: | + uv pip install unittest-ft + - name: Editable build + run: | + uv pip install -v -e . + - name: Run Tests + run: | + uv run --no-project python -m unittest-ft bitarray.test_bitarray From 2e54138c03671147db1fcc8338809750b2e6a15a Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sun, 8 Jun 2025 04:20:40 +0200 Subject: [PATCH 2/6] MAINT: Start by declaring modules are compatible --- bitarray/_bitarray.c | 4 ++++ bitarray/_util.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/bitarray/_bitarray.c b/bitarray/_bitarray.c index d917b7cc8..484e5ed43 100644 --- a/bitarray/_bitarray.c +++ b/bitarray/_bitarray.c @@ -4335,5 +4335,9 @@ PyInit__bitarray(void) PyModule_AddObject(m, "__version__", PyUnicode_FromString(BITARRAY_VERSION)); +#ifdef Py_GIL_DISABLED + PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED); +#endif + return m; } diff --git a/bitarray/_util.c b/bitarray/_util.c index 84abe26a2..48f64c5a1 100644 --- a/bitarray/_util.c +++ b/bitarray/_util.c @@ -2105,5 +2105,9 @@ PyInit__util(void) PyModule_AddObject(m, "_SEGSIZE", PyLong_FromSsize_t(SEGSIZE)); #endif +#ifdef Py_GIL_DISABLED + PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED); +#endif + return m; } From 4bd8e3cf38e2baf7f59c55cf0324005aa9d459b9 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sun, 8 Jun 2025 04:38:51 +0200 Subject: [PATCH 3/6] CI: Setup more complete unittest-ft stuff --- .github/workflows/freethreading_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/freethreading_tests.yml b/.github/workflows/freethreading_tests.yml index 059f39412..a684c21fb 100644 --- a/.github/workflows/freethreading_tests.yml +++ b/.github/workflows/freethreading_tests.yml @@ -42,4 +42,4 @@ jobs: uv pip install -v -e . - name: Run Tests run: | - uv run --no-project python -m unittest-ft bitarray.test_bitarray + uv run --no-project python -m unittest-ft -r -f -s bitarray.test_bitarray From 7522536944db3aba494ac9eb17dab59690852a40 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sun, 8 Jun 2025 04:46:12 +0200 Subject: [PATCH 4/6] MAINT: Try to lock for _all and _any --- bitarray/_bitarray.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/bitarray/_bitarray.c b/bitarray/_bitarray.c index 484e5ed43..828611e0c 100644 --- a/bitarray/_bitarray.c +++ b/bitarray/_bitarray.c @@ -965,7 +965,11 @@ extend_dispatch(bitarrayobject *self, PyObject *obj) static PyObject * bitarray_all(bitarrayobject *self) { - return PyBool_FromLong(find_bit(self, 0, 0, self->nbits, 0) == -1); + Py_ssize_t errind = -1; + Py_BEGIN_CRITICAL_SECTION(self); + errind = find_bit(self, 0, 0, self->nbits, 0); + Py_END_CRITICAL_SECTION(); + return PyBool_FromLong( errind == -1); } PyDoc_STRVAR(all_doc, @@ -978,7 +982,11 @@ Note that `a.all()` is faster than `all(a)`."); static PyObject * bitarray_any(bitarrayobject *self) { - return PyBool_FromLong(find_bit(self, 1, 0, self->nbits, 0) >= 0); + Py_ssize_t errind = -1; + Py_BEGIN_CRITICAL_SECTION(self); + errind = find_bit(self, 1, 0, self->nbits, 0); + Py_END_CRITICAL_SECTION(); + return PyBool_FromLong(errind >= 0); } PyDoc_STRVAR(any_doc, From 21dd0f5380c0f7a5313098cf6508991e255fd99a Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sun, 8 Jun 2025 05:14:54 +0200 Subject: [PATCH 5/6] MAINT: Start trying to use critical sections --- bitarray/_bitarray.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/bitarray/_bitarray.c b/bitarray/_bitarray.c index 828611e0c..e892f3c3f 100644 --- a/bitarray/_bitarray.c +++ b/bitarray/_bitarray.c @@ -1008,7 +1008,9 @@ bitarray_append(bitarrayobject *self, PyObject *value) if (resize(self, self->nbits + 1) < 0) return NULL; + Py_BEGIN_CRITICAL_SECTION(self); setbit(self, self->nbits - 1, vi); + Py_END_CRITICAL_SECTION(); Py_RETURN_NONE; } @@ -1351,7 +1353,9 @@ bitarray_invert(bitarrayobject *self, PyObject *args) PyErr_SetString(PyExc_IndexError, "index out of range"); return NULL; } + Py_BEGIN_CRITICAL_SECTION(self); self->ob_item[i / 8] ^= BITMASK(self, i); + Py_END_CRITICAL_SECTION(); Py_RETURN_NONE; } if (PySlice_Check(arg)) { @@ -1360,12 +1364,18 @@ bitarray_invert(bitarrayobject *self, PyObject *args) if (PySlice_GetIndicesEx(arg, self->nbits, &start, &stop, &step, &slicelength) < 0) return NULL; + Py_BEGIN_CRITICAL_SECTION(self); adjust_step_positive(slicelength, &start, &stop, &step); + Py_END_CRITICAL_SECTION(); + Py_BEGIN_CRITICAL_SECTION(self); invert_range(self, start, stop, step); + Py_END_CRITICAL_SECTION(); Py_RETURN_NONE; } if (arg == Py_None) { + Py_BEGIN_CRITICAL_SECTION(self); invert_span(self, 0, self->nbits); + Py_END_CRITICAL_SECTION(); Py_RETURN_NONE; } From 06a7155a78e14979fcdec6bcce3d7aaf81ef0235 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sun, 8 Jun 2025 05:17:25 +0200 Subject: [PATCH 6/6] CI: Rework --- .github/workflows/freethreading_tests.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/freethreading_tests.yml b/.github/workflows/freethreading_tests.yml index a684c21fb..58652e801 100644 --- a/.github/workflows/freethreading_tests.yml +++ b/.github/workflows/freethreading_tests.yml @@ -40,6 +40,7 @@ jobs: - name: Editable build run: | uv pip install -v -e . + python -m pip install unittest-ft - name: Run Tests run: | - uv run --no-project python -m unittest-ft -r -f -s bitarray.test_bitarray + unittest-ft -r -f -s bitarray.test_bitarray