blob: 428c32c03f8cbe75ef486f7f175a99374d7ead35 [file] [log] [blame]
Guido van Rossumf84a5391997-08-15 00:04:24 +00001/***********************************************************
2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
16
17While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
29
30******************************************************************/
31
Guido van Rossum2e631391996-12-18 18:37:27 +000032#include "Python.h"
33#include <sys/resource.h>
34#include <sys/time.h>
35#include <unistd.h>
36#include <string.h>
37#include <errno.h>
38
Guido van Rossum607b33a1997-08-17 16:24:30 +000039/* On some systems, these aren't in any header file.
40 On others they are, with inconsistent prototypes.
41 We declare the (default) return type, to shut up gcc -Wall;
42 but we can't declare the prototype, to avoid errors
43 when the header files declare it different.
44 Worse, on some Linuxes, getpagesize() returns a size_t... */
45#ifndef linux
46int getrusage();
47int getpagesize();
Guido van Rossum668e4411997-08-05 02:24:57 +000048#endif
Guido van Rossum2e631391996-12-18 18:37:27 +000049
50#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
51
52static PyObject *ResourceError;
53
54static PyObject *
55resource_getrusage(self, args)
56 PyObject *self;
57 PyObject *args;
58{
59 int who;
60 struct rusage ru;
61
62 if (!PyArg_ParseTuple(args, "i", &who))
63 return NULL;
64
65 if (getrusage(who, &ru) == -1) {
66 if (errno == EINVAL) {
67 PyErr_SetString(PyExc_ValueError,
68 "invalid who parameter");
69 return NULL;
70 }
71 PyErr_SetFromErrno(ResourceError);
72 return NULL;
73 }
74
75 /* Yeah, this 16-tuple is way ugly. It's probably a lot less
76 ugly than a dictionary with keys (or object attributes)
77 named things like 'ixrss'.
78 */
79 return Py_BuildValue(
80 "ddiiiiiiiiiiiiii",
81 doubletime(ru.ru_utime), /* user time used */
82 doubletime(ru.ru_stime), /* system time used */
83 ru.ru_maxrss, /* max. resident set size */
84 ru.ru_ixrss, /* shared memory size */
85 ru.ru_idrss, /* unshared memory size */
86 ru.ru_isrss, /* unshared stack size */
87 ru.ru_minflt, /* page faults not requiring I/O*/
88 ru.ru_majflt, /* page faults requiring I/O */
89 ru.ru_nswap, /* number of swap outs */
90 ru.ru_inblock, /* block input operations */
91 ru.ru_oublock, /* block output operations */
92 ru.ru_msgsnd, /* messages sent */
93 ru.ru_msgrcv, /* messages received */
94 ru.ru_nsignals, /* signals received */
95 ru.ru_nvcsw, /* voluntary context switchs */
96 ru.ru_nivcsw /* involuntary context switchs */
97 );
98}
99
100
101static PyObject *
102resource_getrlimit(self, args)
103 PyObject *self;
104 PyObject *args;
105{
106 struct rlimit rl;
107 int resource;
Guido van Rossum2e631391996-12-18 18:37:27 +0000108
109 if (!PyArg_ParseTuple(args, "i", &resource))
110 return NULL;
111
112 if (resource < 0 || resource >= RLIM_NLIMITS) {
113 PyErr_SetString(PyExc_ValueError,
114 "invalid resource specified");
115 return NULL;
116 }
117
118 if (getrlimit(resource, &rl) == -1) {
119 PyErr_SetFromErrno(ResourceError);
120 return NULL;
121 }
122 return Py_BuildValue("ii", rl.rlim_cur, rl.rlim_max);
123}
124
125static PyObject *
126resource_setrlimit(self, args)
127 PyObject *self;
128 PyObject *args;
129{
130 struct rlimit rl;
131 int resource;
Guido van Rossum2e631391996-12-18 18:37:27 +0000132
133 if (!PyArg_ParseTuple(args, "i(ii)", &resource, &rl.rlim_cur,
134 &rl.rlim_max))
135 return NULL;
136
137 if (resource < 0 || resource >= RLIM_NLIMITS) {
138 PyErr_SetString(PyExc_ValueError,
139 "invalid resource specified");
140 return NULL;
141 }
142
143 rl.rlim_cur = rl.rlim_cur & RLIM_INFINITY;
144 rl.rlim_max = rl.rlim_max & RLIM_INFINITY;
145 if (setrlimit(resource, &rl) == -1) {
146 if (errno == EINVAL)
147 PyErr_SetString(PyExc_ValueError,
148 "current limit exceeds maximum limit");
149 else if (errno == EPERM)
150 PyErr_SetString(PyExc_ValueError,
151 "not allowed to raise maximum limit");
152 else
153 PyErr_SetFromErrno(ResourceError);
154 return NULL;
155 }
156 Py_INCREF(Py_None);
157 return Py_None;
158}
159
160static PyObject *
161resource_getpagesize(self, args)
162 PyObject *self;
163 PyObject *args;
164{
165 if (!PyArg_ParseTuple(args, ""))
166 return NULL;
167 return Py_BuildValue("i", getpagesize());
168}
169
170/* List of functions */
171
172static struct PyMethodDef
173resource_methods[] = {
174 {"getrusage", resource_getrusage, 1},
175 {"getrlimit", resource_getrlimit, 1},
176 {"setrlimit", resource_setrlimit, 1},
177 {"getpagesize", resource_getpagesize, 1},
178 {NULL, NULL} /* sentinel */
179};
180
181
182/* Module initialization */
183
184static void
185ins(PyObject *dict, char *name, int value)
186{
187 PyObject *v = PyInt_FromLong((long) value);
188 if (v) {
189 PyDict_SetItemString(dict, name, v);
190 Py_DECREF(v);
191 }
192 /* errors will be checked by initresource() */
193}
194
195void initresource()
196{
197 PyObject *m, *d;
198
199 /* Create the module and add the functions */
200 m = Py_InitModule("resource", resource_methods);
201
202 /* Add some symbolic constants to the module */
203 d = PyModule_GetDict(m);
204 ResourceError = PyString_FromString("resource.error");
205 PyDict_SetItemString(d, "error", ResourceError);
206
207 /* insert constants */
208#ifdef RLIMIT_CPU
209 ins(d, "RLIMIT_CPU", RLIMIT_CPU);
210#endif
211
212#ifdef RLIMIT_FSIZE
213 ins(d, "RLIMIT_FSIZE", RLIMIT_FSIZE);
214#endif
215
216#ifdef RLIMIT_DATA
217 ins(d, "RLIMIT_DATA", RLIMIT_DATA);
218#endif
219
220#ifdef RLIMIT_STACK
221 ins(d, "RLIMIT_STACK", RLIMIT_STACK);
222#endif
223
224#ifdef RLIMIT_CORE
225 ins(d, "RLIMIT_CORE", RLIMIT_CORE);
226#endif
227
228#ifdef RLIMIT_NOFILE
229 ins(d, "RLIMIT_NOFILE", RLIMIT_NOFILE);
230#endif
231
232#ifdef RLIMIT_OFILE
233 ins(d, "RLIMIT_OFILE", RLIMIT_OFILE);
234#endif
235
236#ifdef RLIMIT_VMEM
237 ins(d, "RLIMIT_VMEM", RLIMIT_VMEM);
238#endif
239
240#ifdef RLIMIT_AS
241 ins(d, "RLIMIT_AS", RLIMIT_AS);
242#endif
243
244#ifdef RLIMIT_RSS
245 ins(d, "RLIMIT_RSS", RLIMIT_RSS);
246#endif
247
248#ifdef RLIMIT_NPROC
249 ins(d, "RLIMIT_NPROC", RLIMIT_NPROC);
250#endif
251
252#ifdef RLIMIT_MEMLOCK
253 ins(d, "RLIMIT_MEMLOCK", RLIMIT_MEMLOCK);
254#endif
255
256#ifdef RUSAGE_SELF
257 ins(d, "RUSAGE_SELF", RUSAGE_SELF);
258#endif
259
260#ifdef RUSAGE_CHILDERN
261 ins(d, "RUSAGE_CHILDREN", RUSAGE_CHILDREN);
262#endif
263
264#ifdef RUSAGE_BOTH
265 ins(d, "RUSAGE_BOTH", RUSAGE_BOTH);
266#endif
267
268 /* Check for errors */
269 if (PyErr_Occurred())
270 Py_FatalError("can't initialize module resource");
271}