summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2016-03-04 10:10:49 -0800
committerGiampaolo Rodola <g.rodola@gmail.com>2016-03-04 10:10:49 -0800
commit77ed1de61ec7bf4e289c3632295412cc79fcfd73 (patch)
tree4ee867e4a080568923e42ee604176c276b490f09
parent25ed1fe2f599c32908574a81282a4491903a075e (diff)
downloadpsutil-77ed1de61ec7bf4e289c3632295412cc79fcfd73.tar.gz
fix #789 / cpu_times / windows: add interrupt and dpc times
-rw-r--r--HISTORY.rst2
-rw-r--r--docs/index.rst7
-rw-r--r--psutil/_psutil_windows.c28
-rw-r--r--psutil/_pswindows.py15
-rw-r--r--psutil/arch/windows/ntextapi.h22
5 files changed, 59 insertions, 15 deletions
diff --git a/HISTORY.rst b/HISTORY.rst
index 56bcb486..c2b040ee 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -9,6 +9,8 @@ Bug tracker at https://github.com/giampaolo/psutil/issues
mode and flags.
- #779: Process.cpu_times() returns two new fields, 'children_user' and
'children_system' (always set to 0 on OSX and Windows).
+- #789: [Windows] psutil.cpu_times() return two new fields: "interrupt" and
+ "dpc". Same for psutil.cpu_times_percent().
**Bug fixes**
diff --git a/docs/index.rst b/docs/index.rst
index 04327ce0..2a881208 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -68,6 +68,8 @@ CPU
- **steal** *(Linux 2.6.11+)*
- **guest** *(Linux 2.6.24+)*
- **guest_nice** *(Linux 3.2.0+)*
+ - **interrupt** *(Windows)*
+ - **dpc** *(Windows)*
When *percpu* is ``True`` return a list of namedtuples for each logical CPU
on the system.
@@ -80,6 +82,8 @@ CPU
>>> psutil.cpu_times()
scputimes(user=17411.7, nice=77.99, system=3797.02, idle=51266.57, iowait=732.58, irq=0.01, softirq=142.43, steal=0.0, guest=0.0, guest_nice=0.0)
+ .. versionchanged:: 4.1.0 added *interrupt* and *dpc* fields on Windows.
+
.. function:: cpu_percent(interval=None, percpu=False)
Return a float representing the current system-wide CPU utilization as a
@@ -128,6 +132,9 @@ CPU
``None`` it will return a meaningless ``0.0`` value which you are supposed
to ignore.
+ .. versionchanged:: 4.1.0 two new *interrupt* and *dpc* fields are returned
+ on Windows.
+
.. function:: cpu_count(logical=True)
Return the number of logical CPUs in the system (same as
diff --git a/psutil/_psutil_windows.c b/psutil/_psutil_windows.c
index 092ebb0c..05ad39d5 100644
--- a/psutil/_psutil_windows.c
+++ b/psutil/_psutil_windows.c
@@ -954,9 +954,9 @@ psutil_per_cpu_times(PyObject *self, PyObject *args) {
NTQSI_PROC NtQuerySystemInformation;
HINSTANCE hNtDll;
- float idle, kernel, user;
+ float idle, kernel, systemt, user, interrupt, dpc;
NTSTATUS status;
- SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi = NULL;
+ _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi = NULL;
SYSTEM_INFO si;
UINT i;
PyObject *py_tuple = NULL;
@@ -981,11 +981,11 @@ psutil_per_cpu_times(PyObject *self, PyObject *args) {
// retrives number of processors
GetSystemInfo(&si);
- // allocates an array of SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
+ // allocates an array of _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
// structures, one per processor
- sppi = (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *) \
+ sppi = (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *) \
malloc(si.dwNumberOfProcessors * \
- sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
+ sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
if (sppi == NULL) {
PyErr_NoMemory();
goto error;
@@ -996,7 +996,7 @@ psutil_per_cpu_times(PyObject *self, PyObject *args) {
SystemProcessorPerformanceInformation,
sppi,
si.dwNumberOfProcessors * sizeof
- (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION),
+ (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION),
NULL);
if (status != 0) {
PyErr_SetFromWindowsErr(0);
@@ -1005,7 +1005,7 @@ psutil_per_cpu_times(PyObject *self, PyObject *args) {
// computes system global times summing each
// processor value
- idle = user = kernel = 0;
+ idle = user = kernel = interrupt = dpc = 0;
for (i = 0; i < si.dwNumberOfProcessors; i++) {
py_tuple = NULL;
user = (float)((HI_T * sppi[i].UserTime.HighPart) +
@@ -1014,14 +1014,22 @@ psutil_per_cpu_times(PyObject *self, PyObject *args) {
(LO_T * sppi[i].IdleTime.LowPart));
kernel = (float)((HI_T * sppi[i].KernelTime.HighPart) +
(LO_T * sppi[i].KernelTime.LowPart));
+ interrupt = (float)((HI_T * sppi[i].InterruptTime.HighPart) +
+ (LO_T * sppi[i].InterruptTime.LowPart));
+ dpc = (float)((HI_T * sppi[i].DpcTime.HighPart) +
+ (LO_T * sppi[i].DpcTime.LowPart));
+
// kernel time includes idle time on windows
// we return only busy kernel time subtracting
// idle time from kernel time
+ systemt = kernel - idle;
py_tuple = Py_BuildValue(
- "(ddd)",
+ "(ddddd)",
user,
- kernel - idle,
- idle
+ systemt,
+ idle,
+ interrupt,
+ dpc
);
if (!py_tuple)
goto error;
diff --git a/psutil/_pswindows.py b/psutil/_pswindows.py
index 25ed2a59..4143afd7 100644
--- a/psutil/_pswindows.py
+++ b/psutil/_pswindows.py
@@ -82,7 +82,8 @@ if enum is not None:
globals().update(Priority.__members__)
-scputimes = namedtuple('scputimes', ['user', 'system', 'idle'])
+scputimes = namedtuple('scputimes',
+ ['user', 'system', 'idle', 'interrupt', 'dpc'])
svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free'])
pmem = namedtuple(
'pmem', ['rss', 'vms',
@@ -181,15 +182,19 @@ def disk_partitions(all):
def cpu_times():
"""Return system CPU times as a named tuple."""
user, system, idle = cext.cpu_times()
- return scputimes(user, system, idle)
+ # Internally, GetSystemTimes() is used, and it doesn't return
+ # interrupt and dpc times. cext.per_cpu_times() does, so we
+ # rely on it to get those only.
+ percpu_summed = scputimes(*[sum(n) for n in zip(*cext.per_cpu_times())])
+ return scputimes(user, system, idle,
+ percpu_summed.interrupt, percpu_summed.dpc)
def per_cpu_times():
"""Return system per-CPU times as a list of named tuples."""
ret = []
- for cpu_t in cext.per_cpu_times():
- user, system, idle = cpu_t
- item = scputimes(user, system, idle)
+ for user, system, idle, interrupt, dpc in cext.per_cpu_times():
+ item = scputimes(user, system, idle, interrupt, dpc)
ret.append(item)
return ret
diff --git a/psutil/arch/windows/ntextapi.h b/psutil/arch/windows/ntextapi.h
index 4f843e02..7cfa6fa5 100644
--- a/psutil/arch/windows/ntextapi.h
+++ b/psutil/arch/windows/ntextapi.h
@@ -7,6 +7,17 @@
#define __NTEXTAPI_H__
#include <winternl.h>
+
+typedef struct {
+ LARGE_INTEGER IdleTime;
+ LARGE_INTEGER KernelTime;
+ LARGE_INTEGER UserTime;
+ LARGE_INTEGER DpcTime;
+ LARGE_INTEGER InterruptTime;
+ ULONG InterruptCount;
+} _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
+
+
typedef enum _KTHREAD_STATE {
Initialized,
Ready,
@@ -20,6 +31,7 @@ typedef enum _KTHREAD_STATE {
MaximumThreadState
} KTHREAD_STATE, *PKTHREAD_STATE;
+
typedef enum _KWAIT_REASON {
Executive = 0,
FreePage = 1,
@@ -61,11 +73,13 @@ typedef enum _KWAIT_REASON {
MaximumWaitReason = 37
} KWAIT_REASON, *PKWAIT_REASON;
+
typedef struct _CLIENT_ID {
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
+
typedef struct _SYSTEM_THREAD_INFORMATION {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
@@ -80,8 +94,10 @@ typedef struct _SYSTEM_THREAD_INFORMATION {
KWAIT_REASON WaitReason;
} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION;
+
typedef struct _TEB *PTEB;
+
// private
typedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION {
SYSTEM_THREAD_INFORMATION ThreadInfo;
@@ -94,6 +110,7 @@ typedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION {
ULONG_PTR Reserved4;
} SYSTEM_EXTENDED_THREAD_INFORMATION, *PSYSTEM_EXTENDED_THREAD_INFORMATION;
+
typedef struct _SYSTEM_PROCESS_INFORMATION2 {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
@@ -151,6 +168,7 @@ typedef struct _WINSTATION_INFO {
FILETIME CurrentTime;
} WINSTATION_INFO, *PWINSTATION_INFO;
+
typedef BOOLEAN (WINAPI * PWINSTATIONQUERYINFORMATIONW)
(HANDLE,ULONG,WINSTATIONINFOCLASS,PVOID,ULONG,PULONG);
@@ -162,6 +180,7 @@ typedef BOOLEAN (WINAPI * PWINSTATIONQUERYINFORMATIONW)
*/
typedef LONG NTSTATUS;
+
typedef NTSTATUS (NTAPI *_NtQueryInformationProcess)(
HANDLE ProcessHandle,
DWORD ProcessInformationClass,
@@ -170,6 +189,7 @@ typedef NTSTATUS (NTAPI *_NtQueryInformationProcess)(
PDWORD ReturnLength
);
+
typedef NTSTATUS (NTAPI *_NtSetInformationProcess)(
HANDLE ProcessHandle,
DWORD ProcessInformationClass,
@@ -177,6 +197,7 @@ typedef NTSTATUS (NTAPI *_NtSetInformationProcess)(
DWORD ProcessInformationLength
);
+
typedef enum _PROCESSINFOCLASS2 {
_ProcessBasicInformation,
ProcessQuotaLimits,
@@ -224,6 +245,7 @@ typedef enum _PROCESSINFOCLASS2 {
MaxProcessInfoClass
} PROCESSINFOCLASS2;
+
#define PROCESSINFOCLASS PROCESSINFOCLASS2
#define ProcessBasicInformation _ProcessBasicInformation
#define ProcessWow64Information _ProcessWow64Information