Skip to content

Commit

Permalink
#941: cpu frequency - windows implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
giampaolo committed Jan 20, 2017
1 parent 76690f2 commit 17cbdf8
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 2 deletions.
4 changes: 3 additions & 1 deletion psutil/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@
"pid_exists", "pids", "process_iter", "wait_procs", # proc
"virtual_memory", "swap_memory", # memory
"cpu_times", "cpu_percent", "cpu_times_percent", "cpu_count", # cpu
"cpu_stats", "cpu_freq",
"cpu_stats", # "cpu_freq",
"net_io_counters", "net_connections", "net_if_addrs", # network
"net_if_stats",
"disk_io_counters", "disk_partitions", "disk_usage", # disk
Expand Down Expand Up @@ -1869,6 +1869,8 @@ def cpu_freq():
"""
return _psplatform.cpu_freq()

__all__.append("cpu_freq")


# =====================================================================
# --- system memory related functions
Expand Down
67 changes: 67 additions & 0 deletions psutil/_psutil_windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <iphlpapi.h>
#include <wtsapi32.h>
#include <Winsvc.h>
#include <PowrProf.h>

// Link with Iphlpapi.lib
#pragma comment(lib, "IPHLPAPI.lib")
Expand Down Expand Up @@ -145,6 +146,16 @@ typedef struct _MIB_UDP6TABLE_OWNER_PID {
} MIB_UDP6TABLE_OWNER_PID, *PMIB_UDP6TABLE_OWNER_PID;
#endif

typedef struct _PROCESSOR_POWER_INFORMATION {
ULONG Number;
ULONG MaxMhz;
ULONG CurrentMhz;
ULONG MhzLimit;
ULONG MaxIdleState;
ULONG CurrentIdleState;
} PROCESSOR_POWER_INFORMATION, *PPROCESSOR_POWER_INFORMATION;


PIP_ADAPTER_ADDRESSES
psutil_get_nic_addresses() {
// allocate a 15 KB buffer to start with
Expand Down Expand Up @@ -3391,6 +3402,60 @@ psutil_cpu_stats(PyObject *self, PyObject *args) {
}


/*
* Return CPU frequency.
*/
static PyObject *
psutil_cpu_freq(PyObject *self, PyObject *args) {
PROCESSOR_POWER_INFORMATION *ppi;
NTSTATUS ret;
size_t size;
LPBYTE pBuffer = NULL;
ULONG current;
ULONG max;
unsigned int num_cpus;
SYSTEM_INFO system_info;
system_info.dwNumberOfProcessors = 0;

// Get the number of CPUs.
GetSystemInfo(&system_info);
if (system_info.dwNumberOfProcessors == 0)
num_cpus = 1;
else
num_cpus = system_info.dwNumberOfProcessors;

// Allocate size.
size = num_cpus * sizeof(PROCESSOR_POWER_INFORMATION);
pBuffer = (BYTE*)LocalAlloc(LPTR, size);
if (! pBuffer) {
PyErr_SetFromWindowsErr(0);
return NULL;
}

// Syscall.
ret = CallNtPowerInformation(
ProcessorInformation, NULL, 0, pBuffer, size);
if (ret != 0) {
PyErr_SetString(PyExc_RuntimeError,
"CallNtPowerInformation syscall failed");
goto error;
}

// Results.
ppi = (PROCESSOR_POWER_INFORMATION *)pBuffer;
max = ppi->MaxMhz;
current = ppi->CurrentMhz;
LocalFree(pBuffer);

return Py_BuildValue("kk", current, max);

error:
if (pBuffer != NULL)
LocalFree(pBuffer);
return NULL;
}


// ------------------------ Python init ---------------------------

static PyMethodDef
Expand Down Expand Up @@ -3495,6 +3560,8 @@ PsutilMethods[] = {
"Return NICs stats."},
{"cpu_stats", psutil_cpu_stats, METH_VARARGS,
"Return NICs stats."},
{"cpu_freq", psutil_cpu_freq, METH_VARARGS,
"Return CPU frequency."},

// --- windows services
{"winservice_enumerate", psutil_winservice_enumerate, METH_VARARGS,
Expand Down
6 changes: 6 additions & 0 deletions psutil/_pswindows.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,12 @@ def cpu_stats():
syscalls)


def cpu_freq():
curr, max_ = cext.cpu_freq()
min_ = 0
return [_common.scpufreq(curr, min_, max_)]


# =====================================================================
# --- network
# =====================================================================
Expand Down
5 changes: 5 additions & 0 deletions psutil/tests/test_memory_leaks.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,11 @@ def test_per_cpu_times(self):
def test_cpu_stats(self):
self.execute(psutil.cpu_stats)

@skip_if_linux()
@unittest.skipUnless(hasattr(psutil, "cpu_freq"), "platform not supported")
def test_cpu_freq(self):
self.execute(psutil.cpu_freq)

# --- mem

def test_virtual_memory(self):
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def get_winver():
define_macros=macros,
libraries=[
"psapi", "kernel32", "advapi32", "shell32", "netapi32",
"iphlpapi", "wtsapi32", "ws2_32",
"iphlpapi", "wtsapi32", "ws2_32", "PowrProf",
],
# extra_compile_args=["/Z7"],
# extra_link_args=["/DEBUG"]
Expand Down

0 comments on commit 17cbdf8

Please sign in to comment.