Index: third_party/psutil/psutil/_psutil_bsd.c |
diff --git a/third_party/psutil/psutil/_psutil_bsd.c b/third_party/psutil/psutil/_psutil_bsd.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7586d9f1f54f5763aaad96dc270914186adb1310 |
--- /dev/null |
+++ b/third_party/psutil/psutil/_psutil_bsd.c |
@@ -0,0 +1,566 @@ |
+/* |
+ * $Id: _psutil_bsd.c 780 2010-11-10 18:42:47Z jloden $ |
+ * |
+ * FreeBSD platform-specific module methods for _psutil_bsd |
+ */ |
+ |
+#include <Python.h> |
+#include <assert.h> |
+#include <errno.h> |
+#include <stdlib.h> |
+#include <stdio.h> |
+#include <signal.h> |
+#include <sys/types.h> |
+#include <sys/sysctl.h> |
+#include <sys/param.h> |
+#include <sys/user.h> |
+#include <sys/proc.h> |
+#include <sys/vmmeter.h> /* needed for vmtotal struct */ |
+ |
+#include "_psutil_bsd.h" |
+#include "arch/bsd/process_info.h" |
+ |
+/* |
+ * define the psutil C module methods and initialize the module. |
+ */ |
+static PyMethodDef |
+PsutilMethods[] = |
+{ |
+ // --- per-process functions |
+ |
+ {"get_process_name", get_process_name, METH_VARARGS, |
+ "Return process name"}, |
+ {"get_process_cmdline", get_process_cmdline, METH_VARARGS, |
+ "Return process cmdline as a list of cmdline arguments"}, |
+ {"get_process_ppid", get_process_ppid, METH_VARARGS, |
+ "Return process ppid as an integer"}, |
+ {"get_process_uid", get_process_uid, METH_VARARGS, |
+ "Return process real user id as an integer"}, |
+ {"get_process_gid", get_process_gid, METH_VARARGS, |
+ "Return process real group id as an integer"}, |
+ {"get_cpu_times", get_cpu_times, METH_VARARGS, |
+ "Return tuple of user/kern time for the given PID"}, |
+ {"get_process_create_time", get_process_create_time, METH_VARARGS, |
+ "Return a float indicating the process create time expressed in " |
+ "seconds since the epoch"}, |
+ {"get_memory_info", get_memory_info, METH_VARARGS, |
+ "Return a tuple of RSS/VMS memory information"}, |
+ {"get_process_num_threads", get_process_num_threads, METH_VARARGS, |
+ "Return number of threads used by process"}, |
+ |
+ |
+ // --- system-related functions |
+ |
+ {"get_pid_list", get_pid_list, METH_VARARGS, |
+ "Returns a list of PIDs currently running on the system"}, |
+ {"get_num_cpus", get_num_cpus, METH_VARARGS, |
+ "Return number of CPUs on the system"}, |
+ {"get_total_phymem", get_total_phymem, METH_VARARGS, |
+ "Return the total amount of physical memory, in bytes"}, |
+ {"get_avail_phymem", get_avail_phymem, METH_VARARGS, |
+ "Return the amount of available physical memory, in bytes"}, |
+ {"get_total_virtmem", get_total_virtmem, METH_VARARGS, |
+ "Return the total amount of virtual memory, in bytes"}, |
+ {"get_avail_virtmem", get_avail_virtmem, METH_VARARGS, |
+ "Return the amount of available virtual memory, in bytes"}, |
+ {"get_system_cpu_times", get_system_cpu_times, METH_VARARGS, |
+ "Return system cpu times as a tuple (user, system, nice, idle, irc)"}, |
+ |
+ {NULL, NULL, 0, NULL} |
+}; |
+ |
+struct module_state { |
+ PyObject *error; |
+}; |
+ |
+#if PY_MAJOR_VERSION >= 3 |
+#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) |
+#else |
+#define GETSTATE(m) (&_state) |
+static struct module_state _state; |
+#endif |
+ |
+#if PY_MAJOR_VERSION >= 3 |
+ |
+static int |
+psutil_bsd_traverse(PyObject *m, visitproc visit, void *arg) { |
+ Py_VISIT(GETSTATE(m)->error); |
+ return 0; |
+} |
+ |
+static int |
+psutil_bsd_clear(PyObject *m) { |
+ Py_CLEAR(GETSTATE(m)->error); |
+ return 0; |
+} |
+ |
+static struct PyModuleDef |
+moduledef = { |
+ PyModuleDef_HEAD_INIT, |
+ "psutil_bsd", |
+ NULL, |
+ sizeof(struct module_state), |
+ PsutilMethods, |
+ NULL, |
+ psutil_bsd_traverse, |
+ psutil_bsd_clear, |
+ NULL |
+}; |
+ |
+#define INITERROR return NULL |
+ |
+PyObject * |
+PyInit__psutil_bsd(void) |
+ |
+#else |
+#define INITERROR return |
+ |
+void init_psutil_bsd(void) |
+#endif |
+{ |
+#if PY_MAJOR_VERSION >= 3 |
+ PyObject *module = PyModule_Create(&moduledef); |
+#else |
+ PyObject *module = Py_InitModule("_psutil_bsd", PsutilMethods); |
+#endif |
+ if (module == NULL) { |
+ INITERROR; |
+ } |
+ struct module_state *st = GETSTATE(module); |
+ |
+ st->error = PyErr_NewException("_psutil_bsd.Error", NULL, NULL); |
+ if (st->error == NULL) { |
+ Py_DECREF(module); |
+ INITERROR; |
+ } |
+#if PY_MAJOR_VERSION >= 3 |
+ return module; |
+#endif |
+} |
+ |
+ |
+/* |
+ * Utility function which fills a kinfo_proc struct based on process pid |
+ */ |
+static int |
+get_kinfo_proc(const pid_t pid, struct kinfo_proc *proc) |
+{ |
+ int mib[4]; |
+ size_t size; |
+ mib[0] = CTL_KERN; |
+ mib[1] = KERN_PROC; |
+ mib[2] = KERN_PROC_PID; |
+ mib[3] = pid; |
+ |
+ size = sizeof(struct kinfo_proc); |
+ |
+ if (sysctl((int*)mib, 4, proc, &size, NULL, 0) == -1) { |
+ PyErr_SetFromErrno(PyExc_OSError); |
+ return -1; |
+ } |
+ |
+ /* |
+ * sysctl stores 0 in the size if we can't find the process information. |
+ * Set errno to ESRCH which will be translated in NoSuchProcess later on. |
+ */ |
+ if (size == 0) { |
+ errno = ESRCH; |
+ PyErr_SetFromErrno(PyExc_OSError); |
+ return -1; |
+ } |
+ return 0; |
+} |
+ |
+ |
+/* |
+ * Return a Python list of all the PIDs running on the system. |
+ */ |
+static PyObject* |
+get_pid_list(PyObject* self, PyObject* args) |
+{ |
+ kinfo_proc *proclist = NULL; |
+ kinfo_proc *orig_address = NULL; |
+ size_t num_processes; |
+ size_t idx; |
+ PyObject* retlist = PyList_New(0); |
+ PyObject* pid; |
+ |
+ if (get_proc_list(&proclist, &num_processes) != 0) { |
+ Py_DECREF(retlist); |
+ PyErr_SetString(PyExc_RuntimeError, "failed to retrieve process list."); |
+ return NULL; |
+ } |
+ |
+ if (num_processes > 0) { |
+ orig_address = proclist; // save so we can free it after we're done |
+ for (idx=0; idx < num_processes; idx++) { |
+ pid = Py_BuildValue("i", proclist->ki_pid); |
+ PyList_Append(retlist, pid); |
+ Py_XDECREF(pid); |
+ proclist++; |
+ } |
+ free(orig_address); |
+ } |
+ |
+ return retlist; |
+} |
+ |
+ |
+/* |
+ * Return process name from kinfo_proc as a Python string. |
+ */ |
+static PyObject* |
+get_process_name(PyObject* self, PyObject* args) |
+{ |
+ long pid; |
+ struct kinfo_proc kp; |
+ if (! PyArg_ParseTuple(args, "l", &pid)) { |
+ return NULL; |
+ } |
+ if (get_kinfo_proc(pid, &kp) == -1) { |
+ return NULL; |
+ } |
+ return Py_BuildValue("s", kp.ki_comm); |
+} |
+ |
+ |
+/* |
+ * Return process cmdline as a Python list of cmdline arguments. |
+ */ |
+static PyObject* |
+get_process_cmdline(PyObject* self, PyObject* args) |
+{ |
+ long pid; |
+ PyObject* arglist = NULL; |
+ |
+ if (! PyArg_ParseTuple(args, "l", &pid)) { |
+ return NULL; |
+ } |
+ |
+ // get the commandline, defined in arch/bsd/process_info.c |
+ arglist = get_arg_list(pid); |
+ |
+ // get_arg_list() returns NULL only if getcmdargs failed with ESRCH |
+ // (no process with that PID) |
+ if (NULL == arglist) { |
+ return PyErr_SetFromErrno(PyExc_OSError); |
+ } |
+ return Py_BuildValue("N", arglist); |
+} |
+ |
+ |
+/* |
+ * Return process parent pid from kinfo_proc as a Python integer. |
+ */ |
+static PyObject* |
+get_process_ppid(PyObject* self, PyObject* args) |
+{ |
+ long pid; |
+ struct kinfo_proc kp; |
+ if (! PyArg_ParseTuple(args, "l", &pid)) { |
+ return NULL; |
+ } |
+ if (get_kinfo_proc(pid, &kp) == -1) { |
+ return NULL; |
+ } |
+ return Py_BuildValue("l", (long)kp.ki_ppid); |
+} |
+ |
+ |
+/* |
+ * Return process real uid from kinfo_proc as a Python integer. |
+ */ |
+static PyObject* |
+get_process_uid(PyObject* self, PyObject* args) |
+{ |
+ long pid; |
+ struct kinfo_proc kp; |
+ if (! PyArg_ParseTuple(args, "l", &pid)) { |
+ return NULL; |
+ } |
+ if (get_kinfo_proc(pid, &kp) == -1) { |
+ return NULL; |
+ } |
+ return Py_BuildValue("l", (long)kp.ki_ruid); |
+} |
+ |
+ |
+/* |
+ * Return process real group id from ki_comm as a Python integer. |
+ */ |
+static PyObject* |
+get_process_gid(PyObject* self, PyObject* args) |
+{ |
+ long pid; |
+ struct kinfo_proc kp; |
+ if (! PyArg_ParseTuple(args, "l", &pid)) { |
+ return NULL; |
+ } |
+ if (get_kinfo_proc(pid, &kp) == -1) { |
+ return NULL; |
+ } |
+ return Py_BuildValue("l", (long)kp.ki_rgid); |
+} |
+ |
+ |
+/* |
+ * Return number of threads used by process as a Python integer. |
+ */ |
+static PyObject* |
+get_process_num_threads(PyObject* self, PyObject* args) |
+{ |
+ long pid; |
+ struct kinfo_proc kp; |
+ if (! PyArg_ParseTuple(args, "l", &pid)) { |
+ return NULL; |
+ } |
+ if (get_kinfo_proc(pid, &kp) == -1) { |
+ return NULL; |
+ } |
+ return Py_BuildValue("l", (long)kp.ki_numthreads); |
+} |
+ |
+ |
+ |
+// convert a timeval struct to a double |
+#define TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0) |
+ |
+ |
+/* |
+ * Return a Python tuple (user_time, kernel_time) |
+ */ |
+static PyObject* |
+get_cpu_times(PyObject* self, PyObject* args) |
+{ |
+ long pid; |
+ double user_t, sys_t; |
+ struct kinfo_proc kp; |
+ if (! PyArg_ParseTuple(args, "l", &pid)) { |
+ return NULL; |
+ } |
+ if (get_kinfo_proc(pid, &kp) == -1) { |
+ return NULL; |
+ } |
+ // convert from microseconds to seconds |
+ user_t = TV2DOUBLE(kp.ki_rusage.ru_utime); |
+ sys_t = TV2DOUBLE(kp.ki_rusage.ru_stime); |
+ return Py_BuildValue("(dd)", user_t, sys_t); |
+} |
+ |
+ |
+/* |
+ * Return a Python integer indicating the number of CPUs on the system |
+ */ |
+static PyObject* |
+get_num_cpus(PyObject* self, PyObject* args) |
+{ |
+ int mib[2]; |
+ int ncpu; |
+ size_t len; |
+ |
+ mib[0] = CTL_HW; |
+ mib[1] = HW_NCPU; |
+ len = sizeof(ncpu); |
+ |
+ if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) { |
+ PyErr_SetFromErrno(0); |
+ return NULL; |
+ } |
+ |
+ return Py_BuildValue("i", ncpu); |
+} |
+ |
+ |
+/* |
+ * Return a Python float indicating the process create time expressed in |
+ * seconds since the epoch. |
+ */ |
+static PyObject* |
+get_process_create_time(PyObject* self, PyObject* args) |
+{ |
+ long pid; |
+ struct kinfo_proc kp; |
+ if (! PyArg_ParseTuple(args, "l", &pid)) { |
+ return NULL; |
+ } |
+ if (get_kinfo_proc(pid, &kp) == -1) { |
+ return NULL; |
+ } |
+ return Py_BuildValue("d", TV2DOUBLE(kp.ki_start)); |
+} |
+ |
+ |
+/* |
+ * Return the RSS and VMS as a Python tuple. |
+ */ |
+static PyObject* |
+get_memory_info(PyObject* self, PyObject* args) |
+{ |
+ long pid; |
+ struct kinfo_proc kp; |
+ if (! PyArg_ParseTuple(args, "l", &pid)) { |
+ return NULL; |
+ } |
+ if (get_kinfo_proc(pid, &kp) == -1) { |
+ return NULL; |
+ } |
+ return Py_BuildValue("(ll)", ptoa(kp.ki_rssize), (long)kp.ki_size); |
+} |
+ |
+ |
+/* |
+ * Return a Python integer indicating the total amount of physical memory |
+ * in bytes. |
+ */ |
+static PyObject* |
+get_total_phymem(PyObject* self, PyObject* args) |
+{ |
+ long total_phymem; |
+ int mib[2]; |
+ size_t len; |
+ |
+ mib[0] = CTL_HW; |
+ mib[1] = HW_PHYSMEM; |
+ len = sizeof(total_phymem); |
+ |
+ if (sysctl(mib, 2, &total_phymem, &len, NULL, 0) == -1) { |
+ PyErr_SetFromErrno(0); |
+ return NULL; |
+ } |
+ |
+ return Py_BuildValue("l", total_phymem); |
+} |
+ |
+ |
+/* |
+ * Return a Python long indicating the amount of available physical memory in |
+ * bytes. |
+ */ |
+static PyObject* |
+get_avail_phymem(PyObject* self, PyObject* args) |
+{ |
+ unsigned long v_inactive_count = 0; |
+ unsigned long v_cache_count = 0; |
+ unsigned long v_free_count = 0; |
+ long total_mem = 0; |
+ long long avail_mem = 0; |
+ size_t size = sizeof(unsigned long); |
+ size_t psize = sizeof(total_mem); |
+ int pagesize = getpagesize(); |
+ |
+ if (sysctlbyname("hw.physmem", &total_mem, &psize, NULL, 0) == -1) { |
+ PyErr_SetFromErrno(0); |
+ return NULL; |
+ } |
+ |
+ if (sysctlbyname("vm.stats.vm.v_inactive_count", &v_inactive_count, |
+ &size, NULL, 0) == -1) { |
+ PyErr_SetFromErrno(0); |
+ return NULL; |
+ } |
+ |
+ if (sysctlbyname("vm.stats.vm.v_cache_count", |
+ &v_cache_count, &size, NULL, 0) == -1) { |
+ PyErr_SetFromErrno(0); |
+ return NULL; |
+ } |
+ |
+ if (sysctlbyname("vm.stats.vm.v_free_count", |
+ &v_free_count, &size, NULL, 0) == -1) { |
+ PyErr_SetFromErrno(0); |
+ return NULL; |
+ } |
+ |
+ avail_mem = (v_inactive_count + v_cache_count + v_free_count) * pagesize; |
+ // used_mem = total_mem - avail_mem; |
+ |
+ return Py_BuildValue("L", avail_mem); |
+} |
+ |
+ |
+/* |
+ * Return a Python long indicating the total amount of virtual memory |
+ * in bytes. |
+ */ |
+static PyObject* |
+get_total_virtmem(PyObject* self, PyObject* args) |
+{ |
+ int mib[2]; |
+ struct vmtotal vm; |
+ size_t size; |
+ long long total_vmem; |
+ |
+ mib[0] = CTL_VM; |
+ mib[1] = VM_METER; |
+ size = sizeof(vm); |
+ sysctl(mib, 2, &vm, &size, NULL, 0); |
+ |
+ // vmtotal struct: |
+ // http://fxr.watson.org/fxr/source/sys/vmmeter.h?v=FREEBSD54 |
+ // note: value is returned in page, so we must multiply by size of a page |
+ total_vmem = (long long)vm.t_vm * (long long)getpagesize(); |
+ return Py_BuildValue("L", total_vmem); |
+} |
+ |
+ |
+/* |
+ * Return a Python long indicating the avail amount of virtual memory |
+ * in bytes. |
+ */ |
+static PyObject* |
+get_avail_virtmem(PyObject* self, PyObject* args) |
+{ |
+ int mib[2]; |
+ struct vmtotal vm; |
+ size_t size; |
+ long long total_vmem; |
+ long long avail_vmem; |
+ |
+ mib[0] = CTL_VM; |
+ mib[1] = VM_METER; |
+ size = sizeof(vm); |
+ sysctl(mib, 2, &vm, &size, NULL, 0); |
+ |
+ // vmtotal struct: |
+ // http://fxr.watson.org/fxr/source/sys/vmmeter.h?v=FREEBSD54 |
+ // note: value is returned in page, so we must multiply by size of a page |
+ total_vmem = (long long)vm.t_vm * (long long)getpagesize(); |
+ avail_vmem = total_vmem - ((long long)vm.t_avm * (long long)getpagesize()); |
+ return Py_BuildValue("L", avail_vmem); |
+} |
+ |
+ |
+/* |
+ * Return a Python tuple representing user, kernel and idle CPU times |
+ */ |
+static PyObject* |
+get_system_cpu_times(PyObject* self, PyObject* args) |
+{ |
+ long cpu_time[CPUSTATES]; |
+ size_t size; |
+ |
+ size = sizeof(cpu_time); |
+ |
+ if (sysctlbyname("kern.cp_time", &cpu_time, &size, NULL, 0) == -1) { |
+ PyErr_SetFromErrno(0); |
+ return NULL; |
+ } |
+ |
+ /* |
+ #define CP_USER 0 |
+ #define CP_NICE 1 |
+ #define CP_SYS 2 |
+ #define CP_INTR 3 |
+ #define CP_IDLE 4 |
+ #define CPUSTATES 5 |
+ */ |
+ //user, nice, system, idle, iowait, irqm, softirq |
+ return Py_BuildValue("(ddddd)", |
+ (double)cpu_time[CP_USER] / CLOCKS_PER_SEC, |
+ (double)cpu_time[CP_NICE] / CLOCKS_PER_SEC, |
+ (double)cpu_time[CP_SYS] / CLOCKS_PER_SEC, |
+ (double)cpu_time[CP_IDLE] / CLOCKS_PER_SEC, |
+ (double)cpu_time[CP_INTR] / CLOCKS_PER_SEC |
+ ); |
+} |
+ |