blob: 48d148d7819894bc843daa3f69cad2f2f5471045 [file] [log] [blame]
Guido van Rossum2e631391996-12-18 18:37:27 +00001#include "Python.h"
2#include <sys/resource.h>
3#include <sys/time.h>
4#include <unistd.h>
5#include <string.h>
6#include <errno.h>
7
8/* don't know why this isn't defined in a header file */
9#ifndef getrusage
10int getrusage(int who, struct rusage *rusage);
11#endif
12
13#ifndef getpagesize
14int getpagesize(void);
15#endif
16
17#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
18
19static PyObject *ResourceError;
20
21static PyObject *
22resource_getrusage(self, args)
23 PyObject *self;
24 PyObject *args;
25{
26 int who;
27 struct rusage ru;
28
29 if (!PyArg_ParseTuple(args, "i", &who))
30 return NULL;
31
32 if (getrusage(who, &ru) == -1) {
33 if (errno == EINVAL) {
34 PyErr_SetString(PyExc_ValueError,
35 "invalid who parameter");
36 return NULL;
37 }
38 PyErr_SetFromErrno(ResourceError);
39 return NULL;
40 }
41
42 /* Yeah, this 16-tuple is way ugly. It's probably a lot less
43 ugly than a dictionary with keys (or object attributes)
44 named things like 'ixrss'.
45 */
46 return Py_BuildValue(
47 "ddiiiiiiiiiiiiii",
48 doubletime(ru.ru_utime), /* user time used */
49 doubletime(ru.ru_stime), /* system time used */
50 ru.ru_maxrss, /* max. resident set size */
51 ru.ru_ixrss, /* shared memory size */
52 ru.ru_idrss, /* unshared memory size */
53 ru.ru_isrss, /* unshared stack size */
54 ru.ru_minflt, /* page faults not requiring I/O*/
55 ru.ru_majflt, /* page faults requiring I/O */
56 ru.ru_nswap, /* number of swap outs */
57 ru.ru_inblock, /* block input operations */
58 ru.ru_oublock, /* block output operations */
59 ru.ru_msgsnd, /* messages sent */
60 ru.ru_msgrcv, /* messages received */
61 ru.ru_nsignals, /* signals received */
62 ru.ru_nvcsw, /* voluntary context switchs */
63 ru.ru_nivcsw /* involuntary context switchs */
64 );
65}
66
67
68static PyObject *
69resource_getrlimit(self, args)
70 PyObject *self;
71 PyObject *args;
72{
73 struct rlimit rl;
74 int resource;
75 char *errstr;
76
77 if (!PyArg_ParseTuple(args, "i", &resource))
78 return NULL;
79
80 if (resource < 0 || resource >= RLIM_NLIMITS) {
81 PyErr_SetString(PyExc_ValueError,
82 "invalid resource specified");
83 return NULL;
84 }
85
86 if (getrlimit(resource, &rl) == -1) {
87 PyErr_SetFromErrno(ResourceError);
88 return NULL;
89 }
90 return Py_BuildValue("ii", rl.rlim_cur, rl.rlim_max);
91}
92
93static PyObject *
94resource_setrlimit(self, args)
95 PyObject *self;
96 PyObject *args;
97{
98 struct rlimit rl;
99 int resource;
100 char *errstr;
101
102 if (!PyArg_ParseTuple(args, "i(ii)", &resource, &rl.rlim_cur,
103 &rl.rlim_max))
104 return NULL;
105
106 if (resource < 0 || resource >= RLIM_NLIMITS) {
107 PyErr_SetString(PyExc_ValueError,
108 "invalid resource specified");
109 return NULL;
110 }
111
112 rl.rlim_cur = rl.rlim_cur & RLIM_INFINITY;
113 rl.rlim_max = rl.rlim_max & RLIM_INFINITY;
114 if (setrlimit(resource, &rl) == -1) {
115 if (errno == EINVAL)
116 PyErr_SetString(PyExc_ValueError,
117 "current limit exceeds maximum limit");
118 else if (errno == EPERM)
119 PyErr_SetString(PyExc_ValueError,
120 "not allowed to raise maximum limit");
121 else
122 PyErr_SetFromErrno(ResourceError);
123 return NULL;
124 }
125 Py_INCREF(Py_None);
126 return Py_None;
127}
128
129static PyObject *
130resource_getpagesize(self, args)
131 PyObject *self;
132 PyObject *args;
133{
134 if (!PyArg_ParseTuple(args, ""))
135 return NULL;
136 return Py_BuildValue("i", getpagesize());
137}
138
139/* List of functions */
140
141static struct PyMethodDef
142resource_methods[] = {
143 {"getrusage", resource_getrusage, 1},
144 {"getrlimit", resource_getrlimit, 1},
145 {"setrlimit", resource_setrlimit, 1},
146 {"getpagesize", resource_getpagesize, 1},
147 {NULL, NULL} /* sentinel */
148};
149
150
151/* Module initialization */
152
153static void
154ins(PyObject *dict, char *name, int value)
155{
156 PyObject *v = PyInt_FromLong((long) value);
157 if (v) {
158 PyDict_SetItemString(dict, name, v);
159 Py_DECREF(v);
160 }
161 /* errors will be checked by initresource() */
162}
163
164void initresource()
165{
166 PyObject *m, *d;
167
168 /* Create the module and add the functions */
169 m = Py_InitModule("resource", resource_methods);
170
171 /* Add some symbolic constants to the module */
172 d = PyModule_GetDict(m);
173 ResourceError = PyString_FromString("resource.error");
174 PyDict_SetItemString(d, "error", ResourceError);
175
176 /* insert constants */
177#ifdef RLIMIT_CPU
178 ins(d, "RLIMIT_CPU", RLIMIT_CPU);
179#endif
180
181#ifdef RLIMIT_FSIZE
182 ins(d, "RLIMIT_FSIZE", RLIMIT_FSIZE);
183#endif
184
185#ifdef RLIMIT_DATA
186 ins(d, "RLIMIT_DATA", RLIMIT_DATA);
187#endif
188
189#ifdef RLIMIT_STACK
190 ins(d, "RLIMIT_STACK", RLIMIT_STACK);
191#endif
192
193#ifdef RLIMIT_CORE
194 ins(d, "RLIMIT_CORE", RLIMIT_CORE);
195#endif
196
197#ifdef RLIMIT_NOFILE
198 ins(d, "RLIMIT_NOFILE", RLIMIT_NOFILE);
199#endif
200
201#ifdef RLIMIT_OFILE
202 ins(d, "RLIMIT_OFILE", RLIMIT_OFILE);
203#endif
204
205#ifdef RLIMIT_VMEM
206 ins(d, "RLIMIT_VMEM", RLIMIT_VMEM);
207#endif
208
209#ifdef RLIMIT_AS
210 ins(d, "RLIMIT_AS", RLIMIT_AS);
211#endif
212
213#ifdef RLIMIT_RSS
214 ins(d, "RLIMIT_RSS", RLIMIT_RSS);
215#endif
216
217#ifdef RLIMIT_NPROC
218 ins(d, "RLIMIT_NPROC", RLIMIT_NPROC);
219#endif
220
221#ifdef RLIMIT_MEMLOCK
222 ins(d, "RLIMIT_MEMLOCK", RLIMIT_MEMLOCK);
223#endif
224
225#ifdef RUSAGE_SELF
226 ins(d, "RUSAGE_SELF", RUSAGE_SELF);
227#endif
228
229#ifdef RUSAGE_CHILDERN
230 ins(d, "RUSAGE_CHILDREN", RUSAGE_CHILDREN);
231#endif
232
233#ifdef RUSAGE_BOTH
234 ins(d, "RUSAGE_BOTH", RUSAGE_BOTH);
235#endif
236
237 /* Check for errors */
238 if (PyErr_Occurred())
239 Py_FatalError("can't initialize module resource");
240}