17db96d56Sopenharmony_ci/*
27db96d56Sopenharmony_ci * Extension module used by multiprocessing package
37db96d56Sopenharmony_ci *
47db96d56Sopenharmony_ci * multiprocessing.c
57db96d56Sopenharmony_ci *
67db96d56Sopenharmony_ci * Copyright (c) 2006-2008, R Oudkerk
77db96d56Sopenharmony_ci * Licensed to PSF under a Contributor Agreement.
87db96d56Sopenharmony_ci */
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_ci#include "multiprocessing.h"
117db96d56Sopenharmony_ci
127db96d56Sopenharmony_ci/*[python input]
137db96d56Sopenharmony_ciclass HANDLE_converter(CConverter):
147db96d56Sopenharmony_ci    type = "HANDLE"
157db96d56Sopenharmony_ci    format_unit = '"F_HANDLE"'
167db96d56Sopenharmony_ci
177db96d56Sopenharmony_ci[python start generated code]*/
187db96d56Sopenharmony_ci/*[python end generated code: output=da39a3ee5e6b4b0d input=9fad6080b79ace91]*/
197db96d56Sopenharmony_ci
207db96d56Sopenharmony_ci/*[clinic input]
217db96d56Sopenharmony_cimodule _multiprocessing
227db96d56Sopenharmony_ci[clinic start generated code]*/
237db96d56Sopenharmony_ci/*[clinic end generated code: output=da39a3ee5e6b4b0d input=01e0745f380ac6e3]*/
247db96d56Sopenharmony_ci
257db96d56Sopenharmony_ci#include "clinic/multiprocessing.c.h"
267db96d56Sopenharmony_ci
277db96d56Sopenharmony_ci/*
287db96d56Sopenharmony_ci * Function which raises exceptions based on error codes
297db96d56Sopenharmony_ci */
307db96d56Sopenharmony_ci
317db96d56Sopenharmony_ciPyObject *
327db96d56Sopenharmony_ci_PyMp_SetError(PyObject *Type, int num)
337db96d56Sopenharmony_ci{
347db96d56Sopenharmony_ci    switch (num) {
357db96d56Sopenharmony_ci#ifdef MS_WINDOWS
367db96d56Sopenharmony_ci    case MP_STANDARD_ERROR:
377db96d56Sopenharmony_ci        if (Type == NULL)
387db96d56Sopenharmony_ci            Type = PyExc_OSError;
397db96d56Sopenharmony_ci        PyErr_SetExcFromWindowsErr(Type, 0);
407db96d56Sopenharmony_ci        break;
417db96d56Sopenharmony_ci    case MP_SOCKET_ERROR:
427db96d56Sopenharmony_ci        if (Type == NULL)
437db96d56Sopenharmony_ci            Type = PyExc_OSError;
447db96d56Sopenharmony_ci        PyErr_SetExcFromWindowsErr(Type, WSAGetLastError());
457db96d56Sopenharmony_ci        break;
467db96d56Sopenharmony_ci#else /* !MS_WINDOWS */
477db96d56Sopenharmony_ci    case MP_STANDARD_ERROR:
487db96d56Sopenharmony_ci    case MP_SOCKET_ERROR:
497db96d56Sopenharmony_ci        if (Type == NULL)
507db96d56Sopenharmony_ci            Type = PyExc_OSError;
517db96d56Sopenharmony_ci        PyErr_SetFromErrno(Type);
527db96d56Sopenharmony_ci        break;
537db96d56Sopenharmony_ci#endif /* !MS_WINDOWS */
547db96d56Sopenharmony_ci    case MP_MEMORY_ERROR:
557db96d56Sopenharmony_ci        PyErr_NoMemory();
567db96d56Sopenharmony_ci        break;
577db96d56Sopenharmony_ci    case MP_EXCEPTION_HAS_BEEN_SET:
587db96d56Sopenharmony_ci        break;
597db96d56Sopenharmony_ci    default:
607db96d56Sopenharmony_ci        PyErr_Format(PyExc_RuntimeError,
617db96d56Sopenharmony_ci                     "unknown error number %d", num);
627db96d56Sopenharmony_ci    }
637db96d56Sopenharmony_ci    return NULL;
647db96d56Sopenharmony_ci}
657db96d56Sopenharmony_ci
667db96d56Sopenharmony_ci#ifdef MS_WINDOWS
677db96d56Sopenharmony_ci/*[clinic input]
687db96d56Sopenharmony_ci_multiprocessing.closesocket
697db96d56Sopenharmony_ci
707db96d56Sopenharmony_ci    handle: HANDLE
717db96d56Sopenharmony_ci    /
727db96d56Sopenharmony_ci
737db96d56Sopenharmony_ci[clinic start generated code]*/
747db96d56Sopenharmony_ci
757db96d56Sopenharmony_cistatic PyObject *
767db96d56Sopenharmony_ci_multiprocessing_closesocket_impl(PyObject *module, HANDLE handle)
777db96d56Sopenharmony_ci/*[clinic end generated code: output=214f359f900966f4 input=8a20706dd386c6cc]*/
787db96d56Sopenharmony_ci{
797db96d56Sopenharmony_ci    int ret;
807db96d56Sopenharmony_ci
817db96d56Sopenharmony_ci    Py_BEGIN_ALLOW_THREADS
827db96d56Sopenharmony_ci    ret = closesocket((SOCKET) handle);
837db96d56Sopenharmony_ci    Py_END_ALLOW_THREADS
847db96d56Sopenharmony_ci
857db96d56Sopenharmony_ci    if (ret)
867db96d56Sopenharmony_ci        return PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError());
877db96d56Sopenharmony_ci    Py_RETURN_NONE;
887db96d56Sopenharmony_ci}
897db96d56Sopenharmony_ci
907db96d56Sopenharmony_ci/*[clinic input]
917db96d56Sopenharmony_ci_multiprocessing.recv
927db96d56Sopenharmony_ci
937db96d56Sopenharmony_ci    handle: HANDLE
947db96d56Sopenharmony_ci    size: int
957db96d56Sopenharmony_ci    /
967db96d56Sopenharmony_ci
977db96d56Sopenharmony_ci[clinic start generated code]*/
987db96d56Sopenharmony_ci
997db96d56Sopenharmony_cistatic PyObject *
1007db96d56Sopenharmony_ci_multiprocessing_recv_impl(PyObject *module, HANDLE handle, int size)
1017db96d56Sopenharmony_ci/*[clinic end generated code: output=92322781ba9ff598 input=6a5b0834372cee5b]*/
1027db96d56Sopenharmony_ci{
1037db96d56Sopenharmony_ci    int nread;
1047db96d56Sopenharmony_ci    PyObject *buf;
1057db96d56Sopenharmony_ci
1067db96d56Sopenharmony_ci    buf = PyBytes_FromStringAndSize(NULL, size);
1077db96d56Sopenharmony_ci    if (!buf)
1087db96d56Sopenharmony_ci        return NULL;
1097db96d56Sopenharmony_ci
1107db96d56Sopenharmony_ci    Py_BEGIN_ALLOW_THREADS
1117db96d56Sopenharmony_ci    nread = recv((SOCKET) handle, PyBytes_AS_STRING(buf), size, 0);
1127db96d56Sopenharmony_ci    Py_END_ALLOW_THREADS
1137db96d56Sopenharmony_ci
1147db96d56Sopenharmony_ci    if (nread < 0) {
1157db96d56Sopenharmony_ci        Py_DECREF(buf);
1167db96d56Sopenharmony_ci        return PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError());
1177db96d56Sopenharmony_ci    }
1187db96d56Sopenharmony_ci    _PyBytes_Resize(&buf, nread);
1197db96d56Sopenharmony_ci    return buf;
1207db96d56Sopenharmony_ci}
1217db96d56Sopenharmony_ci
1227db96d56Sopenharmony_ci/*[clinic input]
1237db96d56Sopenharmony_ci_multiprocessing.send
1247db96d56Sopenharmony_ci
1257db96d56Sopenharmony_ci    handle: HANDLE
1267db96d56Sopenharmony_ci    buf: Py_buffer
1277db96d56Sopenharmony_ci    /
1287db96d56Sopenharmony_ci
1297db96d56Sopenharmony_ci[clinic start generated code]*/
1307db96d56Sopenharmony_ci
1317db96d56Sopenharmony_cistatic PyObject *
1327db96d56Sopenharmony_ci_multiprocessing_send_impl(PyObject *module, HANDLE handle, Py_buffer *buf)
1337db96d56Sopenharmony_ci/*[clinic end generated code: output=52d7df0519c596cb input=41dce742f98d2210]*/
1347db96d56Sopenharmony_ci{
1357db96d56Sopenharmony_ci    int ret, length;
1367db96d56Sopenharmony_ci
1377db96d56Sopenharmony_ci    length = (int)Py_MIN(buf->len, INT_MAX);
1387db96d56Sopenharmony_ci
1397db96d56Sopenharmony_ci    Py_BEGIN_ALLOW_THREADS
1407db96d56Sopenharmony_ci    ret = send((SOCKET) handle, buf->buf, length, 0);
1417db96d56Sopenharmony_ci    Py_END_ALLOW_THREADS
1427db96d56Sopenharmony_ci
1437db96d56Sopenharmony_ci    if (ret < 0)
1447db96d56Sopenharmony_ci        return PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError());
1457db96d56Sopenharmony_ci    return PyLong_FromLong(ret);
1467db96d56Sopenharmony_ci}
1477db96d56Sopenharmony_ci
1487db96d56Sopenharmony_ci#endif
1497db96d56Sopenharmony_ci
1507db96d56Sopenharmony_ci/*[clinic input]
1517db96d56Sopenharmony_ci_multiprocessing.sem_unlink
1527db96d56Sopenharmony_ci
1537db96d56Sopenharmony_ci    name: str
1547db96d56Sopenharmony_ci    /
1557db96d56Sopenharmony_ci
1567db96d56Sopenharmony_ci[clinic start generated code]*/
1577db96d56Sopenharmony_ci
1587db96d56Sopenharmony_cistatic PyObject *
1597db96d56Sopenharmony_ci_multiprocessing_sem_unlink_impl(PyObject *module, const char *name)
1607db96d56Sopenharmony_ci/*[clinic end generated code: output=fcbfeb1ed255e647 input=bf939aff9564f1d5]*/
1617db96d56Sopenharmony_ci{
1627db96d56Sopenharmony_ci    return _PyMp_sem_unlink(name);
1637db96d56Sopenharmony_ci}
1647db96d56Sopenharmony_ci
1657db96d56Sopenharmony_ci/*
1667db96d56Sopenharmony_ci * Function table
1677db96d56Sopenharmony_ci */
1687db96d56Sopenharmony_ci
1697db96d56Sopenharmony_cistatic PyMethodDef module_methods[] = {
1707db96d56Sopenharmony_ci#ifdef MS_WINDOWS
1717db96d56Sopenharmony_ci    _MULTIPROCESSING_CLOSESOCKET_METHODDEF
1727db96d56Sopenharmony_ci    _MULTIPROCESSING_RECV_METHODDEF
1737db96d56Sopenharmony_ci    _MULTIPROCESSING_SEND_METHODDEF
1747db96d56Sopenharmony_ci#endif
1757db96d56Sopenharmony_ci#if !defined(POSIX_SEMAPHORES_NOT_ENABLED) && !defined(__ANDROID__)
1767db96d56Sopenharmony_ci    _MULTIPROCESSING_SEM_UNLINK_METHODDEF
1777db96d56Sopenharmony_ci#endif
1787db96d56Sopenharmony_ci    {NULL}
1797db96d56Sopenharmony_ci};
1807db96d56Sopenharmony_ci
1817db96d56Sopenharmony_ci
1827db96d56Sopenharmony_ci/*
1837db96d56Sopenharmony_ci * Initialize
1847db96d56Sopenharmony_ci */
1857db96d56Sopenharmony_ci
1867db96d56Sopenharmony_cistatic int
1877db96d56Sopenharmony_cimultiprocessing_exec(PyObject *module)
1887db96d56Sopenharmony_ci{
1897db96d56Sopenharmony_ci#ifdef HAVE_MP_SEMAPHORE
1907db96d56Sopenharmony_ci
1917db96d56Sopenharmony_ci    /* Add _PyMp_SemLock type to module */
1927db96d56Sopenharmony_ci    if (PyModule_AddType(module, &_PyMp_SemLockType) < 0) {
1937db96d56Sopenharmony_ci        return -1;
1947db96d56Sopenharmony_ci    }
1957db96d56Sopenharmony_ci
1967db96d56Sopenharmony_ci    {
1977db96d56Sopenharmony_ci        PyObject *py_sem_value_max;
1987db96d56Sopenharmony_ci        /* Some systems define SEM_VALUE_MAX as an unsigned value that
1997db96d56Sopenharmony_ci         * causes it to be negative when used as an int (NetBSD).
2007db96d56Sopenharmony_ci         *
2017db96d56Sopenharmony_ci         * Issue #28152: Use (0) instead of 0 to fix a warning on dead code
2027db96d56Sopenharmony_ci         * when using clang -Wunreachable-code. */
2037db96d56Sopenharmony_ci        if ((int)(SEM_VALUE_MAX) < (0))
2047db96d56Sopenharmony_ci            py_sem_value_max = PyLong_FromLong(INT_MAX);
2057db96d56Sopenharmony_ci        else
2067db96d56Sopenharmony_ci            py_sem_value_max = PyLong_FromLong(SEM_VALUE_MAX);
2077db96d56Sopenharmony_ci
2087db96d56Sopenharmony_ci        if (py_sem_value_max == NULL) {
2097db96d56Sopenharmony_ci            return -1;
2107db96d56Sopenharmony_ci        }
2117db96d56Sopenharmony_ci        if (PyDict_SetItemString(_PyMp_SemLockType.tp_dict, "SEM_VALUE_MAX",
2127db96d56Sopenharmony_ci                             py_sem_value_max) < 0) {
2137db96d56Sopenharmony_ci            Py_DECREF(py_sem_value_max);
2147db96d56Sopenharmony_ci            return -1;
2157db96d56Sopenharmony_ci        }
2167db96d56Sopenharmony_ci        Py_DECREF(py_sem_value_max);
2177db96d56Sopenharmony_ci    }
2187db96d56Sopenharmony_ci
2197db96d56Sopenharmony_ci#endif
2207db96d56Sopenharmony_ci
2217db96d56Sopenharmony_ci    /* Add configuration macros */
2227db96d56Sopenharmony_ci    PyObject *flags = PyDict_New();
2237db96d56Sopenharmony_ci    if (!flags) {
2247db96d56Sopenharmony_ci        return -1;
2257db96d56Sopenharmony_ci    }
2267db96d56Sopenharmony_ci
2277db96d56Sopenharmony_ci#define ADD_FLAG(name)                                          \
2287db96d56Sopenharmony_ci    do {                                                        \
2297db96d56Sopenharmony_ci        PyObject *value = PyLong_FromLong(name);                \
2307db96d56Sopenharmony_ci        if (value == NULL) {                                    \
2317db96d56Sopenharmony_ci            Py_DECREF(flags);                                   \
2327db96d56Sopenharmony_ci            return -1;                                          \
2337db96d56Sopenharmony_ci        }                                                       \
2347db96d56Sopenharmony_ci        if (PyDict_SetItemString(flags, #name, value) < 0) {    \
2357db96d56Sopenharmony_ci            Py_DECREF(flags);                                   \
2367db96d56Sopenharmony_ci            Py_DECREF(value);                                   \
2377db96d56Sopenharmony_ci            return -1;                                          \
2387db96d56Sopenharmony_ci        }                                                       \
2397db96d56Sopenharmony_ci        Py_DECREF(value);                                       \
2407db96d56Sopenharmony_ci    } while (0)
2417db96d56Sopenharmony_ci
2427db96d56Sopenharmony_ci#if defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED)
2437db96d56Sopenharmony_ci    ADD_FLAG(HAVE_SEM_OPEN);
2447db96d56Sopenharmony_ci#endif
2457db96d56Sopenharmony_ci#ifdef HAVE_SEM_TIMEDWAIT
2467db96d56Sopenharmony_ci    ADD_FLAG(HAVE_SEM_TIMEDWAIT);
2477db96d56Sopenharmony_ci#endif
2487db96d56Sopenharmony_ci#ifdef HAVE_BROKEN_SEM_GETVALUE
2497db96d56Sopenharmony_ci    ADD_FLAG(HAVE_BROKEN_SEM_GETVALUE);
2507db96d56Sopenharmony_ci#endif
2517db96d56Sopenharmony_ci#ifdef HAVE_BROKEN_SEM_UNLINK
2527db96d56Sopenharmony_ci    ADD_FLAG(HAVE_BROKEN_SEM_UNLINK);
2537db96d56Sopenharmony_ci#endif
2547db96d56Sopenharmony_ci
2557db96d56Sopenharmony_ci    if (PyModule_AddObject(module, "flags", flags) < 0) {
2567db96d56Sopenharmony_ci        Py_DECREF(flags);
2577db96d56Sopenharmony_ci        return -1;
2587db96d56Sopenharmony_ci    }
2597db96d56Sopenharmony_ci
2607db96d56Sopenharmony_ci    return 0;
2617db96d56Sopenharmony_ci}
2627db96d56Sopenharmony_ci
2637db96d56Sopenharmony_cistatic PyModuleDef_Slot multiprocessing_slots[] = {
2647db96d56Sopenharmony_ci    {Py_mod_exec, multiprocessing_exec},
2657db96d56Sopenharmony_ci    {0, NULL}
2667db96d56Sopenharmony_ci};
2677db96d56Sopenharmony_ci
2687db96d56Sopenharmony_cistatic struct PyModuleDef multiprocessing_module = {
2697db96d56Sopenharmony_ci    PyModuleDef_HEAD_INIT,
2707db96d56Sopenharmony_ci    .m_name = "_multiprocessing",
2717db96d56Sopenharmony_ci    .m_methods = module_methods,
2727db96d56Sopenharmony_ci    .m_slots = multiprocessing_slots,
2737db96d56Sopenharmony_ci};
2747db96d56Sopenharmony_ci
2757db96d56Sopenharmony_ciPyMODINIT_FUNC
2767db96d56Sopenharmony_ciPyInit__multiprocessing(void)
2777db96d56Sopenharmony_ci{
2787db96d56Sopenharmony_ci    return PyModuleDef_Init(&multiprocessing_module);
2797db96d56Sopenharmony_ci}
280