Skip to content

GH-94382: port multiprocessing static types to heap types #94336

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jul 20, 2022
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Port static types of ``_multiprocessing`` module to heap types. Patch by Kumar Aditya.
51 changes: 29 additions & 22 deletions Modules/_multiprocessing/multiprocessing.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,33 +196,39 @@ multiprocessing_exec(PyObject *module)
{
#ifdef HAVE_MP_SEMAPHORE

/* Add _PyMp_SemLock type to module */
if (PyModule_AddType(module, &_PyMp_SemLockType) < 0) {
PyTypeObject *semlock_type = (PyTypeObject *)PyType_FromModuleAndSpec(
module, &_PyMp_SemLockType_spec, NULL);

if (semlock_type == NULL) {
return -1;
}
int rc = PyModule_AddType(module, semlock_type);
Py_DECREF(semlock_type);
if (rc < 0) {
return -1;
}

{
PyObject *py_sem_value_max;
/* Some systems define SEM_VALUE_MAX as an unsigned value that
* causes it to be negative when used as an int (NetBSD).
*
* Issue #28152: Use (0) instead of 0 to fix a warning on dead code
* when using clang -Wunreachable-code. */
if ((int)(SEM_VALUE_MAX) < (0))
py_sem_value_max = PyLong_FromLong(INT_MAX);
else
py_sem_value_max = PyLong_FromLong(SEM_VALUE_MAX);

if (py_sem_value_max == NULL) {
return -1;
}
if (PyDict_SetItemString(_PyMp_SemLockType.tp_dict, "SEM_VALUE_MAX",
py_sem_value_max) < 0) {
Py_DECREF(py_sem_value_max);
return -1;
}
PyObject *py_sem_value_max;
/* Some systems define SEM_VALUE_MAX as an unsigned value that
* causes it to be negative when used as an int (NetBSD).
*
* Issue #28152: Use (0) instead of 0 to fix a warning on dead code
* when using clang -Wunreachable-code. */
if ((int)(SEM_VALUE_MAX) < (0)) {
py_sem_value_max = PyLong_FromLong(INT_MAX);
}
else {
py_sem_value_max = PyLong_FromLong(SEM_VALUE_MAX);
}
if (py_sem_value_max == NULL) {
return -1;
}
if (PyDict_SetItemString(semlock_type->tp_dict, "SEM_VALUE_MAX",
py_sem_value_max) < 0) {
Py_DECREF(py_sem_value_max);
return -1;
}
Py_DECREF(py_sem_value_max);

#endif

Expand Down Expand Up @@ -276,6 +282,7 @@ static PyModuleDef_Slot multiprocessing_slots[] = {
static struct PyModuleDef multiprocessing_module = {
PyModuleDef_HEAD_INIT,
.m_name = "_multiprocessing",
.m_size = 0,
.m_methods = module_methods,
.m_slots = multiprocessing_slots,
};
Expand Down
2 changes: 1 addition & 1 deletion Modules/_multiprocessing/multiprocessing.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ PyObject *_PyMp_SetError(PyObject *Type, int num);
* Externs - not all will really exist on all platforms
*/

extern PyTypeObject _PyMp_SemLockType;
extern PyType_Spec _PyMp_SemLockType_spec;
extern PyObject *_PyMp_sem_unlink(const char *name);

#endif /* MULTIPROCESSING_H */
71 changes: 31 additions & 40 deletions Modules/_multiprocessing/semaphore.c
Original file line number Diff line number Diff line change
Expand Up @@ -568,10 +568,13 @@ _multiprocessing_SemLock__rebuild_impl(PyTypeObject *type, SEM_HANDLE handle,
static void
semlock_dealloc(SemLockObject* self)
{
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
if (self->handle != SEM_FAILED)
SEM_CLOSE(self->handle);
PyMem_Free(self->name);
Py_TYPE(self)->tp_free((PyObject*)self);
tp->tp_free(self);
Py_DECREF(tp);
}

/*[clinic input]
Expand Down Expand Up @@ -701,6 +704,13 @@ _multiprocessing_SemLock___exit___impl(SemLockObject *self,
return _multiprocessing_SemLock_release_impl(self);
}

static int
semlock_traverse(SemLockObject *s, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(s));
return 0;
}

/*
* Semaphore methods
*/
Expand Down Expand Up @@ -739,45 +749,26 @@ static PyMemberDef semlock_members[] = {
* Semaphore type
*/

PyTypeObject _PyMp_SemLockType = {
PyVarObject_HEAD_INIT(NULL, 0)
/* tp_name */ "_multiprocessing.SemLock",
/* tp_basicsize */ sizeof(SemLockObject),
/* tp_itemsize */ 0,
/* tp_dealloc */ (destructor)semlock_dealloc,
/* tp_vectorcall_offset */ 0,
/* tp_getattr */ 0,
/* tp_setattr */ 0,
/* tp_as_async */ 0,
/* tp_repr */ 0,
/* tp_as_number */ 0,
/* tp_as_sequence */ 0,
/* tp_as_mapping */ 0,
/* tp_hash */ 0,
/* tp_call */ 0,
/* tp_str */ 0,
/* tp_getattro */ 0,
/* tp_setattro */ 0,
/* tp_as_buffer */ 0,
/* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/* tp_doc */ "Semaphore/Mutex type",
/* tp_traverse */ 0,
/* tp_clear */ 0,
/* tp_richcompare */ 0,
/* tp_weaklistoffset */ 0,
/* tp_iter */ 0,
/* tp_iternext */ 0,
/* tp_methods */ semlock_methods,
/* tp_members */ semlock_members,
/* tp_getset */ 0,
/* tp_base */ 0,
/* tp_dict */ 0,
/* tp_descr_get */ 0,
/* tp_descr_set */ 0,
/* tp_dictoffset */ 0,
/* tp_init */ 0,
/* tp_alloc */ 0,
/* tp_new */ _multiprocessing_SemLock,
static PyType_Slot _PyMp_SemLockType_slots[] = {
{Py_tp_dealloc, semlock_dealloc},
{Py_tp_getattro, PyObject_GenericGetAttr},
{Py_tp_setattro, PyObject_GenericSetAttr},
{Py_tp_methods, semlock_methods},
{Py_tp_members, semlock_members},
{Py_tp_alloc, PyType_GenericAlloc},
{Py_tp_new, _multiprocessing_SemLock},
{Py_tp_traverse, semlock_traverse},
{Py_tp_free, PyObject_GC_Del},
{Py_tp_doc, (void *)PyDoc_STR("Semaphore/Mutex type")},
{0, 0},
};

PyType_Spec _PyMp_SemLockType_spec = {
.name = "_multiprocessing.SemLock",
.basicsize = sizeof(SemLockObject),
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE),
.slots = _PyMp_SemLockType_slots,
};

/*
Expand Down