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