44#include "Python.h"
55#include "pycore_abstract.h" // _PyNumber_Index()
66#include "pycore_long.h" // _PyLong_IsNegative()
7+ #include "pycore_object.h" // _Py_TryIncrefCompare(), FT_ATOMIC_*()
8+ #include "pycore_critical_section.h"
79
810
11+ static inline PyObject *
12+ member_get_object (const char * addr , const char * obj_addr , PyMemberDef * l )
13+ {
14+ PyObject * v = FT_ATOMIC_LOAD_PTR (* (PyObject * * ) addr );
15+ if (v == NULL ) {
16+ PyErr_Format (PyExc_AttributeError ,
17+ "'%T' object has no attribute '%s'" ,
18+ (PyObject * )obj_addr , l -> name );
19+ }
20+ return v ;
21+ }
22+
923PyObject *
1024PyMember_GetOne (const char * obj_addr , PyMemberDef * l )
1125{
@@ -75,15 +89,19 @@ PyMember_GetOne(const char *obj_addr, PyMemberDef *l)
7589 Py_INCREF (v );
7690 break ;
7791 case Py_T_OBJECT_EX :
78- v = * (PyObject * * )addr ;
79- if (v == NULL ) {
80- PyObject * obj = (PyObject * )obj_addr ;
81- PyTypeObject * tp = Py_TYPE (obj );
82- PyErr_Format (PyExc_AttributeError ,
83- "'%.200s' object has no attribute '%s'" ,
84- tp -> tp_name , l -> name );
85- }
92+ v = member_get_object (addr , obj_addr , l );
93+ #ifndef Py_GIL_DISABLED
8694 Py_XINCREF (v );
95+ #else
96+ if (v != NULL ) {
97+ if (!_Py_TryIncrefCompare ((PyObject * * ) addr , v )) {
98+ Py_BEGIN_CRITICAL_SECTION ((PyObject * ) obj_addr );
99+ v = member_get_object (addr , obj_addr , l );
100+ Py_XINCREF (v );
101+ Py_END_CRITICAL_SECTION ();
102+ }
103+ }
104+ #endif
87105 break ;
88106 case Py_T_LONGLONG :
89107 v = PyLong_FromLongLong (* (long long * )addr );
@@ -92,6 +110,7 @@ PyMember_GetOne(const char *obj_addr, PyMemberDef *l)
92110 v = PyLong_FromUnsignedLongLong (* (unsigned long long * )addr );
93111 break ;
94112 case _Py_T_NONE :
113+ // doesn't require free-threading code path
95114 v = Py_NewRef (Py_None );
96115 break ;
97116 default :
@@ -118,6 +137,9 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
118137 return -1 ;
119138 }
120139
140+ #ifdef Py_GIL_DISABLED
141+ PyObject * obj = (PyObject * ) addr ;
142+ #endif
121143 addr += l -> offset ;
122144
123145 if ((l -> flags & Py_READONLY ))
@@ -281,8 +303,10 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
281303 break ;
282304 case _Py_T_OBJECT :
283305 case Py_T_OBJECT_EX :
306+ Py_BEGIN_CRITICAL_SECTION (obj );
284307 oldv = * (PyObject * * )addr ;
285- * (PyObject * * )addr = Py_XNewRef (v );
308+ FT_ATOMIC_STORE_PTR_RELEASE (* (PyObject * * )addr , Py_XNewRef (v ));
309+ Py_END_CRITICAL_SECTION ();
286310 Py_XDECREF (oldv );
287311 break ;
288312 case Py_T_CHAR : {
0 commit comments