| 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
|
| + );
|
| +}
|
| +
|
|
|