diff --git a/CMakeLists.txt b/CMakeLists.txt index ea18669..5427bd5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,9 +10,7 @@ set(BuildExecutable resource-monitor) set(Build ${BuildDir}/${BuildExecutable}) set(SourceDir ./src) -set(Platform ./platform) -set(WinDep ${Platform}/win32) -set(LinuxDep ${Platform}/linux) +set(LibSysSource ./libsys) set(Include ./include) @@ -21,28 +19,16 @@ find_package(Threads REQUIRED) include_directories(${Build} ${Include}/) -if (WIN32) - file(GLOB_RECURSE PlatformDepSource - ${WinDep}/monitoring/*.cpp - ${WinDep}/ui/*.cpp - ${WinDep}/*.cpp - ) -endif (WIN32) - -if (UNIX) - file(GLOB_RECURSE PlatformDepSource - ${LinuxDep}/monitoring/*.cpp - ${LinuxDep}/ui/*.cpp - ${LinuxDep}/*.cpp - ) -endif (UNIX) +file(GLOB_RECURSE LibSys + ${LibSysSource}/*.cpp +) file(GLOB_RECURSE SourceFiles ${SourceDir}/*.cpp ) add_executable(${Build} - ${PlatformDepSource} + ${LibSys} ${SourceFiles} ) diff --git a/bin/resource-monitor b/bin/resource-monitor index a8327bd..23773a1 100755 Binary files a/bin/resource-monitor and b/bin/resource-monitor differ diff --git a/include/libsys.h b/include/libsys.h new file mode 100644 index 0000000..f9c41ed --- /dev/null +++ b/include/libsys.h @@ -0,0 +1,3 @@ +#pragma once + +#include "../libsys/libsys.h" diff --git a/libsys/common.cpp b/libsys/common.cpp new file mode 100644 index 0000000..3a3d211 --- /dev/null +++ b/libsys/common.cpp @@ -0,0 +1,22 @@ +#include "common.h" + +#include +#include +#include +#include + +std::vector execcommand(std::string command) { + char buffer[128]; + std::vector result; + FILE* pipe = popen(command.c_str(), "r"); + try { + while (fgets(buffer, sizeof buffer, pipe) != NULL) { + result.push_back(buffer); + } + } catch (...) { + pclose(pipe); + throw; + } + pclose(pipe); + return result; +} diff --git a/include/common.h b/libsys/common.h similarity index 100% rename from include/common.h rename to libsys/common.h diff --git a/libsys/cpu.cpp b/libsys/cpu.cpp new file mode 100644 index 0000000..879e4b9 --- /dev/null +++ b/libsys/cpu.cpp @@ -0,0 +1,176 @@ +#include "cpu.h" +#include "common.h" + +#include +#include +#include +#include +#include +#include + +CPU::CPU() { + this->CPU_HARDWARE_THREADS = std::thread::hardware_concurrency(); + this->UPDATE_INTERVAL = 1000; + this->m_isPolling = false; + this->cpuStat = new CPUStat(); + this->cpuStat->HARDWARE_THREADS = this->CPU_HARDWARE_THREADS; + + std::vector lscpu = execcommand("lscpu"); + for (unsigned int i = 0; i < lscpu.size(); i++) { + std::regex architecture("Architecture.*?((?:[a-z][a-z0-9_]*))"); + std::regex maxMHz ("CPU max MHz.*?((?:[0-9].*))"); + std::regex minMHz ("CPU min MHz.*?((?:[0-9].*))"); + std::regex MHz ("CPU MHz.*?((?:[0-9].*))"); + std::smatch m; + + if (std::regex_search(lscpu[i], m, architecture)) { + this->cpuStat->ARCHITECTURE = m[1].str(); + } else if (std::regex_search(lscpu[i], m, maxMHz)) { + this->cpuStat->MAX_FREQ = std::stod(m[1].str()); + } else if (std::regex_search(lscpu[i], m, minMHz)) { + this->cpuStat->MIN_FREQ = std::stod(m[1].str()); + } else if (std::regex_search(lscpu[i], m, MHz)) { + this->cpuStat->FREQ = std::stod(m[1].str()); + } + } + std::cout << "Number of hardware threads supported: " << CPU_HARDWARE_THREADS << std::endl; +} + +CPUStat CPU::getCPUStat() { + CPUStat temp; + this->CPU_Mutex.lock(); + memcpy(&temp, this->cpuStat, sizeof(CPUStat)); + this->CPU_Mutex.unlock(); + return temp; +} + +void CPU::START_CPU_POLLING() { + if (this->m_isPolling) { + return; + } + this->m_isPolling = true; + std::cout << "Starting CPU worker thread" << std::endl; + this->m_pollThread = new std::thread(&CPU::CPU_POLL, this); +} + +void CPU::CPU_POLL(CPU* cpu) { + std::cout << "New CPU worker thread" << std::endl; + + while (true) { + cpu->CPU_Mutex.lock(); + if (!cpu->m_isPolling) { + cpu->CPU_Mutex.unlock(); + return; + } + cpu->CPU_Mutex.unlock(); + + // READ TOTAL CPU + std::vector ProcStatLines; + unsigned long long luser, nice, system, idle, iowait, + irq, softirq = 0; + + std::ifstream ProcStatFile("/proc/stat"); + for (std::string str; std::getline(ProcStatFile, str); ) + ProcStatLines.push_back(str); + + sscanf(ProcStatLines[0].c_str(), "cpu %llu %llu %llu %llu %llu %llu %llu", &luser, + &nice, &system, &idle, &iowait, &irq, &softirq); + + cpu->CPU_Mutex.lock(); + + // CALCULATE TOTAL CPU + cpu->CPU_PREVIOUS_TOTAL = cpu->CPU_TOTAL; + cpu->CPU_PREVIOUS_WORK = cpu->CPU_WORK; + cpu->CPU_TOTAL = luser + nice + system + idle + iowait + irq + softirq; + cpu->CPU_WORK = luser + nice + system; + + cpu->CPU_Mutex.unlock(); + + for (unsigned int thread = 0; thread < cpu->CPU_HARDWARE_THREADS; thread++) { + // READ TOTAL THREAD CPU + unsigned int currentThread = thread + 1; + unsigned long long tluser, tnice, tsystem, tidle, tiowait, + tirq, tsoftirq = 0;[[]] + + sscanf(ProcStatLines[currentThread].c_str(), "%*s %llu %llu %llu %llu %llu %llu %llu", + &tluser, &tnice, &tsystem, &tidle, &tiowait, &tirq, &tsoftirq); + + cpu->CPU_Mutex.lock(); + + // CALCULATE TOTAL THREAD CPU + cpu->CPU_PREVIOUS_CORES_WORK_AND_TOTAL[thread][0] = cpu->CPU_CORES_WORK_AND_TOTAL[thread][0]; + cpu->CPU_PREVIOUS_CORES_WORK_AND_TOTAL[thread][1] = cpu->CPU_CORES_WORK_AND_TOTAL[thread][1]; + cpu->CPU_CORES_WORK_AND_TOTAL[thread][0] = tluser + tnice + tsystem + tidle + tiowait + tirq + tsoftirq; + cpu->CPU_CORES_WORK_AND_TOTAL[thread][1] = tluser + tnice + tsystem; + + cpu->CPU_Mutex.unlock(); + } + cpu->CPU_Mutex.lock(); + + long double totalOverTime = cpu->CPU_PREVIOUS_TOTAL - cpu->CPU_TOTAL; + long double workOverTime = cpu->CPU_PREVIOUS_WORK - cpu->CPU_WORK; + cpu->cpuStat->PERCENT_USAGE = (workOverTime / totalOverTime) * 100; + + cpu->CPU_Mutex.unlock(); + + // GET CURRENT CLOCK SPEED FROM COMMAND OUTPUT FROM LSCPU + std::vector lscpu = execcommand("lscpu"); + for (unsigned int i = 0; i < lscpu.size(); i++) { + std::regex MHz("CPU MHz.*?((?:[0-9].*))"); + std::smatch m; + if (std::regex_search(lscpu[i], m, MHz)) { + cpu->CPU_Mutex.lock(); + cpu->cpuStat->FREQ = std::stod(m[1].str()); + cpu->CPU_Mutex.unlock(); + } + } + + sleep(1); + } +} + +void CPU::END_CPU_POLLING() { + if (!this->m_isPolling) { + return; + } + this->m_isPolling = false; + m_pollThread->join(); + delete m_pollThread; +} + +double CPU::CPU_PERCENT(int core) { + --core; + + long double totalOverTime = 0.0; + long double workOverTime = 0.0; + this->CPU_Mutex.lock(); + + if (core == -1) { + totalOverTime = this->CPU_PREVIOUS_TOTAL - this->CPU_TOTAL; + workOverTime = this->CPU_PREVIOUS_WORK - this->CPU_WORK; + } else { + totalOverTime = this->CPU_PREVIOUS_CORES_WORK_AND_TOTAL[core][0] - this->CPU_CORES_WORK_AND_TOTAL[core][0]; + workOverTime = this->CPU_PREVIOUS_CORES_WORK_AND_TOTAL[core][1] - this->CPU_CORES_WORK_AND_TOTAL[core][1]; + } + + this->CPU_Mutex.unlock(); + + double percent = (workOverTime / totalOverTime) * 100; + if (isnan(percent)) percent = -1; + return (double)percent; +} + +std::vector CPU::CPU_CORE_PERCENT() { + std::vector output; + + // TODO: Return a list of percents, one index is one hardware + //thread, index 0 is total percent + + return output; +} + +CPU::~CPU() { + this->m_isPolling = false; + m_pollThread->join(); + delete m_pollThread; +} diff --git a/include/cpu.h b/libsys/cpu.h similarity index 100% rename from include/cpu.h rename to libsys/cpu.h diff --git a/include/gpu.h b/libsys/gpu.h similarity index 100% rename from include/gpu.h rename to libsys/gpu.h diff --git a/libsys/libsys.h b/libsys/libsys.h new file mode 100644 index 0000000..633b954 --- /dev/null +++ b/libsys/libsys.h @@ -0,0 +1,5 @@ +#pragma once + +#include "common.h" +#include "sys.h" +#include "temp.h" diff --git a/libsys/memstat.cpp b/libsys/memstat.cpp new file mode 100644 index 0000000..55d44d9 --- /dev/null +++ b/libsys/memstat.cpp @@ -0,0 +1,90 @@ +#include "memstat.h" + +#include +#include +#include + +// struct sysinfo { +// long uptime; /* Seconds since boot */ +// unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ +// unsigned long totalram; /* Total usable main memory size */ +// unsigned long freeram; /* Available memory size */ +// unsigned long sharedram; /* Amount of shared memory */ +// unsigned long bufferram; /* Memory used by buffers */ +// unsigned long totalswap; /* Total swap space size */ +// unsigned long freeswap; /* swap space still available */ +// unsigned short procs; /* Number of current processes */ +// unsigned long totalhigh; /* Total high memory size */ +// unsigned long freehigh; /* Available high memory size */ +// unsigned int mem_unit; /* Memory unit size in bytes */ +// char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding for 64 bytes */ +// }; + +Memory::Memory() { + this->UPDATE_INTERVAL = 1000; + this->m_isPolling = false; + memStat = new MemStat(); + struct sysinfo info; + sysinfo(&info); + std::cout << "Total RAM Memory supported: " << info.totalram / 1.049e+6 << "MB" << std::endl; +} + +MemStat Memory::getMemStat() { + MemStat stat; + this->Memory_Mutex.lock(); + memcpy(&stat, this->memStat, sizeof(MemStat)); + this->Memory_Mutex.unlock(); + return stat; +} + +void Memory::START_MEMORY_POLLING() { + if (this->m_isPolling) { + return; + } + this->m_isPolling = true; + std::cout << "Starting memory worker thread" << std::endl; + m_pollThread = new std::thread(&Memory::MEMORY_POLL, this); +} + +void Memory::MEMORY_POLL(Memory* mem) { + std::cout << "New memory worker thread" << std::endl; + + while (true) { + mem->Memory_Mutex.lock(); + if (!mem->m_isPolling) { + mem->Memory_Mutex.unlock(); + return; + } + mem->Memory_Mutex.unlock(); + + struct sysinfo info; + sysinfo(&info); + + mem->Memory_Mutex.lock(); + + mem->memStat->TOTAL_MB = info.totalram / 1.049e+6; + mem->memStat->FREE_MB = info.freeram / 1.049e+6; + mem->memStat->SHARED_MB = info.sharedram / 1.049e+6; + mem->memStat->BUFFER_MB = info.bufferram / 1.049e+6; + mem->memStat->TOTAL_RUNNING_PROCS = info.procs; + + mem->Memory_Mutex.unlock(); + + sleep(1); + } +} + +void Memory::END_MEMORY_POLLING() { + if (!this->m_isPolling) { + return; + } + this->m_isPolling = false; + m_pollThread->join(); + delete m_pollThread; +} + +Memory::~Memory() { + this->m_isPolling = false; + m_pollThread->join(); + delete m_pollThread; +} diff --git a/include/memstat.h b/libsys/memstat.h similarity index 100% rename from include/memstat.h rename to libsys/memstat.h diff --git a/libsys/sys.cpp b/libsys/sys.cpp new file mode 100644 index 0000000..5a31321 --- /dev/null +++ b/libsys/sys.cpp @@ -0,0 +1,25 @@ +#include "sys.h" + +System::System() { + this->m_Sys = new Sys(); + + if (CPU_Instance = NULL) { + CPU_Instance = new CPU(); + } + + if (Memory_Instance == NULL) { + Memory_Instance = new Memory(); + } + + +} + +Sys System::getSystemSpec() { + Sys temp; + memcpy(&temp, m_Sys, sizeof(Sys)); + return temp; +} + +System::~System() { + +} diff --git a/include/sys.h b/libsys/sys.h similarity index 77% rename from include/sys.h rename to libsys/sys.h index 304b537..ae248c7 100644 --- a/include/sys.h +++ b/libsys/sys.h @@ -1,9 +1,8 @@ #pragma once -#include -#include -#include -#include +#include "cpu.h" +#include "gpu.h" +#include "memstat.h" struct Sys { unsigned long long SYSTEM_UPTIME; diff --git a/include/temp.h b/libsys/temp.h similarity index 100% rename from include/temp.h rename to libsys/temp.h diff --git a/src/main.cpp b/src/main.cpp index 60c7297..0b682e4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include