tmux-mem-cpu-load/openbsd/memory.cc
Jasper Lievisse Adriaanse 52540329e5 Switch to using uvmexp which is the prefered way of retrieving memory information
Also fixup some page shifting and casting issues which led to incorrect
amounts of memory being displayed. This also fixes a crash with --colors (#20)
2015-03-01 13:45:31 +01:00

124 lines
3.2 KiB
C++

/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap
*
* Copyright 2012 Matthew McCormick
* Copyright 2015 Pawel 'l0ner' Soltys
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <sstream>
#include <string>
// Ugly fix to compilation on OpenBSD 5.6
// these need to be before include sys/mount.h
// and be in this exact order. Otherwise compiling on
// OpenBSD 5.6 will fail with missing NGROUPS define
// or missing gid_t typedefs
#ifdef OPENBSD_WORKAROUND
#include <sys/types.h> // typedefs
#include <sys/param.h> // missing NGROUPS
#include <sys/ucred.h>
#else
#include <sys/types.h>
#endif
#include <sys/mount.h> // VFS_* which we use to get cache
#include <sys/sysctl.h>
#include "error.h"
#include "memory.h"
#include "luts.h"
#include "conversions.h"
static int pageshift;
#ifndef LOG1024
#define LOG1024 10
#endif
#define pagesh(size) ((size) << pageshift)
std::string mem_string( bool use_colors = false )
{
std::ostringstream oss;
// These values are in bytes
int64_t total_mem = 0;
int64_t used_mem = 0;
int32_t free_mem = 0;
size_t size;
// get page size
static int hw_pagesize[] = { CTL_HW, HW_PAGESIZE };
int page_size = 0;
size = sizeof( page_size );
if( sysctl( hw_pagesize, 2, &page_size, &size, NULL, 0 ) < 0 )
{
error( "memory: error getting page size" );
}
// calculate how far we must shift the variables
pageshift = 0;
while( page_size > 1 )
{
pageshift++;
page_size >>= 1;
}
pageshift -= LOG1024;
// get vm memory stats
static int uvmexp_mib[] = { CTL_VM, VM_UVMEXP };
struct uvmexp uvmexp;
size = sizeof( uvmexp );
if( sysctl( uvmexp_mib, 2, &uvmexp, &size, NULL, 0 ) < 0 )
{
error( "memory: error getting vm memory stats" );
}
// In case we need it, this gets the cached memory (bcstats.numbufpages)
static int vm_bcstats[] = { CTL_VFS, VFS_GENERIC, VFS_BCACHESTAT };
struct bcachestats bcstats;
size = sizeof( bcstats );
if( sysctl( vm_bcstats, 3, &bcstats, &size, NULL, 0 ) < 0 )
{
error( "memory: error getting cached memory size" );
}
// calculations based on libgtop
used_mem = (uint64_t) pagesh (uvmexp.npages - uvmexp.free) << LOG1024;
free_mem = (uint64_t) pagesh( uvmexp.free ) << LOG1024;
// from nagios-memory plugin
used_mem -= pagesh( bcstats.numbufpages );
free_mem += pagesh( bcstats.numbufpages );
// calculate total memory
total_mem = (uint64_t) pagesh( uvmexp.npages ) << LOG1024;
if( use_colors )
{
oss << mem_lut[( 100 * used_mem ) / total_mem];
}
oss << convert_unit( used_mem, MEGABYTES )
<< '/' << convert_unit( total_mem, MEGABYTES ) << "MB";
if( use_colors )
{
oss << "#[fg=default,bg=default]";
}
return oss.str();
}