diff options
author | Giampaolo Rodola <g.rodola@gmail.com> | 2016-03-04 10:10:49 -0800 |
---|---|---|
committer | Giampaolo Rodola <g.rodola@gmail.com> | 2016-03-04 10:10:49 -0800 |
commit | 77ed1de61ec7bf4e289c3632295412cc79fcfd73 (patch) | |
tree | 4ee867e4a080568923e42ee604176c276b490f09 | |
parent | 25ed1fe2f599c32908574a81282a4491903a075e (diff) | |
download | psutil-77ed1de61ec7bf4e289c3632295412cc79fcfd73.tar.gz |
fix #789 / cpu_times / windows: add interrupt and dpc times
-rw-r--r-- | HISTORY.rst | 2 | ||||
-rw-r--r-- | docs/index.rst | 7 | ||||
-rw-r--r-- | psutil/_psutil_windows.c | 28 | ||||
-rw-r--r-- | psutil/_pswindows.py | 15 | ||||
-rw-r--r-- | psutil/arch/windows/ntextapi.h | 22 |
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 |