From f513a3c1d321df52e54135b0d1dc5432a883c2cd Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 5 Nov 2024 08:43:56 -0700 Subject: [PATCH 1/9] _PyCrossInterpreterData -> _PyXIData_t --- Include/internal/pycore_crossinterp.h | 26 +++++++-------- Modules/_interpchannelsmodule.c | 44 +++++++++++------------- Modules/_interpqueuesmodule.c | 30 ++++++++--------- Modules/_interpreters_common.h | 2 +- Modules/_interpretersmodule.c | 9 +++-- Modules/_testinternalcapi.c | 8 ++--- Python/crossinterp.c | 48 +++++++++++++-------------- Python/crossinterp_data_lookup.h | 41 ++++++++++------------- 8 files changed, 94 insertions(+), 114 deletions(-) diff --git a/Include/internal/pycore_crossinterp.h b/Include/internal/pycore_crossinterp.h index 2dd165eae74850..c35d3b1cf79420 100644 --- a/Include/internal/pycore_crossinterp.h +++ b/Include/internal/pycore_crossinterp.h @@ -38,11 +38,11 @@ extern int _Py_CallInInterpreterAndRawFree( /* cross-interpreter data */ /**************************/ -typedef struct _xid _PyCrossInterpreterData; -typedef PyObject *(*xid_newobjectfunc)(_PyCrossInterpreterData *); +typedef struct _xid _PyXIData_t; +typedef PyObject *(*xid_newobjectfunc)(_PyXIData_t *); typedef void (*xid_freefunc)(void *); -// _PyCrossInterpreterData is similar to Py_buffer as an effectively +// _PyXIData_t is similar to Py_buffer as an effectively // opaque struct that holds data outside the object machinery. This // is necessary to pass safely between interpreters in the same process. struct _xid { @@ -84,8 +84,8 @@ struct _xid { xid_freefunc free; }; -PyAPI_FUNC(_PyCrossInterpreterData *) _PyCrossInterpreterData_New(void); -PyAPI_FUNC(void) _PyCrossInterpreterData_Free(_PyCrossInterpreterData *data); +PyAPI_FUNC(_PyXIData_t *) _PyCrossInterpreterData_New(void); +PyAPI_FUNC(void) _PyCrossInterpreterData_Free(_PyXIData_t *data); #define _PyCrossInterpreterData_DATA(DATA) ((DATA)->data) #define _PyCrossInterpreterData_OBJ(DATA) ((DATA)->obj) @@ -96,15 +96,15 @@ PyAPI_FUNC(void) _PyCrossInterpreterData_Free(_PyCrossInterpreterData *data); /* defining cross-interpreter data */ PyAPI_FUNC(void) _PyCrossInterpreterData_Init( - _PyCrossInterpreterData *data, + _PyXIData_t *data, PyInterpreterState *interp, void *shared, PyObject *obj, xid_newobjectfunc new_object); PyAPI_FUNC(int) _PyCrossInterpreterData_InitWithSize( - _PyCrossInterpreterData *, + _PyXIData_t *, PyInterpreterState *interp, const size_t, PyObject *, xid_newobjectfunc); PyAPI_FUNC(void) _PyCrossInterpreterData_Clear( - PyInterpreterState *, _PyCrossInterpreterData *); + PyInterpreterState *, _PyXIData_t *); // Normally the Init* functions are sufficient. The only time // additional initialization might be needed is to set the "free" func, @@ -129,10 +129,10 @@ PyAPI_FUNC(void) _PyCrossInterpreterData_Clear( /* using cross-interpreter data */ PyAPI_FUNC(int) _PyObject_CheckCrossInterpreterData(PyObject *); -PyAPI_FUNC(int) _PyObject_GetCrossInterpreterData(PyObject *, _PyCrossInterpreterData *); -PyAPI_FUNC(PyObject *) _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *); -PyAPI_FUNC(int) _PyCrossInterpreterData_Release(_PyCrossInterpreterData *); -PyAPI_FUNC(int) _PyCrossInterpreterData_ReleaseAndRawFree(_PyCrossInterpreterData *); +PyAPI_FUNC(int) _PyObject_GetCrossInterpreterData(PyObject *, _PyXIData_t *); +PyAPI_FUNC(PyObject *) _PyCrossInterpreterData_NewObject(_PyXIData_t *); +PyAPI_FUNC(int) _PyCrossInterpreterData_Release(_PyXIData_t *); +PyAPI_FUNC(int) _PyCrossInterpreterData_ReleaseAndRawFree(_PyXIData_t *); /* cross-interpreter data registry */ @@ -142,7 +142,7 @@ PyAPI_FUNC(int) _PyCrossInterpreterData_ReleaseAndRawFree(_PyCrossInterpreterDat // crossinterpdatafunc. It would be simpler and more efficient. typedef int (*crossinterpdatafunc)(PyThreadState *tstate, PyObject *, - _PyCrossInterpreterData *); + _PyXIData_t *); struct _xidregitem; diff --git a/Modules/_interpchannelsmodule.c b/Modules/_interpchannelsmodule.c index 8e6b21db76e01c..86bbc67ffc0796 100644 --- a/Modules/_interpchannelsmodule.c +++ b/Modules/_interpchannelsmodule.c @@ -6,7 +6,7 @@ #endif #include "Python.h" -#include "pycore_crossinterp.h" // struct _xid +#include "pycore_crossinterp.h" // _PyXIData_t #include "pycore_interp.h" // _PyInterpreterState_LookUpID() #include "pycore_pystate.h" // _PyInterpreterState_GetIDObject() @@ -59,7 +59,7 @@ _globals (static struct globals): first (struct _channelitem *): next (struct _channelitem *): ... - data (_PyCrossInterpreterData *): + data (_PyXIData_t *): data (void *) obj (PyObject *) interpid (int64_t) @@ -80,7 +80,7 @@ The above state includes the following allocations by the module: * 1 struct _channelqueue * for each item in each channel: * 1 struct _channelitem - * 1 _PyCrossInterpreterData + * 1 _PyXIData_t The only objects in that global state are the references held by each channel's queue, which are safely managed via the _PyCrossInterpreterData_*() @@ -102,7 +102,7 @@ API.. The module does not create any objects that are shared globally. #define XID_FREE 2 static int -_release_xid_data(_PyCrossInterpreterData *data, int flags) +_release_xid_data(_PyXIData_t *data, int flags) { int ignoreexc = flags & XID_IGNORE_EXC; PyObject *exc; @@ -519,7 +519,7 @@ typedef struct _channelitem { This is necessary because item->data might be NULL, meaning the interpreter has been destroyed. */ int64_t interpid; - _PyCrossInterpreterData *data; + _PyXIData_t *data; _waiting_t *waiting; int unboundop; struct _channelitem *next; @@ -533,7 +533,7 @@ _channelitem_ID(_channelitem *item) static void _channelitem_init(_channelitem *item, - int64_t interpid, _PyCrossInterpreterData *data, + int64_t interpid, _PyXIData_t *data, _waiting_t *waiting, int unboundop) { if (interpid < 0) { @@ -580,7 +580,7 @@ _channelitem_clear(_channelitem *item) } static _channelitem * -_channelitem_new(int64_t interpid, _PyCrossInterpreterData *data, +_channelitem_new(int64_t interpid, _PyXIData_t *data, _waiting_t *waiting, int unboundop) { _channelitem *item = GLOBAL_MALLOC(_channelitem); @@ -611,7 +611,7 @@ _channelitem_free_all(_channelitem *item) static void _channelitem_popped(_channelitem *item, - _PyCrossInterpreterData **p_data, _waiting_t **p_waiting, + _PyXIData_t **p_data, _waiting_t **p_waiting, int *p_unboundop) { assert(item->waiting == NULL || item->waiting->status == WAITING_ACQUIRED); @@ -691,7 +691,7 @@ _channelqueue_free(_channelqueue *queue) static int _channelqueue_put(_channelqueue *queue, - int64_t interpid, _PyCrossInterpreterData *data, + int64_t interpid, _PyXIData_t *data, _waiting_t *waiting, int unboundop) { _channelitem *item = _channelitem_new(interpid, data, waiting, unboundop); @@ -717,7 +717,7 @@ _channelqueue_put(_channelqueue *queue, static int _channelqueue_get(_channelqueue *queue, - _PyCrossInterpreterData **p_data, _waiting_t **p_waiting, + _PyXIData_t **p_data, _waiting_t **p_waiting, int *p_unboundop) { _channelitem *item = queue->first; @@ -769,7 +769,7 @@ _channelqueue_find(_channelqueue *queue, _channelitem_id_t itemid, static void _channelqueue_remove(_channelqueue *queue, _channelitem_id_t itemid, - _PyCrossInterpreterData **p_data, _waiting_t **p_waiting) + _PyXIData_t **p_data, _waiting_t **p_waiting) { _channelitem *prev = NULL; _channelitem *item = NULL; @@ -1128,8 +1128,7 @@ _channel_free(_channel_state *chan) static int _channel_add(_channel_state *chan, int64_t interpid, - _PyCrossInterpreterData *data, _waiting_t *waiting, - int unboundop) + _PyXIData_t *data, _waiting_t *waiting, int unboundop) { int res = -1; PyThread_acquire_lock(chan->mutex, WAIT_LOCK); @@ -1156,8 +1155,7 @@ _channel_add(_channel_state *chan, int64_t interpid, static int _channel_next(_channel_state *chan, int64_t interpid, - _PyCrossInterpreterData **p_data, _waiting_t **p_waiting, - int *p_unboundop) + _PyXIData_t **p_data, _waiting_t **p_waiting, int *p_unboundop) { int err = 0; PyThread_acquire_lock(chan->mutex, WAIT_LOCK); @@ -1193,7 +1191,7 @@ _channel_next(_channel_state *chan, int64_t interpid, static void _channel_remove(_channel_state *chan, _channelitem_id_t itemid) { - _PyCrossInterpreterData *data = NULL; + _PyXIData_t *data = NULL; _waiting_t *waiting = NULL; PyThread_acquire_lock(chan->mutex, WAIT_LOCK); @@ -1776,7 +1774,7 @@ channel_send(_channels *channels, int64_t cid, PyObject *obj, } // Convert the object to cross-interpreter data. - _PyCrossInterpreterData *data = GLOBAL_MALLOC(_PyCrossInterpreterData); + _PyXIData_t *data = GLOBAL_MALLOC(_PyXIData_t); if (data == NULL) { PyThread_release_lock(mutex); return -1; @@ -1904,7 +1902,7 @@ channel_recv(_channels *channels, int64_t cid, PyObject **res, int *p_unboundop) // Past this point we are responsible for releasing the mutex. // Pop off the next item from the channel. - _PyCrossInterpreterData *data = NULL; + _PyXIData_t *data = NULL; _waiting_t *waiting = NULL; err = _channel_next(chan, interpid, &data, &waiting, p_unboundop); PyThread_release_lock(mutex); @@ -2545,7 +2543,7 @@ struct _channelid_xid { }; static PyObject * -_channelid_from_xid(_PyCrossInterpreterData *data) +_channelid_from_xid(_PyXIData_t *data) { struct _channelid_xid *xid = \ (struct _channelid_xid *)_PyCrossInterpreterData_DATA(data); @@ -2594,8 +2592,7 @@ _channelid_from_xid(_PyCrossInterpreterData *data) } static int -_channelid_shared(PyThreadState *tstate, PyObject *obj, - _PyCrossInterpreterData *data) +_channelid_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) { if (_PyCrossInterpreterData_InitWithSize( data, tstate->interp, sizeof(struct _channelid_xid), obj, @@ -2745,7 +2742,7 @@ _get_current_channelend_type(int end) } static PyObject * -_channelend_from_xid(_PyCrossInterpreterData *data) +_channelend_from_xid(_PyXIData_t *data) { channelid *cidobj = (channelid *)_channelid_from_xid(data); if (cidobj == NULL) { @@ -2762,8 +2759,7 @@ _channelend_from_xid(_PyCrossInterpreterData *data) } static int -_channelend_shared(PyThreadState *tstate, PyObject *obj, - _PyCrossInterpreterData *data) +_channelend_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) { PyObject *cidobj = PyObject_GetAttrString(obj, "_id"); if (cidobj == NULL) { diff --git a/Modules/_interpqueuesmodule.c b/Modules/_interpqueuesmodule.c index 297a1763a98ce6..55b8c4cbb70cdd 100644 --- a/Modules/_interpqueuesmodule.c +++ b/Modules/_interpqueuesmodule.c @@ -6,7 +6,7 @@ #endif #include "Python.h" -#include "pycore_crossinterp.h" // struct _xid +#include "pycore_crossinterp.h" // _PyXIData_t #define REGISTERS_HEAP_TYPES #define HAS_UNBOUND_ITEMS @@ -30,7 +30,7 @@ #define XID_FREE 2 static int -_release_xid_data(_PyCrossInterpreterData *data, int flags) +_release_xid_data(_PyXIData_t *data, int flags) { int ignoreexc = flags & XID_IGNORE_EXC; PyObject *exc; @@ -400,7 +400,7 @@ typedef struct _queueitem { This is necessary because item->data might be NULL, meaning the interpreter has been destroyed. */ int64_t interpid; - _PyCrossInterpreterData *data; + _PyXIData_t *data; int fmt; int unboundop; struct _queueitem *next; @@ -408,8 +408,7 @@ typedef struct _queueitem { static void _queueitem_init(_queueitem *item, - int64_t interpid, _PyCrossInterpreterData *data, - int fmt, int unboundop) + int64_t interpid, _PyXIData_t *data, int fmt, int unboundop) { if (interpid < 0) { interpid = _get_interpid(data); @@ -447,8 +446,7 @@ _queueitem_clear(_queueitem *item) } static _queueitem * -_queueitem_new(int64_t interpid, _PyCrossInterpreterData *data, - int fmt, int unboundop) +_queueitem_new(int64_t interpid, _PyXIData_t *data, int fmt, int unboundop) { _queueitem *item = GLOBAL_MALLOC(_queueitem); if (item == NULL) { @@ -478,7 +476,7 @@ _queueitem_free_all(_queueitem *item) static void _queueitem_popped(_queueitem *item, - _PyCrossInterpreterData **p_data, int *p_fmt, int *p_unboundop) + _PyXIData_t **p_data, int *p_fmt, int *p_unboundop) { *p_data = item->data; *p_fmt = item->fmt; @@ -633,7 +631,7 @@ _queue_unlock(_queue *queue) } static int -_queue_add(_queue *queue, int64_t interpid, _PyCrossInterpreterData *data, +_queue_add(_queue *queue, int64_t interpid, _PyXIData_t *data, int fmt, int unboundop) { int err = _queue_lock(queue); @@ -671,7 +669,7 @@ _queue_add(_queue *queue, int64_t interpid, _PyCrossInterpreterData *data, static int _queue_next(_queue *queue, - _PyCrossInterpreterData **p_data, int *p_fmt, int *p_unboundop) + _PyXIData_t **p_data, int *p_fmt, int *p_unboundop) { int err = _queue_lock(queue); if (err < 0) { @@ -1138,7 +1136,7 @@ queue_put(_queues *queues, int64_t qid, PyObject *obj, int fmt, int unboundop) assert(queue != NULL); // Convert the object to cross-interpreter data. - _PyCrossInterpreterData *data = GLOBAL_MALLOC(_PyCrossInterpreterData); + _PyXIData_t *data = GLOBAL_MALLOC(_PyXIData_t); if (data == NULL) { _queue_unmark_waiter(queue, queues->mutex); return -1; @@ -1184,7 +1182,7 @@ queue_get(_queues *queues, int64_t qid, assert(queue != NULL); // Pop off the next item from the queue. - _PyCrossInterpreterData *data = NULL; + _PyXIData_t *data = NULL; err = _queue_next(queue, &data, p_fmt, p_unboundop); _queue_unmark_waiter(queue, queues->mutex); if (err != 0) { @@ -1258,8 +1256,7 @@ queue_get_count(_queues *queues, int64_t qid, Py_ssize_t *p_count) /* external Queue objects ***************************************************/ -static int _queueobj_shared(PyThreadState *, - PyObject *, _PyCrossInterpreterData *); +static int _queueobj_shared(PyThreadState *, PyObject *, _PyXIData_t *); static int set_external_queue_type(module_state *state, PyTypeObject *queue_type) @@ -1339,7 +1336,7 @@ _queueid_xid_free(void *data) } static PyObject * -_queueobj_from_xid(_PyCrossInterpreterData *data) +_queueobj_from_xid(_PyXIData_t *data) { int64_t qid = *(int64_t *)_PyCrossInterpreterData_DATA(data); PyObject *qidobj = PyLong_FromLongLong(qid); @@ -1367,8 +1364,7 @@ _queueobj_from_xid(_PyCrossInterpreterData *data) } static int -_queueobj_shared(PyThreadState *tstate, PyObject *queueobj, - _PyCrossInterpreterData *data) +_queueobj_shared(PyThreadState *tstate, PyObject *queueobj, _PyXIData_t *data) { PyObject *qidobj = PyObject_GetAttrString(queueobj, "_id"); if (qidobj == NULL) { diff --git a/Modules/_interpreters_common.h b/Modules/_interpreters_common.h index 0d2e0c9efd3837..5b281c4f496a09 100644 --- a/Modules/_interpreters_common.h +++ b/Modules/_interpreters_common.h @@ -22,7 +22,7 @@ clear_xid_class(PyTypeObject *cls) static inline int64_t -_get_interpid(_PyCrossInterpreterData *data) +_get_interpid(_PyXIData_t *data) { int64_t interpid; if (data != NULL) { diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index 63f2bb38768511..c3924d24dbd684 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -7,7 +7,7 @@ #include "Python.h" #include "pycore_abstract.h" // _PyIndex_Check() -#include "pycore_crossinterp.h" // struct _xid +#include "pycore_crossinterp.h" // _PyXIData_t #include "pycore_interp.h" // _PyInterpreterState_IDIncref() #include "pycore_initconfig.h" // _PyErr_SetFromPyStatus() #include "pycore_modsupport.h" // _PyArg_BadArgument() @@ -84,7 +84,7 @@ typedef struct { } XIBufferViewObject; static PyObject * -xibufferview_from_xid(PyTypeObject *cls, _PyCrossInterpreterData *data) +xibufferview_from_xid(PyTypeObject *cls, _PyXIData_t *data) { assert(_PyCrossInterpreterData_DATA(data) != NULL); assert(_PyCrossInterpreterData_OBJ(data) == NULL); @@ -154,7 +154,7 @@ static PyType_Spec XIBufferViewType_spec = { static PyTypeObject * _get_current_xibufferview_type(void); static PyObject * -_memoryview_from_xid(_PyCrossInterpreterData *data) +_memoryview_from_xid(_PyXIData_t *data) { PyTypeObject *cls = _get_current_xibufferview_type(); if (cls == NULL) { @@ -168,8 +168,7 @@ _memoryview_from_xid(_PyCrossInterpreterData *data) } static int -_memoryview_shared(PyThreadState *tstate, PyObject *obj, - _PyCrossInterpreterData *data) +_memoryview_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) { Py_buffer *view = PyMem_RawMalloc(sizeof(Py_buffer)); if (view == NULL) { diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index eb98b433c6c6af..69559bf04ef4c1 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -1786,8 +1786,7 @@ interpreter_refcount_linked(PyObject *self, PyObject *idobj) static void _xid_capsule_destructor(PyObject *capsule) { - _PyCrossInterpreterData *data = \ - (_PyCrossInterpreterData *)PyCapsule_GetPointer(capsule, NULL); + _PyXIData_t *data = (_PyXIData_t *)PyCapsule_GetPointer(capsule, NULL); if (data != NULL) { assert(_PyCrossInterpreterData_Release(data) == 0); _PyCrossInterpreterData_Free(data); @@ -1802,7 +1801,7 @@ get_crossinterp_data(PyObject *self, PyObject *args) return NULL; } - _PyCrossInterpreterData *data = _PyCrossInterpreterData_New(); + _PyXIData_t *data = _PyCrossInterpreterData_New(); if (data == NULL) { return NULL; } @@ -1826,8 +1825,7 @@ restore_crossinterp_data(PyObject *self, PyObject *args) return NULL; } - _PyCrossInterpreterData *data = \ - (_PyCrossInterpreterData *)PyCapsule_GetPointer(capsule, NULL); + _PyXIData_t *data = (_PyXIData_t *)PyCapsule_GetPointer(capsule, NULL); if (data == NULL) { return NULL; } diff --git a/Python/crossinterp.c b/Python/crossinterp.c index 0aca322d987dba..7e7d7945e77195 100644 --- a/Python/crossinterp.c +++ b/Python/crossinterp.c @@ -3,7 +3,7 @@ #include "Python.h" #include "pycore_ceval.h" // _Py_simple_func -#include "pycore_crossinterp.h" // struct _xid +#include "pycore_crossinterp.h" // _PyXIData_t #include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_namespace.h" //_PyNamespace_New() #include "pycore_pyerrors.h" // _PyErr_Clear() @@ -71,11 +71,10 @@ static crossinterpdatafunc lookup_getdata(PyInterpreterState *, PyObject *); /* lifecycle */ -_PyCrossInterpreterData * +_PyXIData_t * _PyCrossInterpreterData_New(void) { - _PyCrossInterpreterData *xid = PyMem_RawMalloc( - sizeof(_PyCrossInterpreterData)); + _PyXIData_t *xid = PyMem_RawMalloc(sizeof(_PyXIData_t)); if (xid == NULL) { PyErr_NoMemory(); } @@ -83,7 +82,7 @@ _PyCrossInterpreterData_New(void) } void -_PyCrossInterpreterData_Free(_PyCrossInterpreterData *xid) +_PyCrossInterpreterData_Free(_PyXIData_t *xid) { PyInterpreterState *interp = PyInterpreterState_Get(); _PyCrossInterpreterData_Clear(interp, xid); @@ -94,20 +93,20 @@ _PyCrossInterpreterData_Free(_PyCrossInterpreterData *xid) /* defining cross-interpreter data */ static inline void -_xidata_init(_PyCrossInterpreterData *data) +_xidata_init(_PyXIData_t *data) { // If the value is being reused // then _xidata_clear() should have been called already. assert(data->data == NULL); assert(data->obj == NULL); - *data = (_PyCrossInterpreterData){0}; + *data = (_PyXIData_t){0}; _PyCrossInterpreterData_INTERPID(data) = -1; } static inline void -_xidata_clear(_PyCrossInterpreterData *data) +_xidata_clear(_PyXIData_t *data) { - // _PyCrossInterpreterData only has two members that need to be + // _PyXIData_t only has two members that need to be // cleaned up, if set: "data" must be freed and "obj" must be decref'ed. // In both cases the original (owning) interpreter must be used, // which is the caller's responsibility to ensure. @@ -121,7 +120,7 @@ _xidata_clear(_PyCrossInterpreterData *data) } void -_PyCrossInterpreterData_Init(_PyCrossInterpreterData *data, +_PyCrossInterpreterData_Init(_PyXIData_t *data, PyInterpreterState *interp, void *shared, PyObject *obj, xid_newobjectfunc new_object) @@ -145,7 +144,7 @@ _PyCrossInterpreterData_Init(_PyCrossInterpreterData *data, } int -_PyCrossInterpreterData_InitWithSize(_PyCrossInterpreterData *data, +_PyCrossInterpreterData_InitWithSize(_PyXIData_t *data, PyInterpreterState *interp, const size_t size, PyObject *obj, xid_newobjectfunc new_object) @@ -164,8 +163,7 @@ _PyCrossInterpreterData_InitWithSize(_PyCrossInterpreterData *data, } void -_PyCrossInterpreterData_Clear(PyInterpreterState *interp, - _PyCrossInterpreterData *data) +_PyCrossInterpreterData_Clear(PyInterpreterState *interp, _PyXIData_t *data) { assert(data != NULL); // This must be called in the owning interpreter. @@ -179,7 +177,7 @@ _PyCrossInterpreterData_Clear(PyInterpreterState *interp, /* using cross-interpreter data */ static int -_check_xidata(PyThreadState *tstate, _PyCrossInterpreterData *data) +_check_xidata(PyThreadState *tstate, _PyXIData_t *data) { // data->data can be anything, including NULL, so we don't check it. @@ -235,13 +233,13 @@ _PyObject_CheckCrossInterpreterData(PyObject *obj) } int -_PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data) +_PyObject_GetCrossInterpreterData(PyObject *obj, _PyXIData_t *data) { PyThreadState *tstate = PyThreadState_Get(); PyInterpreterState *interp = tstate->interp; // Reset data before re-populating. - *data = (_PyCrossInterpreterData){0}; + *data = (_PyXIData_t){0}; _PyCrossInterpreterData_INTERPID(data) = -1; // Call the "getdata" func for the object. @@ -271,7 +269,7 @@ _PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data) } PyObject * -_PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data) +_PyCrossInterpreterData_NewObject(_PyXIData_t *data) { return data->new_object(data); } @@ -279,12 +277,12 @@ _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data) static int _call_clear_xidata(void *data) { - _xidata_clear((_PyCrossInterpreterData *)data); + _xidata_clear((_PyXIData_t *)data); return 0; } static int -_xidata_release(_PyCrossInterpreterData *data, int rawfree) +_xidata_release(_PyXIData_t *data, int rawfree) { if ((data->data == NULL || data->free == NULL) && data->obj == NULL) { // Nothing to release! @@ -321,13 +319,13 @@ _xidata_release(_PyCrossInterpreterData *data, int rawfree) } int -_PyCrossInterpreterData_Release(_PyCrossInterpreterData *data) +_PyCrossInterpreterData_Release(_PyXIData_t *data) { return _xidata_release(data, 0); } int -_PyCrossInterpreterData_ReleaseAndRawFree(_PyCrossInterpreterData *data) +_PyCrossInterpreterData_ReleaseAndRawFree(_PyXIData_t *data) { return _xidata_release(data, 1); } @@ -446,7 +444,7 @@ _format_TracebackException(PyObject *tbexc) static int -_release_xid_data(_PyCrossInterpreterData *data, int rawfree) +_release_xid_data(_PyXIData_t *data, int rawfree) { PyObject *exc = PyErr_GetRaisedException(); int res = rawfree @@ -1094,7 +1092,7 @@ _PyXI_ApplyError(_PyXI_error *error) typedef struct _sharednsitem { const char *name; - _PyCrossInterpreterData *data; + _PyXIData_t *data; // We could have a "PyCrossInterpreterData _data" field, so it would // be allocated as part of the item and avoid an extra allocation. // However, doing so adds a bunch of complexity because we must @@ -1141,7 +1139,7 @@ _sharednsitem_set_value(_PyXI_namespace_item *item, PyObject *value) { assert(_sharednsitem_is_initialized(item)); assert(item->data == NULL); - item->data = PyMem_RawMalloc(sizeof(_PyCrossInterpreterData)); + item->data = PyMem_RawMalloc(sizeof(_PyXIData_t)); if (item->data == NULL) { PyErr_NoMemory(); return -1; @@ -1159,7 +1157,7 @@ _sharednsitem_set_value(_PyXI_namespace_item *item, PyObject *value) static void _sharednsitem_clear_value(_PyXI_namespace_item *item) { - _PyCrossInterpreterData *data = item->data; + _PyXIData_t *data = item->data; if (data != NULL) { item->data = NULL; int rawfree = 1; diff --git a/Python/crossinterp_data_lookup.h b/Python/crossinterp_data_lookup.h index 863919ad42fb97..ec36b9ece2d822 100644 --- a/Python/crossinterp_data_lookup.h +++ b/Python/crossinterp_data_lookup.h @@ -304,15 +304,14 @@ struct _shared_bytes_data { }; static PyObject * -_new_bytes_object(_PyCrossInterpreterData *data) +_new_bytes_object(_PyXIData_t *data) { struct _shared_bytes_data *shared = (struct _shared_bytes_data *)(data->data); return PyBytes_FromStringAndSize(shared->bytes, shared->len); } static int -_bytes_shared(PyThreadState *tstate, PyObject *obj, - _PyCrossInterpreterData *data) +_bytes_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) { if (_PyCrossInterpreterData_InitWithSize( data, tstate->interp, sizeof(struct _shared_bytes_data), obj, @@ -338,15 +337,14 @@ struct _shared_str_data { }; static PyObject * -_new_str_object(_PyCrossInterpreterData *data) +_new_str_object(_PyXIData_t *data) { struct _shared_str_data *shared = (struct _shared_str_data *)(data->data); return PyUnicode_FromKindAndData(shared->kind, shared->buffer, shared->len); } static int -_str_shared(PyThreadState *tstate, PyObject *obj, - _PyCrossInterpreterData *data) +_str_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) { if (_PyCrossInterpreterData_InitWithSize( data, tstate->interp, sizeof(struct _shared_str_data), obj, @@ -365,14 +363,13 @@ _str_shared(PyThreadState *tstate, PyObject *obj, // int static PyObject * -_new_long_object(_PyCrossInterpreterData *data) +_new_long_object(_PyXIData_t *data) { return PyLong_FromSsize_t((Py_ssize_t)(data->data)); } static int -_long_shared(PyThreadState *tstate, PyObject *obj, - _PyCrossInterpreterData *data) +_long_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) { /* Note that this means the size of shareable ints is bounded by * sys.maxsize. Hence on 32-bit architectures that is half the @@ -394,15 +391,14 @@ _long_shared(PyThreadState *tstate, PyObject *obj, // float static PyObject * -_new_float_object(_PyCrossInterpreterData *data) +_new_float_object(_PyXIData_t *data) { double * value_ptr = data->data; return PyFloat_FromDouble(*value_ptr); } static int -_float_shared(PyThreadState *tstate, PyObject *obj, - _PyCrossInterpreterData *data) +_float_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) { if (_PyCrossInterpreterData_InitWithSize( data, tstate->interp, sizeof(double), NULL, @@ -419,15 +415,14 @@ _float_shared(PyThreadState *tstate, PyObject *obj, // None static PyObject * -_new_none_object(_PyCrossInterpreterData *data) +_new_none_object(_PyXIData_t *data) { // XXX Singleton refcounts are problematic across interpreters... return Py_NewRef(Py_None); } static int -_none_shared(PyThreadState *tstate, PyObject *obj, - _PyCrossInterpreterData *data) +_none_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) { _PyCrossInterpreterData_Init(data, tstate->interp, NULL, NULL, _new_none_object); @@ -438,7 +433,7 @@ _none_shared(PyThreadState *tstate, PyObject *obj, // bool static PyObject * -_new_bool_object(_PyCrossInterpreterData *data) +_new_bool_object(_PyXIData_t *data) { if (data->data){ Py_RETURN_TRUE; @@ -447,8 +442,7 @@ _new_bool_object(_PyCrossInterpreterData *data) } static int -_bool_shared(PyThreadState *tstate, PyObject *obj, - _PyCrossInterpreterData *data) +_bool_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) { _PyCrossInterpreterData_Init(data, tstate->interp, (void *) (Py_IsTrue(obj) ? (uintptr_t) 1 : (uintptr_t) 0), NULL, @@ -461,11 +455,11 @@ _bool_shared(PyThreadState *tstate, PyObject *obj, struct _shared_tuple_data { Py_ssize_t len; - _PyCrossInterpreterData **data; + _PyXIData_t **data; }; static PyObject * -_new_tuple_object(_PyCrossInterpreterData *data) +_new_tuple_object(_PyXIData_t *data) { struct _shared_tuple_data *shared = (struct _shared_tuple_data *)(data->data); PyObject *tuple = PyTuple_New(shared->len); @@ -504,8 +498,7 @@ _tuple_shared_free(void* data) } static int -_tuple_shared(PyThreadState *tstate, PyObject *obj, - _PyCrossInterpreterData *data) +_tuple_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) { Py_ssize_t len = PyTuple_GET_SIZE(obj); if (len < 0) { @@ -518,14 +511,14 @@ _tuple_shared(PyThreadState *tstate, PyObject *obj, } shared->len = len; - shared->data = (_PyCrossInterpreterData **) PyMem_Calloc(shared->len, sizeof(_PyCrossInterpreterData *)); + shared->data = (_PyXIData_t **) PyMem_Calloc(shared->len, sizeof(_PyXIData_t *)); if (shared->data == NULL) { PyErr_NoMemory(); return -1; } for (Py_ssize_t i = 0; i < shared->len; i++) { - _PyCrossInterpreterData *data = _PyCrossInterpreterData_New(); + _PyXIData_t *data = _PyCrossInterpreterData_New(); if (data == NULL) { goto error; // PyErr_NoMemory already set } From 873973a8ff5deee4b8de025118477d657dc4fd99 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 5 Nov 2024 08:50:02 -0700 Subject: [PATCH 2/9] crossinterpdatafunc -> xidatafunc --- Include/internal/pycore_crossinterp.h | 17 ++++++++--------- Modules/_interpreters_common.h | 2 +- Python/crossinterp.c | 10 +++++----- Python/crossinterp_data_lookup.h | 20 +++++++++----------- 4 files changed, 23 insertions(+), 26 deletions(-) diff --git a/Include/internal/pycore_crossinterp.h b/Include/internal/pycore_crossinterp.h index c35d3b1cf79420..a02d81cfb185b4 100644 --- a/Include/internal/pycore_crossinterp.h +++ b/Include/internal/pycore_crossinterp.h @@ -54,7 +54,7 @@ struct _xid { // is non-NULL only if the data remains bound to the object in some // way, such that the object must be "released" (via a decref) when // the data is released. In that case the code that sets the field, - // likely a registered "crossinterpdatafunc", is responsible for + // likely a registered "xidatafunc", is responsible for // ensuring it owns the reference (i.e. incref). PyObject *obj; // interp is the ID of the owning interpreter of the original @@ -114,9 +114,9 @@ PyAPI_FUNC(void) _PyCrossInterpreterData_Clear( (DATA)->free = (FUNC); \ } while (0) // Additionally, some shareable types are essentially light wrappers -// around other shareable types. The crossinterpdatafunc of the wrapper +// around other shareable types. The xidatafunc of the wrapper // can often be implemented by calling the wrapped object's -// crossinterpdatafunc and then changing the "new_object" function. +// xidatafunc and then changing the "new_object" function. // We have _PyCrossInterpreterData_SET_NEW_OBJECT() here for that, // but might be better to have a function like // _PyCrossInterpreterData_AdaptToWrapper() instead. @@ -139,10 +139,9 @@ PyAPI_FUNC(int) _PyCrossInterpreterData_ReleaseAndRawFree(_PyXIData_t *); // For now we use a global registry of shareable classes. An // alternative would be to add a tp_* slot for a class's -// crossinterpdatafunc. It would be simpler and more efficient. +// xidatafunc. It would be simpler and more efficient. -typedef int (*crossinterpdatafunc)(PyThreadState *tstate, PyObject *, - _PyXIData_t *); +typedef int (*xidatafunc)(PyThreadState *tstate, PyObject *, _PyXIData_t *); struct _xidregitem; @@ -154,7 +153,7 @@ struct _xidregitem { /* This is NULL for builtin types. */ PyObject *weakref; size_t refcount; - crossinterpdatafunc getdata; + xidatafunc getdata; }; struct _xidregistry { @@ -164,9 +163,9 @@ struct _xidregistry { struct _xidregitem *head; }; -PyAPI_FUNC(int) _PyCrossInterpreterData_RegisterClass(PyTypeObject *, crossinterpdatafunc); +PyAPI_FUNC(int) _PyCrossInterpreterData_RegisterClass(PyTypeObject *, xidatafunc); PyAPI_FUNC(int) _PyCrossInterpreterData_UnregisterClass(PyTypeObject *); -PyAPI_FUNC(crossinterpdatafunc) _PyCrossInterpreterData_Lookup(PyObject *); +PyAPI_FUNC(xidatafunc) _PyCrossInterpreterData_Lookup(PyObject *); /*****************************/ diff --git a/Modules/_interpreters_common.h b/Modules/_interpreters_common.h index 5b281c4f496a09..725b4d45f7ec61 100644 --- a/Modules/_interpreters_common.h +++ b/Modules/_interpreters_common.h @@ -6,7 +6,7 @@ static int -ensure_xid_class(PyTypeObject *cls, crossinterpdatafunc getdata) +ensure_xid_class(PyTypeObject *cls, xidatafunc getdata) { //assert(cls->tp_flags & Py_TPFLAGS_HEAPTYPE); return _PyCrossInterpreterData_RegisterClass(cls, getdata); diff --git a/Python/crossinterp.c b/Python/crossinterp.c index 7e7d7945e77195..56e75b80777e48 100644 --- a/Python/crossinterp.c +++ b/Python/crossinterp.c @@ -57,15 +57,15 @@ _Py_CallInInterpreterAndRawFree(PyInterpreterState *interp, /* cross-interpreter data */ /**************************/ -/* registry of {type -> crossinterpdatafunc} */ +/* registry of {type -> xidatafunc} */ /* For now we use a global registry of shareable classes. An alternative would be to add a tp_* slot for a class's - crossinterpdatafunc. It would be simpler and more efficient. */ + xidatafunc. It would be simpler and more efficient. */ static void xid_lookup_init(PyInterpreterState *); static void xid_lookup_fini(PyInterpreterState *); -static crossinterpdatafunc lookup_getdata(PyInterpreterState *, PyObject *); +static xidatafunc lookup_getdata(PyInterpreterState *, PyObject *); #include "crossinterp_data_lookup.h" @@ -222,7 +222,7 @@ int _PyObject_CheckCrossInterpreterData(PyObject *obj) { PyInterpreterState *interp = PyInterpreterState_Get(); - crossinterpdatafunc getdata = lookup_getdata(interp, obj); + xidatafunc getdata = lookup_getdata(interp, obj); if (getdata == NULL) { if (!PyErr_Occurred()) { _set_xid_lookup_failure(interp, obj, NULL); @@ -244,7 +244,7 @@ _PyObject_GetCrossInterpreterData(PyObject *obj, _PyXIData_t *data) // Call the "getdata" func for the object. Py_INCREF(obj); - crossinterpdatafunc getdata = lookup_getdata(interp, obj); + xidatafunc getdata = lookup_getdata(interp, obj); if (getdata == NULL) { Py_DECREF(obj); if (!PyErr_Occurred()) { diff --git a/Python/crossinterp_data_lookup.h b/Python/crossinterp_data_lookup.h index ec36b9ece2d822..b9910ba53c31b0 100644 --- a/Python/crossinterp_data_lookup.h +++ b/Python/crossinterp_data_lookup.h @@ -1,8 +1,7 @@ -static crossinterpdatafunc _lookup_getdata_from_registry( - PyInterpreterState *, PyObject *); +static xidatafunc _lookup_getdata_from_registry(PyInterpreterState *, PyObject *); -static crossinterpdatafunc +static xidatafunc lookup_getdata(PyInterpreterState *interp, PyObject *obj) { /* Cross-interpreter objects are looked up by exact match on the class. @@ -11,7 +10,7 @@ lookup_getdata(PyInterpreterState *interp, PyObject *obj) return _lookup_getdata_from_registry(interp, obj); } -crossinterpdatafunc +xidatafunc _PyCrossInterpreterData_Lookup(PyObject *obj) { PyInterpreterState *interp = PyInterpreterState_Get(); @@ -20,12 +19,12 @@ _PyCrossInterpreterData_Lookup(PyObject *obj) /***********************************************/ -/* a registry of {type -> crossinterpdatafunc} */ +/* a registry of {type -> xidatafunc} */ /***********************************************/ /* For now we use a global registry of shareable classes. An alternative would be to add a tp_* slot for a class's - crossinterpdatafunc. It would be simpler and more efficient. */ + xidatafunc. It would be simpler and more efficient. */ /* registry lifecycle */ @@ -155,7 +154,7 @@ _xidregistry_find_type(struct _xidregistry *xidregistry, PyTypeObject *cls) return NULL; } -static crossinterpdatafunc +static xidatafunc _lookup_getdata_from_registry(PyInterpreterState *interp, PyObject *obj) { PyTypeObject *cls = Py_TYPE(obj); @@ -164,7 +163,7 @@ _lookup_getdata_from_registry(PyInterpreterState *interp, PyObject *obj) _xidregistry_lock(xidregistry); struct _xidregitem *matched = _xidregistry_find_type(xidregistry, cls); - crossinterpdatafunc func = matched != NULL ? matched->getdata : NULL; + xidatafunc func = matched != NULL ? matched->getdata : NULL; _xidregistry_unlock(xidregistry); return func; @@ -175,7 +174,7 @@ _lookup_getdata_from_registry(PyInterpreterState *interp, PyObject *obj) static int _xidregistry_add_type(struct _xidregistry *xidregistry, - PyTypeObject *cls, crossinterpdatafunc getdata) + PyTypeObject *cls, xidatafunc getdata) { struct _xidregitem *newhead = PyMem_RawMalloc(sizeof(struct _xidregitem)); if (newhead == NULL) { @@ -238,8 +237,7 @@ _xidregistry_clear(struct _xidregistry *xidregistry) } int -_PyCrossInterpreterData_RegisterClass(PyTypeObject *cls, - crossinterpdatafunc getdata) +_PyCrossInterpreterData_RegisterClass(PyTypeObject *cls, xidatafunc getdata) { if (!PyType_Check(cls)) { PyErr_Format(PyExc_ValueError, "only classes may be registered"); From 9057584614339bbc3cc662da6745532c0391a225 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 5 Nov 2024 09:22:10 -0700 Subject: [PATCH 3/9] CrossInterpreterData -> XIData --- Include/internal/pycore_crossinterp.h | 47 +++++++++--------- Modules/_interpchannelsmodule.c | 26 +++++----- Modules/_interpqueuesmodule.c | 23 +++++---- Modules/_interpreters_common.h | 6 +-- Modules/_interpretersmodule.c | 15 +++--- Modules/_testinternalcapi.c | 16 +++--- Python/crossinterp.c | 70 +++++++++++++-------------- Python/crossinterp_data_lookup.h | 35 ++++++-------- 8 files changed, 115 insertions(+), 123 deletions(-) diff --git a/Include/internal/pycore_crossinterp.h b/Include/internal/pycore_crossinterp.h index a02d81cfb185b4..2f8fbfe31949f4 100644 --- a/Include/internal/pycore_crossinterp.h +++ b/Include/internal/pycore_crossinterp.h @@ -47,7 +47,7 @@ typedef void (*xid_freefunc)(void *); // is necessary to pass safely between interpreters in the same process. struct _xid { // data is the cross-interpreter-safe derivation of a Python object - // (see _PyObject_GetCrossInterpreterData). It will be NULL if the + // (see _PyObject_GetXIData). It will be NULL if the // new_object func (below) encodes the data. void *data; // obj is the Python object from which the data was derived. This @@ -59,7 +59,7 @@ struct _xid { PyObject *obj; // interp is the ID of the owning interpreter of the original // object. It corresponds to the active interpreter when - // _PyObject_GetCrossInterpreterData() was called. This should only + // _PyObject_GetXIData() was called. This should only // be set by the cross-interpreter machinery. // // We use the ID rather than the PyInterpreterState to avoid issues @@ -77,39 +77,38 @@ struct _xid { // okay (e.g. bytes) and for those types this field should be set // to NULL. However, for most the data was allocated just for // cross-interpreter use, so it must be freed when - // _PyCrossInterpreterData_Release is called or the memory will + // _PyXIData_Release is called or the memory will // leak. In that case, at the very least this field should be set // to PyMem_RawFree (the default if not explicitly set to NULL). // The call will happen with the original interpreter activated. xid_freefunc free; }; -PyAPI_FUNC(_PyXIData_t *) _PyCrossInterpreterData_New(void); -PyAPI_FUNC(void) _PyCrossInterpreterData_Free(_PyXIData_t *data); +PyAPI_FUNC(_PyXIData_t *) _PyXIData_New(void); +PyAPI_FUNC(void) _PyXIData_Free(_PyXIData_t *data); -#define _PyCrossInterpreterData_DATA(DATA) ((DATA)->data) -#define _PyCrossInterpreterData_OBJ(DATA) ((DATA)->obj) -#define _PyCrossInterpreterData_INTERPID(DATA) ((DATA)->interpid) +#define _PyXIData_DATA(DATA) ((DATA)->data) +#define _PyXIData_OBJ(DATA) ((DATA)->obj) +#define _PyXIData_INTERPID(DATA) ((DATA)->interpid) // Users should not need getters for "new_object" or "free". /* defining cross-interpreter data */ -PyAPI_FUNC(void) _PyCrossInterpreterData_Init( +PyAPI_FUNC(void) _PyXIData_Init( _PyXIData_t *data, PyInterpreterState *interp, void *shared, PyObject *obj, xid_newobjectfunc new_object); -PyAPI_FUNC(int) _PyCrossInterpreterData_InitWithSize( +PyAPI_FUNC(int) _PyXIData_InitWithSize( _PyXIData_t *, PyInterpreterState *interp, const size_t, PyObject *, xid_newobjectfunc); -PyAPI_FUNC(void) _PyCrossInterpreterData_Clear( - PyInterpreterState *, _PyXIData_t *); +PyAPI_FUNC(void) _PyXIData_Clear( PyInterpreterState *, _PyXIData_t *); // Normally the Init* functions are sufficient. The only time // additional initialization might be needed is to set the "free" func, // though that should be infrequent. -#define _PyCrossInterpreterData_SET_FREE(DATA, FUNC) \ +#define _PyXIData_SET_FREE(DATA, FUNC) \ do { \ (DATA)->free = (FUNC); \ } while (0) @@ -117,10 +116,10 @@ PyAPI_FUNC(void) _PyCrossInterpreterData_Clear( // around other shareable types. The xidatafunc of the wrapper // can often be implemented by calling the wrapped object's // xidatafunc and then changing the "new_object" function. -// We have _PyCrossInterpreterData_SET_NEW_OBJECT() here for that, +// We have _PyXIData_SET_NEW_OBJECT() here for that, // but might be better to have a function like -// _PyCrossInterpreterData_AdaptToWrapper() instead. -#define _PyCrossInterpreterData_SET_NEW_OBJECT(DATA, FUNC) \ +// _PyXIData_AdaptToWrapper() instead. +#define _PyXIData_SET_NEW_OBJECT(DATA, FUNC) \ do { \ (DATA)->new_object = (FUNC); \ } while (0) @@ -128,11 +127,11 @@ PyAPI_FUNC(void) _PyCrossInterpreterData_Clear( /* using cross-interpreter data */ -PyAPI_FUNC(int) _PyObject_CheckCrossInterpreterData(PyObject *); -PyAPI_FUNC(int) _PyObject_GetCrossInterpreterData(PyObject *, _PyXIData_t *); -PyAPI_FUNC(PyObject *) _PyCrossInterpreterData_NewObject(_PyXIData_t *); -PyAPI_FUNC(int) _PyCrossInterpreterData_Release(_PyXIData_t *); -PyAPI_FUNC(int) _PyCrossInterpreterData_ReleaseAndRawFree(_PyXIData_t *); +PyAPI_FUNC(int) _PyObject_CheckXIData(PyObject *); +PyAPI_FUNC(int) _PyObject_GetXIData(PyObject *, _PyXIData_t *); +PyAPI_FUNC(PyObject *) _PyXIData_NewObject(_PyXIData_t *); +PyAPI_FUNC(int) _PyXIData_Release(_PyXIData_t *); +PyAPI_FUNC(int) _PyXIData_ReleaseAndRawFree(_PyXIData_t *); /* cross-interpreter data registry */ @@ -163,9 +162,9 @@ struct _xidregistry { struct _xidregitem *head; }; -PyAPI_FUNC(int) _PyCrossInterpreterData_RegisterClass(PyTypeObject *, xidatafunc); -PyAPI_FUNC(int) _PyCrossInterpreterData_UnregisterClass(PyTypeObject *); -PyAPI_FUNC(xidatafunc) _PyCrossInterpreterData_Lookup(PyObject *); +PyAPI_FUNC(int) _PyXIData_RegisterClass(PyTypeObject *, xidatafunc); +PyAPI_FUNC(int) _PyXIData_UnregisterClass(PyTypeObject *); +PyAPI_FUNC(xidatafunc) _PyXIData_Lookup(PyObject *); /*****************************/ diff --git a/Modules/_interpchannelsmodule.c b/Modules/_interpchannelsmodule.c index 86bbc67ffc0796..1b163932e81f70 100644 --- a/Modules/_interpchannelsmodule.c +++ b/Modules/_interpchannelsmodule.c @@ -83,7 +83,7 @@ The above state includes the following allocations by the module: * 1 _PyXIData_t The only objects in that global state are the references held by each -channel's queue, which are safely managed via the _PyCrossInterpreterData_*() +channel's queue, which are safely managed via the _PyXIData_*() API.. The module does not create any objects that are shared globally. */ @@ -111,10 +111,10 @@ _release_xid_data(_PyXIData_t *data, int flags) } int res; if (flags & XID_FREE) { - res = _PyCrossInterpreterData_ReleaseAndRawFree(data); + res = _PyXIData_ReleaseAndRawFree(data); } else { - res = _PyCrossInterpreterData_Release(data); + res = _PyXIData_Release(data); } if (res < 0) { /* The owning interpreter is already destroyed. */ @@ -541,8 +541,8 @@ _channelitem_init(_channelitem *item, } else { assert(data == NULL - || _PyCrossInterpreterData_INTERPID(data) < 0 - || interpid == _PyCrossInterpreterData_INTERPID(data)); + || _PyXIData_INTERPID(data) < 0 + || interpid == _PyXIData_INTERPID(data)); } *item = (_channelitem){ .interpid = interpid, @@ -634,7 +634,7 @@ _channelitem_clear_interpreter(_channelitem *item) assert(item->unboundop != UNBOUND_REMOVE); return 0; } - assert(_PyCrossInterpreterData_INTERPID(item->data) == item->interpid); + assert(_PyXIData_INTERPID(item->data) == item->interpid); switch (item->unboundop) { case UNBOUND_REMOVE: @@ -1779,7 +1779,7 @@ channel_send(_channels *channels, int64_t cid, PyObject *obj, PyThread_release_lock(mutex); return -1; } - if (_PyObject_GetCrossInterpreterData(obj, data) != 0) { + if (_PyObject_GetXIData(obj, data) != 0) { PyThread_release_lock(mutex); GLOBAL_FREE(data); return -1; @@ -1917,7 +1917,7 @@ channel_recv(_channels *channels, int64_t cid, PyObject **res, int *p_unboundop) } // Convert the data back to an object. - PyObject *obj = _PyCrossInterpreterData_NewObject(data); + PyObject *obj = _PyXIData_NewObject(data); if (obj == NULL) { assert(PyErr_Occurred()); // It was allocated in channel_send(), so we free it. @@ -2545,8 +2545,7 @@ struct _channelid_xid { static PyObject * _channelid_from_xid(_PyXIData_t *data) { - struct _channelid_xid *xid = \ - (struct _channelid_xid *)_PyCrossInterpreterData_DATA(data); + struct _channelid_xid *xid = (struct _channelid_xid *)_PyXIData_DATA(data); // It might not be imported yet, so we can't use _get_current_module(). PyObject *mod = PyImport_ImportModule(MODULE_NAME_STR); @@ -2594,15 +2593,14 @@ _channelid_from_xid(_PyXIData_t *data) static int _channelid_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) { - if (_PyCrossInterpreterData_InitWithSize( + if (_PyXIData_InitWithSize( data, tstate->interp, sizeof(struct _channelid_xid), obj, _channelid_from_xid ) < 0) { return -1; } - struct _channelid_xid *xid = \ - (struct _channelid_xid *)_PyCrossInterpreterData_DATA(data); + struct _channelid_xid *xid = (struct _channelid_xid *)_PyXIData_DATA(data); xid->cid = ((channelid *)obj)->cid; xid->end = ((channelid *)obj)->end; xid->resolve = ((channelid *)obj)->resolve; @@ -2770,7 +2768,7 @@ _channelend_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) if (res < 0) { return -1; } - _PyCrossInterpreterData_SET_NEW_OBJECT(data, _channelend_from_xid); + _PyXIData_SET_NEW_OBJECT(data, _channelend_from_xid); return 0; } diff --git a/Modules/_interpqueuesmodule.c b/Modules/_interpqueuesmodule.c index 55b8c4cbb70cdd..8d0e223db7ff19 100644 --- a/Modules/_interpqueuesmodule.c +++ b/Modules/_interpqueuesmodule.c @@ -39,10 +39,10 @@ _release_xid_data(_PyXIData_t *data, int flags) } int res; if (flags & XID_FREE) { - res = _PyCrossInterpreterData_ReleaseAndRawFree(data); + res = _PyXIData_ReleaseAndRawFree(data); } else { - res = _PyCrossInterpreterData_Release(data); + res = _PyXIData_Release(data); } if (res < 0) { /* The owning interpreter is already destroyed. */ @@ -415,8 +415,8 @@ _queueitem_init(_queueitem *item, } else { assert(data == NULL - || _PyCrossInterpreterData_INTERPID(data) < 0 - || interpid == _PyCrossInterpreterData_INTERPID(data)); + || _PyXIData_INTERPID(data) < 0 + || interpid == _PyXIData_INTERPID(data)); } assert(check_unbound(unboundop)); *item = (_queueitem){ @@ -496,7 +496,7 @@ _queueitem_clear_interpreter(_queueitem *item) assert(item->unboundop != UNBOUND_REMOVE); return 0; } - assert(_PyCrossInterpreterData_INTERPID(item->data) == item->interpid); + assert(_PyXIData_INTERPID(item->data) == item->interpid); switch (item->unboundop) { case UNBOUND_REMOVE: @@ -1141,12 +1141,12 @@ queue_put(_queues *queues, int64_t qid, PyObject *obj, int fmt, int unboundop) _queue_unmark_waiter(queue, queues->mutex); return -1; } - if (_PyObject_GetCrossInterpreterData(obj, data) != 0) { + if (_PyObject_GetXIData(obj, data) != 0) { _queue_unmark_waiter(queue, queues->mutex); GLOBAL_FREE(data); return -1; } - assert(_PyCrossInterpreterData_INTERPID(data) == \ + assert(_PyXIData_INTERPID(data) == \ PyInterpreterState_GetID(PyInterpreterState_Get())); // Add the data to the queue. @@ -1194,7 +1194,7 @@ queue_get(_queues *queues, int64_t qid, } // Convert the data back to an object. - PyObject *obj = _PyCrossInterpreterData_NewObject(data); + PyObject *obj = _PyXIData_NewObject(data); if (obj == NULL) { assert(PyErr_Occurred()); // It was allocated in queue_put(), so we free it. @@ -1338,7 +1338,7 @@ _queueid_xid_free(void *data) static PyObject * _queueobj_from_xid(_PyXIData_t *data) { - int64_t qid = *(int64_t *)_PyCrossInterpreterData_DATA(data); + int64_t qid = *(int64_t *)_PyXIData_DATA(data); PyObject *qidobj = PyLong_FromLongLong(qid); if (qidobj == NULL) { return NULL; @@ -1384,9 +1384,8 @@ _queueobj_shared(PyThreadState *tstate, PyObject *queueobj, _PyXIData_t *data) if (raw == NULL) { return -1; } - _PyCrossInterpreterData_Init(data, tstate->interp, raw, NULL, - _queueobj_from_xid); - _PyCrossInterpreterData_SET_FREE(data, _queueid_xid_free); + _PyXIData_Init(data, tstate->interp, raw, NULL, _queueobj_from_xid); + _PyXIData_SET_FREE(data, _queueid_xid_free); return 0; } diff --git a/Modules/_interpreters_common.h b/Modules/_interpreters_common.h index 725b4d45f7ec61..b0e31a33734dab 100644 --- a/Modules/_interpreters_common.h +++ b/Modules/_interpreters_common.h @@ -9,14 +9,14 @@ static int ensure_xid_class(PyTypeObject *cls, xidatafunc getdata) { //assert(cls->tp_flags & Py_TPFLAGS_HEAPTYPE); - return _PyCrossInterpreterData_RegisterClass(cls, getdata); + return _PyXIData_RegisterClass(cls, getdata); } #ifdef REGISTERS_HEAP_TYPES static int clear_xid_class(PyTypeObject *cls) { - return _PyCrossInterpreterData_UnregisterClass(cls); + return _PyXIData_UnregisterClass(cls); } #endif @@ -26,7 +26,7 @@ _get_interpid(_PyXIData_t *data) { int64_t interpid; if (data != NULL) { - interpid = _PyCrossInterpreterData_INTERPID(data); + interpid = _PyXIData_INTERPID(data); assert(!PyErr_Occurred()); } else { diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index c3924d24dbd684..95acdd69e53260 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -86,16 +86,16 @@ typedef struct { static PyObject * xibufferview_from_xid(PyTypeObject *cls, _PyXIData_t *data) { - assert(_PyCrossInterpreterData_DATA(data) != NULL); - assert(_PyCrossInterpreterData_OBJ(data) == NULL); - assert(_PyCrossInterpreterData_INTERPID(data) >= 0); + assert(_PyXIData_DATA(data) != NULL); + assert(_PyXIData_OBJ(data) == NULL); + assert(_PyXIData_INTERPID(data) >= 0); XIBufferViewObject *self = PyObject_Malloc(sizeof(XIBufferViewObject)); if (self == NULL) { return NULL; } PyObject_Init((PyObject *)self, cls); - self->view = (Py_buffer *)_PyCrossInterpreterData_DATA(data); - self->interpid = _PyCrossInterpreterData_INTERPID(data); + self->view = (Py_buffer *)_PyXIData_DATA(data); + self->interpid = _PyXIData_INTERPID(data); return (PyObject *)self; } @@ -178,8 +178,7 @@ _memoryview_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) PyMem_RawFree(view); return -1; } - _PyCrossInterpreterData_Init(data, tstate->interp, view, NULL, - _memoryview_from_xid); + _PyXIData_Init(data, tstate->interp, view, NULL, _memoryview_from_xid); return 0; } @@ -1182,7 +1181,7 @@ object_is_shareable(PyObject *self, PyObject *args, PyObject *kwds) return NULL; } - if (_PyObject_CheckCrossInterpreterData(obj) == 0) { + if (_PyObject_CheckXIData(obj) == 0) { Py_RETURN_TRUE; } PyErr_Clear(); diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index 69559bf04ef4c1..83f415c027afb6 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -1788,8 +1788,8 @@ _xid_capsule_destructor(PyObject *capsule) { _PyXIData_t *data = (_PyXIData_t *)PyCapsule_GetPointer(capsule, NULL); if (data != NULL) { - assert(_PyCrossInterpreterData_Release(data) == 0); - _PyCrossInterpreterData_Free(data); + assert(_PyXIData_Release(data) == 0); + _PyXIData_Free(data); } } @@ -1801,18 +1801,18 @@ get_crossinterp_data(PyObject *self, PyObject *args) return NULL; } - _PyXIData_t *data = _PyCrossInterpreterData_New(); + _PyXIData_t *data = _PyXIData_New(); if (data == NULL) { return NULL; } - if (_PyObject_GetCrossInterpreterData(obj, data) != 0) { - _PyCrossInterpreterData_Free(data); + if (_PyObject_GetXIData(obj, data) != 0) { + _PyXIData_Free(data); return NULL; } PyObject *capsule = PyCapsule_New(data, NULL, _xid_capsule_destructor); if (capsule == NULL) { - assert(_PyCrossInterpreterData_Release(data) == 0); - _PyCrossInterpreterData_Free(data); + assert(_PyXIData_Release(data) == 0); + _PyXIData_Free(data); } return capsule; } @@ -1829,7 +1829,7 @@ restore_crossinterp_data(PyObject *self, PyObject *args) if (data == NULL) { return NULL; } - return _PyCrossInterpreterData_NewObject(data); + return _PyXIData_NewObject(data); } diff --git a/Python/crossinterp.c b/Python/crossinterp.c index 56e75b80777e48..b3fde155f196e9 100644 --- a/Python/crossinterp.c +++ b/Python/crossinterp.c @@ -72,7 +72,7 @@ static xidatafunc lookup_getdata(PyInterpreterState *, PyObject *); /* lifecycle */ _PyXIData_t * -_PyCrossInterpreterData_New(void) +_PyXIData_New(void) { _PyXIData_t *xid = PyMem_RawMalloc(sizeof(_PyXIData_t)); if (xid == NULL) { @@ -82,10 +82,10 @@ _PyCrossInterpreterData_New(void) } void -_PyCrossInterpreterData_Free(_PyXIData_t *xid) +_PyXIData_Free(_PyXIData_t *xid) { PyInterpreterState *interp = PyInterpreterState_Get(); - _PyCrossInterpreterData_Clear(interp, xid); + _PyXIData_Clear(interp, xid); PyMem_RawFree(xid); } @@ -100,7 +100,7 @@ _xidata_init(_PyXIData_t *data) assert(data->data == NULL); assert(data->obj == NULL); *data = (_PyXIData_t){0}; - _PyCrossInterpreterData_INTERPID(data) = -1; + _PyXIData_INTERPID(data) = -1; } static inline void @@ -120,10 +120,10 @@ _xidata_clear(_PyXIData_t *data) } void -_PyCrossInterpreterData_Init(_PyXIData_t *data, - PyInterpreterState *interp, - void *shared, PyObject *obj, - xid_newobjectfunc new_object) +_PyXIData_Init(_PyXIData_t *data, + PyInterpreterState *interp, + void *shared, PyObject *obj, + xid_newobjectfunc new_object) { assert(data != NULL); assert(new_object != NULL); @@ -131,29 +131,29 @@ _PyCrossInterpreterData_Init(_PyXIData_t *data, data->data = shared; if (obj != NULL) { assert(interp != NULL); - // released in _PyCrossInterpreterData_Clear() + // released in _PyXIData_Clear() data->obj = Py_NewRef(obj); } // Ideally every object would know its owning interpreter. // Until then, we have to rely on the caller to identify it // (but we don't need it in all cases). - _PyCrossInterpreterData_INTERPID(data) = (interp != NULL) + _PyXIData_INTERPID(data) = (interp != NULL) ? PyInterpreterState_GetID(interp) : -1; data->new_object = new_object; } int -_PyCrossInterpreterData_InitWithSize(_PyXIData_t *data, - PyInterpreterState *interp, - const size_t size, PyObject *obj, - xid_newobjectfunc new_object) +_PyXIData_InitWithSize(_PyXIData_t *data, + PyInterpreterState *interp, + const size_t size, PyObject *obj, + xid_newobjectfunc new_object) { assert(size > 0); // For now we always free the shared data in the same interpreter // where it was allocated, so the interpreter is required. assert(interp != NULL); - _PyCrossInterpreterData_Init(data, interp, NULL, obj, new_object); + _PyXIData_Init(data, interp, NULL, obj, new_object); data->data = PyMem_RawMalloc(size); if (data->data == NULL) { return -1; @@ -163,13 +163,13 @@ _PyCrossInterpreterData_InitWithSize(_PyXIData_t *data, } void -_PyCrossInterpreterData_Clear(PyInterpreterState *interp, _PyXIData_t *data) +_PyXIData_Clear(PyInterpreterState *interp, _PyXIData_t *data) { assert(data != NULL); // This must be called in the owning interpreter. assert(interp == NULL - || _PyCrossInterpreterData_INTERPID(data) == -1 - || _PyCrossInterpreterData_INTERPID(data) == PyInterpreterState_GetID(interp)); + || _PyXIData_INTERPID(data) == -1 + || _PyXIData_INTERPID(data) == PyInterpreterState_GetID(interp)); _xidata_clear(data); } @@ -183,7 +183,7 @@ _check_xidata(PyThreadState *tstate, _PyXIData_t *data) // data->obj may be NULL, so we don't check it. - if (_PyCrossInterpreterData_INTERPID(data) < 0) { + if (_PyXIData_INTERPID(data) < 0) { PyErr_SetString(PyExc_SystemError, "missing interp"); return -1; } @@ -219,7 +219,7 @@ _set_xid_lookup_failure(PyInterpreterState *interp, } int -_PyObject_CheckCrossInterpreterData(PyObject *obj) +_PyObject_CheckXIData(PyObject *obj) { PyInterpreterState *interp = PyInterpreterState_Get(); xidatafunc getdata = lookup_getdata(interp, obj); @@ -233,14 +233,14 @@ _PyObject_CheckCrossInterpreterData(PyObject *obj) } int -_PyObject_GetCrossInterpreterData(PyObject *obj, _PyXIData_t *data) +_PyObject_GetXIData(PyObject *obj, _PyXIData_t *data) { PyThreadState *tstate = PyThreadState_Get(); PyInterpreterState *interp = tstate->interp; // Reset data before re-populating. *data = (_PyXIData_t){0}; - _PyCrossInterpreterData_INTERPID(data) = -1; + _PyXIData_INTERPID(data) = -1; // Call the "getdata" func for the object. Py_INCREF(obj); @@ -259,9 +259,9 @@ _PyObject_GetCrossInterpreterData(PyObject *obj, _PyXIData_t *data) } // Fill in the blanks and validate the result. - _PyCrossInterpreterData_INTERPID(data) = PyInterpreterState_GetID(interp); + _PyXIData_INTERPID(data) = PyInterpreterState_GetID(interp); if (_check_xidata(tstate, data) != 0) { - (void)_PyCrossInterpreterData_Release(data); + (void)_PyXIData_Release(data); return -1; } @@ -269,7 +269,7 @@ _PyObject_GetCrossInterpreterData(PyObject *obj, _PyXIData_t *data) } PyObject * -_PyCrossInterpreterData_NewObject(_PyXIData_t *data) +_PyXIData_NewObject(_PyXIData_t *data) { return data->new_object(data); } @@ -297,7 +297,7 @@ _xidata_release(_PyXIData_t *data, int rawfree) // Switch to the original interpreter. PyInterpreterState *interp = _PyInterpreterState_LookUpID( - _PyCrossInterpreterData_INTERPID(data)); + _PyXIData_INTERPID(data)); if (interp == NULL) { // The interpreter was already destroyed. // This function shouldn't have been called. @@ -319,13 +319,13 @@ _xidata_release(_PyXIData_t *data, int rawfree) } int -_PyCrossInterpreterData_Release(_PyXIData_t *data) +_PyXIData_Release(_PyXIData_t *data) { return _xidata_release(data, 0); } int -_PyCrossInterpreterData_ReleaseAndRawFree(_PyXIData_t *data) +_PyXIData_ReleaseAndRawFree(_PyXIData_t *data) { return _xidata_release(data, 1); } @@ -448,11 +448,11 @@ _release_xid_data(_PyXIData_t *data, int rawfree) { PyObject *exc = PyErr_GetRaisedException(); int res = rawfree - ? _PyCrossInterpreterData_Release(data) - : _PyCrossInterpreterData_ReleaseAndRawFree(data); + ? _PyXIData_Release(data) + : _PyXIData_ReleaseAndRawFree(data); if (res < 0) { /* The owning interpreter is already destroyed. */ - _PyCrossInterpreterData_Clear(NULL, data); + _PyXIData_Clear(NULL, data); // XXX Emit a warning? PyErr_Clear(); } @@ -1093,7 +1093,7 @@ _PyXI_ApplyError(_PyXI_error *error) typedef struct _sharednsitem { const char *name; _PyXIData_t *data; - // We could have a "PyCrossInterpreterData _data" field, so it would + // We could have a "PyXIData _data" field, so it would // be allocated as part of the item and avoid an extra allocation. // However, doing so adds a bunch of complexity because we must // ensure the item isn't freed before a pending call might happen @@ -1129,7 +1129,7 @@ _sharednsitem_has_value(_PyXI_namespace_item *item, int64_t *p_interpid) return 0; } if (p_interpid != NULL) { - *p_interpid = _PyCrossInterpreterData_INTERPID(item->data); + *p_interpid = _PyXIData_INTERPID(item->data); } return 1; } @@ -1144,7 +1144,7 @@ _sharednsitem_set_value(_PyXI_namespace_item *item, PyObject *value) PyErr_NoMemory(); return -1; } - if (_PyObject_GetCrossInterpreterData(value, item->data) != 0) { + if (_PyObject_GetXIData(value, item->data) != 0) { PyMem_RawFree(item->data); item->data = NULL; // The caller may want to propagate PyExc_NotShareableError @@ -1203,7 +1203,7 @@ _sharednsitem_apply(_PyXI_namespace_item *item, PyObject *ns, PyObject *dflt) } PyObject *value; if (item->data != NULL) { - value = _PyCrossInterpreterData_NewObject(item->data); + value = _PyXIData_NewObject(item->data); if (value == NULL) { Py_DECREF(name); return -1; diff --git a/Python/crossinterp_data_lookup.h b/Python/crossinterp_data_lookup.h index b9910ba53c31b0..4269d10d301986 100644 --- a/Python/crossinterp_data_lookup.h +++ b/Python/crossinterp_data_lookup.h @@ -11,7 +11,7 @@ lookup_getdata(PyInterpreterState *interp, PyObject *obj) } xidatafunc -_PyCrossInterpreterData_Lookup(PyObject *obj) +_PyXIData_Lookup(PyObject *obj) { PyInterpreterState *interp = PyInterpreterState_Get(); return lookup_getdata(interp, obj); @@ -237,7 +237,7 @@ _xidregistry_clear(struct _xidregistry *xidregistry) } int -_PyCrossInterpreterData_RegisterClass(PyTypeObject *cls, xidatafunc getdata) +_PyXIData_RegisterClass(PyTypeObject *cls, xidatafunc getdata) { if (!PyType_Check(cls)) { PyErr_Format(PyExc_ValueError, "only classes may be registered"); @@ -268,7 +268,7 @@ _PyCrossInterpreterData_RegisterClass(PyTypeObject *cls, xidatafunc getdata) } int -_PyCrossInterpreterData_UnregisterClass(PyTypeObject *cls) +_PyXIData_UnregisterClass(PyTypeObject *cls) { int res = 0; PyInterpreterState *interp = _PyInterpreterState_GET(); @@ -311,7 +311,7 @@ _new_bytes_object(_PyXIData_t *data) static int _bytes_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) { - if (_PyCrossInterpreterData_InitWithSize( + if (_PyXIData_InitWithSize( data, tstate->interp, sizeof(struct _shared_bytes_data), obj, _new_bytes_object ) < 0) @@ -320,7 +320,7 @@ _bytes_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) } struct _shared_bytes_data *shared = (struct _shared_bytes_data *)data->data; if (PyBytes_AsStringAndSize(obj, &shared->bytes, &shared->len) < 0) { - _PyCrossInterpreterData_Clear(tstate->interp, data); + _PyXIData_Clear(tstate->interp, data); return -1; } return 0; @@ -344,7 +344,7 @@ _new_str_object(_PyXIData_t *data) static int _str_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) { - if (_PyCrossInterpreterData_InitWithSize( + if (_PyXIData_InitWithSize( data, tstate->interp, sizeof(struct _shared_str_data), obj, _new_str_object ) < 0) @@ -380,8 +380,7 @@ _long_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) } return -1; } - _PyCrossInterpreterData_Init(data, tstate->interp, (void *)value, NULL, - _new_long_object); + _PyXIData_Init(data, tstate->interp, (void *)value, NULL, _new_long_object); // data->obj and data->free remain NULL return 0; } @@ -398,7 +397,7 @@ _new_float_object(_PyXIData_t *data) static int _float_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) { - if (_PyCrossInterpreterData_InitWithSize( + if (_PyXIData_InitWithSize( data, tstate->interp, sizeof(double), NULL, _new_float_object ) < 0) @@ -422,8 +421,7 @@ _new_none_object(_PyXIData_t *data) static int _none_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) { - _PyCrossInterpreterData_Init(data, tstate->interp, NULL, NULL, - _new_none_object); + _PyXIData_Init(data, tstate->interp, NULL, NULL, _new_none_object); // data->data, data->obj and data->free remain NULL return 0; } @@ -442,7 +440,7 @@ _new_bool_object(_PyXIData_t *data) static int _bool_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) { - _PyCrossInterpreterData_Init(data, tstate->interp, + _PyXIData_Init(data, tstate->interp, (void *) (Py_IsTrue(obj) ? (uintptr_t) 1 : (uintptr_t) 0), NULL, _new_bool_object); // data->obj and data->free remain NULL @@ -466,7 +464,7 @@ _new_tuple_object(_PyXIData_t *data) } for (Py_ssize_t i = 0; i < shared->len; i++) { - PyObject *item = _PyCrossInterpreterData_NewObject(shared->data[i]); + PyObject *item = _PyXIData_NewObject(shared->data[i]); if (item == NULL){ Py_DECREF(tuple); return NULL; @@ -485,8 +483,8 @@ _tuple_shared_free(void* data) #endif for (Py_ssize_t i = 0; i < shared->len; i++) { if (shared->data[i] != NULL) { - assert(_PyCrossInterpreterData_INTERPID(shared->data[i]) == interpid); - _PyCrossInterpreterData_Release(shared->data[i]); + assert(_PyXIData_INTERPID(shared->data[i]) == interpid); + _PyXIData_Release(shared->data[i]); PyMem_RawFree(shared->data[i]); shared->data[i] = NULL; } @@ -516,7 +514,7 @@ _tuple_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) } for (Py_ssize_t i = 0; i < shared->len; i++) { - _PyXIData_t *data = _PyCrossInterpreterData_New(); + _PyXIData_t *data = _PyXIData_New(); if (data == NULL) { goto error; // PyErr_NoMemory already set } @@ -524,7 +522,7 @@ _tuple_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) int res = -1; if (!_Py_EnterRecursiveCallTstate(tstate, " while sharing a tuple")) { - res = _PyObject_GetCrossInterpreterData(item, data); + res = _PyObject_GetXIData(item, data); _Py_LeaveRecursiveCallTstate(tstate); } if (res < 0) { @@ -533,8 +531,7 @@ _tuple_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) } shared->data[i] = data; } - _PyCrossInterpreterData_Init( - data, tstate->interp, shared, obj, _new_tuple_object); + _PyXIData_Init(data, tstate->interp, shared, obj, _new_tuple_object); data->free = _tuple_shared_free; return 0; From 759d39905b34119e9b714b226db3d3fba5f06233 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 5 Nov 2024 09:30:41 -0700 Subject: [PATCH 4/9] Adjust declaration groups. --- Include/internal/pycore_crossinterp.h | 28 +++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/Include/internal/pycore_crossinterp.h b/Include/internal/pycore_crossinterp.h index 2f8fbfe31949f4..aea246f8c9f747 100644 --- a/Include/internal/pycore_crossinterp.h +++ b/Include/internal/pycore_crossinterp.h @@ -93,6 +93,22 @@ PyAPI_FUNC(void) _PyXIData_Free(_PyXIData_t *data); // Users should not need getters for "new_object" or "free". +/* getting cross-interpreter data */ + +typedef int (*xidatafunc)(PyThreadState *tstate, PyObject *, _PyXIData_t *); + +PyAPI_FUNC(xidatafunc) _PyXIData_Lookup(PyObject *); +PyAPI_FUNC(int) _PyObject_CheckXIData(PyObject *); +PyAPI_FUNC(int) _PyObject_GetXIData(PyObject *, _PyXIData_t *); + + +/* using cross-interpreter data */ + +PyAPI_FUNC(PyObject *) _PyXIData_NewObject(_PyXIData_t *); +PyAPI_FUNC(int) _PyXIData_Release(_PyXIData_t *); +PyAPI_FUNC(int) _PyXIData_ReleaseAndRawFree(_PyXIData_t *); + + /* defining cross-interpreter data */ PyAPI_FUNC(void) _PyXIData_Init( @@ -125,23 +141,12 @@ PyAPI_FUNC(void) _PyXIData_Clear( PyInterpreterState *, _PyXIData_t *); } while (0) -/* using cross-interpreter data */ - -PyAPI_FUNC(int) _PyObject_CheckXIData(PyObject *); -PyAPI_FUNC(int) _PyObject_GetXIData(PyObject *, _PyXIData_t *); -PyAPI_FUNC(PyObject *) _PyXIData_NewObject(_PyXIData_t *); -PyAPI_FUNC(int) _PyXIData_Release(_PyXIData_t *); -PyAPI_FUNC(int) _PyXIData_ReleaseAndRawFree(_PyXIData_t *); - - /* cross-interpreter data registry */ // For now we use a global registry of shareable classes. An // alternative would be to add a tp_* slot for a class's // xidatafunc. It would be simpler and more efficient. -typedef int (*xidatafunc)(PyThreadState *tstate, PyObject *, _PyXIData_t *); - struct _xidregitem; struct _xidregitem { @@ -164,7 +169,6 @@ struct _xidregistry { PyAPI_FUNC(int) _PyXIData_RegisterClass(PyTypeObject *, xidatafunc); PyAPI_FUNC(int) _PyXIData_UnregisterClass(PyTypeObject *); -PyAPI_FUNC(xidatafunc) _PyXIData_Lookup(PyObject *); /*****************************/ From ccf3edc32e504b393ca62d702c4da5981f28d438 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 5 Nov 2024 11:53:12 -0700 Subject: [PATCH 5/9] Move an include to the right file. --- Python/crossinterp.c | 1 - Python/crossinterp_data_lookup.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Python/crossinterp.c b/Python/crossinterp.c index b3fde155f196e9..bb203f87804ee2 100644 --- a/Python/crossinterp.c +++ b/Python/crossinterp.c @@ -7,7 +7,6 @@ #include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_namespace.h" //_PyNamespace_New() #include "pycore_pyerrors.h" // _PyErr_Clear() -#include "pycore_weakref.h" // _PyWeakref_GET_REF() /**************/ diff --git a/Python/crossinterp_data_lookup.h b/Python/crossinterp_data_lookup.h index 4269d10d301986..dd034db15dc9fc 100644 --- a/Python/crossinterp_data_lookup.h +++ b/Python/crossinterp_data_lookup.h @@ -1,3 +1,5 @@ +#include "pycore_weakref.h" // _PyWeakref_GET_REF() + static xidatafunc _lookup_getdata_from_registry(PyInterpreterState *, PyObject *); From 81eacbfa089344afda05eec62b75bafc16f7b9f1 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 5 Nov 2024 11:00:59 -0700 Subject: [PATCH 6/9] Use the local typedefs. --- Python/crossinterp_data_lookup.h | 68 +++++++++++++++++--------------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/Python/crossinterp_data_lookup.h b/Python/crossinterp_data_lookup.h index dd034db15dc9fc..12b68676e0ce32 100644 --- a/Python/crossinterp_data_lookup.h +++ b/Python/crossinterp_data_lookup.h @@ -1,6 +1,12 @@ #include "pycore_weakref.h" // _PyWeakref_GET_REF() +typedef struct _xidregistry dlregistry_t; +typedef struct _xidregitem dlregitem_t; + + +// forward + static xidatafunc _lookup_getdata_from_registry(PyInterpreterState *, PyObject *); static xidatafunc @@ -31,10 +37,10 @@ _PyXIData_Lookup(PyObject *obj) /* registry lifecycle */ -static void _register_builtins_for_crossinterpreter_data(struct _xidregistry *); +static void _register_builtins_for_crossinterpreter_data(dlregistry_t *); static void -_xidregistry_init(struct _xidregistry *registry) +_xidregistry_init(dlregistry_t *registry) { if (registry->initialized) { return; @@ -48,10 +54,10 @@ _xidregistry_init(struct _xidregistry *registry) } } -static void _xidregistry_clear(struct _xidregistry *); +static void _xidregistry_clear(dlregistry_t *); static void -_xidregistry_fini(struct _xidregistry *registry) +_xidregistry_fini(dlregistry_t *registry) { if (!registry->initialized) { return; @@ -86,7 +92,7 @@ xid_lookup_fini(PyInterpreterState *interp) /* registry thread safety */ static void -_xidregistry_lock(struct _xidregistry *registry) +_xidregistry_lock(dlregistry_t *registry) { if (registry->global) { PyMutex_Lock(®istry->mutex); @@ -95,7 +101,7 @@ _xidregistry_lock(struct _xidregistry *registry) } static void -_xidregistry_unlock(struct _xidregistry *registry) +_xidregistry_unlock(dlregistry_t *registry) { if (registry->global) { PyMutex_Unlock(®istry->mutex); @@ -105,35 +111,34 @@ _xidregistry_unlock(struct _xidregistry *registry) /* accessing the registry */ -static inline struct _xidregistry * +static inline dlregistry_t * _get_global_xidregistry(_PyRuntimeState *runtime) { return &runtime->xi.registry; } -static inline struct _xidregistry * +static inline dlregistry_t * _get_xidregistry(PyInterpreterState *interp) { return &interp->xi.registry; } -static inline struct _xidregistry * +static inline dlregistry_t * _get_xidregistry_for_type(PyInterpreterState *interp, PyTypeObject *cls) { - struct _xidregistry *registry = _get_global_xidregistry(interp->runtime); + dlregistry_t *registry = _get_global_xidregistry(interp->runtime); if (cls->tp_flags & Py_TPFLAGS_HEAPTYPE) { registry = _get_xidregistry(interp); } return registry; } -static struct _xidregitem * _xidregistry_remove_entry( - struct _xidregistry *, struct _xidregitem *); +static dlregitem_t* _xidregistry_remove_entry(dlregistry_t *, dlregitem_t *); -static struct _xidregitem * -_xidregistry_find_type(struct _xidregistry *xidregistry, PyTypeObject *cls) +static dlregitem_t * +_xidregistry_find_type(dlregistry_t *xidregistry, PyTypeObject *cls) { - struct _xidregitem *cur = xidregistry->head; + dlregitem_t *cur = xidregistry->head; while (cur != NULL) { if (cur->weakref != NULL) { // cur is/was a heap type. @@ -161,10 +166,10 @@ _lookup_getdata_from_registry(PyInterpreterState *interp, PyObject *obj) { PyTypeObject *cls = Py_TYPE(obj); - struct _xidregistry *xidregistry = _get_xidregistry_for_type(interp, cls); + dlregistry_t *xidregistry = _get_xidregistry_for_type(interp, cls); _xidregistry_lock(xidregistry); - struct _xidregitem *matched = _xidregistry_find_type(xidregistry, cls); + dlregitem_t *matched = _xidregistry_find_type(xidregistry, cls); xidatafunc func = matched != NULL ? matched->getdata : NULL; _xidregistry_unlock(xidregistry); @@ -175,14 +180,14 @@ _lookup_getdata_from_registry(PyInterpreterState *interp, PyObject *obj) /* updating the registry */ static int -_xidregistry_add_type(struct _xidregistry *xidregistry, +_xidregistry_add_type(dlregistry_t *xidregistry, PyTypeObject *cls, xidatafunc getdata) { - struct _xidregitem *newhead = PyMem_RawMalloc(sizeof(struct _xidregitem)); + dlregitem_t *newhead = PyMem_RawMalloc(sizeof(dlregitem_t)); if (newhead == NULL) { return -1; } - *newhead = (struct _xidregitem){ + *newhead = (dlregitem_t){ // We do not keep a reference, to avoid keeping the class alive. .cls = cls, .refcount = 1, @@ -204,11 +209,10 @@ _xidregistry_add_type(struct _xidregistry *xidregistry, return 0; } -static struct _xidregitem * -_xidregistry_remove_entry(struct _xidregistry *xidregistry, - struct _xidregitem *entry) +static dlregitem_t * +_xidregistry_remove_entry(dlregistry_t *xidregistry, dlregitem_t *entry) { - struct _xidregitem *next = entry->next; + dlregitem_t *next = entry->next; if (entry->prev != NULL) { assert(entry->prev->next == entry); entry->prev->next = next; @@ -226,12 +230,12 @@ _xidregistry_remove_entry(struct _xidregistry *xidregistry, } static void -_xidregistry_clear(struct _xidregistry *xidregistry) +_xidregistry_clear(dlregistry_t *xidregistry) { - struct _xidregitem *cur = xidregistry->head; + dlregitem_t *cur = xidregistry->head; xidregistry->head = NULL; while (cur != NULL) { - struct _xidregitem *next = cur->next; + dlregitem_t *next = cur->next; Py_XDECREF(cur->weakref); PyMem_RawFree(cur); cur = next; @@ -252,10 +256,10 @@ _PyXIData_RegisterClass(PyTypeObject *cls, xidatafunc getdata) int res = 0; PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _xidregistry *xidregistry = _get_xidregistry_for_type(interp, cls); + dlregistry_t *xidregistry = _get_xidregistry_for_type(interp, cls); _xidregistry_lock(xidregistry); - struct _xidregitem *matched = _xidregistry_find_type(xidregistry, cls); + dlregitem_t *matched = _xidregistry_find_type(xidregistry, cls); if (matched != NULL) { assert(matched->getdata == getdata); matched->refcount += 1; @@ -274,10 +278,10 @@ _PyXIData_UnregisterClass(PyTypeObject *cls) { int res = 0; PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _xidregistry *xidregistry = _get_xidregistry_for_type(interp, cls); + dlregistry_t *xidregistry = _get_xidregistry_for_type(interp, cls); _xidregistry_lock(xidregistry); - struct _xidregitem *matched = _xidregistry_find_type(xidregistry, cls); + dlregitem_t *matched = _xidregistry_find_type(xidregistry, cls); if (matched != NULL) { assert(matched->refcount > 0); matched->refcount -= 1; @@ -545,7 +549,7 @@ _tuple_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data) // registration static void -_register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry) +_register_builtins_for_crossinterpreter_data(dlregistry_t *xidregistry) { // None if (_xidregistry_add_type(xidregistry, (PyTypeObject *)PyObject_Type(Py_None), _none_shared) != 0) { From 8c2586d1c7297f4f76ee54a2a0f6db6fbb87ac24 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 5 Nov 2024 11:59:05 -0700 Subject: [PATCH 7/9] Split out pycore_crossinterp_data_registry.h. --- Include/internal/pycore_crossinterp.h | 29 ++--------------- .../pycore_crossinterp_data_registry.h | 31 +++++++++++++++++++ Makefile.pre.in | 1 + PCbuild/pythoncore.vcxproj | 1 + PCbuild/pythoncore.vcxproj.filters | 3 ++ 5 files changed, 39 insertions(+), 26 deletions(-) create mode 100644 Include/internal/pycore_crossinterp_data_registry.h diff --git a/Include/internal/pycore_crossinterp.h b/Include/internal/pycore_crossinterp.h index aea246f8c9f747..9e7d3cb24f1029 100644 --- a/Include/internal/pycore_crossinterp.h +++ b/Include/internal/pycore_crossinterp.h @@ -143,32 +143,9 @@ PyAPI_FUNC(void) _PyXIData_Clear( PyInterpreterState *, _PyXIData_t *); /* cross-interpreter data registry */ -// For now we use a global registry of shareable classes. An -// alternative would be to add a tp_* slot for a class's -// xidatafunc. It would be simpler and more efficient. - -struct _xidregitem; - -struct _xidregitem { - struct _xidregitem *prev; - struct _xidregitem *next; - /* This can be a dangling pointer, but only if weakref is set. */ - PyTypeObject *cls; - /* This is NULL for builtin types. */ - PyObject *weakref; - size_t refcount; - xidatafunc getdata; -}; - -struct _xidregistry { - int global; /* builtin types or heap types */ - int initialized; - PyMutex mutex; - struct _xidregitem *head; -}; - -PyAPI_FUNC(int) _PyXIData_RegisterClass(PyTypeObject *, xidatafunc); -PyAPI_FUNC(int) _PyXIData_UnregisterClass(PyTypeObject *); +#define Py_CORE_CROSSINTERP_DATA_REGISTRY_H +#include "pycore_crossinterp_data_registry.h" +#undef Py_CORE_CROSSINTERP_DATA_REGISTRY_H /*****************************/ diff --git a/Include/internal/pycore_crossinterp_data_registry.h b/Include/internal/pycore_crossinterp_data_registry.h new file mode 100644 index 00000000000000..507d31720f633d --- /dev/null +++ b/Include/internal/pycore_crossinterp_data_registry.h @@ -0,0 +1,31 @@ +#ifndef Py_CORE_CROSSINTERP_DATA_REGISTRY_H +# error "this header must not be included directly" +#endif + + +// For now we use a global registry of shareable classes. An +// alternative would be to add a tp_* slot for a class's +// xidatafunc. It would be simpler and more efficient. + +struct _xidregitem; + +struct _xidregitem { + struct _xidregitem *prev; + struct _xidregitem *next; + /* This can be a dangling pointer, but only if weakref is set. */ + PyTypeObject *cls; + /* This is NULL for builtin types. */ + PyObject *weakref; + size_t refcount; + xidatafunc getdata; +}; + +struct _xidregistry { + int global; /* builtin types or heap types */ + int initialized; + PyMutex mutex; + struct _xidregitem *head; +}; + +PyAPI_FUNC(int) _PyXIData_RegisterClass(PyTypeObject *, xidatafunc); +PyAPI_FUNC(int) _PyXIData_UnregisterClass(PyTypeObject *); diff --git a/Makefile.pre.in b/Makefile.pre.in index aa7fa4e29d84c2..e3113c41a8c0ce 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1202,6 +1202,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_context.h \ $(srcdir)/Include/internal/pycore_critical_section.h \ $(srcdir)/Include/internal/pycore_crossinterp.h \ + $(srcdir)/Include/internal/pycore_crossinterp_data_registry.h \ $(srcdir)/Include/internal/pycore_debug_offsets.h \ $(srcdir)/Include/internal/pycore_descrobject.h \ $(srcdir)/Include/internal/pycore_dict.h \ diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index a4881e9256e4dd..93684c0db9fedd 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -229,6 +229,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 6b294683320a73..41c0d46ca7803c 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -609,6 +609,9 @@ Include\internal + + Include\internal + Include\internal From 5eb7adb8377d33fa5d818b505929ced2bb2c73e5 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 5 Nov 2024 09:55:33 -0700 Subject: [PATCH 8/9] Wrap _PyXIData_registry_t with a new _PyXIData_lookup_t. --- Include/internal/pycore_crossinterp.h | 9 ++-- .../pycore_crossinterp_data_registry.h | 5 ++ Include/internal/pycore_runtime_init.h | 6 ++- Python/crossinterp.c | 18 ++++++-- Python/crossinterp_data_lookup.h | 46 +++++++++---------- Python/pystate.c | 2 +- 6 files changed, 50 insertions(+), 36 deletions(-) diff --git a/Include/internal/pycore_crossinterp.h b/Include/internal/pycore_crossinterp.h index 9e7d3cb24f1029..e91e911feb38cc 100644 --- a/Include/internal/pycore_crossinterp.h +++ b/Include/internal/pycore_crossinterp.h @@ -97,6 +97,8 @@ PyAPI_FUNC(void) _PyXIData_Free(_PyXIData_t *data); typedef int (*xidatafunc)(PyThreadState *tstate, PyObject *, _PyXIData_t *); +typedef struct _xid_lookup_state _PyXIData_lookup_t; + PyAPI_FUNC(xidatafunc) _PyXIData_Lookup(PyObject *); PyAPI_FUNC(int) _PyObject_CheckXIData(PyObject *); PyAPI_FUNC(int) _PyObject_GetXIData(PyObject *, _PyXIData_t *); @@ -154,14 +156,12 @@ PyAPI_FUNC(void) _PyXIData_Clear( PyInterpreterState *, _PyXIData_t *); struct _xi_runtime_state { // builtin types - // XXX Remove this field once we have a tp_* slot. - struct _xidregistry registry; + _PyXIData_lookup_t data_lookup; }; struct _xi_state { // heap types - // XXX Remove this field once we have a tp_* slot. - struct _xidregistry registry; + _PyXIData_lookup_t data_lookup; // heap types PyObject *PyExc_NotShareableError; @@ -169,7 +169,6 @@ struct _xi_state { extern PyStatus _PyXI_Init(PyInterpreterState *interp); extern void _PyXI_Fini(PyInterpreterState *interp); - extern PyStatus _PyXI_InitTypes(PyInterpreterState *interp); extern void _PyXI_FiniTypes(PyInterpreterState *interp); diff --git a/Include/internal/pycore_crossinterp_data_registry.h b/Include/internal/pycore_crossinterp_data_registry.h index 507d31720f633d..2990c6af62e952 100644 --- a/Include/internal/pycore_crossinterp_data_registry.h +++ b/Include/internal/pycore_crossinterp_data_registry.h @@ -29,3 +29,8 @@ struct _xidregistry { PyAPI_FUNC(int) _PyXIData_RegisterClass(PyTypeObject *, xidatafunc); PyAPI_FUNC(int) _PyXIData_UnregisterClass(PyTypeObject *); + +struct _xid_lookup_state { + // XXX Remove this field once we have a tp_* slot. + struct _xidregistry registry; +}; diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h index e99febab2f3d57..bd3d704cb77730 100644 --- a/Include/internal/pycore_runtime_init.h +++ b/Include/internal/pycore_runtime_init.h @@ -50,8 +50,10 @@ extern PyTypeObject _PyExc_MemoryError; .next_id = -1, \ }, \ .xi = { \ - .registry = { \ - .global = 1, \ + .data_lookup = { \ + .registry = { \ + .global = 1, \ + }, \ }, \ }, \ /* A TSS key must be initialized with Py_tss_NEEDS_INIT \ diff --git a/Python/crossinterp.c b/Python/crossinterp.c index bb203f87804ee2..2daba99988c12a 100644 --- a/Python/crossinterp.c +++ b/Python/crossinterp.c @@ -9,6 +9,10 @@ #include "pycore_pyerrors.h" // _PyErr_Clear() +#define _PyXI_GET_GLOBAL_STATE(interp) (&(interp)->runtime->xi) +#define _PyXI_GET_STATE(interp) (&(interp)->xi) + + /**************/ /* exceptions */ /**************/ @@ -62,8 +66,8 @@ _Py_CallInInterpreterAndRawFree(PyInterpreterState *interp, alternative would be to add a tp_* slot for a class's xidatafunc. It would be simpler and more efficient. */ -static void xid_lookup_init(PyInterpreterState *); -static void xid_lookup_fini(PyInterpreterState *); +static void xid_lookup_init(_PyXIData_lookup_t *); +static void xid_lookup_fini(_PyXIData_lookup_t *); static xidatafunc lookup_getdata(PyInterpreterState *, PyObject *); #include "crossinterp_data_lookup.h" @@ -1773,7 +1777,10 @@ PyStatus _PyXI_Init(PyInterpreterState *interp) { // Initialize the XID lookup state (e.g. registry). - xid_lookup_init(interp); + if (_Py_IsMainInterpreter(interp)) { + xid_lookup_init(&_PyXI_GET_GLOBAL_STATE(interp)->data_lookup); + } + xid_lookup_init(&_PyXI_GET_STATE(interp)->data_lookup); // Initialize exceptions (heap types). if (_init_not_shareable_error_type(interp) < 0) { @@ -1793,7 +1800,10 @@ _PyXI_Fini(PyInterpreterState *interp) _fini_not_shareable_error_type(interp); // Finalize the XID lookup state (e.g. registry). - xid_lookup_fini(interp); + xid_lookup_fini(&_PyXI_GET_STATE(interp)->data_lookup); + if (_Py_IsMainInterpreter(interp)) { + xid_lookup_fini(&_PyXI_GET_GLOBAL_STATE(interp)->data_lookup); + } } PyStatus diff --git a/Python/crossinterp_data_lookup.h b/Python/crossinterp_data_lookup.h index 12b68676e0ce32..88c662a3df00d6 100644 --- a/Python/crossinterp_data_lookup.h +++ b/Python/crossinterp_data_lookup.h @@ -6,9 +6,25 @@ typedef struct _xidregitem dlregitem_t; // forward - +static void _xidregistry_init(dlregistry_t *); +static void _xidregistry_fini(dlregistry_t *); static xidatafunc _lookup_getdata_from_registry(PyInterpreterState *, PyObject *); + +/* used in crossinterp.c */ + +static void +xid_lookup_init(_PyXIData_lookup_t *state) +{ + _xidregistry_init(&state->registry); +} + +static void +xid_lookup_fini(_PyXIData_lookup_t *state) +{ + _xidregistry_fini(&state->registry); +} + static xidatafunc lookup_getdata(PyInterpreterState *interp, PyObject *obj) { @@ -18,6 +34,9 @@ lookup_getdata(PyInterpreterState *interp, PyObject *obj) return _lookup_getdata_from_registry(interp, obj); } + +/* exported API */ + xidatafunc _PyXIData_Lookup(PyObject *obj) { @@ -67,27 +86,6 @@ _xidregistry_fini(dlregistry_t *registry) _xidregistry_clear(registry); } -static inline struct _xidregistry * _get_global_xidregistry(_PyRuntimeState *); -static inline struct _xidregistry * _get_xidregistry(PyInterpreterState *); - -static void -xid_lookup_init(PyInterpreterState *interp) -{ - if (_Py_IsMainInterpreter(interp)) { - _xidregistry_init(_get_global_xidregistry(interp->runtime)); - } - _xidregistry_init(_get_xidregistry(interp)); -} - -static void -xid_lookup_fini(PyInterpreterState *interp) -{ - _xidregistry_fini(_get_xidregistry(interp)); - if (_Py_IsMainInterpreter(interp)) { - _xidregistry_fini(_get_global_xidregistry(interp->runtime)); - } -} - /* registry thread safety */ @@ -114,13 +112,13 @@ _xidregistry_unlock(dlregistry_t *registry) static inline dlregistry_t * _get_global_xidregistry(_PyRuntimeState *runtime) { - return &runtime->xi.registry; + return &runtime->xi.data_lookup.registry; } static inline dlregistry_t * _get_xidregistry(PyInterpreterState *interp) { - return &interp->xi.registry; + return &interp->xi.data_lookup.registry; } static inline dlregistry_t * diff --git a/Python/pystate.c b/Python/pystate.c index 36b31f3b9e4200..8143896355b28e 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -396,7 +396,7 @@ _Py_COMP_DIAG_POP #define LOCKS_INIT(runtime) \ { \ &(runtime)->interpreters.mutex, \ - &(runtime)->xi.registry.mutex, \ + &(runtime)->xi.data_lookup.registry.mutex, \ &(runtime)->unicode_state.ids.mutex, \ &(runtime)->imports.extensions.mutex, \ &(runtime)->ceval.pending_mainthread.mutex, \ From ab27394a84382331fa9726fdcf6e4eb304605301 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 5 Nov 2024 14:57:52 -0700 Subject: [PATCH 9/9] Fix the c-analyzer. --- Tools/c-analyzer/cpython/_parser.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Tools/c-analyzer/cpython/_parser.py b/Tools/c-analyzer/cpython/_parser.py index 3a73f65f8ff7b3..21be53e78841d5 100644 --- a/Tools/c-analyzer/cpython/_parser.py +++ b/Tools/c-analyzer/cpython/_parser.py @@ -290,6 +290,7 @@ def clean_lines(text): Modules/_sre/sre_lib.h LOCAL(type) static inline type Modules/_sre/sre_lib.h SRE(F) sre_ucs2_##F Objects/stringlib/codecs.h STRINGLIB_IS_UNICODE 1 +Include/internal/pycore_crossinterp_data_registry.h Py_CORE_CROSSINTERP_DATA_REGISTRY_H 1 # @end=tsv@ ''')[1:] pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy