#include "pycore_ceval.h" // _Py_EnterRecursiveCall()
#include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString()
#include "pycore_pyatomic_ft_wrappers.h"
+#include "pycore_object.h"
#ifdef MS_WIN32
# include "pycore_modsupport.h" // _PyArg_NoKeywords()
#endif
.slots = ctype_type_slots,
};
-/*
- PyCStructType_Type - a meta type/class. Creating a new class using this one as
- __metaclass__ will call the constructor StructUnionType_new.
- It initializes the C accessible fields somehow.
-*/
-
static PyCArgObject *
-StructUnionType_paramfunc(ctypes_state *st, CDataObject *self)
+StructUnionType_paramfunc_lock_held(ctypes_state *st, CDataObject *self)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
PyCArgObject *parg;
PyObject *obj;
void *ptr;
if (ptr == NULL) {
return NULL;
}
- locked_memcpy_from(ptr, self, self->b_size);
+ memcpy(ptr, self->b_ptr, self->b_size);
/* Create a Python object which calls PyMem_Free(ptr) in
its deallocator. The object will be destroyed
return parg;
}
+/*
+ PyCStructType_Type - a meta type/class. Creating a new class using this one as
+ __metaclass__ will call the constructor StructUnionType_new.
+ It initializes the C accessible fields somehow.
+*/
+static PyCArgObject *
+StructUnionType_paramfunc(ctypes_state *st, CDataObject *self)
+{
+ PyCArgObject *res;
+ Py_BEGIN_CRITICAL_SECTION(self);
+ res = StructUnionType_paramfunc_lock_held(st, self);
+ Py_END_CRITICAL_SECTION();
+ return res;
+}
+
static int
StructUnionType_init(PyObject *self, PyObject *args, PyObject *kwds, int isStruct)
{
result = generic_pycdata_new(st, (PyTypeObject *)type, NULL, NULL);
if (result != NULL) {
- locked_memcpy_to((CDataObject *) result, (char *)buffer->buf + offset, info->size);
+ assert(_PyObject_IsUniquelyReferenced(result));
+ memcpy(((CDataObject *) result)->b_ptr, (char *)buffer->buf + offset, info->size);
}
return result;
}
goto fail;
}
- locked_memcpy_to(self, ptr, size);
+ memcpy(self->b_ptr, ptr, size);
PyBuffer_Release(&view);
return 0;
static PyObject *
WCharArray_get_value_lock_held(PyObject *op)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
Py_ssize_t i;
PyObject *res;
CDataObject *self = _CDataObject_CAST(op);
static int
WCharArray_set_value_lock_held(PyObject *op, PyObject *value)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
CDataObject *self = _CDataObject_CAST(op);
if (value == NULL) {
}
static PyCArgObject *
-PyCSimpleType_paramfunc(ctypes_state *st, CDataObject *self)
+PyCSimpleType_paramfunc_lock_held(ctypes_state *st, CDataObject *self)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
const char *fmt;
PyCArgObject *parg;
struct fielddesc *fd;
parg->tag = fmt[0];
parg->pffi_type = fd->pffi_type;
parg->obj = Py_NewRef(self);
- locked_memcpy_from(&parg->value, self, self->b_size);
+ memcpy(&parg->value, self->b_ptr, self->b_size);
return parg;
}
+static PyCArgObject *
+PyCSimpleType_paramfunc(ctypes_state *st, CDataObject *self)
+{
+ PyCArgObject *res;
+ Py_BEGIN_CRITICAL_SECTION(self);
+ res = PyCSimpleType_paramfunc_lock_held(st, self);
+ Py_END_CRITICAL_SECTION();
+ return res;
+}
+
static int
PyCSimpleType_init(PyObject *self, PyObject *args, PyObject *kwds)
{
return PyUnicode_FromStringAndSize(string, cp-string);
}
-/*
- * Keep a reference to 'keep' in the 'target', at index 'index'.
- *
- * If 'keep' is None, do nothing.
- *
- * Otherwise create a dictionary (if it does not yet exist) id the root
- * objects 'b_objects' item, which will store the 'keep' object under a unique
- * key.
- *
- * The unique_key helper travels the target's b_base pointer down to the root,
- * building a string containing hex-formatted indexes found during traversal,
- * separated by colons.
- *
- * The index tuple is used as a key into the root object's b_objects dict.
- *
- * Note: This function steals a refcount of the third argument, even if it
- * fails!
- */
static int
-KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep)
+KeepRef_lock_held(CDataObject *target, Py_ssize_t index, PyObject *keep)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(target);
int result;
CDataObject *ob;
PyObject *key;
return result;
}
+/*
+ * Keep a reference to 'keep' in the 'target', at index 'index'.
+ *
+ * If 'keep' is None, do nothing.
+ *
+ * Otherwise create a dictionary (if it does not yet exist) id the root
+ * objects 'b_objects' item, which will store the 'keep' object under a unique
+ * key.
+ *
+ * The unique_key helper travels the target's b_base pointer down to the root,
+ * building a string containing hex-formatted indexes found during traversal,
+ * separated by colons.
+ *
+ * The index tuple is used as a key into the root object's b_objects dict.
+ *
+ * Note: This function steals a refcount of the third argument, even if it
+ * fails!
+ */
+static int
+KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep)
+{
+ int res;
+ Py_BEGIN_CRITICAL_SECTION(target);
+ res = KeepRef_lock_held(target, index, keep);
+ Py_END_CRITICAL_SECTION();
+ return res;
+}
+
/******************************************************************/
/*
PyCData_Type
PyCData_get(ctypes_state *st, PyObject *type, GETFUNC getfunc, PyObject *src,
Py_ssize_t index, Py_ssize_t size, char *adr)
{
- CDataObject *cdata = _CDataObject_CAST(src);
if (getfunc) {
PyObject *res;
- LOCK_PTR(cdata);
+ Py_BEGIN_CRITICAL_SECTION(src);
res = getfunc(adr, size);
- UNLOCK_PTR(cdata);
+ Py_END_CRITICAL_SECTION();
return res;
}
assert(type);
}
if (info && info->getfunc && !_ctypes_simple_instance(st, type)) {
PyObject *res;
- LOCK_PTR(cdata);
+ Py_BEGIN_CRITICAL_SECTION(src);
res = info->getfunc(adr, size);
- UNLOCK_PTR(cdata);
+ Py_END_CRITICAL_SECTION();
return res;
}
return PyCData_FromBaseObj(st, type, src, index, adr);
if (setfunc) {
PyObject *res;
- LOCK_PTR(dst);
+ Py_BEGIN_CRITICAL_SECTION(dst);
res = setfunc(ptr, value, size);
- UNLOCK_PTR(dst);
+ Py_END_CRITICAL_SECTION();
return res;
}
if (!CDataObject_Check(st, value)) {
}
if (info && info->setfunc) {
PyObject *res;
- LOCK_PTR(dst);
+ Py_BEGIN_CRITICAL_SECTION(dst);
res = info->setfunc(ptr, value, size);
- UNLOCK_PTR(dst);
+ Py_END_CRITICAL_SECTION();
return res;
}
/*
Py_DECREF(ob);
return result;
} else if (value == Py_None && PyCPointerTypeObject_Check(st, type)) {
- LOCK_PTR(dst);
+ Py_BEGIN_CRITICAL_SECTION(dst);
*(void **)ptr = NULL;
- UNLOCK_PTR(dst);
+ Py_END_CRITICAL_SECTION();
Py_RETURN_NONE;
} else {
PyErr_Format(PyExc_TypeError,
if (err == -1)
return NULL;
if (err) {
- locked_memcpy_from(ptr, src, size);
+ Py_BEGIN_CRITICAL_SECTION(src);
+ memcpy(ptr, src->b_ptr, size);
if (PyCPointerTypeObject_Check(st, type)) {
/* XXX */
}
value = GetKeepedObjects(src);
+ Py_END_CRITICAL_SECTION();
if (value == NULL)
return NULL;
((PyTypeObject *)type)->tp_name);
return NULL;
}
- LOCK_PTR(src);
+ Py_BEGIN_CRITICAL_SECTION(src);
*(void **)ptr = src->b_ptr;
- UNLOCK_PTR(src);
keep = GetKeepedObjects(src);
+ Py_END_CRITICAL_SECTION();
if (keep == NULL)
return NULL;
static PyObject *
PyCFuncPtr_call_lock_held(PyObject *op, PyObject *inargs, PyObject *kwds)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
PyObject *restype;
PyObject *converters;
PyObject *checker;
return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES);
if (step == 1) {
PyObject *res;
- LOCK_PTR(self);
+ Py_BEGIN_CRITICAL_SECTION(self);
res = PyBytes_FromStringAndSize(ptr + start,
slicelen);
- UNLOCK_PTR(self);
+ Py_END_CRITICAL_SECTION();
return res;
}
dest = (char *)PyMem_Malloc(slicelen);
if (dest == NULL)
return PyErr_NoMemory();
- LOCK_PTR(self);
+ Py_BEGIN_CRITICAL_SECTION(self);
for (cur = start, i = 0; i < slicelen;
cur += step, i++) {
dest[i] = ptr[cur];
}
- UNLOCK_PTR(self);
+ Py_END_CRITICAL_SECTION();
np = PyBytes_FromStringAndSize(dest, slicelen);
PyMem_Free(dest);
return Py_GetConstant(Py_CONSTANT_EMPTY_STR);
if (step == 1) {
PyObject *res;
- LOCK_PTR(self);
+ Py_BEGIN_CRITICAL_SECTION(self);
res = PyUnicode_FromWideChar(ptr + start,
slicelen);
- UNLOCK_PTR(self);
+ Py_END_CRITICAL_SECTION();
return res;
}
return NULL;
}
- LOCK_PTR(self);
+ Py_BEGIN_CRITICAL_SECTION(self);
for (cur = start, i = 0; i < slicelen;
cur += step, i++) {
dest[i] = ptr[cur];
}
- UNLOCK_PTR(self);
+ Py_END_CRITICAL_SECTION();
np = PyUnicode_FromWideChar(dest, slicelen);
PyMem_Free(dest);
{
int cmp;
CDataObject *self = _CDataObject_CAST(op);
- LOCK_PTR(self);
+ Py_BEGIN_CRITICAL_SECTION(self);
cmp = memcmp(self->b_ptr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", self->b_size);
- UNLOCK_PTR(self);
+ Py_END_CRITICAL_SECTION();
return cmp;
}
Pointer_item_lock_held(PyObject *myself, Py_ssize_t index)
{
CDataObject *self = _CDataObject_CAST(myself);
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
Py_ssize_t size;
Py_ssize_t offset;
PyObject *proto;
}
static PyObject *
-Pointer_item(PyObject *myself, Py_ssize_t index)
+Pointer_item(PyObject *self, Py_ssize_t index)
{
- CDataObject *self = _CDataObject_CAST(myself);
PyObject *res;
- // TODO: The plan is to make LOCK_PTR() a mutex instead of a critical
- // section someday, so when that happens, this needs to get refactored
- // to be re-entrant safe.
- // This goes for all the locks here.
- LOCK_PTR(self);
- res = Pointer_item_lock_held(myself, index);
- UNLOCK_PTR(self);
+ Py_BEGIN_CRITICAL_SECTION(self);
+ res = Pointer_item_lock_held(self, index);
+ Py_END_CRITICAL_SECTION();
return res;
}
Pointer_ass_item_lock_held(PyObject *myself, Py_ssize_t index, PyObject *value)
{
CDataObject *self = _CDataObject_CAST(myself);
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
Py_ssize_t size;
Py_ssize_t offset;
PyObject *proto;
}
static int
-Pointer_ass_item(PyObject *myself, Py_ssize_t index, PyObject *value)
+Pointer_ass_item(PyObject *self, Py_ssize_t index, PyObject *value)
{
- CDataObject *self = _CDataObject_CAST(myself);
int res;
- LOCK_PTR(self);
- res = Pointer_ass_item_lock_held(myself, index, value);
- UNLOCK_PTR(self);
+ Py_BEGIN_CRITICAL_SECTION(self);
+ res = Pointer_ass_item_lock_held(self, index, value);
+ Py_END_CRITICAL_SECTION();
return res;
}
static PyObject *
Pointer_get_contents_lock_held(PyObject *self, void *closure)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
void *deref = *(void **)_CDataObject_CAST(self)->b_ptr;
if (deref == NULL) {
PyErr_SetString(PyExc_ValueError,
}
static PyObject *
-Pointer_get_contents(PyObject *myself, void *closure)
+Pointer_get_contents(PyObject *self, void *closure)
{
- CDataObject *self = _CDataObject_CAST(myself);
PyObject *res;
- LOCK_PTR(self);
- res = Pointer_get_contents_lock_held(myself, closure);
- UNLOCK_PTR(self);
+ Py_BEGIN_CRITICAL_SECTION(self);
+ res = Pointer_get_contents_lock_held(self, closure);
+ Py_END_CRITICAL_SECTION();
return res;
}
static int
-Pointer_set_contents(PyObject *op, PyObject *value, void *closure)
+Pointer_set_contents_lock_held(PyObject *op, PyObject *value, void *closure)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
CDataObject *dst;
PyObject *keep;
CDataObject *self = _CDataObject_CAST(op);
}
dst = (CDataObject *)value;
- if (dst != self) {
- LOCK_PTR(dst);
- locked_deref_assign(self, dst->b_ptr);
- UNLOCK_PTR(dst);
- } else {
- LOCK_PTR(self);
- *((void **)self->b_ptr) = dst->b_ptr;
- UNLOCK_PTR(self);
- }
+ *((void **)self->b_ptr) = dst->b_ptr;
/*
A Pointer instance must keep the value it points to alive. So, a
return KeepRef(self, 0, keep);
}
+static int
+Pointer_set_contents(PyObject *op, PyObject *value, void *closure)
+{
+ int res;
+ Py_BEGIN_CRITICAL_SECTION2(op, value);
+ res = Pointer_set_contents_lock_held(op, value, closure);
+ Py_END_CRITICAL_SECTION2();
+ return res;
+}
+
static PyGetSetDef Pointer_getsets[] = {
{ "contents", Pointer_get_contents, Pointer_set_contents,
"the object this pointer points to (read-write)", NULL },
copy_pointer_to_list_lock_held(PyObject *myself, PyObject *np, Py_ssize_t len,
Py_ssize_t start, Py_ssize_t step)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(myself);
Py_ssize_t i;
size_t cur;
for (cur = start, i = 0; i < len; cur += step, i++) {
return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES);
if (step == 1) {
PyObject *res;
- LOCK_PTR(self);
+ Py_BEGIN_CRITICAL_SECTION(self);
char *ptr = *(void **)self->b_ptr;
res = PyBytes_FromStringAndSize(ptr + start,
len);
- UNLOCK_PTR(self);
+ Py_END_CRITICAL_SECTION();
return res;
}
dest = (char *)PyMem_Malloc(len);
if (dest == NULL)
return PyErr_NoMemory();
- LOCK_PTR(self);
+ Py_BEGIN_CRITICAL_SECTION(self);
char *ptr = *(void **)self->b_ptr;
for (cur = start, i = 0; i < len; cur += step, i++) {
dest[i] = ptr[cur];
}
- UNLOCK_PTR(self);
+ Py_END_CRITICAL_SECTION();
np = PyBytes_FromStringAndSize(dest, len);
PyMem_Free(dest);
return np;
return Py_GetConstant(Py_CONSTANT_EMPTY_STR);
if (step == 1) {
PyObject *res;
- LOCK_PTR(self);
+ Py_BEGIN_CRITICAL_SECTION(self);
wchar_t *ptr = *(wchar_t **)self->b_ptr;
res = PyUnicode_FromWideChar(ptr + start,
len);
- UNLOCK_PTR(self);
+ Py_END_CRITICAL_SECTION();
return res;
}
dest = PyMem_New(wchar_t, len);
if (dest == NULL)
return PyErr_NoMemory();
- LOCK_PTR(self);
+ Py_BEGIN_CRITICAL_SECTION(self);
wchar_t *ptr = *(wchar_t **)self->b_ptr;
for (cur = start, i = 0; i < len; cur += step, i++) {
dest[i] = ptr[cur];
}
- UNLOCK_PTR(self);
+ Py_END_CRITICAL_SECTION();
np = PyUnicode_FromWideChar(dest, len);
PyMem_Free(dest);
return np;
return NULL;
int res;
- LOCK_PTR(self);
+ Py_BEGIN_CRITICAL_SECTION(myself);
res = copy_pointer_to_list_lock_held(myself, np, len, start, step);
- UNLOCK_PTR(self);
+ Py_END_CRITICAL_SECTION();
if (res < 0) {
Py_DECREF(np);
return NULL;
}
static PyObject *
-cast(void *ptr, PyObject *src, PyObject *ctype)
+cast_lock_held(void *ptr, PyObject *src, PyObject *ctype)
{
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(src);
PyObject *mod = PyType_GetModuleByDef(Py_TYPE(ctype), &_ctypesmodule);
if (!mod) {
PyErr_SetString(PyExc_TypeError,
}
}
/* Should we assert that result is a pointer type? */
- locked_memcpy_to(result, &ptr, sizeof(void *));
+ memcpy(result->b_ptr, &ptr, sizeof(void *));
return (PyObject *)result;
failed:
return NULL;
}
+static PyObject *
+cast(void *ptr, PyObject *src, PyObject *ctype)
+{
+ PyObject *res;
+ Py_BEGIN_CRITICAL_SECTION(src);
+ res = cast_lock_held(ptr, src, ctype);
+ Py_END_CRITICAL_SECTION();
+ return res;
+}
static PyObject *
wstring_at(const wchar_t *ptr, int size)
PyInit__ctypes(void)
{
return PyModuleDef_Init(&_ctypesmodule);
-}
\ No newline at end of file
+}