diff options
author | AlexSm <alex@ydb.tech> | 2024-03-05 10:40:59 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-05 12:40:59 +0300 |
commit | 1ac13c847b5358faba44dbb638a828e24369467b (patch) | |
tree | 07672b4dd3604ad3dee540a02c6494cb7d10dc3d /contrib/tools/python3/Modules/resource.c | |
parent | ffcca3e7f7958ddc6487b91d3df8c01054bd0638 (diff) | |
download | ydb-1ac13c847b5358faba44dbb638a828e24369467b.tar.gz |
Library import 16 (#2433)
Co-authored-by: robot-piglet <robot-piglet@yandex-team.com>
Co-authored-by: deshevoy <deshevoy@yandex-team.com>
Co-authored-by: robot-contrib <robot-contrib@yandex-team.com>
Co-authored-by: thegeorg <thegeorg@yandex-team.com>
Co-authored-by: robot-ya-builder <robot-ya-builder@yandex-team.com>
Co-authored-by: svidyuk <svidyuk@yandex-team.com>
Co-authored-by: shadchin <shadchin@yandex-team.com>
Co-authored-by: robot-ratatosk <robot-ratatosk@yandex-team.com>
Co-authored-by: innokentii <innokentii@yandex-team.com>
Co-authored-by: arkady-e1ppa <arkady-e1ppa@yandex-team.com>
Co-authored-by: snermolaev <snermolaev@yandex-team.com>
Co-authored-by: dimdim11 <dimdim11@yandex-team.com>
Co-authored-by: kickbutt <kickbutt@yandex-team.com>
Co-authored-by: abdullinsaid <abdullinsaid@yandex-team.com>
Co-authored-by: korsunandrei <korsunandrei@yandex-team.com>
Co-authored-by: petrk <petrk@yandex-team.com>
Co-authored-by: miroslav2 <miroslav2@yandex-team.com>
Co-authored-by: serjflint <serjflint@yandex-team.com>
Co-authored-by: akhropov <akhropov@yandex-team.com>
Co-authored-by: prettyboy <prettyboy@yandex-team.com>
Co-authored-by: ilikepugs <ilikepugs@yandex-team.com>
Co-authored-by: hiddenpath <hiddenpath@yandex-team.com>
Co-authored-by: mikhnenko <mikhnenko@yandex-team.com>
Co-authored-by: spreis <spreis@yandex-team.com>
Co-authored-by: andreyshspb <andreyshspb@yandex-team.com>
Co-authored-by: dimaandreev <dimaandreev@yandex-team.com>
Co-authored-by: rashid <rashid@yandex-team.com>
Co-authored-by: robot-ydb-importer <robot-ydb-importer@yandex-team.com>
Co-authored-by: r-vetrov <r-vetrov@yandex-team.com>
Co-authored-by: ypodlesov <ypodlesov@yandex-team.com>
Co-authored-by: zaverden <zaverden@yandex-team.com>
Co-authored-by: vpozdyayev <vpozdyayev@yandex-team.com>
Co-authored-by: robot-cozmo <robot-cozmo@yandex-team.com>
Co-authored-by: v-korovin <v-korovin@yandex-team.com>
Co-authored-by: arikon <arikon@yandex-team.com>
Co-authored-by: khoden <khoden@yandex-team.com>
Co-authored-by: psydmm <psydmm@yandex-team.com>
Co-authored-by: robot-javacom <robot-javacom@yandex-team.com>
Co-authored-by: dtorilov <dtorilov@yandex-team.com>
Co-authored-by: sennikovmv <sennikovmv@yandex-team.com>
Co-authored-by: hcpp <hcpp@ydb.tech>
Diffstat (limited to 'contrib/tools/python3/Modules/resource.c')
-rw-r--r-- | contrib/tools/python3/Modules/resource.c | 556 |
1 files changed, 556 insertions, 0 deletions
diff --git a/contrib/tools/python3/Modules/resource.c b/contrib/tools/python3/Modules/resource.c new file mode 100644 index 0000000000..3c89468c48 --- /dev/null +++ b/contrib/tools/python3/Modules/resource.c @@ -0,0 +1,556 @@ + +#include "Python.h" +#include <sys/resource.h> +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#include <time.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> + +/* On some systems, these aren't in any header file. + On others they are, with inconsistent prototypes. + We declare the (default) return type, to shut up gcc -Wall; + but we can't declare the prototype, to avoid errors + when the header files declare it different. + Worse, on some Linuxes, getpagesize() returns a size_t... */ + +#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001) + +/*[clinic input] +module resource +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e89d38ed52609d7c]*/ + +/*[python input] +class pid_t_converter(CConverter): + type = 'pid_t' + format_unit = '" _Py_PARSE_PID "' + + def parse_arg(self, argname, displayname): + return """ + {paramname} = PyLong_AsPid({argname}); + if ({paramname} == -1 && PyErr_Occurred()) {{{{ + goto exit; + }}}} + """.format(argname=argname, paramname=self.parser_name) +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=5af1c116d56cbb5a]*/ + +#include "clinic/resource.c.h" + +PyDoc_STRVAR(struct_rusage__doc__, +"struct_rusage: Result from getrusage.\n\n" +"This object may be accessed either as a tuple of\n" +" (utime,stime,maxrss,ixrss,idrss,isrss,minflt,majflt,\n" +" nswap,inblock,oublock,msgsnd,msgrcv,nsignals,nvcsw,nivcsw)\n" +"or via the attributes ru_utime, ru_stime, ru_maxrss, and so on."); + +static PyStructSequence_Field struct_rusage_fields[] = { + {"ru_utime", "user time used"}, + {"ru_stime", "system time used"}, + {"ru_maxrss", "max. resident set size"}, + {"ru_ixrss", "shared memory size"}, + {"ru_idrss", "unshared data size"}, + {"ru_isrss", "unshared stack size"}, + {"ru_minflt", "page faults not requiring I/O"}, + {"ru_majflt", "page faults requiring I/O"}, + {"ru_nswap", "number of swap outs"}, + {"ru_inblock", "block input operations"}, + {"ru_oublock", "block output operations"}, + {"ru_msgsnd", "IPC messages sent"}, + {"ru_msgrcv", "IPC messages received"}, + {"ru_nsignals", "signals received"}, + {"ru_nvcsw", "voluntary context switches"}, + {"ru_nivcsw", "involuntary context switches"}, + {0} +}; + +static PyStructSequence_Desc struct_rusage_desc = { + "resource.struct_rusage", /* name */ + struct_rusage__doc__, /* doc */ + struct_rusage_fields, /* fields */ + 16 /* n_in_sequence */ +}; + +typedef struct { + PyTypeObject *StructRUsageType; +} resourcemodulestate; + + +static inline resourcemodulestate* +get_resource_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (resourcemodulestate *)state; +} + +static struct PyModuleDef resourcemodule; + +#ifdef HAVE_GETRUSAGE +/*[clinic input] +resource.getrusage + + who: int + / + +[clinic start generated code]*/ + +static PyObject * +resource_getrusage_impl(PyObject *module, int who) +/*[clinic end generated code: output=8fad2880ba6a9843 input=5c857bcc5b9ccb1b]*/ +{ + struct rusage ru; + PyObject *result; + + if (getrusage(who, &ru) == -1) { + if (errno == EINVAL) { + PyErr_SetString(PyExc_ValueError, + "invalid who parameter"); + return NULL; + } + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + result = PyStructSequence_New( + get_resource_state(module)->StructRUsageType); + if (!result) + return NULL; + + PyStructSequence_SET_ITEM(result, 0, + PyFloat_FromDouble(doubletime(ru.ru_utime))); + PyStructSequence_SET_ITEM(result, 1, + PyFloat_FromDouble(doubletime(ru.ru_stime))); + PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong(ru.ru_maxrss)); + PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong(ru.ru_ixrss)); + PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong(ru.ru_idrss)); + PyStructSequence_SET_ITEM(result, 5, PyLong_FromLong(ru.ru_isrss)); + PyStructSequence_SET_ITEM(result, 6, PyLong_FromLong(ru.ru_minflt)); + PyStructSequence_SET_ITEM(result, 7, PyLong_FromLong(ru.ru_majflt)); + PyStructSequence_SET_ITEM(result, 8, PyLong_FromLong(ru.ru_nswap)); + PyStructSequence_SET_ITEM(result, 9, PyLong_FromLong(ru.ru_inblock)); + PyStructSequence_SET_ITEM(result, 10, PyLong_FromLong(ru.ru_oublock)); + PyStructSequence_SET_ITEM(result, 11, PyLong_FromLong(ru.ru_msgsnd)); + PyStructSequence_SET_ITEM(result, 12, PyLong_FromLong(ru.ru_msgrcv)); + PyStructSequence_SET_ITEM(result, 13, PyLong_FromLong(ru.ru_nsignals)); + PyStructSequence_SET_ITEM(result, 14, PyLong_FromLong(ru.ru_nvcsw)); + PyStructSequence_SET_ITEM(result, 15, PyLong_FromLong(ru.ru_nivcsw)); + + if (PyErr_Occurred()) { + Py_DECREF(result); + return NULL; + } + + return result; +} +#endif + +static int +py2rlimit(PyObject *limits, struct rlimit *rl_out) +{ + PyObject *curobj, *maxobj; + limits = PySequence_Tuple(limits); + if (!limits) + /* Here limits is a borrowed reference */ + return -1; + + if (PyTuple_GET_SIZE(limits) != 2) { + PyErr_SetString(PyExc_ValueError, + "expected a tuple of 2 integers"); + goto error; + } + curobj = PyTuple_GET_ITEM(limits, 0); + maxobj = PyTuple_GET_ITEM(limits, 1); +#if !defined(HAVE_LARGEFILE_SUPPORT) + rl_out->rlim_cur = PyLong_AsLong(curobj); + if (rl_out->rlim_cur == (rlim_t)-1 && PyErr_Occurred()) + goto error; + rl_out->rlim_max = PyLong_AsLong(maxobj); + if (rl_out->rlim_max == (rlim_t)-1 && PyErr_Occurred()) + goto error; +#else + /* The limits are probably bigger than a long */ + rl_out->rlim_cur = PyLong_AsLongLong(curobj); + if (rl_out->rlim_cur == (rlim_t)-1 && PyErr_Occurred()) + goto error; + rl_out->rlim_max = PyLong_AsLongLong(maxobj); + if (rl_out->rlim_max == (rlim_t)-1 && PyErr_Occurred()) + goto error; +#endif + + Py_DECREF(limits); + rl_out->rlim_cur = rl_out->rlim_cur & RLIM_INFINITY; + rl_out->rlim_max = rl_out->rlim_max & RLIM_INFINITY; + return 0; + +error: + Py_DECREF(limits); + return -1; +} + +static PyObject* +rlimit2py(struct rlimit rl) +{ + if (sizeof(rl.rlim_cur) > sizeof(long)) { + return Py_BuildValue("LL", + (long long) rl.rlim_cur, + (long long) rl.rlim_max); + } + return Py_BuildValue("ll", (long) rl.rlim_cur, (long) rl.rlim_max); +} + +/*[clinic input] +resource.getrlimit + + resource: int + / + +[clinic start generated code]*/ + +static PyObject * +resource_getrlimit_impl(PyObject *module, int resource) +/*[clinic end generated code: output=98327b25061ffe39 input=a697cb0004cb3c36]*/ +{ + struct rlimit rl; + + if (resource < 0 || resource >= RLIM_NLIMITS) { + PyErr_SetString(PyExc_ValueError, + "invalid resource specified"); + return NULL; + } + + if (getrlimit(resource, &rl) == -1) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + return rlimit2py(rl); +} + +/*[clinic input] +resource.setrlimit + + resource: int + limits: object + / + +[clinic start generated code]*/ + +static PyObject * +resource_setrlimit_impl(PyObject *module, int resource, PyObject *limits) +/*[clinic end generated code: output=4e82ec3f34d013d1 input=6235a6ce23b4ca75]*/ +{ + struct rlimit rl; + + if (resource < 0 || resource >= RLIM_NLIMITS) { + PyErr_SetString(PyExc_ValueError, + "invalid resource specified"); + return NULL; + } + + if (PySys_Audit("resource.setrlimit", "iO", resource, + limits ? limits : Py_None) < 0) { + return NULL; + } + + if (py2rlimit(limits, &rl) < 0) { + return NULL; + } + + if (setrlimit(resource, &rl) == -1) { + if (errno == EINVAL) + PyErr_SetString(PyExc_ValueError, + "current limit exceeds maximum limit"); + else if (errno == EPERM) + PyErr_SetString(PyExc_ValueError, + "not allowed to raise maximum limit"); + else + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + Py_RETURN_NONE; +} + +#ifdef HAVE_PRLIMIT +/*[clinic input] +resource.prlimit + + pid: pid_t + resource: int + limits: object = None + / + +[clinic start generated code]*/ + +static PyObject * +resource_prlimit_impl(PyObject *module, pid_t pid, int resource, + PyObject *limits) +/*[clinic end generated code: output=6ebc49ff8c3a816e input=54bb69c9585e33bf]*/ +{ + struct rlimit old_limit, new_limit; + int retval; + + if (resource < 0 || resource >= RLIM_NLIMITS) { + PyErr_SetString(PyExc_ValueError, + "invalid resource specified"); + return NULL; + } + + if (PySys_Audit("resource.prlimit", "iiO", pid, resource, + limits ? limits : Py_None) < 0) { + return NULL; + } + + if (limits != Py_None) { + if (py2rlimit(limits, &new_limit) < 0) { + return NULL; + } + retval = prlimit(pid, resource, &new_limit, &old_limit); + } + else { + retval = prlimit(pid, resource, NULL, &old_limit); + } + + if (retval == -1) { + if (errno == EINVAL) { + PyErr_SetString(PyExc_ValueError, + "current limit exceeds maximum limit"); + } else { + PyErr_SetFromErrno(PyExc_OSError); + } + return NULL; + } + return rlimit2py(old_limit); +} +#endif /* HAVE_PRLIMIT */ + +/*[clinic input] +resource.getpagesize -> int +[clinic start generated code]*/ + +static int +resource_getpagesize_impl(PyObject *module) +/*[clinic end generated code: output=9ba93eb0f3d6c3a9 input=546545e8c1f42085]*/ +{ + long pagesize = 0; +#if defined(HAVE_GETPAGESIZE) + pagesize = getpagesize(); +#elif defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE) + pagesize = sysconf(_SC_PAGE_SIZE); +#else +# error "unsupported platform: resource.getpagesize()" +#endif + return pagesize; +} + +/* List of functions */ + +static struct PyMethodDef +resource_methods[] = { + RESOURCE_GETRUSAGE_METHODDEF + RESOURCE_GETRLIMIT_METHODDEF + RESOURCE_PRLIMIT_METHODDEF + RESOURCE_SETRLIMIT_METHODDEF + RESOURCE_GETPAGESIZE_METHODDEF + {NULL, NULL} /* sentinel */ +}; + + +/* Module initialization */ + +static int +resource_exec(PyObject *module) +{ + resourcemodulestate *state = get_resource_state(module); +#define ADD_INT(module, value) \ + do { \ + if (PyModule_AddIntConstant(module, #value, value) < 0) { \ + return -1; \ + } \ + } while (0) + + /* Add some symbolic constants to the module */ + Py_INCREF(PyExc_OSError); + if (PyModule_AddObject(module, "error", PyExc_OSError) < 0) { + Py_DECREF(PyExc_OSError); + return -1; + } + + state->StructRUsageType = PyStructSequence_NewType(&struct_rusage_desc); + if (state->StructRUsageType == NULL) { + return -1; + } + if (PyModule_AddType(module, state->StructRUsageType) < 0) { + return -1; + } + + /* insert constants */ +#ifdef RLIMIT_CPU + ADD_INT(module, RLIMIT_CPU); +#endif + +#ifdef RLIMIT_FSIZE + ADD_INT(module, RLIMIT_FSIZE); +#endif + +#ifdef RLIMIT_DATA + ADD_INT(module, RLIMIT_DATA); +#endif + +#ifdef RLIMIT_STACK + ADD_INT(module, RLIMIT_STACK); +#endif + +#ifdef RLIMIT_CORE + ADD_INT(module, RLIMIT_CORE); +#endif + +#ifdef RLIMIT_NOFILE + ADD_INT(module, RLIMIT_NOFILE); +#endif + +#ifdef RLIMIT_OFILE + ADD_INT(module, RLIMIT_OFILE); +#endif + +#ifdef RLIMIT_VMEM + ADD_INT(module, RLIMIT_VMEM); +#endif + +#ifdef RLIMIT_AS + ADD_INT(module, RLIMIT_AS); +#endif + +#ifdef RLIMIT_RSS + ADD_INT(module, RLIMIT_RSS); +#endif + +#ifdef RLIMIT_NPROC + ADD_INT(module, RLIMIT_NPROC); +#endif + +#ifdef RLIMIT_MEMLOCK + ADD_INT(module, RLIMIT_MEMLOCK); +#endif + +#ifdef RLIMIT_SBSIZE + ADD_INT(module, RLIMIT_SBSIZE); +#endif + +/* Linux specific */ +#ifdef RLIMIT_MSGQUEUE + ADD_INT(module, RLIMIT_MSGQUEUE); +#endif + +#ifdef RLIMIT_NICE + ADD_INT(module, RLIMIT_NICE); +#endif + +#ifdef RLIMIT_RTPRIO + ADD_INT(module, RLIMIT_RTPRIO); +#endif + +#ifdef RLIMIT_RTTIME + ADD_INT(module, RLIMIT_RTTIME); +#endif + +#ifdef RLIMIT_SIGPENDING + ADD_INT(module, RLIMIT_SIGPENDING); +#endif + +/* target */ +#ifdef RUSAGE_SELF + ADD_INT(module, RUSAGE_SELF); +#endif + +#ifdef RUSAGE_CHILDREN + ADD_INT(module, RUSAGE_CHILDREN); +#endif + +#ifdef RUSAGE_BOTH + ADD_INT(module, RUSAGE_BOTH); +#endif + +#ifdef RUSAGE_THREAD + ADD_INT(module, RUSAGE_THREAD); +#endif + +/* FreeBSD specific */ + +#ifdef RLIMIT_SWAP + ADD_INT(module, RLIMIT_SWAP); +#endif + +#ifdef RLIMIT_SBSIZE + ADD_INT(module, RLIMIT_SBSIZE); +#endif + +#ifdef RLIMIT_NPTS + ADD_INT(module, RLIMIT_NPTS); +#endif + +#ifdef RLIMIT_KQUEUES + ADD_INT(module, RLIMIT_KQUEUES); +#endif + + PyObject *v; + if (sizeof(RLIM_INFINITY) > sizeof(long)) { + v = PyLong_FromLongLong((long long) RLIM_INFINITY); + } else + { + v = PyLong_FromLong((long) RLIM_INFINITY); + } + if (!v) { + return -1; + } + + if (PyModule_AddObject(module, "RLIM_INFINITY", v) < 0) { + Py_DECREF(v); + return -1; + } + return 0; + +#undef ADD_INT +} + +static struct PyModuleDef_Slot resource_slots[] = { + {Py_mod_exec, resource_exec}, + {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, + {0, NULL} +}; + +static int +resourcemodule_traverse(PyObject *m, visitproc visit, void *arg) { + Py_VISIT(get_resource_state(m)->StructRUsageType); + return 0; +} + +static int +resourcemodule_clear(PyObject *m) { + Py_CLEAR(get_resource_state(m)->StructRUsageType); + return 0; +} + +static void +resourcemodule_free(void *m) { + resourcemodule_clear((PyObject *)m); +} + +static struct PyModuleDef resourcemodule = { + PyModuleDef_HEAD_INIT, + .m_name = "resource", + .m_size = sizeof(resourcemodulestate), + .m_methods = resource_methods, + .m_slots = resource_slots, + .m_traverse = resourcemodule_traverse, + .m_clear = resourcemodule_clear, + .m_free = resourcemodule_free, +}; + +PyMODINIT_FUNC +PyInit_resource(void) +{ + return PyModuleDef_Init(&resourcemodule); +} |