interrupt and context switch parameters correctly implemented on Windows
authorVictor Kirhenshtein <victor@netxms.org>
Wed, 14 Dec 2016 16:19:13 +0000 (18:19 +0200)
committerVictor Kirhenshtein <victor@netxms.org>
Wed, 14 Dec 2016 16:19:13 +0000 (18:19 +0200)
ChangeLog
include/nms_agent.h
src/agent/subagents/winnt/cpu.cpp
src/agent/subagents/winnt/main.cpp

index 1afd08d..1f6770d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -20,6 +20,8 @@
 - Added support for CHAP, MS-CHAPv1, and MS-CHAPv2 in RADIUS authentication
 - MySQL monitoring subagent
 - Fixed FreeBSD 11 compatibility issues
+- Implemented interrupt and context switch counters in platform subagents
+- Implemented CPU interrupt time parameters on Windows
 - Management console:
        - File manager improvements
 - Fixed issues: #106, #130, #174, #185, #526, #569, #876, #953, #1031, #1043, #1069, #1090, #1097, #1156, #1192, #1201, #1205, #1206, #1233, #1258, #1285, #1292, #1300, #1312, #1314, #1318, #1320, #1323, #1326, #1329, #1332, #1338, #1348, #1349, #1360, #1361, #1362
index 86f39f9..9edafac 100644 (file)
 #define DCIDESC_PDH_COUNTERVALUE                  _T("Value of PDH counter {instance}")
 #define DCIDESC_PDH_VERSION                       _T("Version of PDH.DLL")
 #define DCIDESC_SYSTEM_UPTIME                     _T("System uptime")
+
 #define DCIDESC_SYSTEM_CPU_LOADAVG                _T("Average CPU load for last minute")
 #define DCIDESC_SYSTEM_CPU_LOADAVG5               _T("Average CPU load for last 5 minutes")
 #define DCIDESC_SYSTEM_CPU_LOADAVG15              _T("Average CPU load for last 15 minutes")
-#define DCIDESC_SYSTEM_CPU_INTERRUPTS             _T("Total CPU interrupts")
-#define DCIDESC_SYSTEM_CPU_CONTEXT_SWITCHES       _T("Total CPU context switches")
+
+#define DCIDESC_SYSTEM_CPU_INTERRUPTS             _T("CPU interrupt count")
+#define DCIDESC_SYSTEM_CPU_INTERRUPTS_EX          _T("CPU {instance} interrupt count")
+#define DCIDESC_SYSTEM_CPU_CONTEXT_SWITCHES       _T("CPU context switch count")
 
 #define DCIDESC_SYSTEM_CPU_USAGE_EX               _T("Average CPU {instance} utilization for last minute")
 #define DCIDESC_SYSTEM_CPU_USAGE5_EX              _T("Average CPU {instance} utilization for last 5 minutes")
index 82894ed..ec359aa 100644 (file)
@@ -28,8 +28,9 @@ static SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *s_cpuTimes = NULL;
 static UINT32 *s_usage = NULL;
 static UINT32 *s_idle = NULL;
 static UINT32 *s_kernel = NULL;
-static UINT64 *s_user = NULL;
-static UINT64 s_intr, s_ctxt;
+static UINT32 *s_user = NULL;
+static UINT32 *s_interrupt = NULL;
+static UINT32 *s_interruptCount = NULL;
 static int s_bpos = 0;
 static CRITICAL_SECTION s_lock;
 
@@ -44,7 +45,6 @@ static THREAD_RESULT THREAD_CALL CPUStatCollector(void *arg)
    SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *curr = &s_cpuTimes[s_cpuCount];
 
    ULONG cpuTimesLen = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * s_cpuCount;
-   ULONG cpuCtxtLen = sizeof(SYSTEM_INTERRUPT_INFORMATION) * s_cpuCount;
    ULONG size;
    NtQuerySystemInformation(SystemProcessorPerformanceInformation, s_cpuTimes, cpuTimesLen, &size);
 
@@ -54,30 +54,32 @@ static THREAD_RESULT THREAD_CALL CPUStatCollector(void *arg)
       {
          memcpy(curr, prev, cpuTimesLen);
       }
-      SYSTEM_INTERRUPT_INFORMATION ctxt
-      NtQuerySystemInformation(SystemInterruptInformation, &ctxt, cpuCtxtLen, &size);
 
       UINT64 sysIdle = 0;
       UINT64 sysKernel = 0;
       UINT64 sysUser = 0;
-      UINT64 intr = 0;
-      UINT64 ctxt = 0;
+      UINT64 sysInterrupt = 0;
 
       EnterCriticalSection(&s_lock);
 
+      s_interruptCount[s_cpuCount] = 0;
+
       int idx = s_bpos;
       for(int i = 0; i < s_cpuCount; i++, idx++)
       {
          UINT64 idle = curr[i].IdleTime.QuadPart - prev[i].IdleTime.QuadPart;
          UINT64 kernel = curr[i].KernelTime.QuadPart - prev[i].KernelTime.QuadPart;
          UINT64 user = curr[i].UserTime.QuadPart - prev[i].UserTime.QuadPart;
+         UINT64 interrupt = curr[i].Reserved1[1].QuadPart - prev[i].Reserved1[1].QuadPart;
          UINT64 total = kernel + user;  // kernel time includes idle time
-         intr += curr[i].InterruptCount;
-         ctxt += ctxt[i].ContextSwitches;
+
+         s_interruptCount[i] = curr[i].Reserved2;
+         s_interruptCount[s_cpuCount] += curr[i].Reserved2;
 
          sysIdle += idle;
          sysKernel += kernel;
          sysUser += user;
+         sysInterrupt += interrupt;
 
          if (total > 0)
          {
@@ -85,6 +87,7 @@ static THREAD_RESULT THREAD_CALL CPUStatCollector(void *arg)
             s_idle[idx] = (UINT32)(idle * 10000 / total);
             s_kernel[idx] = (UINT32)((kernel - idle) * 10000 / total);
             s_user[idx] = (UINT32)(user * 10000 / total);
+            s_interrupt[idx] = (UINT32)(interrupt * 10000 / total);
          }
          else
          {
@@ -92,12 +95,10 @@ static THREAD_RESULT THREAD_CALL CPUStatCollector(void *arg)
             s_idle[idx] = 0;
             s_kernel[idx] = 0;
             s_user[idx] = 0;
+            s_interrupt[idx] = 0;
          }
       }
 
-      s_intr = intr;
-      s_ctxt = ctxt;
-
       UINT64 sysTotal = sysKernel + sysUser;
       if (sysTotal > 0)
       {
@@ -105,6 +106,7 @@ static THREAD_RESULT THREAD_CALL CPUStatCollector(void *arg)
          s_idle[idx] = (UINT32)(sysIdle * 10000 / sysTotal);
          s_kernel[idx] = (UINT32)((sysKernel - sysIdle) * 10000 / sysTotal);
          s_user[idx] = (UINT32)(sysUser * 10000 / sysTotal);
+         s_interrupt[idx] = (UINT32)(sysInterrupt * 10000 / sysTotal);
       }
       else
       {
@@ -112,6 +114,7 @@ static THREAD_RESULT THREAD_CALL CPUStatCollector(void *arg)
          s_idle[idx] = 0;
          s_kernel[idx] = 0;
          s_user[idx] = 0;
+         s_interrupt[idx] = 0;
       }
 
       s_bpos += s_cpuCount + 1;
@@ -154,6 +157,8 @@ void StartCPUStatCollector()
    s_idle = (UINT32 *)calloc(900, sizeof(UINT32) * (s_cpuCount + 1));
    s_kernel = (UINT32 *)calloc(900, sizeof(UINT32) * (s_cpuCount + 1));
    s_user = (UINT32 *)calloc(900, sizeof(UINT32) * (s_cpuCount + 1));
+   s_interrupt = (UINT32 *)calloc(900, sizeof(UINT32) * (s_cpuCount + 1));
+   s_interruptCount = (UINT32 *)calloc(sizeof(UINT32), s_cpuCount + 1);
    InitializeCriticalSectionAndSpinCount(&s_lock, 1000);
    s_collectorThread = ThreadCreateEx(CPUStatCollector, 0, NULL);
 }
@@ -175,7 +180,7 @@ void StopCPUStatCollector()
 /**
  * Handler for System.CPU.Usage parameters
  */
-LONG H_CPUUsage(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
+LONG H_CpuUsage(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
 {
    int cpuIndex;
    if (arg[0] == 'T')   // Total
@@ -223,6 +228,9 @@ LONG H_CPUUsage(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractComm
       case 'I':
          data = s_idle;
          break;
+      case 'q':
+         data = s_interrupt;
+         break;
       case 's':
          data = s_kernel;
          break;
@@ -249,19 +257,44 @@ LONG H_CPUUsage(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractComm
 }
 
 /*
- * Handler for CPU Context Switch parameter
+ * Handler for System.CPU.ContextSwitches parameter
  */
-LONG H_CpuCswitch(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
+LONG H_CpuContextSwitches(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
 {
-   ret_uint(value, s_ctxt);
+   SYSTEM_INTERRUPT_INFORMATION interrupts;
+   ULONG size;
+   if (NtQuerySystemInformation(SystemInterruptInformation, &interrupts, sizeof(SYSTEM_INTERRUPT_INFORMATION), &size) != 0)
+      return SYSINFO_RC_ERROR;
+
+   // First 4 bytes in SYSTEM_INTERRUPT_INFORMATION is context switch count
+   // (according to http://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/interrupt.htm)
+   ret_uint(value, *((UINT32 *)interrupts.Reserved1));
    return SYSINFO_RC_SUCCESS;
 }
 
 /*
- * Handler for CPU Interrupts parameter
+ * Handler for System.CPU.Interrupts parameters
  */
 LONG H_CpuInterrupts(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
 {
-   ret_uint(value, s_intr);
+   int cpuIndex;
+   if (arg[0] == 'T')   // Total
+   {
+      cpuIndex = s_cpuCount;
+   }
+   else
+   {
+      TCHAR buffer[64];
+      if (!AgentGetParameterArg(param, 1, buffer, 64))
+         return SYSINFO_RC_UNSUPPORTED;
+      cpuIndex = _tcstol(buffer, NULL, 10);
+      if ((cpuIndex < 0) || (cpuIndex >= s_cpuCount))
+         return SYSINFO_RC_UNSUPPORTED;
+   }
+
+   EnterCriticalSection(&s_lock);
+   ret_uint(value, s_interruptCount[cpuIndex]);
+   LeaveCriticalSection(&s_lock);
+
    return SYSINFO_RC_SUCCESS;
 }
index a2aac3b..6273210 100644 (file)
@@ -31,7 +31,9 @@ LONG H_AgentDesktop(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCo
 LONG H_AppAddressSpace(const TCHAR *pszCmd, const TCHAR *pArg, TCHAR *pValue, AbstractCommSession *session);
 LONG H_ArpCache(const TCHAR *cmd, const TCHAR *arg, StringList *value, AbstractCommSession *session);
 LONG H_ConnectedUsers(const TCHAR *pszCmd, const TCHAR *pArg, TCHAR *pValue, AbstractCommSession *session);
-LONG H_CPUUsage(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
+LONG H_CpuContextSwitches(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
+LONG H_CpuInterrupts(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
+LONG H_CpuUsage(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
 LONG H_Desktops(const TCHAR *cmd, const TCHAR *arg, StringList *value, AbstractCommSession *session);
 LONG H_HandleCount(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
 LONG H_InstalledProducts(const TCHAR *cmd, const TCHAR *arg, Table *value, AbstractCommSession *);
@@ -53,8 +55,6 @@ LONG H_ServiceTable(const TCHAR *pszCmd, const TCHAR *pArg, Table *value, Abstra
 LONG H_SysUpdateTime(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
 LONG H_ThreadCount(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
 LONG H_WindowStations(const TCHAR *cmd, const TCHAR *arg, StringList *value, AbstractCommSession *session);
-LONG H_CpuCswitch(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
-LONG H_CpuInterrupts(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
 
 void StartCPUStatCollector();
 void StopCPUStatCollector();
@@ -182,6 +182,7 @@ static void SubAgentShutdown()
 static NETXMS_SUBAGENT_PARAM m_parameters[] =
 {
    { _T("Agent.Desktop"), H_AgentDesktop, NULL, DCI_DT_STRING, _T("Desktop associated with agent process") },
+
    { _T("Net.Interface.64BitCounters"), H_NetInterface64bitSupport, NULL, DCI_DT_INT, DCIDESC_NET_INTERFACE_64BITCOUNTERS },
    { _T("Net.Interface.AdminStatus(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_ADMIN_STATUS, DCI_DT_INT, DCIDESC_NET_INTERFACE_ADMINSTATUS },
    { _T("Net.Interface.BytesIn(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_BYTES_IN, DCI_DT_UINT, DCIDESC_NET_INTERFACE_BYTESIN },
@@ -199,9 +200,12 @@ static NETXMS_SUBAGENT_PARAM m_parameters[] =
    { _T("Net.Interface.PacketsOut(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_PACKETS_OUT, DCI_DT_UINT, DCIDESC_NET_INTERFACE_PACKETSOUT },
    { _T("Net.Interface.PacketsOut64(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_PACKETS_OUT_64, DCI_DT_UINT64, DCIDESC_NET_INTERFACE_PACKETSOUT },
    { _T("Net.Interface.Speed(*)"), H_NetInterfaceStats, (TCHAR *)NETINFO_IF_SPEED, DCI_DT_UINT64, DCIDESC_NET_INTERFACE_SPEED },
+
    { _T("Net.IP.Forwarding"), H_NetIPStats, (TCHAR *)NETINFO_IP_FORWARDING, DCI_DT_INT, DCIDESC_NET_IP_FORWARDING },
+
        { _T("Net.RemoteShareStatus(*)"), H_RemoteShareStatus, _T("C"), DCI_DT_INT, _T("Status of remote shared resource") },
        { _T("Net.RemoteShareStatusText(*)"), H_RemoteShareStatus, _T("T"), DCI_DT_STRING, _T("Status of remote shared resource as text") },
+
        { _T("Process.Count(*)"), H_ProcCountSpecific, _T("N"), DCI_DT_INT, DCIDESC_PROCESS_COUNT },
        { _T("Process.CountEx(*)"), H_ProcCountSpecific, _T("E"), DCI_DT_INT, DCIDESC_PROCESS_COUNTEX },
        { _T("Process.CPUTime(*)"), H_ProcInfo, (TCHAR *)PROCINFO_CPUTIME, DCI_DT_UINT64, DCIDESC_PROCESS_CPUTIME },
@@ -219,51 +223,61 @@ static NETXMS_SUBAGENT_PARAM m_parameters[] =
        { _T("Process.UserTime(*)"), H_ProcInfo, (TCHAR *)PROCINFO_UTIME, DCI_DT_UINT64, DCIDESC_PROCESS_USERTIME },
        { _T("Process.VMSize(*)"), H_ProcInfo, (TCHAR *)PROCINFO_VMSIZE, DCI_DT_UINT64, DCIDESC_PROCESS_VMSIZE },
        { _T("Process.WkSet(*)"), H_ProcInfo, (TCHAR *)PROCINFO_WKSET, DCI_DT_UINT64, DCIDESC_PROCESS_WKSET },
+
        { _T("System.AppAddressSpace"), H_AppAddressSpace, NULL, DCI_DT_UINT, DCIDESC_SYSTEM_APPADDRESSSPACE },
        { _T("System.ConnectedUsers"), H_ConnectedUsers, NULL, DCI_DT_INT, DCIDESC_SYSTEM_CONNECTEDUSERS },
 
-       { _T("System.CPU.Interrupts"), H_CpuInterrupts, _T("T0i"), DCI_DT_UINT, DCIDESC_SYSTEM_CPU_INTERRUPTS },
-       { _T("System.CPU.ContextSwitches"), H_CpuCswitch, _T("T0C"), DCI_DT_UINT, DCIDESC_SYSTEM_CPU_CONTEXT_SWITCHES },
+       { _T("System.CPU.Interrupts"), H_CpuInterrupts, _T("T"), DCI_DT_UINT, DCIDESC_SYSTEM_CPU_INTERRUPTS },
+       { _T("System.CPU.Interrupts(*)"), H_CpuInterrupts, _T("C"), DCI_DT_UINT, DCIDESC_SYSTEM_CPU_INTERRUPTS_EX },
+       { _T("System.CPU.ContextSwitches"), H_CpuContextSwitches, NULL, DCI_DT_UINT, DCIDESC_SYSTEM_CPU_CONTEXT_SWITCHES },
    
-   { _T("System.CPU.CurrentUsage"), H_CPUUsage, _T("T0U"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR },
-   { _T("System.CPU.CurrentUsage.Idle"), H_CPUUsage, _T("T0I"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR_IDLE },
-   { _T("System.CPU.CurrentUsage.System"), H_CPUUsage, _T("T0s"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR_SYSTEM },
-   { _T("System.CPU.CurrentUsage.User"), H_CPUUsage, _T("T0u"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR_USER },
-
-   { _T("System.CPU.CurrentUsage(*)"), H_CPUUsage, _T("C0U"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR_EX },
-   { _T("System.CPU.CurrentUsage.Idle(*)"), H_CPUUsage, _T("C0I"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR_IDLE_EX },
-   { _T("System.CPU.CurrentUsage.System(*)"), H_CPUUsage, _T("C0s"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR_SYSTEM_EX },
-   { _T("System.CPU.CurrentUsage.User(*)"), H_CPUUsage, _T("C0u"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR_USER_EX },
-
-   { _T("System.CPU.Usage"), H_CPUUsage, _T("T1U"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE },
-   { _T("System.CPU.Usage.Idle"), H_CPUUsage, _T("T1I"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE_IDLE },
-   { _T("System.CPU.Usage.System"), H_CPUUsage, _T("T1s"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE_SYSTEM },
-   { _T("System.CPU.Usage.User"), H_CPUUsage, _T("T1u"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE_USER },
+   { _T("System.CPU.CurrentUsage"), H_CpuUsage, _T("T0U"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR },
+   { _T("System.CPU.CurrentUsage.Idle"), H_CpuUsage, _T("T0I"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR_IDLE },
+   { _T("System.CPU.CurrentUsage.Irq"), H_CpuUsage, _T("T0q"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR_IRQ },
+   { _T("System.CPU.CurrentUsage.System"), H_CpuUsage, _T("T0s"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR_SYSTEM },
+   { _T("System.CPU.CurrentUsage.User"), H_CpuUsage, _T("T0u"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR_USER },
+
+   { _T("System.CPU.CurrentUsage(*)"), H_CpuUsage, _T("C0U"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR_EX },
+   { _T("System.CPU.CurrentUsage.Idle(*)"), H_CpuUsage, _T("C0I"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR_IDLE_EX },
+   { _T("System.CPU.CurrentUsage.Irq(*)"), H_CpuUsage, _T("C0q"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR_IRQ_EX },
+   { _T("System.CPU.CurrentUsage.System(*)"), H_CpuUsage, _T("C0s"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR_SYSTEM_EX },
+   { _T("System.CPU.CurrentUsage.User(*)"), H_CpuUsage, _T("C0u"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR_USER_EX },
+
+   { _T("System.CPU.Usage"), H_CpuUsage, _T("T1U"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE },
+   { _T("System.CPU.Usage.Idle"), H_CpuUsage, _T("T1I"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE_IDLE },
+   { _T("System.CPU.Usage.Irq"), H_CpuUsage, _T("T1q"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE_IRQ },
+   { _T("System.CPU.Usage.System"), H_CpuUsage, _T("T1s"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE_SYSTEM },
+   { _T("System.CPU.Usage.User"), H_CpuUsage, _T("T1u"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE_USER },
        
-   { _T("System.CPU.Usage(*)"), H_CPUUsage, _T("C1U"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE_EX },
-   { _T("System.CPU.Usage.Idle(*)"), H_CPUUsage, _T("C1I"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE_IDLE_EX },
-   { _T("System.CPU.Usage.System(*)"), H_CPUUsage, _T("C1s"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE_SYSTEM_EX },
-   { _T("System.CPU.Usage.User(*)"), H_CPUUsage, _T("C1u"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE_USER_EX },
+   { _T("System.CPU.Usage(*)"), H_CpuUsage, _T("C1U"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE_EX },
+   { _T("System.CPU.Usage.Idle(*)"), H_CpuUsage, _T("C1I"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE_IDLE_EX },
+   { _T("System.CPU.Usage.Irq(*)"), H_CpuUsage, _T("C1q"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE_IRQ_EX },
+   { _T("System.CPU.Usage.System(*)"), H_CpuUsage, _T("C1s"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE_SYSTEM_EX },
+   { _T("System.CPU.Usage.User(*)"), H_CpuUsage, _T("C1u"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE_USER_EX },
    
-   { _T("System.CPU.Usage5"), H_CPUUsage, _T("T2U"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE5 },
-   { _T("System.CPU.Usage5.Idle"), H_CPUUsage, _T("T2I"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE5_IDLE },
-   { _T("System.CPU.Usage5.System"), H_CPUUsage, _T("T2s"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE5_SYSTEM },
-   { _T("System.CPU.Usage5.User"), H_CPUUsage, _T("T2u"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE5_USER },
+   { _T("System.CPU.Usage5"), H_CpuUsage, _T("T2U"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE5 },
+   { _T("System.CPU.Usage5.Idle"), H_CpuUsage, _T("T2I"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE5_IDLE },
+   { _T("System.CPU.Usage5.Irq"), H_CpuUsage, _T("T2q"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE5_IRQ },
+   { _T("System.CPU.Usage5.System"), H_CpuUsage, _T("T2s"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE5_SYSTEM },
+   { _T("System.CPU.Usage5.User"), H_CpuUsage, _T("T2u"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE5_USER },
    
-   { _T("System.CPU.Usage5(*)"), H_CPUUsage, _T("C2U"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE5_EX },
-   { _T("System.CPU.Usage.Idle(*)"), H_CPUUsage, _T("C2I"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE5_IDLE_EX },
-   { _T("System.CPU.Usage.System(*)"), H_CPUUsage, _T("C2s"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE5_SYSTEM_EX },
-   { _T("System.CPU.Usage.User(*)"), H_CPUUsage, _T("C2u"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE5_USER_EX },
+   { _T("System.CPU.Usage5(*)"), H_CpuUsage, _T("C2U"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE5_EX },
+   { _T("System.CPU.Usage.Idle(*)"), H_CpuUsage, _T("C2I"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE5_IDLE_EX },
+   { _T("System.CPU.Usage.Irq(*)"), H_CpuUsage, _T("C2q"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE5_IRQ_EX },
+   { _T("System.CPU.Usage.System(*)"), H_CpuUsage, _T("C2s"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE5_SYSTEM_EX },
+   { _T("System.CPU.Usage.User(*)"), H_CpuUsage, _T("C2u"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE5_USER_EX },
    
-   { _T("System.CPU.Usage15"), H_CPUUsage, _T("T3U"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE15 },
-   { _T("System.CPU.Usage5.Idle"), H_CPUUsage, _T("T3I"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE15_IDLE },
-   { _T("System.CPU.Usage5.System"), H_CPUUsage, _T("T3s"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE15_SYSTEM },
-   { _T("System.CPU.Usage5.User"), H_CPUUsage, _T("T3u"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE15_USER },
+   { _T("System.CPU.Usage15"), H_CpuUsage, _T("T3U"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE15 },
+   { _T("System.CPU.Usage15.Idle"), H_CpuUsage, _T("T3I"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE15_IDLE },
+   { _T("System.CPU.Usage15.Irq"), H_CpuUsage, _T("T3q"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE15_IRQ },
+   { _T("System.CPU.Usage15.System"), H_CpuUsage, _T("T3s"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE15_SYSTEM },
+   { _T("System.CPU.Usage15.User"), H_CpuUsage, _T("T3u"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE15_USER },
    
-   { _T("System.CPU.Usage15(*)"), H_CPUUsage, _T("C3U"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE15_EX },
-   { _T("System.CPU.Usage15.Idle(*)"), H_CPUUsage, _T("C3I"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE15_IDLE_EX },
-   { _T("System.CPU.Usage15.System(*)"), H_CPUUsage, _T("C3s"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE15_SYSTEM_EX },
-   { _T("System.CPU.Usage15.User(*)"), H_CPUUsage, _T("C3u"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE15_USER_EX },
+   { _T("System.CPU.Usage15(*)"), H_CpuUsage, _T("C3U"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE15_EX },
+   { _T("System.CPU.Usage15.Idle(*)"), H_CpuUsage, _T("C3I"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE15_IDLE_EX },
+   { _T("System.CPU.Usage15.Irq(*)"), H_CpuUsage, _T("C3q"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE15_IRQ_EX },
+   { _T("System.CPU.Usage15.System(*)"), H_CpuUsage, _T("C3s"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE15_SYSTEM_EX },
+   { _T("System.CPU.Usage15.User(*)"), H_CpuUsage, _T("C3u"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGE15_USER_EX },
        
    { _T("System.HandleCount"), H_HandleCount, NULL, DCI_DT_UINT, DCIDESC_SYSTEM_HANDLECOUNT },
        { _T("System.ProcessCount"), H_ProcCount, NULL, DCI_DT_UINT, DCIDESC_SYSTEM_PROCESSCOUNT },