/** * Populates the host_memory structure using data retrieved using * GlobalMemoryStatusEx function and the Memory performance counter * object. * Returns FALSE if call to GlobalMemoryStatusEx produces an error, TRUE otherwise. * Note that the Windows use of memory and classification of use does * not map cleanly to Linux terms. * We are using Windows available memory for mem_free. Available memory * includes standby memory (memory removed from a process's working set * - its physical memory - on route to disk, but is still available to be recalled) * and free and zero page list bytes. Windows Resource Monitor reports free memory * as free page list bytes. * Memory\\Cache Bytes is used for mem_cached since this really does appear to be * the Linux equivalent of cache (file system cache). * Windows Resource Monitor reports cached as Standby+Modified this is not the * equivalent of Linux file system cache. * Windows also does not seem to report swapping (all memory associated with a process * swapped in/out of memory). Memory\\Pages Input/sec and Memory\\Pages Output/sec * are used for page_in and page_out. */ BOOL readMemoryCounters(SFLHost_mem_counters *mem) { MEMORYSTATUSEX memStat; memStat.dwLength = sizeof(memStat); if (GlobalMemoryStatusEx(&memStat) == 0){ myLog(LOG_ERR,"GlobalMemoryStatusEx failed: %d\n",GetLastError()); return FALSE; } mem->mem_total = memStat.ullTotalPhys; mem->mem_free = memStat.ullAvailPhys; mem->swap_total = memStat.ullTotalPageFile; mem->swap_free = memStat.ullAvailPageFile; PDH_HQUERY query; if (PdhOpenQuery(NULL, 0, &query) == ERROR_SUCCESS) { PDH_HCOUNTER cache, pageIn, pageOut; if (addCounterToQuery(MEM_COUNTER_OBJECT, NULL, MEM_COUNTER_CACHE, &query, &cache) == ERROR_SUCCESS && addCounterToQuery(MEM_COUNTER_OBJECT, NULL, MEM_COUNTER_PAGE_IN, &query, &pageIn) == ERROR_SUCCESS && addCounterToQuery(MEM_COUNTER_OBJECT, NULL, MEM_COUNTER_PAGE_OUT, &query, &pageOut) == ERROR_SUCCESS && PdhCollectQueryData(query) == ERROR_SUCCESS) { mem->mem_cached= getRawCounterValue(&cache); mem->page_in = (uint32_t)getRawCounterValue(&pageIn); mem->page_out = (uint32_t)getRawCounterValue(&pageOut); } PdhCloseQuery(query); } //There are no obvious Windows equivalents mem->mem_shared = UNKNOWN_COUNTER_64; mem->mem_buffers = UNKNOWN_COUNTER_64; //using the definition that swapping is when all the memory associated with a //process is moved in/out of RAM mem->swap_in = UNKNOWN_COUNTER; mem->swap_out = UNKNOWN_COUNTER; myLog(LOG_INFO, "readMemoryCounters:\n\ttotal: \t\t%I64d\n\tfree: \t\t%I64d\n" "\tcached: \t%I64d\n\tpage_in: \t%d\n\tpage_out: \t%d\n" "\tswap_total: \t%I64d\n\tswap_free: \t%I64d\n", mem->mem_total,mem->mem_free, mem->mem_cached,mem->page_in,mem->page_out, mem->swap_total, mem->swap_free); return TRUE; }
/* * Uses PDH to obtain the host_cpu counters and populates the * SFLHost_spu_counters stucture. * Uses Processor, System, and Process performance counter objects * for CPU time, interrupts and contexts and registry to obtain CPU speed. */ void readCpuCounters(SFLHost_cpu_counters *cpu) { cpu->load_one = (float)load_1; cpu->load_five = (float)load_5; cpu->load_fifteen = (float)load_15; PDH_HQUERY query; if (PdhOpenQuery(NULL, 0, &query) == ERROR_SUCCESS) { PDH_HCOUNTER userTime, systemTime, idleTime, intrTime, interrupts, contexts, uptime, processes; if (addCounterToQuery(CPU_COUNTER_OBJECT, COUNTER_INSTANCE_TOTAL, CPU_COUNTER_USER, &query, &userTime) == ERROR_SUCCESS && addCounterToQuery(CPU_COUNTER_OBJECT, COUNTER_INSTANCE_TOTAL, CPU_COUNTER_SYSTEM, &query, &systemTime) == ERROR_SUCCESS && addCounterToQuery(CPU_COUNTER_OBJECT, COUNTER_INSTANCE_TOTAL, CPU_COUNTER_IDLE, &query, &idleTime) == ERROR_SUCCESS && addCounterToQuery(CPU_COUNTER_OBJECT, COUNTER_INSTANCE_TOTAL, CPU_COUNTER_INTR, &query, &intrTime) == ERROR_SUCCESS && addCounterToQuery(CPU_COUNTER_OBJECT, COUNTER_INSTANCE_TOTAL, CPU_COUNTER_INTERRUPTS, &query, &interrupts) == ERROR_SUCCESS && addCounterToQuery(SYS_COUNTER_OBJECT, NULL, SYS_COUNTER_CONTEXTS, &query, &contexts) == ERROR_SUCCESS && addCounterToQuery(SYS_COUNTER_OBJECT, NULL, SYS_COUNTER_UPTIME, &query, &uptime) == ERROR_SUCCESS && addCounterToQuery(SYS_COUNTER_OBJECT, NULL, SYS_COUNTER_PROCESSES, &query, &processes) == ERROR_SUCCESS && PdhCollectQueryData(query) == ERROR_SUCCESS) { //CPU time is in 100ns units, divide by 10000 for ms cpu->cpu_user = (uint32_t)(getRawCounterValue(&userTime)/tick_to_ms); cpu->cpu_system = (uint32_t)(getRawCounterValue(&systemTime)/tick_to_ms); cpu->cpu_idle = (uint32_t)(getRawCounterValue(&idleTime)/tick_to_ms); cpu->cpu_intr = (uint32_t)(getRawCounterValue(&intrTime)/tick_to_ms); cpu->interrupts = (uint32_t)getRawCounterValue(&interrupts); cpu->contexts = (uint32_t)getRawCounterValue(&contexts); cpu->uptime = (uint32_t)getCookedCounterValue(&uptime); cpu->proc_total = (uint32_t)getRawCounterValue(&processes); } PdhCloseQuery(query); } if (PdhOpenQuery(NULL, 0, &query) == ERROR_SUCCESS) { PDH_HCOUNTER threads; if (addCounterToQuery(THR_COUNTER_OBJECT, COUNTER_INSTANCE_ALL, THR_COUNTER_STATE, &query, &threads) == ERROR_SUCCESS && PdhCollectQueryData(query) == ERROR_SUCCESS) { PPDH_RAW_COUNTER_ITEM_W values = NULL; uint32_t threadCount = getRawCounterValues(&threads, &values); if (threadCount > 0) { for (uint32_t i = 0; i < threadCount; i++) { if (values[i].RawValue.FirstValue == 2 && wcsncmp(L"Idle", values[i].szName, 4) != 0) { //count the threads that are running (state==2) and are not owned by the idle process. //the name of each thread state counter starts with the process name. cpu->proc_run++; } } my_free(values); } } PdhCloseQuery(query); } cpu->cpu_num = getCpuNum(); DWORD dwRet,cbData = sizeof(DWORD); HKEY hkey; // see http://support.microsoft.com/kb/888282 for ways to determine CPU speed dwRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "hardware\\description\\system\\centralprocessor\\0", 0, KEY_QUERY_VALUE, &hkey); if(dwRet == ERROR_SUCCESS) { dwRet = RegQueryValueEx( hkey, "~MHz", NULL, NULL, (LPBYTE) &cpu->cpu_speed, &cbData ); if(dwRet != ERROR_SUCCESS) cpu->cpu_speed = UNKNOWN_GAUGE; RegCloseKey(hkey); } //These have no obvious Windows equivalent cpu->cpu_sintr = UNKNOWN_COUNTER; cpu->cpu_nice = UNKNOWN_COUNTER; cpu->cpu_wio = UNKNOWN_COUNTER; myLog(LOG_INFO, "readCpuCounters:\n\tload_one:\t%f\n\tload_five:\t%f\n\tload_fifteen:\t%f\n" "\tuptime:\t\t%lus\n\tcpu_num:\t%d\n" "\tcpu speed:\t%d MHz\n\tuser:\t\t%lu\n\tsystem:\t\t%lu\n\tidle:\t\t%lu\n\tirq:\t\t%lu\n" "\tcontexts:\t%lu\n\tinterrupts:\t%lu\n" "\tproc_total:\t%lu\n\tproc_run:\t%lu\n", cpu->load_one, cpu->load_five, cpu->load_fifteen, cpu->uptime, cpu->cpu_num, cpu->cpu_speed, cpu->cpu_user,cpu->cpu_system, cpu->cpu_idle, cpu->cpu_intr, cpu->contexts, cpu->interrupts, cpu->proc_total, cpu->proc_run); }
static PDH_STATUS addCounter(wchar_t *counterName, PDH_HCOUNTER *counter) { return addCounterToQuery(NIO_COUNTER_OBJECT, COUNTER_INSTANCE_ALL, counterName, &query, counter); }
/** * Convenience function for addCounterToQuery with counter object always IF_COUNTER_OBJECT. * Adds the counter with path constructed from IF_COUNTER_OBJECT, instance, counterName, * to the query, with counter query results referenced by *counter. * Returns PDH_STATUS from adding a counter to the query, ERROR_SUCCESS on success. * wchar_t *instance counter instance name (eg switchGUID-portGUID) (null terminated). * wchar_t *counterName English name of counter (null terminated). * PDH_HQUERY *query handle for the query. * PDH_HCOUNTER *counter handle for the counter query results. */ static PDH_STATUS addCounter(wchar_t *instance, wchar_t *counterName, PDH_HQUERY *query, PDH_HCOUNTER *counter) { return addCounterToQuery(IF_COUNTER_OBJECT, instance, counterName, query, counter); }