Skip to content

Commit 6c010f2

Browse files
authored
Merge branch 'main' into cmaloney/pyio_fileio_readall
2 parents 5cee34e + 99ed302 commit 6c010f2

34 files changed

+266
-156
lines changed

.github/workflows/build.yml

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -512,26 +512,20 @@ jobs:
512512
run: xvfb-run make ci
513513

514514
build_tsan:
515-
name: 'Thread sanitizer'
516-
needs: check_source
517-
if: needs.check_source.outputs.run_tests == 'true'
518-
uses: ./.github/workflows/reusable-tsan.yml
519-
with:
520-
config_hash: ${{ needs.check_source.outputs.config_hash }}
521-
options: ./configure --config-cache --with-thread-sanitizer --with-pydebug
522-
suppressions_path: Tools/tsan/supressions.txt
523-
tsan_logs_artifact_name: tsan-logs-default
524-
525-
build_tsan_free_threading:
526-
name: 'Thread sanitizer (free-threading)'
515+
name: >-
516+
Thread sanitizer
517+
${{ fromJSON(matrix.free-threading) && '(free-threading)' || '' }}
527518
needs: check_source
528519
if: needs.check_source.outputs.run_tests == 'true'
520+
strategy:
521+
matrix:
522+
free-threading:
523+
- false
524+
- true
529525
uses: ./.github/workflows/reusable-tsan.yml
530526
with:
531527
config_hash: ${{ needs.check_source.outputs.config_hash }}
532-
options: ./configure --config-cache --disable-gil --with-thread-sanitizer --with-pydebug
533-
suppressions_path: Tools/tsan/suppressions_free_threading.txt
534-
tsan_logs_artifact_name: tsan-logs-free-threading
528+
free-threading: ${{ matrix.free-threading }}
535529

536530
# CIFuzz job based on https://google.github.io/oss-fuzz/getting-started/continuous-integration/
537531
cifuzz:
@@ -591,7 +585,6 @@ jobs:
591585
- test_hypothesis
592586
- build_asan
593587
- build_tsan
594-
- build_tsan_free_threading
595588
- cifuzz
596589

597590
runs-on: ubuntu-latest
@@ -625,7 +618,6 @@ jobs:
625618
build_windows,
626619
build_asan,
627620
build_tsan,
628-
build_tsan_free_threading,
629621
'
630622
|| ''
631623
}}

.github/workflows/reusable-tsan.yml

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,11 @@ on:
66
config_hash:
77
required: true
88
type: string
9-
options:
10-
required: true
11-
type: string
12-
suppressions_path:
13-
description: 'A repo relative path to the suppressions file'
14-
required: true
15-
type: string
16-
tsan_logs_artifact_name:
17-
description: 'Name of the TSAN logs artifact. Must be unique for each job.'
18-
required: true
19-
type: string
9+
free-threading:
10+
description: Whether to use free-threaded mode
11+
required: false
12+
type: boolean
13+
default: false
2014

2115
env:
2216
FORCE_COLOR: 1
@@ -26,9 +20,6 @@ jobs:
2620
name: 'Thread sanitizer'
2721
runs-on: ubuntu-24.04
2822
timeout-minutes: 60
29-
env:
30-
OPTIONS: ${{ inputs.options }}
31-
SUPPRESSIONS_PATH: ${{ inputs.suppressions_path }}
3223
steps:
3324
- uses: actions/checkout@v4
3425
with:
@@ -55,7 +46,11 @@ jobs:
5546
sudo sysctl -w vm.mmap_rnd_bits=28
5647
- name: TSAN Option Setup
5748
run: |
58-
echo "TSAN_OPTIONS=log_path=${GITHUB_WORKSPACE}/tsan_log suppressions=${GITHUB_WORKSPACE}/${SUPPRESSIONS_PATH} handle_segv=0" >> "$GITHUB_ENV"
49+
echo "TSAN_OPTIONS=log_path=${GITHUB_WORKSPACE}/tsan_log suppressions=${GITHUB_WORKSPACE}/Tools/tsan/suppressions${{
50+
fromJSON(inputs.free-threading)
51+
&& '_free_threading'
52+
|| ''
53+
}}.txt handle_segv=0" >> "$GITHUB_ENV"
5954
echo "CC=clang" >> "$GITHUB_ENV"
6055
echo "CXX=clang++" >> "$GITHUB_ENV"
6156
- name: Add ccache to PATH
@@ -67,7 +62,12 @@ jobs:
6762
save: ${{ github.event_name == 'push' }}
6863
max-size: "200M"
6964
- name: Configure CPython
70-
run: "${OPTIONS}"
65+
run: >-
66+
./configure
67+
--config-cache
68+
--with-thread-sanitizer
69+
--with-pydebug
70+
${{ fromJSON(inputs.free-threading) && '--disable-gil' || '' }}
7171
- name: Build CPython
7272
run: make -j4
7373
- name: Display build info
@@ -81,6 +81,11 @@ jobs:
8181
if: always()
8282
uses: actions/upload-artifact@v4
8383
with:
84-
name: ${{ inputs.tsan_logs_artifact_name }}
84+
name: >-
85+
tsan-logs-${{
86+
fromJSON(inputs.free-threading)
87+
&& 'free-threading'
88+
|| 'default'
89+
}}
8590
path: tsan_log.*
8691
if-no-files-found: ignore

.github/workflows/reusable-windows.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ env:
2424
2525
jobs:
2626
build:
27-
name: 'build and test (${{ inputs.arch }})'
27+
name: ${{ inputs.arch == 'arm64' && 'build' || 'build and test' }} (${{ inputs.arch }})
2828
runs-on: ${{ inputs.os }}
2929
timeout-minutes: 60
3030
env:

Include/cpython/longintrepr.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ typedef long stwodigits; /* signed variant of twodigits */
7676
- 1: Zero
7777
- 2: Negative
7878
79-
The third lowest bit of lv_tag is reserved for an immortality flag, but is
80-
not currently used.
79+
The third lowest bit of lv_tag is
80+
set to 1 for the small ints.
8181
8282
In a normalized number, ob_digit[ndigits-1] (the most significant
8383
digit) is never zero. Also, in all cases, for all valid i,

Include/cpython/pyatomic.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -574,15 +574,15 @@ static inline void _Py_atomic_fence_release(void);
574574

575575
#if _Py_USE_GCC_BUILTIN_ATOMICS
576576
# define Py_ATOMIC_GCC_H
577-
# include "cpython/pyatomic_gcc.h"
577+
# include "pyatomic_gcc.h"
578578
# undef Py_ATOMIC_GCC_H
579579
#elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)
580580
# define Py_ATOMIC_STD_H
581-
# include "cpython/pyatomic_std.h"
581+
# include "pyatomic_std.h"
582582
# undef Py_ATOMIC_STD_H
583583
#elif defined(_MSC_VER)
584584
# define Py_ATOMIC_MSC_H
585-
# include "cpython/pyatomic_msc.h"
585+
# include "pyatomic_msc.h"
586586
# undef Py_ATOMIC_MSC_H
587587
#else
588588
# error "no available pyatomic implementation for this platform/compiler"

Include/cpython/pythread.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ PyAPI_DATA(const long long) PY_TIMEOUT_MAX;
2222
*/
2323
# define NATIVE_TSS_KEY_T unsigned long
2424
#elif defined(HAVE_PTHREAD_STUBS)
25-
# include "cpython/pthread_stubs.h"
25+
# include "pthread_stubs.h"
2626
# define NATIVE_TSS_KEY_T pthread_key_t
2727
#else
2828
# error "Require native threads. See https://bugs.python.org/issue31370"

Include/internal/pycore_frame.h

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,6 @@ static inline void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *
159159
// Don't leave a dangling pointer to the old frame when creating generators
160160
// and coroutines:
161161
dest->previous = NULL;
162-
163-
#ifdef Py_GIL_DISABLED
164-
PyCodeObject *co = _PyFrame_GetCode(dest);
165-
for (int i = stacktop; i < co->co_nlocalsplus + co->co_stacksize; i++) {
166-
dest->localsplus[i] = PyStackRef_NULL;
167-
}
168-
#endif
169162
}
170163

171164
#ifdef Py_GIL_DISABLED
@@ -222,16 +215,6 @@ _PyFrame_Initialize(
222215
for (int i = null_locals_from; i < code->co_nlocalsplus; i++) {
223216
frame->localsplus[i] = PyStackRef_NULL;
224217
}
225-
226-
#ifdef Py_GIL_DISABLED
227-
// On GIL disabled, we walk the entire stack in GC. Since stacktop
228-
// is not always in sync with the real stack pointer, we have
229-
// no choice but to traverse the entire stack.
230-
// This just makes sure we don't pass the GC invalid stack values.
231-
for (int i = code->co_nlocalsplus; i < code->co_nlocalsplus + code->co_stacksize; i++) {
232-
frame->localsplus[i] = PyStackRef_NULL;
233-
}
234-
#endif
235218
}
236219

237220
/* Gets the pointer to the locals array
@@ -405,13 +388,6 @@ _PyFrame_PushTrampolineUnchecked(PyThreadState *tstate, PyCodeObject *code, int
405388
frame->lltrace = 0;
406389
#endif
407390
frame->return_offset = 0;
408-
409-
#ifdef Py_GIL_DISABLED
410-
assert(code->co_nlocalsplus == 0);
411-
for (int i = 0; i < code->co_stacksize; i++) {
412-
frame->localsplus[i] = PyStackRef_NULL;
413-
}
414-
#endif
415391
return frame;
416392
}
417393

Include/internal/pycore_freelist_state.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ extern "C" {
1111
# define PyTuple_MAXSAVESIZE 20 // Largest tuple to save on freelist
1212
# define Py_tuple_MAXFREELIST 2000 // Maximum number of tuples of each size to save
1313
# define Py_lists_MAXFREELIST 80
14+
# define Py_list_iters_MAXFREELIST 10
15+
# define Py_tuple_iters_MAXFREELIST 10
1416
# define Py_dicts_MAXFREELIST 80
1517
# define Py_dictkeys_MAXFREELIST 80
1618
# define Py_floats_MAXFREELIST 100
@@ -40,6 +42,8 @@ struct _Py_freelists {
4042
struct _Py_freelist ints;
4143
struct _Py_freelist tuples[PyTuple_MAXSAVESIZE];
4244
struct _Py_freelist lists;
45+
struct _Py_freelist list_iters;
46+
struct _Py_freelist tuple_iters;
4347
struct _Py_freelist dicts;
4448
struct _Py_freelist dictkeys;
4549
struct _Py_freelist slices;

Include/internal/pycore_long.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,14 @@ PyAPI_FUNC(int) _PyLong_Size_t_Converter(PyObject *, void *);
159159

160160
/* Long value tag bits:
161161
* 0-1: Sign bits value = (1-sign), ie. negative=2, positive=0, zero=1.
162-
* 2: Reserved for immortality bit
162+
* 2: Set to 1 for the small ints
163163
* 3+ Unsigned digit count
164164
*/
165165
#define SIGN_MASK 3
166166
#define SIGN_ZERO 1
167167
#define SIGN_NEGATIVE 2
168168
#define NON_SIZE_BITS 3
169+
#define IMMORTALITY_BIT_MASK (1 << 2)
169170

170171
/* The functions _PyLong_IsCompact and _PyLong_CompactValue are defined
171172
* in Include/cpython/longobject.h, since they need to be inline.
@@ -196,7 +197,7 @@ PyAPI_FUNC(int) _PyLong_Size_t_Converter(PyObject *, void *);
196197
static inline int
197198
_PyLong_IsNonNegativeCompact(const PyLongObject* op) {
198199
assert(PyLong_Check(op));
199-
return op->long_value.lv_tag <= (1 << NON_SIZE_BITS);
200+
return ((op->long_value.lv_tag & ~IMMORTALITY_BIT_MASK) <= (1 << NON_SIZE_BITS));
200201
}
201202

202203

@@ -298,7 +299,7 @@ _PyLong_FlipSign(PyLongObject *op) {
298299
.long_value = { \
299300
.lv_tag = TAG_FROM_SIGN_AND_SIZE( \
300301
(val) == 0 ? 0 : ((val) < 0 ? -1 : 1), \
301-
(val) == 0 ? 0 : 1), \
302+
(val) == 0 ? 0 : 1) | IMMORTALITY_BIT_MASK, \
302303
{ ((val) >= 0 ? (val) : -(val)) }, \
303304
} \
304305
}

Include/internal/pycore_opcode_metadata.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)