OLD | NEW |
| (Empty) |
1 /* | |
2 * $Id: _psutil_linux.c 1142 2011-10-05 18:45:49Z g.rodola $ | |
3 * | |
4 * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. | |
5 * Use of this source code is governed by a BSD-style license that can be | |
6 * found in the LICENSE file. | |
7 * | |
8 * Linux-specific functions. | |
9 */ | |
10 | |
11 #include <Python.h> | |
12 #include <errno.h> | |
13 #include <stdlib.h> | |
14 #include <mntent.h> | |
15 #include <sys/syscall.h> | |
16 #include <linux/unistd.h> | |
17 | |
18 #include "_psutil_linux.h" | |
19 | |
20 | |
21 #define HAS_IOPRIO defined(__NR_ioprio_get) && defined(__NR_ioprio_set) | |
22 | |
23 #if HAS_IOPRIO | |
24 enum { | |
25 IOPRIO_WHO_PROCESS = 1, | |
26 }; | |
27 | |
28 static inline int | |
29 ioprio_get(int which, int who) | |
30 { | |
31 return syscall(__NR_ioprio_get, which, who); | |
32 } | |
33 | |
34 static inline int | |
35 ioprio_set(int which, int who, int ioprio) | |
36 { | |
37 return syscall(__NR_ioprio_set, which, who, ioprio); | |
38 } | |
39 | |
40 #define IOPRIO_CLASS_SHIFT 13 | |
41 #define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1) | |
42 | |
43 #define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT) | |
44 #define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK) | |
45 #define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data) | |
46 | |
47 | |
48 /* | |
49 * Return a (ioclass, iodata) Python tuple representing process I/O priority. | |
50 */ | |
51 static PyObject* | |
52 linux_ioprio_get(PyObject* self, PyObject* args) | |
53 { | |
54 long pid; | |
55 int ioprio, ioclass, iodata; | |
56 if (! PyArg_ParseTuple(args, "l", &pid)) { | |
57 return NULL; | |
58 } | |
59 ioprio = ioprio_get(IOPRIO_WHO_PROCESS, pid); | |
60 if (ioprio == -1) { | |
61 return PyErr_SetFromErrno(PyExc_OSError); | |
62 } | |
63 ioclass = IOPRIO_PRIO_CLASS(ioprio); | |
64 iodata = IOPRIO_PRIO_DATA(ioprio); | |
65 return Py_BuildValue("ii", ioclass, iodata); | |
66 } | |
67 | |
68 | |
69 /* | |
70 * A wrapper around ioprio_set(); sets process I/O priority. | |
71 * ioclass can be either IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE | |
72 * or 0. iodata goes from 0 to 7 depending on ioclass specified. | |
73 */ | |
74 static PyObject* | |
75 linux_ioprio_set(PyObject* self, PyObject* args) | |
76 { | |
77 long pid; | |
78 int ioprio, ioclass, iodata; | |
79 int retval; | |
80 | |
81 if (! PyArg_ParseTuple(args, "lii", &pid, &ioclass, &iodata)) { | |
82 return NULL; | |
83 } | |
84 ioprio = IOPRIO_PRIO_VALUE(ioclass, iodata); | |
85 retval = ioprio_set(IOPRIO_WHO_PROCESS, pid, ioprio); | |
86 if (retval == -1) { | |
87 return PyErr_SetFromErrno(PyExc_OSError); | |
88 } | |
89 Py_INCREF(Py_None); | |
90 return Py_None; | |
91 } | |
92 #endif | |
93 | |
94 | |
95 /* | |
96 * Return disk mounted partitions as a list of tuples including device, | |
97 * mount point and filesystem type | |
98 */ | |
99 static PyObject* | |
100 get_disk_partitions(PyObject* self, PyObject* args) | |
101 { | |
102 FILE *file; | |
103 struct mntent *entry; | |
104 PyObject* py_retlist = PyList_New(0); | |
105 PyObject* py_tuple; | |
106 | |
107 // MOUNTED constant comes from mntent.h and it's == '/etc/mtab' | |
108 Py_BEGIN_ALLOW_THREADS | |
109 file = setmntent(MOUNTED, "r"); | |
110 Py_END_ALLOW_THREADS | |
111 if ((file == 0) || (file == NULL)) { | |
112 return PyErr_SetFromErrno(PyExc_OSError); | |
113 } | |
114 | |
115 while ((entry = getmntent(file))) { | |
116 if (entry == NULL) { | |
117 endmntent(file); | |
118 return PyErr_Format(PyExc_RuntimeError, "getmntent() failed"); | |
119 } | |
120 py_tuple = Py_BuildValue("(sss)", entry->mnt_fsname, // device | |
121 entry->mnt_dir, // mount point | |
122 entry->mnt_type); // fs type | |
123 PyList_Append(py_retlist, py_tuple); | |
124 Py_XDECREF(py_tuple); | |
125 } | |
126 | |
127 endmntent(file); | |
128 return py_retlist; | |
129 } | |
130 | |
131 | |
132 /* | |
133 * Define the psutil C module methods and initialize the module. | |
134 */ | |
135 static PyMethodDef | |
136 PsutilMethods[] = | |
137 { | |
138 #if HAS_IOPRIO | |
139 {"ioprio_get", linux_ioprio_get, METH_VARARGS, | |
140 "Get process I/O priority"}, | |
141 {"ioprio_set", linux_ioprio_set, METH_VARARGS, | |
142 "Set process I/O priority"}, | |
143 #endif | |
144 {"get_disk_partitions", get_disk_partitions, METH_VARARGS, | |
145 "Return disk mounted partitions as a list of tuples including " | |
146 "device, mount point and filesystem type"}, | |
147 | |
148 {NULL, NULL, 0, NULL} | |
149 }; | |
150 | |
151 struct module_state { | |
152 PyObject *error; | |
153 }; | |
154 | |
155 #if PY_MAJOR_VERSION >= 3 | |
156 #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) | |
157 #else | |
158 #define GETSTATE(m) (&_state) | |
159 #endif | |
160 | |
161 #if PY_MAJOR_VERSION >= 3 | |
162 | |
163 static int | |
164 psutil_linux_traverse(PyObject *m, visitproc visit, void *arg) { | |
165 Py_VISIT(GETSTATE(m)->error); | |
166 return 0; | |
167 } | |
168 | |
169 static int | |
170 psutil_linux_clear(PyObject *m) { | |
171 Py_CLEAR(GETSTATE(m)->error); | |
172 return 0; | |
173 } | |
174 | |
175 static struct PyModuleDef | |
176 moduledef = { | |
177 PyModuleDef_HEAD_INIT, | |
178 "psutil_linux", | |
179 NULL, | |
180 sizeof(struct module_state), | |
181 PsutilMethods, | |
182 NULL, | |
183 psutil_linux_traverse, | |
184 psutil_linux_clear, | |
185 NULL | |
186 }; | |
187 | |
188 #define INITERROR return NULL | |
189 | |
190 PyObject * | |
191 PyInit__psutil_linux(void) | |
192 | |
193 #else | |
194 #define INITERROR return | |
195 | |
196 void init_psutil_linux(void) | |
197 #endif | |
198 { | |
199 #if PY_MAJOR_VERSION >= 3 | |
200 PyObject *module = PyModule_Create(&moduledef); | |
201 #else | |
202 PyObject *module = Py_InitModule("_psutil_linux", PsutilMethods); | |
203 #endif | |
204 if (module == NULL) { | |
205 INITERROR; | |
206 } | |
207 #if PY_MAJOR_VERSION >= 3 | |
208 return module; | |
209 #endif | |
210 } | |
211 | |
OLD | NEW |