1717 * along with NSClient++. If not, see <http://www.gnu.org/licenses/>.
1818 */
1919
20- #include < win/windows.hpp>
20+ #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
21+ #include < windows.h>
2122
2223#include < win_sysinfo/win_defines.hpp>
2324#include < win_sysinfo/win_sysinfo.hpp>
@@ -225,7 +226,7 @@ bool g_hasVersion = false;
225226bool g_hasBasicInfo = false ;
226227
227228boost::scoped_array<unsigned long long > g_CPUIdleTimeOld;
228- boost::scoped_array<unsigned long long > g_CPUTotalTimeOld ;
229+ boost::scoped_array<unsigned long long > g_CPUUserTimeOld ;
229230boost::scoped_array<unsigned long long > g_CPUKernelTimeOld;
230231
231232void init_old_buffer (boost::scoped_array<unsigned long long > &array, const std::size_t size) {
@@ -341,16 +342,22 @@ hlp::buffer<BYTE, winapi::SYSTEM_PROCESS_INFORMATION *> system_info::get_system_
341342 throw nsclient::nsclient_exception (" Failed to enumerate processes: unknown error" );
342343}
343344
344- system_info::cpu_load system_info::get_cpu_load () {
345+ double get_rate (unsigned long long part, unsigned long long total) {
346+ auto part_d = static_cast <double >(part);
347+ auto total_d = static_cast <double >(total);
348+ return (part_d * 100.0 ) / total_d;
349+ }
350+
351+ system_info::cpu_load system_info::get_cpu_load_per_core () {
345352 int cores = get_numberOfProcessorscores ();
346353 init_old_buffer (g_CPUIdleTimeOld, cores);
347- init_old_buffer (g_CPUTotalTimeOld , cores);
354+ init_old_buffer (g_CPUUserTimeOld , cores);
348355 init_old_buffer (g_CPUKernelTimeOld, cores);
349356
350357 boost::scoped_array<winapi::SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION> buffer (new winapi::SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[cores]);
351358 if (winapi::NtQuerySystemInformation (winapi::SystemProcessorPerformanceInformation, &buffer[0 ],
352359 sizeof (winapi::SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * cores, NULL ) != 0 ) {
353- throw nsclient::nsclient_exception (" Whoops " );
360+ throw nsclient::nsclient_exception (" Failed to fetch cpu load " );
354361 }
355362
356363 cpu_load result;
@@ -360,18 +367,20 @@ system_info::cpu_load system_info::get_cpu_load() {
360367
361368 for (int i = 0 ; i < cores; i++) {
362369 unsigned long long CPUIdleTime = buffer[i].IdleTime .QuadPart ;
363- unsigned long long CPUKernelTime = buffer[i].KernelTime .QuadPart - buffer[i]. IdleTime . QuadPart ;
364- unsigned long long CPUTotalTime = buffer[i]. KernelTime . QuadPart + buffer[i].UserTime .QuadPart ;
370+ unsigned long long CPUKernelTime = buffer[i].KernelTime .QuadPart ;
371+ unsigned long long CPUUserTime = buffer[i].UserTime .QuadPart ;
365372
366373 unsigned long long CPUIdleTimeDiff = CPUIdleTime - g_CPUIdleTimeOld[i];
367374 unsigned long long CPUKernelTimeDiff = CPUKernelTime - g_CPUKernelTimeOld[i];
368- unsigned long long CPUTotalTimeDiff = CPUTotalTime - g_CPUTotalTimeOld [i];
375+ unsigned long long CPUUserTimeDiff = CPUUserTime - g_CPUUserTimeOld [i];
369376
370- if (CPUTotalTimeDiff != 0 ) {
377+ unsigned long long kernel_time_diff = CPUKernelTimeDiff - CPUIdleTimeDiff;
378+ unsigned long long total_time_diff = CPUKernelTimeDiff + CPUUserTimeDiff;
379+ if (total_time_diff != 0 ) {
371380 result.core [i].core = i;
372- result.core [i].idle = static_cast < double >((( CPUIdleTimeDiff * 100 ) / CPUTotalTimeDiff) );
373- result.core [i].kernel = static_cast < double >(((CPUKernelTimeDiff * 100 ) / CPUTotalTimeDiff) );
374- result.core [i].total = 100.0 - result.core [i].idle ;
381+ result.core [i].idle = get_rate ( CPUIdleTimeDiff, total_time_diff );
382+ result.core [i].kernel = get_rate (kernel_time_diff, total_time_diff );
383+ result.core [i].total = 100 - result.core [i].idle ;
375384 result.total .idle += result.core [i].idle ;
376385 result.total .kernel += result.core [i].kernel ;
377386 result.total .total += result.core [i].total ;
@@ -380,16 +389,56 @@ system_info::cpu_load system_info::get_cpu_load() {
380389 result.core [i].kernel = 0 ;
381390 result.core [i].total = 0 ;
382391 }
383- g_CPUTotalTimeOld[i] = CPUTotalTime;
384392 g_CPUIdleTimeOld[i] = CPUIdleTime;
385393 g_CPUKernelTimeOld[i] = CPUKernelTime;
394+ g_CPUUserTimeOld[i] = CPUUserTime;
386395 }
387396 result.total .idle /= result.cores ;
388397 result.total .kernel /= result.cores ;
389398 result.total .total /= result.cores ;
390399 return result;
391400}
392401
402+ system_info::cpu_load system_info::get_cpu_load_total () {
403+ init_old_buffer (g_CPUIdleTimeOld, 1 );
404+ init_old_buffer (g_CPUUserTimeOld, 1 );
405+ init_old_buffer (g_CPUKernelTimeOld, 1 );
406+
407+ FILETIME lpIdleTime;
408+ FILETIME lpKernelTime;
409+ FILETIME lpUserTime;
410+
411+ if (GetSystemTimes (&lpIdleTime, &lpKernelTime, &lpUserTime) == 0 ) {
412+ throw nsclient::nsclient_exception (" Failed to fetch cpu load" );
413+ }
414+ unsigned long long CPUIdleTime = (static_cast <unsigned long long >(lpIdleTime.dwHighDateTime ) << 32 ) | lpIdleTime.dwLowDateTime ;
415+ unsigned long long CPUKernelTime = (static_cast <unsigned long long >(lpKernelTime.dwHighDateTime ) << 32 ) | lpKernelTime.dwLowDateTime ;
416+ unsigned long long CPUUserTime = (static_cast <unsigned long long >(lpUserTime.dwHighDateTime ) << 32 ) | lpUserTime.dwLowDateTime ;
417+
418+ cpu_load result;
419+ result.cores = 0 ;
420+ result.core .resize (0 );
421+ result.total .idle = result.total .kernel = result.total .total = 0.0 ;
422+
423+ unsigned long long CPUIdleTimeDiff = CPUIdleTime - g_CPUIdleTimeOld[0 ];
424+ // Kernel also includes idle time so we need to subtract that
425+ unsigned long long CPUKernelTimeDiff = CPUKernelTime - g_CPUKernelTimeOld[0 ];
426+ unsigned long long CPUUserTimeDiff = CPUUserTime - g_CPUUserTimeOld[0 ];
427+
428+ unsigned long long kernel_time_diff = CPUKernelTimeDiff - CPUIdleTimeDiff;
429+ unsigned long long used_time_diff = kernel_time_diff + CPUUserTimeDiff;
430+ unsigned long long total_time_diff = CPUKernelTimeDiff + CPUUserTimeDiff;
431+
432+ result.total .idle = get_rate (CPUIdleTimeDiff, total_time_diff);
433+ result.total .kernel = get_rate (kernel_time_diff, total_time_diff);
434+ result.total .total = get_rate (used_time_diff, total_time_diff);
435+
436+ g_CPUIdleTimeOld[0 ] = CPUIdleTime;
437+ g_CPUKernelTimeOld[0 ] = CPUKernelTime;
438+ g_CPUUserTimeOld[0 ] = CPUUserTime;
439+ return result;
440+ }
441+
393442class CheckMemory {
394443 public:
395444 CheckMemory () : hKernel32(NULL ), FEGlobalMemoryStatusEx(NULL ), FEGlobalMemoryStatus(NULL ) {
0 commit comments