3
#include <sys/resource.h>
8
#if defined(HAVE_UNISTD_H)
12
/* On some systems, these aren't in any header file.
13
On others they are, with inconsistent prototypes.
14
We declare the (default) return type, to shut up gcc -Wall;
15
but we can't declare the prototype, to avoid errors
16
when the header files declare it different.
17
Worse, on some Linuxes, getpagesize() returns a size_t... */
19
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
21
PyDoc_STRVAR(struct_rusage__doc__,
22
"struct_rusage: Result from getrusage.\n\n"
23
"This object may be accessed either as a tuple of\n"
24
" (utime,stime,maxrss,ixrss,idrss,isrss,minflt,majflt,\n"
25
" nswap,inblock,oublock,msgsnd,msgrcv,nsignals,nvcsw,nivcsw)\n"
26
"or via the attributes ru_utime, ru_stime, ru_maxrss, and so on.");
28
static PyStructSequence_Field struct_rusage_fields[] = {
29
{"ru_utime", "user time used"},
30
{"ru_stime", "system time used"},
31
{"ru_maxrss", "max. resident set size"},
32
{"ru_ixrss", "shared memory size"},
33
{"ru_idrss", "unshared data size"},
34
{"ru_isrss", "unshared stack size"},
35
{"ru_minflt", "page faults not requiring I/O"},
36
{"ru_majflt", "page faults requiring I/O"},
37
{"ru_nswap", "number of swap outs"},
38
{"ru_inblock", "block input operations"},
39
{"ru_oublock", "block output operations"},
40
{"ru_msgsnd", "IPC messages sent"},
41
{"ru_msgrcv", "IPC messages received"},
42
{"ru_nsignals", "signals received"},
43
{"ru_nvcsw", "voluntary context switches"},
44
{"ru_nivcsw", "involuntary context switches"},
48
static PyStructSequence_Desc struct_rusage_desc = {
49
"resource.struct_rusage", /* name */
50
struct_rusage__doc__, /* doc */
51
struct_rusage_fields, /* fields */
52
16 /* n_in_sequence */
55
static int initialized;
56
static PyTypeObject StructRUsageType;
59
resource_getrusage(PyObject *self, PyObject *args)
65
if (!PyArg_ParseTuple(args, "i:getrusage", &who))
68
if (getrusage(who, &ru) == -1) {
69
if (errno == EINVAL) {
70
PyErr_SetString(PyExc_ValueError,
71
"invalid who parameter");
74
PyErr_SetFromErrno(PyExc_OSError);
78
result = PyStructSequence_New(&StructRUsageType);
82
PyStructSequence_SET_ITEM(result, 0,
83
PyFloat_FromDouble(doubletime(ru.ru_utime)));
84
PyStructSequence_SET_ITEM(result, 1,
85
PyFloat_FromDouble(doubletime(ru.ru_stime)));
86
PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong(ru.ru_maxrss));
87
PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong(ru.ru_ixrss));
88
PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong(ru.ru_idrss));
89
PyStructSequence_SET_ITEM(result, 5, PyLong_FromLong(ru.ru_isrss));
90
PyStructSequence_SET_ITEM(result, 6, PyLong_FromLong(ru.ru_minflt));
91
PyStructSequence_SET_ITEM(result, 7, PyLong_FromLong(ru.ru_majflt));
92
PyStructSequence_SET_ITEM(result, 8, PyLong_FromLong(ru.ru_nswap));
93
PyStructSequence_SET_ITEM(result, 9, PyLong_FromLong(ru.ru_inblock));
94
PyStructSequence_SET_ITEM(result, 10, PyLong_FromLong(ru.ru_oublock));
95
PyStructSequence_SET_ITEM(result, 11, PyLong_FromLong(ru.ru_msgsnd));
96
PyStructSequence_SET_ITEM(result, 12, PyLong_FromLong(ru.ru_msgrcv));
97
PyStructSequence_SET_ITEM(result, 13, PyLong_FromLong(ru.ru_nsignals));
98
PyStructSequence_SET_ITEM(result, 14, PyLong_FromLong(ru.ru_nvcsw));
99
PyStructSequence_SET_ITEM(result, 15, PyLong_FromLong(ru.ru_nivcsw));
101
if (PyErr_Occurred()) {
110
py2rlimit(PyObject *curobj, PyObject *maxobj, struct rlimit *rl_out)
112
#if !defined(HAVE_LARGEFILE_SUPPORT)
113
rl_out->rlim_cur = PyLong_AsLong(curobj);
114
if (rl_out->rlim_cur == (rlim_t)-1 && PyErr_Occurred())
116
rl_out->rlim_max = PyLong_AsLong(maxobj);
117
if (rl_out->rlim_max == (rlim_t)-1 && PyErr_Occurred())
120
/* The limits are probably bigger than a long */
121
rl_out->rlim_cur = PyLong_AsLongLong(curobj);
122
if (rl_out->rlim_cur == (rlim_t)-1 && PyErr_Occurred())
124
rl_out->rlim_max = PyLong_AsLongLong(maxobj);
125
if (rl_out->rlim_max == (rlim_t)-1 && PyErr_Occurred())
129
rl_out->rlim_cur = rl_out->rlim_cur & RLIM_INFINITY;
130
rl_out->rlim_max = rl_out->rlim_max & RLIM_INFINITY;
136
rlimit2py(struct rlimit rl)
138
#if defined(HAVE_LONG_LONG)
139
if (sizeof(rl.rlim_cur) > sizeof(long)) {
140
return Py_BuildValue("LL",
141
(PY_LONG_LONG) rl.rlim_cur,
142
(PY_LONG_LONG) rl.rlim_max);
145
return Py_BuildValue("ll", (long) rl.rlim_cur, (long) rl.rlim_max);
149
resource_getrlimit(PyObject *self, PyObject *args)
154
if (!PyArg_ParseTuple(args, "i:getrlimit", &resource))
157
if (resource < 0 || resource >= RLIM_NLIMITS) {
158
PyErr_SetString(PyExc_ValueError,
159
"invalid resource specified");
163
if (getrlimit(resource, &rl) == -1) {
164
PyErr_SetFromErrno(PyExc_OSError);
167
return rlimit2py(rl);
171
resource_setrlimit(PyObject *self, PyObject *args)
175
PyObject *limits, *curobj, *maxobj;
177
if (!PyArg_ParseTuple(args, "iO:setrlimit", &resource, &limits))
180
if (resource < 0 || resource >= RLIM_NLIMITS) {
181
PyErr_SetString(PyExc_ValueError,
182
"invalid resource specified");
186
limits = PySequence_Tuple(limits);
188
/* Here limits is a borrowed reference */
191
if (PyTuple_GET_SIZE(limits) != 2) {
192
PyErr_SetString(PyExc_ValueError,
193
"expected a tuple of 2 integers");
196
curobj = PyTuple_GET_ITEM(limits, 0);
197
maxobj = PyTuple_GET_ITEM(limits, 1);
199
if (py2rlimit(curobj, maxobj, &rl) < 0) {
203
if (setrlimit(resource, &rl) == -1) {
205
PyErr_SetString(PyExc_ValueError,
206
"current limit exceeds maximum limit");
207
else if (errno == EPERM)
208
PyErr_SetString(PyExc_ValueError,
209
"not allowed to raise maximum limit");
211
PyErr_SetFromErrno(PyExc_OSError);
225
resource_prlimit(PyObject *self, PyObject *args)
227
struct rlimit old_limit, new_limit;
228
int resource, retval;
230
PyObject *curobj=NULL, *maxobj=NULL;
232
if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i|(OO):prlimit",
233
&pid, &resource, &curobj, &maxobj))
236
if (resource < 0 || resource >= RLIM_NLIMITS) {
237
PyErr_SetString(PyExc_ValueError,
238
"invalid resource specified");
242
if (curobj != NULL) {
243
if (py2rlimit(curobj, maxobj, &new_limit) < 0) {
246
retval = prlimit(pid, resource, &new_limit, &old_limit);
249
retval = prlimit(pid, resource, NULL, &old_limit);
253
if (errno == EINVAL) {
254
PyErr_SetString(PyExc_ValueError,
255
"current limit exceeds maximum limit");
257
PyErr_SetFromErrno(PyExc_OSError);
261
return rlimit2py(old_limit);
263
#endif /* HAVE_PRLIMIT */
266
resource_getpagesize(PyObject *self, PyObject *unused)
269
#if defined(HAVE_GETPAGESIZE)
270
pagesize = getpagesize();
271
#elif defined(HAVE_SYSCONF)
272
#if defined(_SC_PAGE_SIZE)
273
pagesize = sysconf(_SC_PAGE_SIZE);
275
/* Irix 5.3 has _SC_PAGESIZE, but not _SC_PAGE_SIZE */
276
pagesize = sysconf(_SC_PAGESIZE);
279
return Py_BuildValue("i", pagesize);
283
/* List of functions */
285
static struct PyMethodDef
286
resource_methods[] = {
287
{"getrusage", resource_getrusage, METH_VARARGS},
288
{"getrlimit", resource_getrlimit, METH_VARARGS},
290
{"prlimit", resource_prlimit, METH_VARARGS},
292
{"setrlimit", resource_setrlimit, METH_VARARGS},
293
{"getpagesize", resource_getpagesize, METH_NOARGS},
294
{NULL, NULL} /* sentinel */
298
/* Module initialization */
301
static struct PyModuleDef resourcemodule = {
302
PyModuleDef_HEAD_INIT,
314
PyInit_resource(void)
318
/* Create the module and add the functions */
319
m = PyModule_Create(&resourcemodule);
323
/* Add some symbolic constants to the module */
324
Py_INCREF(PyExc_OSError);
325
PyModule_AddObject(m, "error", PyExc_OSError);
327
if (PyStructSequence_InitType2(&StructRUsageType,
328
&struct_rusage_desc) < 0)
332
Py_INCREF(&StructRUsageType);
333
PyModule_AddObject(m, "struct_rusage",
334
(PyObject*) &StructRUsageType);
336
/* insert constants */
338
PyModule_AddIntMacro(m, RLIMIT_CPU);
342
PyModule_AddIntMacro(m, RLIMIT_FSIZE);
346
PyModule_AddIntMacro(m, RLIMIT_DATA);
350
PyModule_AddIntMacro(m, RLIMIT_STACK);
354
PyModule_AddIntMacro(m, RLIMIT_CORE);
358
PyModule_AddIntMacro(m, RLIMIT_NOFILE);
362
PyModule_AddIntMacro(m, RLIMIT_OFILE);
366
PyModule_AddIntMacro(m, RLIMIT_VMEM);
370
PyModule_AddIntMacro(m, RLIMIT_AS);
374
PyModule_AddIntMacro(m, RLIMIT_RSS);
378
PyModule_AddIntMacro(m, RLIMIT_NPROC);
381
#ifdef RLIMIT_MEMLOCK
382
PyModule_AddIntMacro(m, RLIMIT_MEMLOCK);
386
PyModule_AddIntMacro(m, RLIMIT_SBSIZE);
390
#ifdef RLIMIT_MSGQUEUE
391
PyModule_AddIntMacro(m, RLIMIT_MSGQUEUE);
395
PyModule_AddIntMacro(m, RLIMIT_NICE);
399
PyModule_AddIntMacro(m, RLIMIT_RTPRIO);
403
PyModule_AddIntMacro(m, RLIMIT_RTTIME);
406
#ifdef RLIMIT_SIGPENDING
407
PyModule_AddIntMacro(m, RLIMIT_SIGPENDING);
412
PyModule_AddIntMacro(m, RUSAGE_SELF);
415
#ifdef RUSAGE_CHILDREN
416
PyModule_AddIntMacro(m, RUSAGE_CHILDREN);
420
PyModule_AddIntMacro(m, RUSAGE_BOTH);
424
PyModule_AddIntMacro(m, RUSAGE_THREAD);
427
#if defined(HAVE_LONG_LONG)
428
if (sizeof(RLIM_INFINITY) > sizeof(long)) {
429
v = PyLong_FromLongLong((PY_LONG_LONG) RLIM_INFINITY);
433
v = PyLong_FromLong((long) RLIM_INFINITY);
436
PyModule_AddObject(m, "RLIM_INFINITY", v);