Skip to content

Commit

Permalink
FreeBSD: move CPU C functions in their own cpu.c module
Browse files Browse the repository at this point in the history
  • Loading branch information
giampaolo committed Dec 24, 2020
1 parent 88a0173 commit 8f7826c
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 122 deletions.
4 changes: 4 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ include psutil/arch/aix/ifaddrs.h
include psutil/arch/aix/net_connections.c
include psutil/arch/aix/net_connections.h
include psutil/arch/aix/net_kernel_structs.h
include psutil/arch/freebsd/cpu.c
include psutil/arch/freebsd/cpu.h
include psutil/arch/freebsd/proc_socks.c
include psutil/arch/freebsd/proc_socks.h
include psutil/arch/freebsd/specific.c
Expand All @@ -60,6 +62,8 @@ include psutil/arch/netbsd/specific.c
include psutil/arch/netbsd/specific.h
include psutil/arch/openbsd/specific.c
include psutil/arch/openbsd/specific.h
include psutil/arch/osx/cpu.c
include psutil/arch/osx/cpu.h
include psutil/arch/osx/process_info.c
include psutil/arch/osx/process_info.h
include psutil/arch/solaris/environ.c
Expand Down
2 changes: 1 addition & 1 deletion psutil/_psbsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ def cpu_count_cores():
# is not supported on this BSD version, in which case we'll mimic
# os.cpu_count() and return None.
ret = None
s = cext.cpu_count_cores()
s = cext.cpu_topology()
if s is not None:
# get rid of padding chars appended at the end of the string
index = s.rfind("</groups>")
Expand Down
5 changes: 3 additions & 2 deletions psutil/_psutil_bsd.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
#include "_psutil_posix.h"

#ifdef PSUTIL_FREEBSD
#include "arch/freebsd/cpu.h"
#include "arch/freebsd/specific.h"
#include "arch/freebsd/sys_socks.h"
#include "arch/freebsd/proc_socks.h"
Expand Down Expand Up @@ -1096,8 +1097,8 @@ static PyMethodDef mod_methods[] = {
"Get process resource limits."},
{"proc_setrlimit", psutil_proc_setrlimit, METH_VARARGS,
"Set process resource limits."},
{"cpu_count_cores", psutil_cpu_count_cores, METH_VARARGS,
"Return an XML string to determine the number CPU cores."},
{"cpu_topology", psutil_cpu_topology, METH_VARARGS,
"Return CPU topology as an XML string."},
#endif
{"proc_environ", psutil_proc_environ, METH_VARARGS,
"Return process environment"},
Expand Down
130 changes: 130 additions & 0 deletions psutil/arch/freebsd/cpu.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

/*
System-wide CPU related functions.
Original code was refactored and moved from psutil/arch/freebsd/specific.c
in 2020 (and was moved in there previously already) from cset.
a4c0a0eb0d2a872ab7a45e47fcf37ef1fde5b012
For reference, here's the git history with original(ish) implementations:
- CPU stats: fb0154ef164d0e5942ac85102ab660b8d2938fbb
- CPU freq: 459556dd1e2979cdee22177339ced0761caf4c83
- CPU cores: e0d6d7865df84dc9a1d123ae452fd311f79b1dde
*/


#include <Python.h>
#include <sys/sysctl.h>

#include "../../_psutil_common.h"
#include "../../_psutil_posix.h"


PyObject *
psutil_cpu_topology(PyObject *self, PyObject *args) {
void *topology = NULL;
size_t size = 0;
PyObject *py_str;

if (sysctlbyname("kern.sched.topology_spec", NULL, &size, NULL, 0))
goto error;

topology = malloc(size);
if (!topology) {
PyErr_NoMemory();
return NULL;
}

if (sysctlbyname("kern.sched.topology_spec", topology, &size, NULL, 0))
goto error;

py_str = Py_BuildValue("s", topology);
free(topology);
return py_str;

error:
if (topology != NULL)
free(topology);
Py_RETURN_NONE;
}


PyObject *
psutil_cpu_stats(PyObject *self, PyObject *args) {
unsigned int v_soft;
unsigned int v_intr;
unsigned int v_syscall;
unsigned int v_trap;
unsigned int v_swtch;
size_t size = sizeof(v_soft);

if (sysctlbyname("vm.stats.sys.v_soft", &v_soft, &size, NULL, 0)) {
return PyErr_SetFromOSErrnoWithSyscall(
"sysctlbyname('vm.stats.sys.v_soft')");
}
if (sysctlbyname("vm.stats.sys.v_intr", &v_intr, &size, NULL, 0)) {
return PyErr_SetFromOSErrnoWithSyscall(
"sysctlbyname('vm.stats.sys.v_intr')");
}
if (sysctlbyname("vm.stats.sys.v_syscall", &v_syscall, &size, NULL, 0)) {
return PyErr_SetFromOSErrnoWithSyscall(
"sysctlbyname('vm.stats.sys.v_syscall')");
}
if (sysctlbyname("vm.stats.sys.v_trap", &v_trap, &size, NULL, 0)) {
return PyErr_SetFromOSErrnoWithSyscall(
"sysctlbyname('vm.stats.sys.v_trap')");
}
if (sysctlbyname("vm.stats.sys.v_swtch", &v_swtch, &size, NULL, 0)) {
return PyErr_SetFromOSErrnoWithSyscall(
"sysctlbyname('vm.stats.sys.v_swtch')");
}

return Py_BuildValue(
"IIIII",
v_swtch, // ctx switches
v_intr, // interrupts
v_soft, // software interrupts
v_syscall, // syscalls
v_trap // traps
);
}


/*
* Return frequency information of a given CPU.
* As of Dec 2018 only CPU 0 appears to be supported and all other
* cores match the frequency of CPU 0.
*/
PyObject *
psutil_cpu_freq(PyObject *self, PyObject *args) {
int current;
int core;
char sensor[26];
char available_freq_levels[1000];
size_t size = sizeof(current);

if (! PyArg_ParseTuple(args, "i", &core))
return NULL;
// https://www.unix.com/man-page/FreeBSD/4/cpufreq/
sprintf(sensor, "dev.cpu.%d.freq", core);
if (sysctlbyname(sensor, &current, &size, NULL, 0))
goto error;

size = sizeof(available_freq_levels);
// https://www.unix.com/man-page/FreeBSD/4/cpufreq/
// In case of failure, an empty string is returned.
sprintf(sensor, "dev.cpu.%d.freq_levels", core);
sysctlbyname(sensor, &available_freq_levels, &size, NULL, 0);

return Py_BuildValue("is", current, available_freq_levels);

error:
if (errno == ENOENT)
PyErr_SetString(PyExc_NotImplementedError, "unable to read frequency");
else
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
11 changes: 11 additions & 0 deletions psutil/arch/freebsd/cpu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

#include <Python.h>

PyObject* psutil_cpu_freq(PyObject* self, PyObject* args);
PyObject* psutil_cpu_stats(PyObject* self, PyObject* args);
PyObject* psutil_cpu_topology(PyObject* self, PyObject* args);
109 changes: 0 additions & 109 deletions psutil/arch/freebsd/specific.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,37 +363,6 @@ psutil_proc_threads(PyObject *self, PyObject *args) {
}


PyObject *
psutil_cpu_count_cores(PyObject *self, PyObject *args) {
// Return an XML string from which we'll determine the number of
// CPU cores in the system.
void *topology = NULL;
size_t size = 0;
PyObject *py_str;

if (sysctlbyname("kern.sched.topology_spec", NULL, &size, NULL, 0))
goto error;

topology = malloc(size);
if (!topology) {
PyErr_NoMemory();
return NULL;
}

if (sysctlbyname("kern.sched.topology_spec", topology, &size, NULL, 0))
goto error;

py_str = Py_BuildValue("s", topology);
free(topology);
return py_str;

error:
if (topology != NULL)
free(topology);
Py_RETURN_NONE;
}


/*
* Return virtual memory usage statistics.
*/
Expand Down Expand Up @@ -932,47 +901,6 @@ psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args) {
}


PyObject *
psutil_cpu_stats(PyObject *self, PyObject *args) {
unsigned int v_soft;
unsigned int v_intr;
unsigned int v_syscall;
unsigned int v_trap;
unsigned int v_swtch;
size_t size = sizeof(v_soft);

if (sysctlbyname("vm.stats.sys.v_soft", &v_soft, &size, NULL, 0)) {
return PyErr_SetFromOSErrnoWithSyscall(
"sysctlbyname('vm.stats.sys.v_soft')");
}
if (sysctlbyname("vm.stats.sys.v_intr", &v_intr, &size, NULL, 0)) {
return PyErr_SetFromOSErrnoWithSyscall(
"sysctlbyname('vm.stats.sys.v_intr')");
}
if (sysctlbyname("vm.stats.sys.v_syscall", &v_syscall, &size, NULL, 0)) {
return PyErr_SetFromOSErrnoWithSyscall(
"sysctlbyname('vm.stats.sys.v_syscall')");
}
if (sysctlbyname("vm.stats.sys.v_trap", &v_trap, &size, NULL, 0)) {
return PyErr_SetFromOSErrnoWithSyscall(
"sysctlbyname('vm.stats.sys.v_trap')");
}
if (sysctlbyname("vm.stats.sys.v_swtch", &v_swtch, &size, NULL, 0)) {
return PyErr_SetFromOSErrnoWithSyscall(
"sysctlbyname('vm.stats.sys.v_swtch')");
}

return Py_BuildValue(
"IIIII",
v_swtch, // ctx switches
v_intr, // interrupts
v_soft, // software interrupts
v_syscall, // syscalls
v_trap // traps
);
}


/*
* Return battery information.
*/
Expand Down Expand Up @@ -1036,43 +964,6 @@ psutil_sensors_cpu_temperature(PyObject *self, PyObject *args) {
}


/*
* Return frequency information of a given CPU.
* As of Dec 2018 only CPU 0 appears to be supported and all other
* cores match the frequency of CPU 0.
*/
PyObject *
psutil_cpu_freq(PyObject *self, PyObject *args) {
int current;
int core;
char sensor[26];
char available_freq_levels[1000];
size_t size = sizeof(current);

if (! PyArg_ParseTuple(args, "i", &core))
return NULL;
// https://www.unix.com/man-page/FreeBSD/4/cpufreq/
sprintf(sensor, "dev.cpu.%d.freq", core);
if (sysctlbyname(sensor, &current, &size, NULL, 0))
goto error;

size = sizeof(available_freq_levels);
// https://www.unix.com/man-page/FreeBSD/4/cpufreq/
// In case of failure, an empty string is returned.
sprintf(sensor, "dev.cpu.%d.freq_levels", core);
sysctlbyname(sensor, &available_freq_levels, &size, NULL, 0);

return Py_BuildValue("is", current, available_freq_levels);

error:
if (errno == ENOENT)
PyErr_SetString(PyExc_NotImplementedError, "unable to read frequency");
else
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}


/*
* An emulation of Linux prlimit(). Returns a (soft, hard) tuple.
*/
Expand Down
14 changes: 4 additions & 10 deletions psutil/arch/freebsd/specific.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,20 @@ typedef struct kinfo_proc kinfo_proc;
int psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount);
int psutil_kinfo_proc(const pid_t pid, struct kinfo_proc *proc);

//
PyObject* psutil_cpu_count_cores(PyObject* self, PyObject* args);
PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args);
PyObject* psutil_get_cmdline(long pid);
PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args);
PyObject* psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args);
PyObject* psutil_proc_cpu_affinity_set(PyObject* self, PyObject* args);
PyObject* psutil_proc_cwd(PyObject* self, PyObject* args);
PyObject* psutil_proc_exe(PyObject* self, PyObject* args);
PyObject* psutil_proc_getrlimit(PyObject* self, PyObject* args);
PyObject* psutil_proc_memory_maps(PyObject* self, PyObject* args);
PyObject* psutil_proc_num_fds(PyObject* self, PyObject* args);
PyObject* psutil_proc_num_threads(PyObject* self, PyObject* args);
PyObject* psutil_proc_threads(PyObject* self, PyObject* args);
PyObject* psutil_proc_getrlimit(PyObject* self, PyObject* args);
PyObject* psutil_proc_setrlimit(PyObject* self, PyObject* args);
PyObject* psutil_swap_mem(PyObject* self, PyObject* args);
PyObject* psutil_virtual_mem(PyObject* self, PyObject* args);
PyObject* psutil_cpu_stats(PyObject* self, PyObject* args);
#if defined(PSUTIL_FREEBSD)
PyObject* psutil_proc_threads(PyObject* self, PyObject* args);
PyObject* psutil_sensors_battery(PyObject* self, PyObject* args);
PyObject* psutil_sensors_cpu_temperature(PyObject* self, PyObject* args);
PyObject* psutil_cpu_freq(PyObject* self, PyObject* args);
#endif
PyObject* psutil_swap_mem(PyObject* self, PyObject* args);
PyObject* psutil_virtual_mem(PyObject* self, PyObject* args);
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ def get_winver():
'psutil._psutil_bsd',
sources=sources + [
'psutil/_psutil_bsd.c',
'psutil/arch/freebsd/cpu.c',
'psutil/arch/freebsd/specific.c',
'psutil/arch/freebsd/sys_socks.c',
'psutil/arch/freebsd/proc_socks.c',
Expand Down

0 comments on commit 8f7826c

Please sign in to comment.