if (ptr == NULL) {
return NULL;
}
- memcpy(ptr, self->b_ptr, self->b_size);
+ locked_memcpy_from(ptr, self, self->b_size);
/* Create a Python object which calls PyMem_Free(ptr) in
its deallocator. The object will be destroyed
result = generic_pycdata_new(st, (PyTypeObject *)type, NULL, NULL);
if (result != NULL) {
- memcpy(((CDataObject *)result)->b_ptr,
- (char *)buffer->buf + offset, info->size);
+ locked_memcpy_to((CDataObject *) result, (char *)buffer->buf + offset, info->size);
}
return result;
}
parg->tag = 'P';
parg->pffi_type = &ffi_type_pointer;
parg->obj = Py_NewRef(self);
- parg->value.p = *(void **)self->b_ptr;
+ parg->value.p = locked_deref(self);
return parg;
}
goto fail;
}
- memcpy(self->b_ptr, ptr, size);
+ locked_memcpy_to(self, ptr, size);
PyBuffer_Release(&view);
return 0;
static PyObject *
CharArray_get_raw(CDataObject *self, void *Py_UNUSED(ignored))
{
- return PyBytes_FromStringAndSize(self->b_ptr, self->b_size);
+ PyObject *res;
+ LOCK_PTR(self);
+ res = PyBytes_FromStringAndSize(self->b_ptr, self->b_size);
+ UNLOCK_PTR(self);
+ return res;
}
static PyObject *
CharArray_get_value(CDataObject *self, void *Py_UNUSED(ignored))
{
Py_ssize_t i;
+ PyObject *res;
+ LOCK_PTR(self);
char *ptr = self->b_ptr;
for (i = 0; i < self->b_size; ++i)
if (*ptr++ == '\0')
break;
- return PyBytes_FromStringAndSize(self->b_ptr, i);
+ res = PyBytes_FromStringAndSize(self->b_ptr, i);
+ UNLOCK_PTR(self);
+ return res;
}
static int
}
ptr = PyBytes_AS_STRING(value);
+ LOCK_PTR(self);
memcpy(self->b_ptr, ptr, size);
if (size < self->b_size)
self->b_ptr[size] = '\0';
+ UNLOCK_PTR(self);
Py_DECREF(value);
return 0;
WCharArray_get_value(CDataObject *self, void *Py_UNUSED(ignored))
{
Py_ssize_t i;
+ PyObject *res;
wchar_t *ptr = (wchar_t *)self->b_ptr;
+ LOCK_PTR(self);
for (i = 0; i < self->b_size/(Py_ssize_t)sizeof(wchar_t); ++i)
if (*ptr++ == (wchar_t)0)
break;
- return PyUnicode_FromWideChar((wchar_t *)self->b_ptr, i);
+ res = PyUnicode_FromWideChar((wchar_t *)self->b_ptr, i);
+ UNLOCK_PTR(self);
+ return res;
}
static int
PyErr_SetString(PyExc_ValueError, "string too long");
return -1;
}
- if (PyUnicode_AsWideChar(value, (wchar_t *)self->b_ptr, size) < 0) {
- return -1;
- }
- return 0;
+ Py_ssize_t rc;
+ LOCK_PTR(self);
+ rc = PyUnicode_AsWideChar(value, (wchar_t *)self->b_ptr, size);
+ UNLOCK_PTR(self);
+ return rc < 0 ? -1 : 0;
}
static PyGetSetDef WCharArray_getsets[] = {
parg->pffi_type = &ffi_type_pointer;
parg->tag = 'P';
Py_INCREF(value);
+ // Function pointers don't change their contents, no need to lock
parg->value.p = *(void **)func->b_ptr;
parg->obj = value;
return (PyObject *)parg;
parg->tag = 'Z';
parg->obj = Py_NewRef(value);
/* Remember: b_ptr points to where the pointer is stored! */
- parg->value.p = *(void **)(((CDataObject *)value)->b_ptr);
+ parg->value.p = locked_deref((CDataObject *)value);
return (PyObject *)parg;
}
}
parg->tag = fmt[0];
parg->pffi_type = fd->pffi_type;
parg->obj = Py_NewRef(self);
- memcpy(&parg->value, self->b_ptr, self->b_size);
+ locked_memcpy_from(&parg->value, self, self->b_size);
return parg;
}
parg->tag = 'P';
parg->pffi_type = &ffi_type_pointer;
parg->obj = Py_NewRef(self);
- parg->value.p = *(void **)self->b_ptr;
+ parg->value.p = locked_deref(self);
return parg;
}
if (dict == NULL) {
return NULL;
}
+ PyObject *bytes;
+ LOCK_PTR(self);
+ bytes = PyBytes_FromStringAndSize(self->b_ptr, self->b_size);
+ UNLOCK_PTR(self);
return Py_BuildValue("O(O(NN))", st->_unpickle, Py_TYPE(myself), dict,
- PyBytes_FromStringAndSize(self->b_ptr, self->b_size));
+ bytes);
}
static PyObject *
}
if (len > self->b_size)
len = self->b_size;
+ // XXX Can we use locked_memcpy_to()?
+ LOCK_PTR(self);
memmove(self->b_ptr, data, len);
+ UNLOCK_PTR(self);
mydict = PyObject_GetAttrString(myself, "__dict__");
if (mydict == NULL) {
return NULL;
static int
PyCData_MallocBuffer(CDataObject *obj, StgInfo *info)
{
+ /* We don't have to lock in this function, because it's only
+ * used in constructors and therefore does not have concurrent
+ * access.
+ */
+ assert (Py_REFCNT(obj) == 1);
+
if ((size_t)info->size <= sizeof(obj->b_value)) {
/* No need to call malloc, can use the default buffer */
obj->b_ptr = (char *)&obj->b_value;
PyCData_get(ctypes_state *st, PyObject *type, GETFUNC getfunc, PyObject *src,
Py_ssize_t index, Py_ssize_t size, char *adr)
{
- if (getfunc)
- return getfunc(adr, size);
+#ifdef Py_GIL_DISABLED
+ // This isn't used if the GIL is enabled, so it causes a compiler warning.
+ CDataObject *cdata = (CDataObject *)src;
+#endif
+ if (getfunc) {
+ PyObject *res;
+ LOCK_PTR(cdata);
+ res = getfunc(adr, size);
+ UNLOCK_PTR(cdata);
+ return res;
+ }
assert(type);
StgInfo *info;
if (PyStgInfo_FromType(st, type, &info) < 0) {
return NULL;
}
if (info && info->getfunc && !_ctypes_simple_instance(st, type)) {
- return info->getfunc(adr, size);
+ PyObject *res;
+ LOCK_PTR(cdata);
+ res = info->getfunc(adr, size);
+ UNLOCK_PTR(cdata);
+ return res;
}
return PyCData_FromBaseObj(st, type, src, index, adr);
}
int err;
if (setfunc) {
- return setfunc(ptr, value, size);
+ PyObject *res;
+ LOCK_PTR(dst);
+ res = setfunc(ptr, value, size);
+ UNLOCK_PTR(dst);
+ return res;
}
if (!CDataObject_Check(st, value)) {
StgInfo *info;
if (PyStgInfo_FromType(st, type, &info) < 0) {
return NULL;
}
- if (info && info->setfunc)
- return info->setfunc(ptr, value, size);
+ if (info && info->setfunc) {
+ PyObject *res;
+ LOCK_PTR(dst);
+ res = info->setfunc(ptr, value, size);
+ UNLOCK_PTR(dst);
+ return res;
+ }
/*
If value is a tuple, we try to call the type with the tuple
and use the result!
Py_DECREF(ob);
return result;
} else if (value == Py_None && PyCPointerTypeObject_Check(st, type)) {
+ LOCK_PTR(dst);
*(void **)ptr = NULL;
+ UNLOCK_PTR(dst);
Py_RETURN_NONE;
} else {
PyErr_Format(PyExc_TypeError,
if (err == -1)
return NULL;
if (err) {
- memcpy(ptr,
- src->b_ptr,
- size);
+ locked_memcpy_from(ptr, src, size);
if (PyCPointerTypeObject_Check(st, type)) {
/* XXX */
((PyTypeObject *)type)->tp_name);
return NULL;
}
+ LOCK_PTR(src);
*(void **)ptr = src->b_ptr;
+ UNLOCK_PTR(src);
keep = GetKeepedObjects(src);
if (keep == NULL)
self->paramflags = Py_XNewRef(paramflags);
+ // No other threads can have this object, no need to
+ // lock it.
*(void **)self->b_ptr = address;
Py_INCREF(dll);
Py_DECREF(ftuple);
if (slicelen <= 0)
return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES);
if (step == 1) {
- return PyBytes_FromStringAndSize(ptr + start,
- slicelen);
+ PyObject *res;
+ LOCK_PTR(self);
+ res = PyBytes_FromStringAndSize(ptr + start,
+ slicelen);
+ UNLOCK_PTR(self);
+ return res;
}
dest = (char *)PyMem_Malloc(slicelen);
if (dest == NULL)
return PyErr_NoMemory();
+ LOCK_PTR(self);
for (cur = start, i = 0; i < slicelen;
cur += step, i++) {
dest[i] = ptr[cur];
}
+ UNLOCK_PTR(self);
np = PyBytes_FromStringAndSize(dest, slicelen);
PyMem_Free(dest);
if (slicelen <= 0)
return Py_GetConstant(Py_CONSTANT_EMPTY_STR);
if (step == 1) {
- return PyUnicode_FromWideChar(ptr + start,
- slicelen);
+ PyObject *res;
+ LOCK_PTR(self);
+ res = PyUnicode_FromWideChar(ptr + start,
+ slicelen);
+ UNLOCK_PTR(self);
+ return res;
}
dest = PyMem_New(wchar_t, slicelen);
return NULL;
}
+ LOCK_PTR(self);
for (cur = start, i = 0; i < slicelen;
cur += step, i++) {
dest[i] = ptr[cur];
}
+ UNLOCK_PTR(self);
np = PyUnicode_FromWideChar(dest, slicelen);
PyMem_Free(dest);
assert(info); /* Cannot be NULL for CDataObject instances */
assert(info->setfunc);
+ LOCK_PTR(self);
result = info->setfunc(self->b_ptr, value, info->size);
+ UNLOCK_PTR(self);
if (!result)
return -1;
}
assert(info); /* Cannot be NULL for CDataObject instances */
assert(info->getfunc);
- return info->getfunc(self->b_ptr, self->b_size);
+ PyObject *res;
+ LOCK_PTR(self);
+ res = info->getfunc(self->b_ptr, self->b_size);
+ UNLOCK_PTR(self);
+ return res;
}
static PyGetSetDef Simple_getsets[] = {
static int Simple_bool(CDataObject *self)
{
- return memcmp(self->b_ptr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", self->b_size);
+ int cmp;
+ LOCK_PTR(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);
+ return cmp;
}
/* "%s(%s)" % (self.__class__.__name__, self.value) */
Py_ssize_t size;
Py_ssize_t offset;
PyObject *proto;
+ void *deref = locked_deref(self);
- if (*(void **)self->b_ptr == NULL) {
+ if (deref == NULL) {
PyErr_SetString(PyExc_ValueError,
"NULL pointer access");
return NULL;
offset = index * iteminfo->size;
return PyCData_get(st, proto, stginfo->getfunc, (PyObject *)self,
- index, size, (*(char **)self->b_ptr) + offset);
+ index, size, (char *)((char *)deref + offset));
}
static int
return -1;
}
- if (*(void **)self->b_ptr == NULL) {
+ void *deref = locked_deref(self);
+ if (deref == NULL) {
PyErr_SetString(PyExc_ValueError,
"NULL pointer access");
return -1;
offset = index * iteminfo->size;
return PyCData_set(st, (PyObject *)self, proto, stginfo->setfunc, value,
- index, size, (*(char **)self->b_ptr) + offset);
+ index, size, ((char *)deref + offset));
}
static PyObject *
Pointer_get_contents(CDataObject *self, void *closure)
{
- if (*(void **)self->b_ptr == NULL) {
+ void *deref = locked_deref(self);
+ if (deref == NULL) {
PyErr_SetString(PyExc_ValueError,
"NULL pointer access");
return NULL;
return PyCData_FromBaseObj(st, stginfo->proto,
(PyObject *)self, 0,
- *(void **)self->b_ptr);
+ deref);
}
static int
}
dst = (CDataObject *)value;
- *(void **)self->b_ptr = dst->b_ptr;
+ locked_deref_assign(self, dst->b_ptr);
/*
A Pointer instance must keep the value it points to alive. So, a
}
assert(iteminfo);
if (iteminfo->getfunc == _ctypes_get_fielddesc("c")->getfunc) {
- char *ptr = *(char **)self->b_ptr;
+ char *ptr = locked_deref(self);
char *dest;
if (len <= 0)
return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES);
if (step == 1) {
- return PyBytes_FromStringAndSize(ptr + start,
- len);
+ PyObject *res;
+ LOCK_PTR(self);
+ res = PyBytes_FromStringAndSize(ptr + start,
+ len);
+ UNLOCK_PTR(self);
+ return res;
}
dest = (char *)PyMem_Malloc(len);
if (dest == NULL)
return PyErr_NoMemory();
+ LOCK_PTR(self);
for (cur = start, i = 0; i < len; cur += step, i++) {
dest[i] = ptr[cur];
}
+ UNLOCK_PTR(self);
np = PyBytes_FromStringAndSize(dest, len);
PyMem_Free(dest);
return np;
}
if (iteminfo->getfunc == _ctypes_get_fielddesc("u")->getfunc) {
- wchar_t *ptr = *(wchar_t **)self->b_ptr;
+ wchar_t *ptr = locked_deref(self);
wchar_t *dest;
if (len <= 0)
return Py_GetConstant(Py_CONSTANT_EMPTY_STR);
if (step == 1) {
- return PyUnicode_FromWideChar(ptr + start,
- len);
+ PyObject *res;
+ LOCK_PTR(self);
+ res = PyUnicode_FromWideChar(ptr + start,
+ len);
+ UNLOCK_PTR(self);
+ return res;
}
dest = PyMem_New(wchar_t, len);
if (dest == NULL)
return PyErr_NoMemory();
+ LOCK_PTR(self);
for (cur = start, i = 0; i < len; cur += step, i++) {
dest[i] = ptr[cur];
}
+ UNLOCK_PTR(self);
np = PyUnicode_FromWideChar(dest, len);
PyMem_Free(dest);
return np;
static int
Pointer_bool(CDataObject *self)
{
- return (*(void **)self->b_ptr != NULL);
+ return locked_deref(self) != NULL;
}
static PyType_Slot pycpointer_slots[] = {
}
}
/* Should we assert that result is a pointer type? */
- memcpy(result->b_ptr, &ptr, sizeof(void *));
+ locked_memcpy_to(result, &ptr, sizeof(void *));
return (PyObject *)result;
failed: