]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-129107: make `bytearray` thread safe (#129108)
authorTomasz Pytel <tompytel@gmail.com>
Sat, 15 Feb 2025 07:19:42 +0000 (02:19 -0500)
committerGitHub <noreply@github.com>
Sat, 15 Feb 2025 07:19:42 +0000 (07:19 +0000)
Co-authored-by: Kumar Aditya <kumaraditya@python.org>
Include/cpython/bytearrayobject.h
Lib/test/test_bytes.py
Misc/NEWS.d/next/Core_and_Builtins/2025-01-20-23-34-14.gh-issue-129107.T5gBva.rst [new file with mode: 0644]
Objects/bytearrayobject.c
Objects/clinic/bytearrayobject.c.h

index 9ba176eb2d3ac2aa650f764d991c37c2d42bd925..4dddef713ce0970abc2acb2302c63469538edbe0 100644 (file)
@@ -29,6 +29,10 @@ static inline char* PyByteArray_AS_STRING(PyObject *op)
 
 static inline Py_ssize_t PyByteArray_GET_SIZE(PyObject *op) {
     PyByteArrayObject *self = _PyByteArray_CAST(op);
+#ifdef Py_GIL_DISABLED
+    return _Py_atomic_load_ssize_relaxed(&(_PyVarObject_CAST(self)->ob_size));
+#else
     return Py_SIZE(self);
+#endif
 }
 #define PyByteArray_GET_SIZE(self) PyByteArray_GET_SIZE(_PyObject_CAST(self))
index 18d619eb6239a1c2c7cfc6d2980a54795a31e252..9c66aebfbdc6dc8a392c483acdd9c6e42a3ca1e4 100644 (file)
@@ -11,12 +11,16 @@ import sys
 import copy
 import functools
 import pickle
+import sysconfig
 import tempfile
 import textwrap
+import threading
 import unittest
 
 import test.support
+from test import support
 from test.support import import_helper
+from test.support import threading_helper
 from test.support import warnings_helper
 import test.string_tests
 import test.list_tests
@@ -2185,5 +2189,336 @@ class BytesSubclassTest(SubclassTest, unittest.TestCase):
     type2test = BytesSubclass
 
 
+class FreeThreadingTest(unittest.TestCase):
+    @unittest.skipUnless(support.Py_GIL_DISABLED, 'this test can only possibly fail with GIL disabled')
+    @threading_helper.reap_threads
+    @threading_helper.requires_working_threading()
+    def test_free_threading_bytearray(self):
+        # Test pretty much everything that can break under free-threading.
+        # Non-deterministic, but at least one of these things will fail if
+        # bytearray module is not free-thread safe.
+
+        def clear(b, a, *args):  # MODIFIES!
+            b.wait()
+            try: a.clear()
+            except BufferError: pass
+
+        def clear2(b, a, c):  # MODIFIES c!
+            b.wait()
+            try: c.clear()
+            except BufferError: pass
+
+        def pop1(b, a):  # MODIFIES!
+            b.wait()
+            try: a.pop()
+            except IndexError: pass
+
+        def append1(b, a):  # MODIFIES!
+            b.wait()
+            a.append(0)
+
+        def insert1(b, a):  # MODIFIES!
+            b.wait()
+            a.insert(0, 0)
+
+        def extend(b, a):  # MODIFIES!
+            c = bytearray(b'0' * 0x400000)
+            b.wait()
+            a.extend(c)
+
+        def remove(b, a):  # MODIFIES!
+            c = ord('0')
+            b.wait()
+            try: a.remove(c)
+            except ValueError: pass
+
+        def reverse(b, a):  # modifies inplace
+            b.wait()
+            a.reverse()
+
+        def reduce(b, a):
+            b.wait()
+            a.__reduce__()
+
+        def reduceex2(b, a):
+            b.wait()
+            a.__reduce_ex__(2)
+
+        def reduceex3(b, a):
+            b.wait()
+            c = a.__reduce_ex__(3)
+            assert not c[1] or 0xdd not in c[1][0]
+
+        def count0(b, a):
+            b.wait()
+            a.count(0)
+
+        def decode(b, a):
+            b.wait()
+            a.decode()
+
+        def find(b, a):
+            c = bytearray(b'0' * 0x40000)
+            b.wait()
+            a.find(c)
+
+        def hex(b, a):
+            b.wait()
+            a.hex('_')
+
+        def join(b, a):
+            b.wait()
+            a.join([b'1', b'2', b'3'])
+
+        def replace(b, a):
+            b.wait()
+            a.replace(b'0', b'')
+
+        def maketrans(b, a, c):
+            b.wait()
+            try: a.maketrans(a, c)
+            except ValueError: pass
+
+        def translate(b, a, c):
+            b.wait()
+            a.translate(c)
+
+        def copy(b, a):
+            b.wait()
+            c = a.copy()
+            if c: assert c[0] == 48  # '0'
+
+        def endswith(b, a):
+            b.wait()
+            assert not a.endswith(b'\xdd')
+
+        def index(b, a):
+            b.wait()
+            try: a.index(b'\xdd')
+            except ValueError: return
+            assert False
+
+        def lstrip(b, a):
+            b.wait()
+            assert not a.lstrip(b'0')
+
+        def partition(b, a):
+            b.wait()
+            assert not a.partition(b'\xdd')[2]
+
+        def removeprefix(b, a):
+            b.wait()
+            assert not a.removeprefix(b'0')
+
+        def removesuffix(b, a):
+            b.wait()
+            assert not a.removesuffix(b'0')
+
+        def rfind(b, a):
+            b.wait()
+            assert a.rfind(b'\xdd') == -1
+
+        def rindex(b, a):
+            b.wait()
+            try: a.rindex(b'\xdd')
+            except ValueError: return
+            assert False
+
+        def rpartition(b, a):
+            b.wait()
+            assert not a.rpartition(b'\xdd')[0]
+
+        def rsplit(b, a):
+            b.wait()
+            assert len(a.rsplit(b'\xdd')) == 1
+
+        def rstrip(b, a):
+            b.wait()
+            assert not a.rstrip(b'0')
+
+        def split(b, a):
+            b.wait()
+            assert len(a.split(b'\xdd')) == 1
+
+        def splitlines(b, a):
+            b.wait()
+            l = len(a.splitlines())
+            assert l > 1 or l == 0
+
+        def startswith(b, a):
+            b.wait()
+            assert not a.startswith(b'\xdd')
+
+        def strip(b, a):
+            b.wait()
+            assert not a.strip(b'0')
+
+        def repeat(b, a):
+            b.wait()
+            a * 2
+
+        def contains(b, a):
+            b.wait()
+            assert 0xdd not in a
+
+        def iconcat(b, a):  # MODIFIES!
+            c = bytearray(b'0' * 0x400000)
+            b.wait()
+            a += c
+
+        def irepeat(b, a):  # MODIFIES!
+            b.wait()
+            a *= 2
+
+        def subscript(b, a):
+            b.wait()
+            try: assert a[0] != 0xdd
+            except IndexError: pass
+
+        def ass_subscript(b, a):  # MODIFIES!
+            c = bytearray(b'0' * 0x400000)
+            b.wait()
+            a[:] = c
+
+        def mod(b, a):
+            c = tuple(range(4096))
+            b.wait()
+            try: a % c
+            except TypeError: pass
+
+        def repr_(b, a):
+            b.wait()
+            repr(a)
+
+        def capitalize(b, a):
+            b.wait()
+            c = a.capitalize()
+            assert not c or c[0] not in (0xdd, 0xcd)
+
+        def center(b, a):
+            b.wait()
+            c = a.center(0x60000)
+            assert not c or c[0x20000] not in (0xdd, 0xcd)
+
+        def expandtabs(b, a):
+            b.wait()
+            c = a.expandtabs()
+            assert not c or c[0] not in (0xdd, 0xcd)
+
+        def ljust(b, a):
+            b.wait()
+            c = a.ljust(0x600000)
+            assert not c or c[0] not in (0xdd, 0xcd)
+
+        def lower(b, a):
+            b.wait()
+            c = a.lower()
+            assert not c or c[0] not in (0xdd, 0xcd)
+
+        def rjust(b, a):
+            b.wait()
+            c = a.rjust(0x600000)
+            assert not c or c[-1] not in (0xdd, 0xcd)
+
+        def swapcase(b, a):
+            b.wait()
+            c = a.swapcase()
+            assert not c or c[-1] not in (0xdd, 0xcd)
+
+        def title(b, a):
+            b.wait()
+            c = a.title()
+            assert not c or c[-1] not in (0xdd, 0xcd)
+
+        def upper(b, a):
+            b.wait()
+            c = a.upper()
+            assert not c or c[-1] not in (0xdd, 0xcd)
+
+        def zfill(b, a):
+            b.wait()
+            c = a.zfill(0x400000)
+            assert not c or c[-1] not in (0xdd, 0xcd)
+
+        def check(funcs, a=None, *args):
+            if a is None:
+                a = bytearray(b'0' * 0x400000)
+
+            barrier = threading.Barrier(len(funcs))
+            threads = []
+
+            for func in funcs:
+                thread = threading.Thread(target=func, args=(barrier, a, *args))
+
+                threads.append(thread)
+
+            with threading_helper.start_threads(threads):
+                pass
+
+            for thread in threads:
+                threading_helper.join_thread(thread)
+
+        # hard errors
+
+        check([clear] + [reduce] * 10)
+        check([clear] + [reduceex2] * 10)
+        check([clear] + [append1] * 10)
+        check([clear] * 10)
+        check([clear] + [count0] * 10)
+        check([clear] + [decode] * 10)
+        check([clear] + [extend] * 10)
+        check([clear] + [find] * 10)
+        check([clear] + [hex] * 10)
+        check([clear] + [insert1] * 10)
+        check([clear] + [join] * 10)
+        check([clear] + [pop1] * 10)
+        check([clear] + [remove] * 10)
+        check([clear] + [replace] * 10)
+        check([clear] + [reverse] * 10)
+        check([clear, clear2] + [maketrans] * 10, bytearray(range(128)), bytearray(range(128)))
+        check([clear] + [translate] * 10, None, bytearray.maketrans(bytearray(range(128)), bytearray(range(128))))
+
+        check([clear] + [repeat] * 10)
+        check([clear] + [iconcat] * 10)
+        check([clear] + [irepeat] * 10)
+        check([clear] + [ass_subscript] * 10)
+        check([clear] + [repr_] * 10)
+
+        # value errors
+
+        check([clear] + [reduceex3] * 10, bytearray(b'a' * 0x40000))
+        check([clear] + [copy] * 10)
+        check([clear] + [endswith] * 10)
+        check([clear] + [index] * 10)
+        check([clear] + [lstrip] * 10)
+        check([clear] + [partition] * 10)
+        check([clear] + [removeprefix] * 10, bytearray(b'0'))
+        check([clear] + [removesuffix] * 10, bytearray(b'0'))
+        check([clear] + [rfind] * 10)
+        check([clear] + [rindex] * 10)
+        check([clear] + [rpartition] * 10)
+        check([clear] + [rsplit] * 10, bytearray(b'0' * 0x4000))
+        check([clear] + [rstrip] * 10)
+        check([clear] + [split] * 10, bytearray(b'0' * 0x4000))
+        check([clear] + [splitlines] * 10, bytearray(b'\n' * 0x400))
+        check([clear] + [startswith] * 10)
+        check([clear] + [strip] * 10)
+
+        check([clear] + [contains] * 10)
+        check([clear] + [subscript] * 10)
+        check([clear] + [mod] * 10, bytearray(b'%d' * 4096))
+
+        check([clear] + [capitalize] * 10, bytearray(b'a' * 0x40000))
+        check([clear] + [center] * 10, bytearray(b'a' * 0x40000))
+        check([clear] + [expandtabs] * 10, bytearray(b'0\t' * 4096))
+        check([clear] + [ljust] * 10, bytearray(b'0' * 0x400000))
+        check([clear] + [lower] * 10, bytearray(b'A' * 0x400000))
+        check([clear] + [rjust] * 10, bytearray(b'0' * 0x400000))
+        check([clear] + [swapcase] * 10, bytearray(b'aA' * 0x200000))
+        check([clear] + [title] * 10, bytearray(b'aA' * 0x200000))
+        check([clear] + [upper] * 10, bytearray(b'a' * 0x400000))
+        check([clear] + [zfill] * 10, bytearray(b'1' * 0x200000))
+
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-20-23-34-14.gh-issue-129107.T5gBva.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-20-23-34-14.gh-issue-129107.T5gBva.rst
new file mode 100644 (file)
index 0000000..fb68f32
--- /dev/null
@@ -0,0 +1 @@
+Make the :type:`bytearray` safe under :term:`free threading`.
index 6133d30f49930a360fb1293c15af330a87188c78..30cc05a1280dd173e281873f62644325edefc03d 100644 (file)
@@ -5,9 +5,11 @@
 #include "pycore_bytes_methods.h"
 #include "pycore_bytesobject.h"
 #include "pycore_ceval.h"         // _PyEval_GetBuiltin()
+#include "pycore_critical_section.h"
 #include "pycore_object.h"        // _PyObject_GC_UNTRACK()
 #include "pycore_strhex.h"        // _Py_strhex_with_sep()
 #include "pycore_long.h"          // _PyLong_FromUnsignedChar()
+#include "pycore_pyatomic_ft_wrappers.h"
 #include "bytesobject.h"
 
 /*[clinic input]
@@ -42,8 +44,9 @@ _getbytevalue(PyObject* arg, int *value)
 }
 
 static int
-bytearray_getbuffer(PyObject *self, Py_buffer *view, int flags)
+bytearray_getbuffer_lock_held(PyObject *self, Py_buffer *view, int flags)
 {
+    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
     PyByteArrayObject *obj = _PyByteArray_CAST(self);
     if (view == NULL) {
         PyErr_SetString(PyExc_BufferError,
@@ -59,12 +62,24 @@ bytearray_getbuffer(PyObject *self, Py_buffer *view, int flags)
     return 0;
 }
 
+static int
+bytearray_getbuffer(PyObject *self, Py_buffer *view, int flags)
+{
+    int ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = bytearray_getbuffer_lock_held(self, view, flags);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
 static void
 bytearray_releasebuffer(PyObject *self, Py_buffer *view)
 {
+    Py_BEGIN_CRITICAL_SECTION(self);
     PyByteArrayObject *obj = _PyByteArray_CAST(self);
     obj->ob_exports--;
     assert(obj->ob_exports >= 0);
+    Py_END_CRITICAL_SECTION();
 }
 
 static int
@@ -170,9 +185,10 @@ PyByteArray_AsString(PyObject *self)
     return PyByteArray_AS_STRING(self);
 }
 
-int
-PyByteArray_Resize(PyObject *self, Py_ssize_t requested_size)
+static int
+bytearray_resize_lock_held(PyObject *self, Py_ssize_t requested_size)
 {
+    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
     void *sval;
     PyByteArrayObject *obj = ((PyByteArrayObject *)self);
     /* All computations are done unsigned to avoid integer overflows
@@ -248,12 +264,22 @@ PyByteArray_Resize(PyObject *self, Py_ssize_t requested_size)
 
     obj->ob_bytes = obj->ob_start = sval;
     Py_SET_SIZE(self, size);
-    obj->ob_alloc = alloc;
+    FT_ATOMIC_STORE_SSIZE_RELAXED(obj->ob_alloc, alloc);
     obj->ob_bytes[size] = '\0'; /* Trailing null byte */
 
     return 0;
 }
 
+int
+PyByteArray_Resize(PyObject *self, Py_ssize_t requested_size)
+{
+    int ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = bytearray_resize_lock_held(self, requested_size);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
 PyObject *
 PyByteArray_Concat(PyObject *a, PyObject *b)
 {
@@ -296,13 +322,13 @@ PyByteArray_Concat(PyObject *a, PyObject *b)
 static Py_ssize_t
 bytearray_length(PyObject *op)
 {
-    PyByteArrayObject *self = _PyByteArray_CAST(op);
-    return Py_SIZE(self);
+    return PyByteArray_GET_SIZE(op);
 }
 
 static PyObject *
-bytearray_iconcat(PyObject *op, PyObject *other)
+bytearray_iconcat_lock_held(PyObject *op, PyObject *other)
 {
+    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
     PyByteArrayObject *self = _PyByteArray_CAST(op);
 
     Py_buffer vo;
@@ -318,7 +344,7 @@ bytearray_iconcat(PyObject *op, PyObject *other)
         return PyErr_NoMemory();
     }
 
-    if (PyByteArray_Resize((PyObject *)self, size + vo.len) < 0) {
+    if (bytearray_resize_lock_held((PyObject *)self, size + vo.len) < 0) {
         PyBuffer_Release(&vo);
         return NULL;
     }
@@ -329,8 +355,19 @@ bytearray_iconcat(PyObject *op, PyObject *other)
 }
 
 static PyObject *
-bytearray_repeat(PyObject *op, Py_ssize_t count)
+bytearray_iconcat(PyObject *op, PyObject *other)
 {
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(op);
+    ret = bytearray_iconcat_lock_held(op, other);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
+static PyObject *
+bytearray_repeat_lock_held(PyObject *op, Py_ssize_t count)
+{
+    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
     PyByteArrayObject *self = _PyByteArray_CAST(op);
     if (count < 0) {
         count = 0;
@@ -350,8 +387,19 @@ bytearray_repeat(PyObject *op, Py_ssize_t count)
 }
 
 static PyObject *
-bytearray_irepeat(PyObject *op, Py_ssize_t count)
+bytearray_repeat(PyObject *op, Py_ssize_t count)
 {
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(op);
+    ret = bytearray_repeat_lock_held(op, count);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
+static PyObject *
+bytearray_irepeat_lock_held(PyObject *op, Py_ssize_t count)
+{
+    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
     PyByteArrayObject *self = _PyByteArray_CAST(op);
     if (count < 0) {
         count = 0;
@@ -365,7 +413,7 @@ bytearray_irepeat(PyObject *op, Py_ssize_t count)
         return PyErr_NoMemory();
     }
     const Py_ssize_t size = mysize * count;
-    if (PyByteArray_Resize((PyObject *)self, size) < 0) {
+    if (bytearray_resize_lock_held((PyObject *)self, size) < 0) {
         return NULL;
     }
 
@@ -376,8 +424,19 @@ bytearray_irepeat(PyObject *op, Py_ssize_t count)
 }
 
 static PyObject *
-bytearray_getitem(PyObject *op, Py_ssize_t i)
+bytearray_irepeat(PyObject *op, Py_ssize_t count)
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(op);
+    ret = bytearray_irepeat_lock_held(op, count);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
+static PyObject *
+bytearray_getitem_lock_held(PyObject *op, Py_ssize_t i)
 {
+    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
     PyByteArrayObject *self = _PyByteArray_CAST(op);
     if (i < 0 || i >= Py_SIZE(self)) {
         PyErr_SetString(PyExc_IndexError, "bytearray index out of range");
@@ -387,8 +446,19 @@ bytearray_getitem(PyObject *op, Py_ssize_t i)
 }
 
 static PyObject *
-bytearray_subscript(PyObject *op, PyObject *index)
+bytearray_getitem(PyObject *op, Py_ssize_t i)
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(op);
+    ret = bytearray_getitem_lock_held(op, i);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
+static PyObject *
+bytearray_subscript_lock_held(PyObject *op, PyObject *index)
 {
+    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
     PyByteArrayObject *self = _PyByteArray_CAST(op);
     if (_PyIndex_Check(index)) {
         Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError);
@@ -445,11 +515,23 @@ bytearray_subscript(PyObject *op, PyObject *index)
     }
 }
 
+static PyObject *
+bytearray_subscript(PyObject *op, PyObject *index)
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(op);
+    ret = bytearray_subscript_lock_held(op, index);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+
+}
+
 static int
 bytearray_setslice_linear(PyByteArrayObject *self,
                           Py_ssize_t lo, Py_ssize_t hi,
                           char *bytes, Py_ssize_t bytes_len)
 {
+    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
     Py_ssize_t avail = hi - lo;
     char *buf = PyByteArray_AS_STRING(self);
     Py_ssize_t growth = bytes_len - avail;
@@ -480,7 +562,7 @@ bytearray_setslice_linear(PyByteArrayObject *self,
             memmove(buf + lo + bytes_len, buf + hi,
                     Py_SIZE(self) - hi);
         }
-        if (PyByteArray_Resize((PyObject *)self,
+        if (bytearray_resize_lock_held((PyObject *)self,
                                Py_SIZE(self) + growth) < 0) {
             /* Issue #19578: Handling the memory allocation failure here is
                tricky here because the bytearray object has already been
@@ -508,7 +590,7 @@ bytearray_setslice_linear(PyByteArrayObject *self,
             return -1;
         }
 
-        if (PyByteArray_Resize((PyObject *)self,
+        if (bytearray_resize_lock_held((PyObject *)self,
                                Py_SIZE(self) + growth) < 0) {
             return -1;
         }
@@ -533,6 +615,7 @@ static int
 bytearray_setslice(PyByteArrayObject *self, Py_ssize_t lo, Py_ssize_t hi,
                PyObject *values)
 {
+    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
     Py_ssize_t needed;
     void *bytes;
     Py_buffer vbytes;
@@ -580,8 +663,9 @@ bytearray_setslice(PyByteArrayObject *self, Py_ssize_t lo, Py_ssize_t hi,
 }
 
 static int
-bytearray_setitem(PyObject *op, Py_ssize_t i, PyObject *value)
+bytearray_setitem_lock_held(PyObject *op, Py_ssize_t i, PyObject *value)
 {
+    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
     PyByteArrayObject *self = _PyByteArray_CAST(op);
 
     // GH-91153: We need to do this *before* the size check, in case value has a
@@ -610,8 +694,19 @@ bytearray_setitem(PyObject *op, Py_ssize_t i, PyObject *value)
 }
 
 static int
-bytearray_ass_subscript(PyObject *op, PyObject *index, PyObject *values)
+bytearray_setitem(PyObject *op, Py_ssize_t i, PyObject *value)
 {
+    int ret;
+    Py_BEGIN_CRITICAL_SECTION(op);
+    ret = bytearray_setitem_lock_held(op, i, value);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
+static int
+bytearray_ass_subscript_lock_held(PyObject *op, PyObject *index, PyObject *values)
+{
+    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
     PyByteArrayObject *self = _PyByteArray_CAST(op);
     Py_ssize_t start, stop, step, slicelen;
     char *buf = PyByteArray_AS_STRING(self);
@@ -685,7 +780,7 @@ bytearray_ass_subscript(PyObject *op, PyObject *index, PyObject *values)
         values = PyByteArray_FromObject(values);
         if (values == NULL)
             return -1;
-        err = bytearray_ass_subscript((PyObject*)self, index, values);
+        err = bytearray_ass_subscript_lock_held((PyObject*)self, index, values);
         Py_DECREF(values);
         return err;
     }
@@ -740,7 +835,7 @@ bytearray_ass_subscript(PyObject *op, PyObject *index, PyObject *values)
                         buf + cur,
                         PyByteArray_GET_SIZE(self) - cur);
             }
-            if (PyByteArray_Resize((PyObject *)self,
+            if (bytearray_resize_lock_held((PyObject *)self,
                                PyByteArray_GET_SIZE(self) - slicelen) < 0)
                 return -1;
 
@@ -765,6 +860,16 @@ bytearray_ass_subscript(PyObject *op, PyObject *index, PyObject *values)
     }
 }
 
+static int
+bytearray_ass_subscript(PyObject *op, PyObject *index, PyObject *values)
+{
+    int ret;
+    Py_BEGIN_CRITICAL_SECTION(op);
+    ret = bytearray_ass_subscript_lock_held(op, index, values);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
 /*[clinic input]
 bytearray.__init__
 
@@ -954,8 +1059,9 @@ slowpath:
 /* Mostly copied from string_repr, but without the
    "smart quote" functionality. */
 static PyObject *
-bytearray_repr(PyObject *op)
+bytearray_repr_lock_held(PyObject *op)
 {
+    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
     PyByteArrayObject *self = _PyByteArray_CAST(op);
     const char *className = _PyType_Name(Py_TYPE(self));
     const char *quote_prefix = "(b";
@@ -1041,6 +1147,16 @@ bytearray_repr(PyObject *op)
     return v;
 }
 
+static PyObject *
+bytearray_repr(PyObject *op)
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(op);
+    ret = bytearray_repr_lock_held(op);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
 static PyObject *
 bytearray_str(PyObject *op)
 {
@@ -1152,6 +1268,7 @@ bytearray_dealloc(PyObject *op)
 
 
 /*[clinic input]
+@critical_section
 @text_signature "($self, sub[, start[, end]], /)"
 bytearray.find
 
@@ -1170,13 +1287,14 @@ Return -1 on failure.
 static PyObject *
 bytearray_find_impl(PyByteArrayObject *self, PyObject *sub, Py_ssize_t start,
                     Py_ssize_t end)
-/*[clinic end generated code: output=413e1cab2ae87da0 input=793dfad803e2952f]*/
+/*[clinic end generated code: output=413e1cab2ae87da0 input=1de9f4558df68336]*/
 {
     return _Py_bytes_find(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
                           sub, start, end);
 }
 
 /*[clinic input]
+@critical_section
 bytearray.count = bytearray.find
 
 Return the number of non-overlapping occurrences of subsection 'sub' in bytes B[start:end].
@@ -1185,7 +1303,7 @@ Return the number of non-overlapping occurrences of subsection 'sub' in bytes B[
 static PyObject *
 bytearray_count_impl(PyByteArrayObject *self, PyObject *sub,
                      Py_ssize_t start, Py_ssize_t end)
-/*[clinic end generated code: output=a21ee2692e4f1233 input=4deb529db38deda8]*/
+/*[clinic end generated code: output=a21ee2692e4f1233 input=2608c30644614724]*/
 {
     return _Py_bytes_count(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
                            sub, start, end);
@@ -1207,6 +1325,7 @@ bytearray_clear_impl(PyByteArrayObject *self)
 }
 
 /*[clinic input]
+@critical_section
 bytearray.copy
 
 Return a copy of B.
@@ -1214,13 +1333,14 @@ Return a copy of B.
 
 static PyObject *
 bytearray_copy_impl(PyByteArrayObject *self)
-/*[clinic end generated code: output=68cfbcfed484c132 input=6597b0c01bccaa9e]*/
+/*[clinic end generated code: output=68cfbcfed484c132 input=b96f8b01f73851ad]*/
 {
     return PyByteArray_FromStringAndSize(PyByteArray_AS_STRING((PyObject *)self),
                                          PyByteArray_GET_SIZE(self));
 }
 
 /*[clinic input]
+@critical_section
 bytearray.index = bytearray.find
 
 Return the lowest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start:end].
@@ -1231,13 +1351,14 @@ Raise ValueError if the subsection is not found.
 static PyObject *
 bytearray_index_impl(PyByteArrayObject *self, PyObject *sub,
                      Py_ssize_t start, Py_ssize_t end)
-/*[clinic end generated code: output=067a1e78efc672a7 input=8cbaf6836dbd2a9a]*/
+/*[clinic end generated code: output=067a1e78efc672a7 input=0086ba0ab9bf44a5]*/
 {
     return _Py_bytes_index(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
                            sub, start, end);
 }
 
 /*[clinic input]
+@critical_section
 bytearray.rfind = bytearray.find
 
 Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start:end].
@@ -1248,13 +1369,14 @@ Return -1 on failure.
 static PyObject *
 bytearray_rfind_impl(PyByteArrayObject *self, PyObject *sub,
                      Py_ssize_t start, Py_ssize_t end)
-/*[clinic end generated code: output=51bf886f932b283c input=eaa107468a158423]*/
+/*[clinic end generated code: output=51bf886f932b283c input=ac73593305d5c1d1]*/
 {
     return _Py_bytes_rfind(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
                            sub, start, end);
 }
 
 /*[clinic input]
+@critical_section
 bytearray.rindex = bytearray.find
 
 Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start:end].
@@ -1265,7 +1387,7 @@ Raise ValueError if the subsection is not found.
 static PyObject *
 bytearray_rindex_impl(PyByteArrayObject *self, PyObject *sub,
                       Py_ssize_t start, Py_ssize_t end)
-/*[clinic end generated code: output=38e1cf66bafb08b9 input=81cf49d0af4d5bd0]*/
+/*[clinic end generated code: output=38e1cf66bafb08b9 input=0cf331bf5ebe0e91]*/
 {
     return _Py_bytes_rindex(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
                             sub, start, end);
@@ -1274,12 +1396,17 @@ bytearray_rindex_impl(PyByteArrayObject *self, PyObject *sub,
 static int
 bytearray_contains(PyObject *self, PyObject *arg)
 {
-    return _Py_bytes_contains(PyByteArray_AS_STRING(self),
-                              PyByteArray_GET_SIZE(self),
-                              arg);
+    int ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = _Py_bytes_contains(PyByteArray_AS_STRING(self),
+                             PyByteArray_GET_SIZE(self),
+                             arg);
+    Py_END_CRITICAL_SECTION();
+    return ret;
 }
 
 /*[clinic input]
+@critical_section
 @text_signature "($self, prefix[, start[, end]], /)"
 bytearray.startswith
 
@@ -1297,13 +1424,14 @@ Return True if the bytearray starts with the specified prefix, False otherwise.
 static PyObject *
 bytearray_startswith_impl(PyByteArrayObject *self, PyObject *subobj,
                           Py_ssize_t start, Py_ssize_t end)
-/*[clinic end generated code: output=a3d9b6d44d3662a6 input=76385e0b376b45c1]*/
+/*[clinic end generated code: output=a3d9b6d44d3662a6 input=ea8d036d09df34b2]*/
 {
     return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
                                 subobj, start, end);
 }
 
 /*[clinic input]
+@critical_section
 @text_signature "($self, suffix[, start[, end]], /)"
 bytearray.endswith
 
@@ -1321,13 +1449,14 @@ Return True if the bytearray ends with the specified suffix, False otherwise.
 static PyObject *
 bytearray_endswith_impl(PyByteArrayObject *self, PyObject *subobj,
                         Py_ssize_t start, Py_ssize_t end)
-/*[clinic end generated code: output=e75ea8c227954caa input=9b8baa879aa3d74b]*/
+/*[clinic end generated code: output=e75ea8c227954caa input=c61b90bb23a689ce]*/
 {
     return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
                               subobj, start, end);
 }
 
 /*[clinic input]
+@critical_section
 bytearray.removeprefix as bytearray_removeprefix
 
     prefix: Py_buffer
@@ -1342,7 +1471,7 @@ bytearray.
 
 static PyObject *
 bytearray_removeprefix_impl(PyByteArrayObject *self, Py_buffer *prefix)
-/*[clinic end generated code: output=6cabc585e7f502e0 input=968aada38aedd262]*/
+/*[clinic end generated code: output=6cabc585e7f502e0 input=4323ba6d275fe7a8]*/
 {
     const char *self_start = PyByteArray_AS_STRING(self);
     Py_ssize_t self_len = PyByteArray_GET_SIZE(self);
@@ -1360,6 +1489,7 @@ bytearray_removeprefix_impl(PyByteArrayObject *self, Py_buffer *prefix)
 }
 
 /*[clinic input]
+@critical_section
 bytearray.removesuffix as bytearray_removesuffix
 
     suffix: Py_buffer
@@ -1374,7 +1504,7 @@ the original bytearray.
 
 static PyObject *
 bytearray_removesuffix_impl(PyByteArrayObject *self, Py_buffer *suffix)
-/*[clinic end generated code: output=2bc8cfb79de793d3 input=c1827e810b2f6b99]*/
+/*[clinic end generated code: output=2bc8cfb79de793d3 input=f71ba2e1a40c47dd]*/
 {
     const char *self_start = PyByteArray_AS_STRING(self);
     Py_ssize_t self_len = PyByteArray_GET_SIZE(self);
@@ -1419,6 +1549,7 @@ bytearray_resize_impl(PyByteArrayObject *self, Py_ssize_t size)
 
 
 /*[clinic input]
+@critical_section
 bytearray.translate
 
     table: object
@@ -1435,7 +1566,7 @@ The remaining characters are mapped through the given translation table.
 static PyObject *
 bytearray_translate_impl(PyByteArrayObject *self, PyObject *table,
                          PyObject *deletechars)
-/*[clinic end generated code: output=b6a8f01c2a74e446 input=cfff956d4d127a9b]*/
+/*[clinic end generated code: output=b6a8f01c2a74e446 input=cd6fa93ca04e05bc]*/
 {
     char *input, *output;
     const char *table_chars;
@@ -1548,6 +1679,7 @@ bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to)
 
 
 /*[clinic input]
+@critical_section
 bytearray.replace
 
     old: Py_buffer
@@ -1566,7 +1698,7 @@ replaced.
 static PyObject *
 bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old,
                        Py_buffer *new, Py_ssize_t count)
-/*[clinic end generated code: output=d39884c4dc59412a input=aa379d988637c7fb]*/
+/*[clinic end generated code: output=d39884c4dc59412a input=6992755672c8a807]*/
 {
     return stringlib_replace((PyObject *)self,
                              (const char *)old->buf, old->len,
@@ -1574,6 +1706,7 @@ bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old,
 }
 
 /*[clinic input]
+@critical_section
 bytearray.split
 
     sep: object = None
@@ -1590,7 +1723,7 @@ Return a list of the sections in the bytearray, using sep as the delimiter.
 static PyObject *
 bytearray_split_impl(PyByteArrayObject *self, PyObject *sep,
                      Py_ssize_t maxsplit)
-/*[clinic end generated code: output=833e2cf385d9a04d input=24f82669f41bf523]*/
+/*[clinic end generated code: output=833e2cf385d9a04d input=1c367486b9938909]*/
 {
     Py_ssize_t len = PyByteArray_GET_SIZE(self), n;
     const char *s = PyByteArray_AS_STRING(self), *sub;
@@ -1616,6 +1749,7 @@ bytearray_split_impl(PyByteArrayObject *self, PyObject *sep,
 }
 
 /*[clinic input]
+@critical_section
 bytearray.partition
 
     sep: object
@@ -1632,8 +1766,8 @@ original bytearray object and two empty bytearray objects.
 [clinic start generated code]*/
 
 static PyObject *
-bytearray_partition(PyByteArrayObject *self, PyObject *sep)
-/*[clinic end generated code: output=45d2525ddd35f957 input=8f644749ee4fc83a]*/
+bytearray_partition_impl(PyByteArrayObject *self, PyObject *sep)
+/*[clinic end generated code: output=b5fa1e03f10cfccb input=632855f986733f34]*/
 {
     PyObject *bytesep, *result;
 
@@ -1653,6 +1787,7 @@ bytearray_partition(PyByteArrayObject *self, PyObject *sep)
 }
 
 /*[clinic input]
+@critical_section
 bytearray.rpartition
 
     sep: object
@@ -1670,8 +1805,8 @@ objects and the copy of the original bytearray object.
 [clinic start generated code]*/
 
 static PyObject *
-bytearray_rpartition(PyByteArrayObject *self, PyObject *sep)
-/*[clinic end generated code: output=440de3c9426115e8 input=7e3df3e6cb8fa0ac]*/
+bytearray_rpartition_impl(PyByteArrayObject *self, PyObject *sep)
+/*[clinic end generated code: output=0186ce7b1ef61289 input=4318e3d125497450]*/
 {
     PyObject *bytesep, *result;
 
@@ -1691,6 +1826,7 @@ bytearray_rpartition(PyByteArrayObject *self, PyObject *sep)
 }
 
 /*[clinic input]
+@critical_section
 bytearray.rsplit = bytearray.split
 
 Return a list of the sections in the bytearray, using sep as the delimiter.
@@ -1701,7 +1837,7 @@ Splitting is done starting at the end of the bytearray and working to the front.
 static PyObject *
 bytearray_rsplit_impl(PyByteArrayObject *self, PyObject *sep,
                       Py_ssize_t maxsplit)
-/*[clinic end generated code: output=a55e0b5a03cb6190 input=a68286e4dd692ffe]*/
+/*[clinic end generated code: output=a55e0b5a03cb6190 input=3cd513c2b94a53c1]*/
 {
     Py_ssize_t len = PyByteArray_GET_SIZE(self), n;
     const char *s = PyByteArray_AS_STRING(self), *sub;
@@ -1727,6 +1863,7 @@ bytearray_rsplit_impl(PyByteArrayObject *self, PyObject *sep,
 }
 
 /*[clinic input]
+@critical_section
 bytearray.reverse
 
 Reverse the order of the values in B in place.
@@ -1734,7 +1871,7 @@ Reverse the order of the values in B in place.
 
 static PyObject *
 bytearray_reverse_impl(PyByteArrayObject *self)
-/*[clinic end generated code: output=9f7616f29ab309d3 input=543356319fc78557]*/
+/*[clinic end generated code: output=9f7616f29ab309d3 input=2f3d5ce3180ffc53]*/
 {
     char swap, *head, *tail;
     Py_ssize_t i, j, n = Py_SIZE(self);
@@ -1761,6 +1898,7 @@ class bytesvalue_converter(CConverter):
 
 
 /*[clinic input]
+@critical_section
 bytearray.insert
 
     index: Py_ssize_t
@@ -1774,7 +1912,7 @@ Insert a single item into the bytearray before the given index.
 
 static PyObject *
 bytearray_insert_impl(PyByteArrayObject *self, Py_ssize_t index, int item)
-/*[clinic end generated code: output=76c775a70e7b07b7 input=b2b5d07e9de6c070]*/
+/*[clinic end generated code: output=76c775a70e7b07b7 input=b3e14ede546dd8cc]*/
 {
     Py_ssize_t n = Py_SIZE(self);
     char *buf;
@@ -1784,7 +1922,7 @@ bytearray_insert_impl(PyByteArrayObject *self, Py_ssize_t index, int item)
                         "cannot add more objects to bytearray");
         return NULL;
     }
-    if (PyByteArray_Resize((PyObject *)self, n + 1) < 0)
+    if (bytearray_resize_lock_held((PyObject *)self, n + 1) < 0)
         return NULL;
     buf = PyByteArray_AS_STRING(self);
 
@@ -1801,7 +1939,88 @@ bytearray_insert_impl(PyByteArrayObject *self, Py_ssize_t index, int item)
     Py_RETURN_NONE;
 }
 
+static PyObject *
+bytearray_isalnum(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = stringlib_isalnum(self, NULL);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
+static PyObject *
+bytearray_isalpha(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = stringlib_isalpha(self, NULL);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
+static PyObject *
+bytearray_isascii(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = stringlib_isascii(self, NULL);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
+static PyObject *
+bytearray_isdigit(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = stringlib_isdigit(self, NULL);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
+static PyObject *
+bytearray_islower(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = stringlib_islower(self, NULL);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
+static PyObject *
+bytearray_isspace(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = stringlib_isspace(self, NULL);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
+static PyObject *
+bytearray_istitle(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = stringlib_istitle(self, NULL);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
+static PyObject *
+bytearray_isupper(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = stringlib_isupper(self, NULL);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
 /*[clinic input]
+@critical_section
 bytearray.append
 
     item: bytesvalue
@@ -1813,7 +2032,7 @@ Append a single item to the end of the bytearray.
 
 static PyObject *
 bytearray_append_impl(PyByteArrayObject *self, int item)
-/*[clinic end generated code: output=a154e19ed1886cb6 input=20d6bec3d1340593]*/
+/*[clinic end generated code: output=a154e19ed1886cb6 input=a874689bac8bd352]*/
 {
     Py_ssize_t n = Py_SIZE(self);
 
@@ -1822,7 +2041,7 @@ bytearray_append_impl(PyByteArrayObject *self, int item)
                         "cannot add more objects to bytearray");
         return NULL;
     }
-    if (PyByteArray_Resize((PyObject *)self, n + 1) < 0)
+    if (bytearray_resize_lock_held((PyObject *)self, n + 1) < 0)
         return NULL;
 
     PyByteArray_AS_STRING(self)[n] = item;
@@ -1830,7 +2049,38 @@ bytearray_append_impl(PyByteArrayObject *self, int item)
     Py_RETURN_NONE;
 }
 
+static PyObject *
+bytearray_capitalize(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = stringlib_capitalize(self, NULL);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
+static PyObject *
+bytearray_center(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = stringlib_center(self, args, nargs);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
+static PyObject *
+bytearray_expandtabs(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = stringlib_expandtabs(self, args, nargs, kwnames);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
 /*[clinic input]
+@critical_section
 bytearray.extend
 
     iterable_of_ints: object
@@ -1841,8 +2091,8 @@ Append all the items from the iterator or sequence to the end of the bytearray.
 [clinic start generated code]*/
 
 static PyObject *
-bytearray_extend(PyByteArrayObject *self, PyObject *iterable_of_ints)
-/*[clinic end generated code: output=98155dbe249170b1 input=c617b3a93249ba28]*/
+bytearray_extend_impl(PyByteArrayObject *self, PyObject *iterable_of_ints)
+/*[clinic end generated code: output=2f25e0ce72b98748 input=86e65beaba444650]*/
 {
     PyObject *it, *item, *bytearray_obj;
     Py_ssize_t buf_size = 0, len = 0;
@@ -1907,7 +2157,7 @@ bytearray_extend(PyByteArrayObject *self, PyObject *iterable_of_ints)
                 buf_size = PY_SSIZE_T_MAX;
             else
                 buf_size = len + addition + 1;
-            if (PyByteArray_Resize((PyObject *)bytearray_obj, buf_size) < 0) {
+            if (bytearray_resize_lock_held((PyObject *)bytearray_obj, buf_size) < 0) {
                 Py_DECREF(it);
                 Py_DECREF(bytearray_obj);
                 return NULL;
@@ -1925,7 +2175,7 @@ bytearray_extend(PyByteArrayObject *self, PyObject *iterable_of_ints)
     }
 
     /* Resize down to exact size. */
-    if (PyByteArray_Resize((PyObject *)bytearray_obj, len) < 0) {
+    if (bytearray_resize_lock_held((PyObject *)bytearray_obj, len) < 0) {
         Py_DECREF(bytearray_obj);
         return NULL;
     }
@@ -1941,6 +2191,7 @@ bytearray_extend(PyByteArrayObject *self, PyObject *iterable_of_ints)
 }
 
 /*[clinic input]
+@critical_section
 bytearray.pop
 
     index: Py_ssize_t = -1
@@ -1955,7 +2206,7 @@ If no index argument is given, will pop the last item.
 
 static PyObject *
 bytearray_pop_impl(PyByteArrayObject *self, Py_ssize_t index)
-/*[clinic end generated code: output=e0ccd401f8021da8 input=3591df2d06c0d237]*/
+/*[clinic end generated code: output=e0ccd401f8021da8 input=fc0fd8de4f97661c]*/
 {
     int value;
     Py_ssize_t n = Py_SIZE(self);
@@ -1978,13 +2229,14 @@ bytearray_pop_impl(PyByteArrayObject *self, Py_ssize_t index)
     buf = PyByteArray_AS_STRING(self);
     value = buf[index];
     memmove(buf + index, buf + index + 1, n - index);
-    if (PyByteArray_Resize((PyObject *)self, n - 1) < 0)
+    if (bytearray_resize_lock_held((PyObject *)self, n - 1) < 0)
         return NULL;
 
     return _PyLong_FromUnsignedChar((unsigned char)value);
 }
 
 /*[clinic input]
+@critical_section
 bytearray.remove
 
     value: bytesvalue
@@ -1996,7 +2248,7 @@ Remove the first occurrence of a value in the bytearray.
 
 static PyObject *
 bytearray_remove_impl(PyByteArrayObject *self, int value)
-/*[clinic end generated code: output=d659e37866709c13 input=121831240cd51ddf]*/
+/*[clinic end generated code: output=d659e37866709c13 input=797588bc77f86afb]*/
 {
     Py_ssize_t where, n = Py_SIZE(self);
     char *buf = PyByteArray_AS_STRING(self);
@@ -2010,7 +2262,7 @@ bytearray_remove_impl(PyByteArrayObject *self, int value)
         return NULL;
 
     memmove(buf + where, buf + where + 1, n - where);
-    if (PyByteArray_Resize((PyObject *)self, n - 1) < 0)
+    if (bytearray_resize_lock_held((PyObject *)self, n - 1) < 0)
         return NULL;
 
     Py_RETURN_NONE;
@@ -2059,6 +2311,7 @@ bytearray_strip_impl_helper(PyByteArrayObject* self, PyObject* bytes, int stript
 }
 
 /*[clinic input]
+@critical_section
 bytearray.strip
 
     bytes: object = None
@@ -2071,12 +2324,63 @@ If the argument is omitted or None, strip leading and trailing ASCII whitespace.
 
 static PyObject *
 bytearray_strip_impl(PyByteArrayObject *self, PyObject *bytes)
-/*[clinic end generated code: output=760412661a34ad5a input=ef7bb59b09c21d62]*/
+/*[clinic end generated code: output=760412661a34ad5a input=1f9026e5ad35388a]*/
 {
     return bytearray_strip_impl_helper(self, bytes, BOTHSTRIP);
 }
 
+static PyObject *
+bytearray_swapcase(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = stringlib_swapcase(self, NULL);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
+static PyObject *
+bytearray_title(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = stringlib_title(self, NULL);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
+static PyObject *
+bytearray_upper(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = stringlib_upper(self, NULL);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
+static PyObject *
+bytearray_lower(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = stringlib_lower(self, NULL);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
+static PyObject *
+bytearray_zfill(PyObject *self, PyObject *arg)
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = stringlib_zfill(self, arg);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
 /*[clinic input]
+@critical_section
 bytearray.lstrip
 
     bytes: object = None
@@ -2089,12 +2393,13 @@ If the argument is omitted or None, strip leading ASCII whitespace.
 
 static PyObject *
 bytearray_lstrip_impl(PyByteArrayObject *self, PyObject *bytes)
-/*[clinic end generated code: output=d005c9d0ab909e66 input=80843f975dd7c480]*/
+/*[clinic end generated code: output=d005c9d0ab909e66 input=ed86e00eb2023625]*/
 {
     return bytearray_strip_impl_helper(self, bytes, LEFTSTRIP);
 }
 
 /*[clinic input]
+@critical_section
 bytearray.rstrip
 
     bytes: object = None
@@ -2107,12 +2412,13 @@ If the argument is omitted or None, strip trailing ASCII whitespace.
 
 static PyObject *
 bytearray_rstrip_impl(PyByteArrayObject *self, PyObject *bytes)
-/*[clinic end generated code: output=030e2fbd2f7276bd input=e728b994954cfd91]*/
+/*[clinic end generated code: output=030e2fbd2f7276bd input=d9ca66cf20fe7649]*/
 {
     return bytearray_strip_impl_helper(self, bytes, RIGHTSTRIP);
 }
 
 /*[clinic input]
+@critical_section
 bytearray.decode
 
     encoding: str(c_default="NULL") = 'utf-8'
@@ -2130,7 +2436,7 @@ Decode the bytearray using the codec registered for encoding.
 static PyObject *
 bytearray_decode_impl(PyByteArrayObject *self, const char *encoding,
                       const char *errors)
-/*[clinic end generated code: output=f57d43f4a00b42c5 input=f28d8f903020257b]*/
+/*[clinic end generated code: output=f57d43f4a00b42c5 input=86c303ee376b8453]*/
 {
     if (encoding == NULL)
         encoding = PyUnicode_GetDefaultEncoding();
@@ -2146,10 +2452,11 @@ static PyObject *
 bytearray_alloc(PyObject *op, PyObject *Py_UNUSED(ignored))
 {
     PyByteArrayObject *self = _PyByteArray_CAST(op);
-    return PyLong_FromSsize_t(self->ob_alloc);
+    return PyLong_FromSsize_t(FT_ATOMIC_LOAD_SSIZE_RELAXED(self->ob_alloc));
 }
 
 /*[clinic input]
+@critical_section
 bytearray.join
 
     iterable_of_bytes: object
@@ -2163,16 +2470,38 @@ The result is returned as a new bytearray object.
 [clinic start generated code]*/
 
 static PyObject *
-bytearray_join(PyByteArrayObject *self, PyObject *iterable_of_bytes)
-/*[clinic end generated code: output=a8516370bf68ae08 input=aba6b1f9b30fcb8e]*/
+bytearray_join_impl(PyByteArrayObject *self, PyObject *iterable_of_bytes)
+/*[clinic end generated code: output=0ced382b5846a7ee input=49627e07ca31ca26]*/
 {
+    PyObject *ret;
     self->ob_exports++; // this protects `self` from being cleared/resized if `iterable_of_bytes` is a custom iterator
-    PyObject* ret = stringlib_bytes_join((PyObject*)self, iterable_of_bytes);
+    ret = stringlib_bytes_join((PyObject*)self, iterable_of_bytes);
     self->ob_exports--; // unexport `self`
     return ret;
 }
 
+static PyObject *
+bytearray_ljust(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = stringlib_ljust(self, args, nargs);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
+static PyObject *
+bytearray_rjust(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    ret = stringlib_rjust(self, args, nargs);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
 /*[clinic input]
+@critical_section
 bytearray.splitlines
 
     keepends: bool = False
@@ -2185,7 +2514,7 @@ true.
 
 static PyObject *
 bytearray_splitlines_impl(PyByteArrayObject *self, int keepends)
-/*[clinic end generated code: output=4223c94b895f6ad9 input=66b2dcdea8d093bf]*/
+/*[clinic end generated code: output=4223c94b895f6ad9 input=874cd662866a66a1]*/
 {
     return stringlib_splitlines(
         (PyObject*) self, PyByteArray_AS_STRING(self),
@@ -2218,6 +2547,7 @@ bytearray_fromhex_impl(PyTypeObject *type, PyObject *string)
 }
 
 /*[clinic input]
+@critical_section
 bytearray.hex
 
     sep: object = NULL
@@ -2242,7 +2572,7 @@ Example:
 
 static PyObject *
 bytearray_hex_impl(PyByteArrayObject *self, PyObject *sep, int bytes_per_sep)
-/*[clinic end generated code: output=29c4e5ef72c565a0 input=808667e49bcccb54]*/
+/*[clinic end generated code: output=29c4e5ef72c565a0 input=7784107de7048873]*/
 {
     char* argbuf = PyByteArray_AS_STRING(self);
     Py_ssize_t arglen = PyByteArray_GET_SIZE(self);
@@ -2276,6 +2606,7 @@ _common_reduce(PyByteArrayObject *self, int proto)
 }
 
 /*[clinic input]
+@critical_section
 bytearray.__reduce__ as bytearray_reduce
 
 Return state information for pickling.
@@ -2283,12 +2614,13 @@ Return state information for pickling.
 
 static PyObject *
 bytearray_reduce_impl(PyByteArrayObject *self)
-/*[clinic end generated code: output=52bf304086464cab input=44b5737ada62dd3f]*/
+/*[clinic end generated code: output=52bf304086464cab input=0fac78e4b7d84dd2]*/
 {
     return _common_reduce(self, 2);
 }
 
 /*[clinic input]
+@critical_section
 bytearray.__reduce_ex__ as bytearray_reduce_ex
 
     proto: int = 0
@@ -2299,7 +2631,7 @@ Return state information for pickling.
 
 static PyObject *
 bytearray_reduce_ex_impl(PyByteArrayObject *self, int proto)
-/*[clinic end generated code: output=52eac33377197520 input=f129bc1a1aa151ee]*/
+/*[clinic end generated code: output=52eac33377197520 input=751718f477033a29]*/
 {
     return _common_reduce(self, proto);
 }
@@ -2315,7 +2647,7 @@ bytearray_sizeof_impl(PyByteArrayObject *self)
 /*[clinic end generated code: output=738abdd17951c427 input=e27320fd98a4bc5a]*/
 {
     size_t res = _PyObject_SIZE(Py_TYPE(self));
-    res += (size_t)self->ob_alloc * sizeof(char);
+    res += (size_t)FT_ATOMIC_LOAD_SSIZE_RELAXED(self->ob_alloc) * sizeof(char);
     return PyLong_FromSize_t(res);
 }
 
@@ -2349,40 +2681,34 @@ static PyMethodDef bytearray_methods[] = {
     BYTEARRAY_REDUCE_EX_METHODDEF
     BYTEARRAY_SIZEOF_METHODDEF
     BYTEARRAY_APPEND_METHODDEF
-    {"capitalize", stringlib_capitalize, METH_NOARGS,
-     _Py_capitalize__doc__},
-    STRINGLIB_CENTER_METHODDEF
+    {"capitalize", bytearray_capitalize, METH_NOARGS, _Py_capitalize__doc__},
+    {"center", _PyCFunction_CAST(bytearray_center), METH_FASTCALL,
+    stringlib_center__doc__},
     BYTEARRAY_CLEAR_METHODDEF
     BYTEARRAY_COPY_METHODDEF
     BYTEARRAY_COUNT_METHODDEF
     BYTEARRAY_DECODE_METHODDEF
     BYTEARRAY_ENDSWITH_METHODDEF
-    STRINGLIB_EXPANDTABS_METHODDEF
+    {"expandtabs", _PyCFunction_CAST(bytearray_expandtabs),
+    METH_FASTCALL|METH_KEYWORDS, stringlib_expandtabs__doc__},
     BYTEARRAY_EXTEND_METHODDEF
     BYTEARRAY_FIND_METHODDEF
     BYTEARRAY_FROMHEX_METHODDEF
     BYTEARRAY_HEX_METHODDEF
     BYTEARRAY_INDEX_METHODDEF
     BYTEARRAY_INSERT_METHODDEF
-    {"isalnum", stringlib_isalnum, METH_NOARGS,
-     _Py_isalnum__doc__},
-    {"isalpha", stringlib_isalpha, METH_NOARGS,
-     _Py_isalpha__doc__},
-    {"isascii", stringlib_isascii, METH_NOARGS,
-     _Py_isascii__doc__},
-    {"isdigit", stringlib_isdigit, METH_NOARGS,
-     _Py_isdigit__doc__},
-    {"islower", stringlib_islower, METH_NOARGS,
-     _Py_islower__doc__},
-    {"isspace", stringlib_isspace, METH_NOARGS,
-     _Py_isspace__doc__},
-    {"istitle", stringlib_istitle, METH_NOARGS,
-     _Py_istitle__doc__},
-    {"isupper", stringlib_isupper, METH_NOARGS,
-     _Py_isupper__doc__},
+    {"isalnum", bytearray_isalnum, METH_NOARGS, _Py_isalnum__doc__},
+    {"isalpha", bytearray_isalpha, METH_NOARGS, _Py_isalpha__doc__},
+    {"isascii", bytearray_isascii, METH_NOARGS, _Py_isascii__doc__},
+    {"isdigit", bytearray_isdigit, METH_NOARGS, _Py_isdigit__doc__},
+    {"islower", bytearray_islower, METH_NOARGS, _Py_islower__doc__},
+    {"isspace", bytearray_isspace, METH_NOARGS, _Py_isspace__doc__},
+    {"istitle", bytearray_istitle, METH_NOARGS, _Py_istitle__doc__},
+    {"isupper", bytearray_isupper, METH_NOARGS, _Py_isupper__doc__},
     BYTEARRAY_JOIN_METHODDEF
-    STRINGLIB_LJUST_METHODDEF
-    {"lower", stringlib_lower, METH_NOARGS, _Py_lower__doc__},
+    {"ljust", _PyCFunction_CAST(bytearray_ljust), METH_FASTCALL,
+    stringlib_ljust__doc__},
+    {"lower", bytearray_lower, METH_NOARGS, _Py_lower__doc__},
     BYTEARRAY_LSTRIP_METHODDEF
     BYTEARRAY_MAKETRANS_METHODDEF
     BYTEARRAY_PARTITION_METHODDEF
@@ -2395,7 +2721,8 @@ static PyMethodDef bytearray_methods[] = {
     BYTEARRAY_REVERSE_METHODDEF
     BYTEARRAY_RFIND_METHODDEF
     BYTEARRAY_RINDEX_METHODDEF
-    STRINGLIB_RJUST_METHODDEF
+    {"rjust", _PyCFunction_CAST(bytearray_rjust), METH_FASTCALL,
+    stringlib_rjust__doc__},
     BYTEARRAY_RPARTITION_METHODDEF
     BYTEARRAY_RSPLIT_METHODDEF
     BYTEARRAY_RSTRIP_METHODDEF
@@ -2403,23 +2730,33 @@ static PyMethodDef bytearray_methods[] = {
     BYTEARRAY_SPLITLINES_METHODDEF
     BYTEARRAY_STARTSWITH_METHODDEF
     BYTEARRAY_STRIP_METHODDEF
-    {"swapcase", stringlib_swapcase, METH_NOARGS,
-     _Py_swapcase__doc__},
-    {"title", stringlib_title, METH_NOARGS, _Py_title__doc__},
+    {"swapcase", bytearray_swapcase, METH_NOARGS, _Py_swapcase__doc__},
+    {"title", bytearray_title, METH_NOARGS, _Py_title__doc__},
     BYTEARRAY_TRANSLATE_METHODDEF
-    {"upper", stringlib_upper, METH_NOARGS, _Py_upper__doc__},
-    STRINGLIB_ZFILL_METHODDEF
+    {"upper", bytearray_upper, METH_NOARGS, _Py_upper__doc__},
+    {"zfill", bytearray_zfill, METH_O, stringlib_zfill__doc__},
     {NULL}
 };
 
 static PyObject *
-bytearray_mod(PyObject *v, PyObject *w)
+bytearray_mod_lock_held(PyObject *v, PyObject *w)
 {
+    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(v);
     if (!PyByteArray_Check(v))
         Py_RETURN_NOTIMPLEMENTED;
     return _PyBytes_FormatEx(PyByteArray_AS_STRING(v), PyByteArray_GET_SIZE(v), w, 1);
 }
 
+static PyObject *
+bytearray_mod(PyObject *v, PyObject *w)
+{
+    PyObject *ret;
+    Py_BEGIN_CRITICAL_SECTION(v);
+    ret = bytearray_mod_lock_held(v, w);
+    Py_END_CRITICAL_SECTION();
+    return ret;
+}
+
 static PyNumberMethods bytearray_as_number = {
     0,              /*nb_add*/
     0,              /*nb_subtract*/
index 03b5a8a516cc0960a2303a58a6e4470d68532b46..183ad13dd3448e17a6a37512138952041605f2e7 100644 (file)
@@ -7,6 +7,7 @@ preserve
 #  include "pycore_runtime.h"     // _Py_ID()
 #endif
 #include "pycore_abstract.h"      // _PyNumber_Index()
+#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
 #include "pycore_modsupport.h"    // _PyArg_UnpackKeywords()
 
 static int
@@ -147,7 +148,9 @@ bytearray_find(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
         goto exit;
     }
 skip_optional:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_find_impl((PyByteArrayObject *)self, sub, start, end);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -196,7 +199,9 @@ bytearray_count(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
         goto exit;
     }
 skip_optional:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_count_impl((PyByteArrayObject *)self, sub, start, end);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -235,7 +240,13 @@ bytearray_copy_impl(PyByteArrayObject *self);
 static PyObject *
 bytearray_copy(PyObject *self, PyObject *Py_UNUSED(ignored))
 {
-    return bytearray_copy_impl((PyByteArrayObject *)self);
+    PyObject *return_value = NULL;
+
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = bytearray_copy_impl((PyByteArrayObject *)self);
+    Py_END_CRITICAL_SECTION();
+
+    return return_value;
 }
 
 PyDoc_STRVAR(bytearray_index__doc__,
@@ -283,7 +294,9 @@ bytearray_index(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
         goto exit;
     }
 skip_optional:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_index_impl((PyByteArrayObject *)self, sub, start, end);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -334,7 +347,9 @@ bytearray_rfind(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
         goto exit;
     }
 skip_optional:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_rfind_impl((PyByteArrayObject *)self, sub, start, end);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -385,7 +400,9 @@ bytearray_rindex(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
         goto exit;
     }
 skip_optional:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_rindex_impl((PyByteArrayObject *)self, sub, start, end);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -436,7 +453,9 @@ bytearray_startswith(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
         goto exit;
     }
 skip_optional:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_startswith_impl((PyByteArrayObject *)self, subobj, start, end);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -487,7 +506,9 @@ bytearray_endswith(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
         goto exit;
     }
 skip_optional:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_endswith_impl((PyByteArrayObject *)self, subobj, start, end);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -518,7 +539,9 @@ bytearray_removeprefix(PyObject *self, PyObject *arg)
     if (PyObject_GetBuffer(arg, &prefix, PyBUF_SIMPLE) != 0) {
         goto exit;
     }
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_removeprefix_impl((PyByteArrayObject *)self, &prefix);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     /* Cleanup for prefix */
@@ -554,7 +577,9 @@ bytearray_removesuffix(PyObject *self, PyObject *arg)
     if (PyObject_GetBuffer(arg, &suffix, PyBUF_SIMPLE) != 0) {
         goto exit;
     }
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_removesuffix_impl((PyByteArrayObject *)self, &suffix);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     /* Cleanup for suffix */
@@ -668,7 +693,9 @@ bytearray_translate(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyO
     }
     deletechars = args[1];
 skip_optional_pos:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_translate_impl((PyByteArrayObject *)self, table, deletechars);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -775,7 +802,9 @@ bytearray_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
         count = ival;
     }
 skip_optional:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_replace_impl((PyByteArrayObject *)self, &old, &new, count);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     /* Cleanup for old */
@@ -872,7 +901,9 @@ bytearray_split(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObjec
         maxsplit = ival;
     }
 skip_optional_pos:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_split_impl((PyByteArrayObject *)self, sep, maxsplit);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -894,6 +925,21 @@ PyDoc_STRVAR(bytearray_partition__doc__,
 #define BYTEARRAY_PARTITION_METHODDEF    \
     {"partition", (PyCFunction)bytearray_partition, METH_O, bytearray_partition__doc__},
 
+static PyObject *
+bytearray_partition_impl(PyByteArrayObject *self, PyObject *sep);
+
+static PyObject *
+bytearray_partition(PyByteArrayObject *self, PyObject *sep)
+{
+    PyObject *return_value = NULL;
+
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = bytearray_partition_impl((PyByteArrayObject *)self, sep);
+    Py_END_CRITICAL_SECTION();
+
+    return return_value;
+}
+
 PyDoc_STRVAR(bytearray_rpartition__doc__,
 "rpartition($self, sep, /)\n"
 "--\n"
@@ -911,6 +957,21 @@ PyDoc_STRVAR(bytearray_rpartition__doc__,
 #define BYTEARRAY_RPARTITION_METHODDEF    \
     {"rpartition", (PyCFunction)bytearray_rpartition, METH_O, bytearray_rpartition__doc__},
 
+static PyObject *
+bytearray_rpartition_impl(PyByteArrayObject *self, PyObject *sep);
+
+static PyObject *
+bytearray_rpartition(PyByteArrayObject *self, PyObject *sep)
+{
+    PyObject *return_value = NULL;
+
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = bytearray_rpartition_impl((PyByteArrayObject *)self, sep);
+    Py_END_CRITICAL_SECTION();
+
+    return return_value;
+}
+
 PyDoc_STRVAR(bytearray_rsplit__doc__,
 "rsplit($self, /, sep=None, maxsplit=-1)\n"
 "--\n"
@@ -995,7 +1056,9 @@ bytearray_rsplit(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje
         maxsplit = ival;
     }
 skip_optional_pos:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_rsplit_impl((PyByteArrayObject *)self, sep, maxsplit);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -1016,7 +1079,13 @@ bytearray_reverse_impl(PyByteArrayObject *self);
 static PyObject *
 bytearray_reverse(PyObject *self, PyObject *Py_UNUSED(ignored))
 {
-    return bytearray_reverse_impl((PyByteArrayObject *)self);
+    PyObject *return_value = NULL;
+
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = bytearray_reverse_impl((PyByteArrayObject *)self);
+    Py_END_CRITICAL_SECTION();
+
+    return return_value;
 }
 
 PyDoc_STRVAR(bytearray_insert__doc__,
@@ -1061,7 +1130,9 @@ bytearray_insert(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
     if (!_getbytevalue(args[1], &item)) {
         goto exit;
     }
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_insert_impl((PyByteArrayObject *)self, index, item);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -1091,7 +1162,9 @@ bytearray_append(PyObject *self, PyObject *arg)
     if (!_getbytevalue(arg, &item)) {
         goto exit;
     }
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_append_impl((PyByteArrayObject *)self, item);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -1109,6 +1182,21 @@ PyDoc_STRVAR(bytearray_extend__doc__,
 #define BYTEARRAY_EXTEND_METHODDEF    \
     {"extend", (PyCFunction)bytearray_extend, METH_O, bytearray_extend__doc__},
 
+static PyObject *
+bytearray_extend_impl(PyByteArrayObject *self, PyObject *iterable_of_ints);
+
+static PyObject *
+bytearray_extend(PyByteArrayObject *self, PyObject *iterable_of_ints)
+{
+    PyObject *return_value = NULL;
+
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = bytearray_extend_impl((PyByteArrayObject *)self, iterable_of_ints);
+    Py_END_CRITICAL_SECTION();
+
+    return return_value;
+}
+
 PyDoc_STRVAR(bytearray_pop__doc__,
 "pop($self, index=-1, /)\n"
 "--\n"
@@ -1152,7 +1240,9 @@ bytearray_pop(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
         index = ival;
     }
 skip_optional:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_pop_impl((PyByteArrayObject *)self, index);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -1182,7 +1272,9 @@ bytearray_remove(PyObject *self, PyObject *arg)
     if (!_getbytevalue(arg, &value)) {
         goto exit;
     }
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_remove_impl((PyByteArrayObject *)self, value);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -1216,7 +1308,9 @@ bytearray_strip(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
     }
     bytes = args[0];
 skip_optional:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_strip_impl((PyByteArrayObject *)self, bytes);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -1250,7 +1344,9 @@ bytearray_lstrip(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
     }
     bytes = args[0];
 skip_optional:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_lstrip_impl((PyByteArrayObject *)self, bytes);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -1284,7 +1380,9 @@ bytearray_rstrip(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
     }
     bytes = args[0];
 skip_optional:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_rstrip_impl((PyByteArrayObject *)self, bytes);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -1386,7 +1484,9 @@ bytearray_decode(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje
         goto exit;
     }
 skip_optional_pos:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_decode_impl((PyByteArrayObject *)self, encoding, errors);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -1405,6 +1505,21 @@ PyDoc_STRVAR(bytearray_join__doc__,
 #define BYTEARRAY_JOIN_METHODDEF    \
     {"join", (PyCFunction)bytearray_join, METH_O, bytearray_join__doc__},
 
+static PyObject *
+bytearray_join_impl(PyByteArrayObject *self, PyObject *iterable_of_bytes);
+
+static PyObject *
+bytearray_join(PyByteArrayObject *self, PyObject *iterable_of_bytes)
+{
+    PyObject *return_value = NULL;
+
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = bytearray_join_impl((PyByteArrayObject *)self, iterable_of_bytes);
+    Py_END_CRITICAL_SECTION();
+
+    return return_value;
+}
+
 PyDoc_STRVAR(bytearray_splitlines__doc__,
 "splitlines($self, /, keepends=False)\n"
 "--\n"
@@ -1466,7 +1581,9 @@ bytearray_splitlines(PyObject *self, PyObject *const *args, Py_ssize_t nargs, Py
         goto exit;
     }
 skip_optional_pos:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_splitlines_impl((PyByteArrayObject *)self, keepends);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -1586,7 +1703,9 @@ bytearray_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject
         goto exit;
     }
 skip_optional_pos:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_hex_impl((PyByteArrayObject *)self, sep, bytes_per_sep);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -1607,7 +1726,13 @@ bytearray_reduce_impl(PyByteArrayObject *self);
 static PyObject *
 bytearray_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
 {
-    return bytearray_reduce_impl((PyByteArrayObject *)self);
+    PyObject *return_value = NULL;
+
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = bytearray_reduce_impl((PyByteArrayObject *)self);
+    Py_END_CRITICAL_SECTION();
+
+    return return_value;
 }
 
 PyDoc_STRVAR(bytearray_reduce_ex__doc__,
@@ -1639,7 +1764,9 @@ bytearray_reduce_ex(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
         goto exit;
     }
 skip_optional:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = bytearray_reduce_ex_impl((PyByteArrayObject *)self, proto);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -1662,4 +1789,4 @@ bytearray_sizeof(PyObject *self, PyObject *Py_UNUSED(ignored))
 {
     return bytearray_sizeof_impl((PyByteArrayObject *)self);
 }
-/*[clinic end generated code: output=41bb67a8a181e733 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=5e33422343b47af9 input=a9049054013a1b77]*/