@@ -69,6 +69,16 @@ typedef struct {
6969 PyObject * str_iter ;
7070} array_state ;
7171
72+ static inline Py_ssize_t Pyarrayobject_GET_SIZE (PyObject * op ) {
73+ arrayobject * ao = (arrayobject * )op ;
74+ #ifdef Py_GIL_DISABLED
75+ return _Py_atomic_load_ssize_relaxed (& (_PyVarObject_CAST (ao )-> ob_size ));
76+ #else
77+ return Py_SIZE (ao );
78+ #endif
79+ }
80+ #define Pyarrayobject_GET_SIZE (op ) Pyarrayobject_GET_SIZE(_PyObject_CAST(op))
81+
7282/* Forward declaration. */
7383static PyObject * array_array_frombytes (PyObject * self , PyObject * bytes );
7484
@@ -137,7 +147,8 @@ array_resize(arrayobject *self, Py_ssize_t newsize)
137147 char * items ;
138148 size_t _new_size ;
139149
140- if (self -> ob_exports > 0 && newsize != Py_SIZE (self )) {
150+ if (FT_ATOMIC_LOAD_SSIZE_RELAXED (self -> ob_exports ) > 0 &&
151+ newsize != Py_SIZE (self )) {
141152 PyErr_SetString (PyExc_BufferError ,
142153 "cannot resize an array that is exporting buffers" );
143154 return -1 ;
@@ -728,7 +739,7 @@ array_dealloc(arrayobject *op)
728739 PyTypeObject * tp = Py_TYPE (op );
729740 PyObject_GC_UnTrack (op );
730741
731- if (op -> ob_exports > 0 ) {
742+ if (FT_ATOMIC_LOAD_SSIZE_RELAXED ( op -> ob_exports ) > 0 ) {
732743 PyErr_SetString (PyExc_SystemError ,
733744 "deallocated array object has exported buffers" );
734745 PyErr_Print ();
@@ -868,11 +879,7 @@ array_richcompare(PyObject *v, PyObject *w, int op)
868879static Py_ssize_t
869880array_length (arrayobject * a )
870881{
871- Py_ssize_t ret ;
872- Py_BEGIN_CRITICAL_SECTION (a ); // overkill but lets not tempt tsan
873- ret = Py_SIZE (a );
874- Py_END_CRITICAL_SECTION ();
875- return ret ;
882+ return Pyarrayobject_GET_SIZE (a );
876883}
877884
878885static PyObject *
@@ -1074,7 +1081,7 @@ array_del_slice(arrayobject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
10741081 /* Issue #4509: If the array has exported buffers and the slice
10751082 assignment would change the size of the array, fail early to make
10761083 sure we don't modify it. */
1077- if (d != 0 && a -> ob_exports > 0 ) {
1084+ if (d != 0 && FT_ATOMIC_LOAD_SSIZE_RELAXED ( a -> ob_exports ) > 0 ) {
10781085 PyErr_SetString (PyExc_BufferError ,
10791086 "cannot resize an array that is exporting buffers" );
10801087 return -1 ;
@@ -2707,7 +2714,8 @@ array_ass_subscr_lock_held(arrayobject* self, PyObject* item, PyObject* value)
27072714 /* Issue #4509: If the array has exported buffers and the slice
27082715 assignment would change the size of the array, fail early to make
27092716 sure we don't modify it. */
2710- if ((needed == 0 || slicelength != needed ) && self -> ob_exports > 0 ) {
2717+ if ((needed == 0 || slicelength != needed ) &&
2718+ FT_ATOMIC_LOAD_SSIZE_RELAXED (self -> ob_exports ) > 0 ) {
27112719 PyErr_SetString (PyExc_BufferError ,
27122720 "cannot resize an array that is exporting buffers" );
27132721 return -1 ;
@@ -2809,6 +2817,7 @@ static const void *emptybuf = "";
28092817static int
28102818array_buffer_getbuf_lock_held (arrayobject * self , Py_buffer * view , int flags )
28112819{
2820+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED (self );
28122821 if (view == NULL ) {
28132822 PyErr_SetString (PyExc_BufferError ,
28142823 "array_buffer_getbuf: view==NULL argument is obsolete" );
@@ -2842,7 +2851,11 @@ array_buffer_getbuf_lock_held(arrayobject *self, Py_buffer *view, int flags)
28422851#endif
28432852 }
28442853
2854+ #ifdef Py_GIL_DISABLED
2855+ _Py_atomic_add_ssize (& self -> ob_exports , 1 );
2856+ #else
28452857 self -> ob_exports ++ ;
2858+ #endif
28462859 return 0 ;
28472860}
28482861
@@ -2859,10 +2872,12 @@ array_buffer_getbuf(arrayobject *self, Py_buffer *view, int flags)
28592872static void
28602873array_buffer_relbuf (arrayobject * self , Py_buffer * view )
28612874{
2862- Py_BEGIN_CRITICAL_SECTION (self );
2875+ #ifdef Py_GIL_DISABLED
2876+ assert (_Py_atomic_add_ssize (& self -> ob_exports , -1 ) >= 1 );
2877+ #else
28632878 self -> ob_exports -- ;
28642879 assert (self -> ob_exports >= 0 );
2865- Py_END_CRITICAL_SECTION ();
2880+ #endif
28662881}
28672882
28682883static PyObject *
@@ -3315,13 +3330,7 @@ array_arrayiterator___setstate__(arrayiterobject *self, PyObject *state)
33153330 index = -1 ;
33163331 }
33173332 else {
3318- Py_ssize_t size ;
3319- #ifdef Py_GIL_DISABLED
3320- size = _Py_atomic_load_ssize_relaxed (
3321- & (_PyVarObject_CAST (self -> ao )-> ob_size ));
3322- #else
3323- size = Py_SIZE (self -> ao );
3324- #endif
3333+ Py_ssize_t size = Pyarrayobject_GET_SIZE (self -> ao );
33253334 if (index > size ) {
33263335 index = size ; /* iterator at end */
33273336 }
0 commit comments