blob: 01fe79c38d6590f3f122f7b9475bfa0124ce5b45 [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;
Guido van Rossum2e631391996-12-18 18:37:27 +000075
76 if (!PyArg_ParseTuple(args, "i", &resource))
77 return NULL;
78
79 if (resource < 0 || resource >= RLIM_NLIMITS) {
80 PyErr_SetString(PyExc_ValueError,
81 "invalid resource specified");
82 return NULL;
83 }
84
85 if (getrlimit(resource, &rl) == -1) {
86 PyErr_SetFromErrno(ResourceError);
87 return NULL;
88 }
89 return Py_BuildValue("ii", rl.rlim_cur, rl.rlim_max);
90}
91
92static PyObject *
93resource_setrlimit(self, args)
94 PyObject *self;
95 PyObject *args;
96{
97 struct rlimit rl;
98 int resource;
Guido van Rossum2e631391996-12-18 18:37:27 +000099
100 if (!PyArg_ParseTuple(args, "i(ii)", &resource, &rl.rlim_cur,
101 &rl.rlim_max))
102 return NULL;
103
104 if (resource < 0 || resource >= RLIM_NLIMITS) {
105 PyErr_SetString(PyExc_ValueError,
106 "invalid resource specified");
107 return NULL;
108 }
109
110 rl.rlim_cur = rl.rlim_cur & RLIM_INFINITY;
111 rl.rlim_max = rl.rlim_max & RLIM_INFINITY;
112 if (setrlimit(resource, &rl) == -1) {
113 if (errno == EINVAL)
114 PyErr_SetString(PyExc_ValueError,
115 "current limit exceeds maximum limit");
116 else if (errno == EPERM)
117 PyErr_SetString(PyExc_ValueError,
118 "not allowed to raise maximum limit");
119 else
120 PyErr_SetFromErrno(ResourceError);
121 return NULL;
122 }
123 Py_INCREF(Py_None);
124 return Py_None;
125}
126
127static PyObject *
128resource_getpagesize(self, args)
129 PyObject *self;
130 PyObject *args;
131{
132 if (!PyArg_ParseTuple(args, ""))
133 return NULL;
134 return Py_BuildValue("i", getpagesize());
135}
136
137/* List of functions */
138
139static struct PyMethodDef
140resource_methods[] = {
141 {"getrusage", resource_getrusage, 1},
142 {"getrlimit", resource_getrlimit, 1},
143 {"setrlimit", resource_setrlimit, 1},
144 {"getpagesize", resource_getpagesize, 1},
145 {NULL, NULL} /* sentinel */
146};
147
148
149/* Module initialization */
150
151static void
152ins(PyObject *dict, char *name, int value)
153{
154 PyObject *v = PyInt_FromLong((long) value);
155 if (v) {
156 PyDict_SetItemString(dict, name, v);
157 Py_DECREF(v);
158 }
159 /* errors will be checked by initresource() */
160}
161
162void initresource()
163{
164 PyObject *m, *d;
165
166 /* Create the module and add the functions */
167 m = Py_InitModule("resource", resource_methods);
168
169 /* Add some symbolic constants to the module */
170 d = PyModule_GetDict(m);
171 ResourceError = PyString_FromString("resource.error");
172 PyDict_SetItemString(d, "error", ResourceError);
173
174 /* insert constants */
175#ifdef RLIMIT_CPU
176 ins(d, "RLIMIT_CPU", RLIMIT_CPU);
177#endif
178
179#ifdef RLIMIT_FSIZE
180 ins(d, "RLIMIT_FSIZE", RLIMIT_FSIZE);
181#endif
182
183#ifdef RLIMIT_DATA
184 ins(d, "RLIMIT_DATA", RLIMIT_DATA);
185#endif
186
187#ifdef RLIMIT_STACK
188 ins(d, "RLIMIT_STACK", RLIMIT_STACK);
189#endif
190
191#ifdef RLIMIT_CORE
192 ins(d, "RLIMIT_CORE", RLIMIT_CORE);
193#endif
194
195#ifdef RLIMIT_NOFILE
196 ins(d, "RLIMIT_NOFILE", RLIMIT_NOFILE);
197#endif
198
199#ifdef RLIMIT_OFILE
200 ins(d, "RLIMIT_OFILE", RLIMIT_OFILE);
201#endif
202
203#ifdef RLIMIT_VMEM
204 ins(d, "RLIMIT_VMEM", RLIMIT_VMEM);
205#endif
206
207#ifdef RLIMIT_AS
208 ins(d, "RLIMIT_AS", RLIMIT_AS);
209#endif
210
211#ifdef RLIMIT_RSS
212 ins(d, "RLIMIT_RSS", RLIMIT_RSS);
213#endif
214
215#ifdef RLIMIT_NPROC
216 ins(d, "RLIMIT_NPROC", RLIMIT_NPROC);
217#endif
218
219#ifdef RLIMIT_MEMLOCK
220 ins(d, "RLIMIT_MEMLOCK", RLIMIT_MEMLOCK);
221#endif
222
223#ifdef RUSAGE_SELF
224 ins(d, "RUSAGE_SELF", RUSAGE_SELF);
225#endif
226
227#ifdef RUSAGE_CHILDERN
228 ins(d, "RUSAGE_CHILDREN", RUSAGE_CHILDREN);
229#endif
230
231#ifdef RUSAGE_BOTH
232 ins(d, "RUSAGE_BOTH", RUSAGE_BOTH);
233#endif
234
235 /* Check for errors */
236 if (PyErr_Occurred())
237 Py_FatalError("can't initialize module resource");
238}