diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..52d6332 --- /dev/null +++ b/.gitignore @@ -0,0 +1,48 @@ +# Compiled source # +################### +*.com +*.class +*.dll +*.exe +*.o +*.so +sysstat + +# CMake generated # +################### +CMakeFiles +Makefile +cmake_install.cmake +CMakeCache.txt +install_manifest.txt +version.h + +# Packages # +############ +# it's better to unpack this files and commit raw source +# git has its own built in compression methods +*.7z +*.dmg +*.gz +*.iso +*.rar +*.tar +*.zip + +# Logs and databases # +###################### +*.log +*.sql +*.sqlite + +# OS generated files # +###################### +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db +*.swp +*.swo diff --git a/linux/cpu.cc b/linux/cpu.cc new file mode 100644 index 0000000..a2b549d --- /dev/null +++ b/linux/cpu.cc @@ -0,0 +1,50 @@ +#include +#include +#include // usleep + +#include "cpu.h" + +float cpu_percentage( unsigned cpu_usage_delay ) { + std::string line; + size_t substrStart = 0; + size_t substrLen; + + // cpu stats + // user, nice, system, idle + // in that order + unsigned long long stats[4]; + + std::ifstream stat_file("/proc/stat"); + getline(stat_file, line); + stat_file.close(); + + // skip "cpu" + substrLen = line.find_first_of(" ", 3); + // parse cpu line + for(unsigned i=0; i < 4; i++) { + substrStart = line.find_first_not_of(" ", substrLen); + substrLen = line.find_first_of (" ", substrStart); + stats[i] = std::stoll( + line.substr(substrStart, substrLen)); + } + + usleep( cpu_usage_delay ); + + stat_file.open("/proc/stat"); + getline(stat_file, stat_line); + stat_file.close(); + + // skip "cpu" + substrLen = line.find_first_of(" ", 3); + // parse cpu line + for(unsigned i=0; i < 4; i++) { + substrStart = line.find_first_not_of(" ", substrLen); + substrLen = line.find_first_of (" ", substrStart); + stats[i] = std::stoll( + line.substr(substrStart, substrLen)) - stats[i]; + } + + return static_cast( stats[0] + stats[1] + stats[2]) / + static_cast( stats[0] + stats[1] + stats[2] + stats[3] ) * 100.0; +} + diff --git a/linux/cpu.h b/linux/cpu.h new file mode 100644 index 0000000..aa9e480 --- /dev/null +++ b/linux/cpu.h @@ -0,0 +1,6 @@ +#ifndef CPU_H_ +#define CPU_H_ + +float cpu_precentage(unsigned); + +#endif diff --git a/linux/load.cc b/linux/load.cc new file mode 100644 index 0000000..df4a54f --- /dev/null +++ b/linux/load.cc @@ -0,0 +1,38 @@ +#include +#include +#include +#include + +#include "../luts.h" + +std::string load_string( bool use_colors = false ) { + std::ostringstream oss; + + std::ifstream loadavg_file( "/proc/loadavg" ); + std::string load_line; + std::getline( loadavg_file, load_line ); + loadavg_file.close(); + + if( use_colors ) { + // Likely does not work on BSD, but not tested + unsigned number_of_cpus = sysconf( _SC_NPROCESSORS_ONLN ); + + float recent_load = stof(load_line.substr( 0, 4 )); + + // colors range from zero to twice the number of cpu's + // for the most recent load metric + unsigned load_percent = static_cast< unsigned int >( + recent_load / number_of_cpus * 0.5f * 100.0f ); + + if( load_percent > 100 ) + load_percent = 100; + + oss << load_lut[load_percent]; + } + + oss << load_line.substr( 0, 14 ); + if( use_colors ) + oss << "#[fg=default,bg=default]"; + + return oss.str(); +} diff --git a/linux/load.h b/linux/load.h new file mode 100644 index 0000000..3b8d814 --- /dev/null +++ b/linux/load.h @@ -0,0 +1,8 @@ +#ifndef LOAD_H_ +#define LOAD_H_ + +#include + +std::string load_string( bool ); + +#endif diff --git a/linux/memory.cc b/linux/memory.cc new file mode 100644 index 0000000..ce37474 --- /dev/null +++ b/linux/memory.cc @@ -0,0 +1,49 @@ +#include +#include + +#include "memory.h" + +std::string mem_string( bool use_colors = false ) { + std::ostringstream oss; + + unsigned int total_mem; + unsigned int used_mem; + unsigned int unused_mem; + + size_t substrStart; + size_t substrLen; + + std::ifstream meminfo_file( "/proc/meminfo" ); + + std::string mem_line; + + getline( meminfo_file, mem_line ); + substrStart = mem_line.find_first_of( ':' ) + 1; + substrLen = mem_line.find_first_of( 'k' ); + total_mem = stoi(mem_line.substr(substrStart, substrLen); + + used_mem = total_mem; + + for( unsigned int i = 0; i < 3; i++ ) { + getline( meminfo_file, mem_line ); + substrStart = mem_line.find_first_of( ':' ) + 1; + substrLen = mem_line.find_first_of( 'k' ); + unused_mem = stoi(mem_line.substr(substrStart, substrLen); + used_mem -= unused_mem; + } + + meminfo_file.close(); + + if( use_colors ) { + oss << mem_lut[(100 * used_mem) / total_mem]; + } + + oss << used_mem / 1024 << '/' << total_mem / 1024 << "MB"; + + if( use_colors ) { + oss << "#[fg=default,bg=default]"; + } + + return oss.str(); +} + diff --git a/linux/memory.h b/linux/memory.h new file mode 100644 index 0000000..196dfd6 --- /dev/null +++ b/linux/memory.h @@ -0,0 +1,8 @@ +#ifndef MEMORY_H_ +#define MEMORY_H_ + +#include + +std::string mem_string( bool ); + +#endif diff --git a/osx/cpu.cc b/osx/cpu.cc new file mode 100644 index 0000000..c670793 --- /dev/null +++ b/osx/cpu.cc @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for sysctl +#include // for integer types + +// OSX or BSD based system, use BSD APIs instead +// See: http://www.opensource.apple.com/source/xnu/xnu-201/osfmk/mach/host_info.h +// and: http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/ +// +host_cpu_load_info_data_t _get_cpu_percentage() { + kern_return_t error; + mach_msg_type_number_t count; + host_cpu_load_info_data_t r_load; + mach_port_t mach_port; + + count = HOST_CPU_LOAD_INFO_COUNT; + mach_port = mach_host_self(); + error = host_statistics(mach_port, HOST_CPU_LOAD_INFO, ( + host_info_t)&r_load, &count); + + if (error != KERN_SUCCESS) + return host_cpu_load_info_data_t(); + + return r_load; +} + +float cpu_percentage( unsigned int cpu_usage_delay ) { + // Get the load times from the XNU kernel + host_cpu_load_info_data_t load1 = _get_cpu_percentage(); + usleep(cpu_usage_delay); + host_cpu_load_info_data_t load2 = _get_cpu_percentage(); + + // Current load times + unsigned long long current_user = load1.cpu_ticks[CPU_STATE_USER]; + unsigned long long current_system = load1.cpu_ticks[CPU_STATE_SYSTEM]; + unsigned long long current_nice = load1.cpu_ticks[CPU_STATE_NICE]; + unsigned long long current_idle = load1.cpu_ticks[CPU_STATE_IDLE]; + // Next load times + unsigned long long next_user = load2.cpu_ticks[CPU_STATE_USER]; + unsigned long long next_system = load2.cpu_ticks[CPU_STATE_SYSTEM]; + unsigned long long next_nice = load2.cpu_ticks[CPU_STATE_NICE]; + unsigned long long next_idle = load2.cpu_ticks[CPU_STATE_IDLE]; + // Difference between the two + unsigned long long diff_user = next_user - current_user; + unsigned long long diff_system = next_system - current_system; + unsigned long long diff_nice = next_nice - current_nice; + unsigned long long diff_idle = next_idle - current_idle; + + return static_cast(diff_user + diff_system + diff_nice) / + static_cast( + diff_user + diff_system + diff_nice + diff_idle) * 100.0; +} + diff --git a/osx/cpu.h b/osx/cpu.h new file mode 100644 index 0000000..2dc2b8f --- /dev/null +++ b/osx/cpu.h @@ -0,0 +1,6 @@ +#ifndef CPU_H_ +#define CPU_H_ + +float cpu_percentage ( unsigned ); + +#endif diff --git a/osx/load.cc b/osx/load.cc new file mode 100644 index 0000000..fd31d60 --- /dev/null +++ b/osx/load.cc @@ -0,0 +1,61 @@ +#include +#include +#include + +#include +#include // getloadavg() + +std::string load_string( bool use_colors = false ) { + std::ostringstream oss; + + // Both apple and BSD style systems have these api calls + // Only get 3 load averages + int nelem = 3; + double averages[3]; + // based on: + // http://www.opensource.apple.com/source/Libc/Libc-262/gen/getloadavg.c + if( getloadavg(averages, nelem) < 0 ) + oss << "0.00 0.00 0.00"; // couldn't get averages. + else + for(int i = 0; i < nelem; ++i) { + // Round to nearest, make sure this is + // only a 0.00 value not a 0.0000 + float avg = floorf( + static_cast(averages[i]) * 100 + 0.5) / 100; + oss << avg << " "; + } + + std::string load_line( oss.str() ); + oss.str( "" ); + + if( use_colors ) { + std::ifstream stat_file( "/proc/stat" ); + std::string stat_line; + std::getline( stat_file, stat_line ); + + // Likely does not work on BSD, but not tested + unsigned number_of_cpus = sysconf( _SC_NPROCESSORS_ONLN ); + + std::istringstream iss( load_line.substr( 0, 4 ) ); + float recent_load; + iss >> recent_load; + // colors range from zero to twice the number of + // cpu's for the most recent load metric + + unsigned load_percent = static_cast< unsigned int >( + recent_load / number_of_cpus * 0.5f * 100.0f ); + + if( load_percent > 100 ) + load_percent = 100; + + oss << load_lut[load_percent]; + } + + oss << load_line.substr( 0, 14 ); + + if( use_colors ) + oss << "#[fg=default,bg=default]"; + + return oss.str(); +} + diff --git a/osx/load.h b/osx/load.h new file mode 100644 index 0000000..3b8d814 --- /dev/null +++ b/osx/load.h @@ -0,0 +1,8 @@ +#ifndef LOAD_H_ +#define LOAD_H_ + +#include + +std::string load_string( bool ); + +#endif diff --git a/osx/memory.cc b/osx/memory.cc new file mode 100644 index 0000000..59782a4 --- /dev/null +++ b/osx/memory.cc @@ -0,0 +1,64 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for sysctl +#include // for integer types + +std::string mem_string( bool use_colors ) { + std::ostringstream oss; + + // These values are in bytes + int64_t total_mem; + int64_t used_mem; + int64_t unused_mem; + + vm_size_t page_size; + mach_port_t mach_port; + mach_msg_type_number_t count; + vm_statistics_data_t vm_stats; + + // Get total physical memory + int mib[2]; + mib[0] = CTL_HW; + mib[1] = HW_MEMSIZE; + size_t length = sizeof(int64_t); + sysctl(mib, 2, &total_mem, &length, NULL, 0); + + mach_port = mach_host_self(); + count = sizeof(vm_stats) / sizeof(natural_t); + if (KERN_SUCCESS == host_page_size( mach_port, &page_size) && + KERN_SUCCESS == host_statistics(mach_port, HOST_VM_INFO, + (host_info_t)&vm_stats, &count)) { + unused_mem = (int64_t)vm_stats.free_count * (int64_t)page_size; + + used_mem = ( + (int64_t)vm_stats.active_count + + (int64_t)vm_stats.inactive_count + + (int64_t)vm_stats.wire_count) * + (int64_t)page_size; + } + + // To kilobytes + used_mem /= 1024; + total_mem /= 1024; + + if( use_colors ) + oss << mem_lut[(100 * used_mem) / total_mem]; + + oss << used_mem / 1024 << '/' << total_mem / 1024 << "MB"; + + if( use_colors ) + oss << "#[fg=default,bg=default]"; + + return oss.str(); +} diff --git a/osx/memory.h b/osx/memory.h new file mode 100644 index 0000000..196dfd6 --- /dev/null +++ b/osx/memory.h @@ -0,0 +1,8 @@ +#ifndef MEMORY_H_ +#define MEMORY_H_ + +#include + +std::string mem_string( bool ); + +#endif diff --git a/version.h.in b/version.h.in new file mode 100644 index 0000000..23711c8 --- /dev/null +++ b/version.h.in @@ -0,0 +1,5 @@ +// the configured options and settings for sysstat +#define tmux-mem-cpu-load_VERSION_MAJOR @tmux-mem-cpu-load_VERSION_MAJOR@ +#define tmux-mem-cpu-load_VERSION_MINOR @tmux-mem-cpu-load_VERSION_MINOR@ +#define tmux-mem-cpu-load_VERSION_PATCH @tmux-mem-cpu-load_VERSION_PATCH@ +