Add support for Mac OSX from Justastic. Refactors the code from Justastic so it works with the Linux code and so it also works for the new colors support. Still need to test on OSX. Conflicts: tmux-mem-cpu-load.cpp
This commit is contained in:
commit
9d072d4ec1
@ -15,6 +15,5 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
add_executable(tmux-mem-cpu-load tmux-mem-cpu-load.cpp)
|
||||
install(TARGETS tmux-mem-cpu-load
|
||||
RUNTIME
|
||||
DESTINATION bin
|
||||
RUNTIME DESTINATION bin
|
||||
)
|
||||
|
@ -27,7 +27,7 @@ Example output::
|
||||
|
||||
^ ^ ^ ^ ^ ^ ^
|
||||
| | | | | | |
|
||||
1 2 3 4 5 6 G
|
||||
1 2 3 4 5 6 7
|
||||
|
||||
1. Currently used memory.
|
||||
2. Available memory.
|
||||
@ -48,10 +48,13 @@ Installation
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Currently only tested on Linux. Mac OSX is known not to work. Patches or
|
||||
hardware are welcome.
|
||||
|
||||
Building
|
||||
~~~~~~~~
|
||||
|
||||
* >= cmake_ -2.6
|
||||
* >= CMake_ -2.6
|
||||
* C++ compiler (e.g. gcc/g++)
|
||||
|
||||
|
||||
@ -107,6 +110,6 @@ Matt McCormick (thewtex) <matt@mmmccormick.com>
|
||||
|
||||
|
||||
.. _tmux: http://tmux.sourceforge.net/
|
||||
.. _cmake: http://www.cmake.org
|
||||
.. _CMake: http://www.cmake.org
|
||||
.. _`project homepage`: http://github.com/thewtex/tmux-mem-cpu-load
|
||||
.. _`terminals with 256 color support`: http://misc.flogisoft.com/bash/tip_colors_and_formatting#terminals_compatibility
|
||||
|
@ -19,11 +19,90 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include <unistd.h> // sleep
|
||||
#include <cmath> // for floorf
|
||||
|
||||
// Apple specific.
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
// Mach kernel includes for getting memory and CPU statistics
|
||||
# include <mach/vm_statistics.h>
|
||||
# include <mach/processor_info.h>
|
||||
# include <mach/mach_types.h>
|
||||
# include <mach/mach_init.h>
|
||||
# include <mach/mach_host.h>
|
||||
# include <mach/host_info.h>
|
||||
# include <mach/mach_error.h>
|
||||
# include <mach/vm_map.h>
|
||||
# include <mach/mach.h>
|
||||
# include <sys/sysctl.h> // for sysctl
|
||||
# include <sys/types.h> // for integer types
|
||||
#endif
|
||||
|
||||
// if we are on a BSD system
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
// TODO: Includes and *BSD support
|
||||
# define BSD_BASED 1
|
||||
#endif
|
||||
|
||||
// Tmux color lookup tables for the different metrics.
|
||||
#include "luts.h"
|
||||
|
||||
// Function declarations.
|
||||
float cpu_percentage( unsigned int cpu_usage_delay );
|
||||
std::string cpu_string( unsigned int cpu_usage_delay,
|
||||
unsigned int graph_lines,
|
||||
bool use_colors = false );
|
||||
std::string mem_string( bool use_colors = false );
|
||||
std::string load_string( bool use_colors = false );
|
||||
|
||||
|
||||
#if defined(BSD_BASED) || (defined(__APPLE__) && defined(__MACH__))
|
||||
// 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;
|
||||
|
||||
#else // Linux
|
||||
float cpu_percentage( unsigned int cpu_usage_delay )
|
||||
{
|
||||
std::string stat_line;
|
||||
@ -79,13 +158,14 @@ float cpu_percentage( unsigned int cpu_usage_delay )
|
||||
diff_system = next_system - current_system;
|
||||
diff_nice = next_nice - current_nice;
|
||||
diff_idle = next_idle - current_idle;
|
||||
#endif // platform
|
||||
|
||||
return static_cast<float>(diff_user + diff_system + diff_nice)/static_cast<float>(diff_user + diff_system + diff_nice + diff_idle)*100.0;
|
||||
}
|
||||
|
||||
std::string cpu_string( unsigned int cpu_usage_delay,
|
||||
unsigned int graph_lines,
|
||||
bool use_colors = false )
|
||||
bool use_colors )
|
||||
{
|
||||
std::string meter( graph_lines + 2, ' ' );
|
||||
meter[0] = '[';
|
||||
@ -121,15 +201,56 @@ std::string cpu_string( unsigned int cpu_usage_delay,
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string mem_string( bool use_colors = false )
|
||||
|
||||
std::string mem_string( bool use_colors )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
#if defined(BSD_BASED) || (defined(__APPLE__) && defined(__MACH__))
|
||||
// OSX or BSD based system, use BSD APIs instead
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
// 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
|
||||
#endif // Apple
|
||||
// TODO BSD
|
||||
|
||||
used_mem /= 1024;
|
||||
total_mem /= 1024;
|
||||
|
||||
#else // Linux
|
||||
unsigned int total_mem;
|
||||
unsigned int used_mem;
|
||||
unsigned int unused_mem;
|
||||
size_t line_start_pos;
|
||||
size_t line_end_pos;
|
||||
std::istringstream iss;
|
||||
std::ostringstream oss;
|
||||
std::string mem_line;
|
||||
|
||||
std::ifstream meminfo_file( "/proc/meminfo" );
|
||||
@ -154,6 +275,8 @@ std::string mem_string( bool use_colors = false )
|
||||
}
|
||||
meminfo_file.close();
|
||||
|
||||
#endif // platform
|
||||
|
||||
if( use_colors )
|
||||
{
|
||||
oss << mem_lut[(100 * used_mem) / total_mem];
|
||||
@ -167,27 +290,47 @@ std::string mem_string( bool use_colors = false )
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string load_string( bool use_colors = false )
|
||||
|
||||
std::string load_string( bool use_colors )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
#if defined(BSD_BASED) || (defined(__APPLE__) && defined(__MACH__))
|
||||
// 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<float>(averages[i]) * 100 + 0.5) / 100;
|
||||
oss << avg << " ";
|
||||
}
|
||||
}
|
||||
|
||||
#else // Linux
|
||||
std::ifstream loadavg_file( "/proc/loadavg" );
|
||||
std::string load_line;
|
||||
std::getline( loadavg_file, load_line );
|
||||
loadavg_file.close();
|
||||
|
||||
#endif // platform
|
||||
|
||||
if( use_colors )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
std::ifstream stat_file( "/proc/stat" );
|
||||
std::string stat_line;
|
||||
std::getline( stat_file, stat_line );
|
||||
unsigned int number_of_cpus = 0;
|
||||
std::getline( stat_file, stat_line );
|
||||
do
|
||||
{
|
||||
++number_of_cpus;
|
||||
std::getline( stat_file, stat_line );
|
||||
}
|
||||
while( stat_line.compare( 0, 3, "cpu" ) == 0 && stat_file.good() );
|
||||
stat_file.close();
|
||||
// Likely does not work on BSD, but not tested
|
||||
unsigned int number_of_cpus = sysconf( _SC_NPROCESSORS_ONLN );
|
||||
|
||||
std::istringstream iss( load_line.substr( 0, 4 ) );
|
||||
float recent_load;
|
||||
@ -199,16 +342,18 @@ std::string load_string( bool use_colors = false )
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
return load_line.substr( 0, 14 );
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user