2015-07-12 18:47:43 +00:00
/*
htop - darwin / Platform . c
( C ) 2014 Hisham H . Muhammad
( C ) 2015 David C . Hunt
Released under the GNU GPL , see the COPYING file
in the source distribution for its full text .
*/
# include "Platform.h"
# include "CPUMeter.h"
# include "MemoryMeter.h"
# include "SwapMeter.h"
# include "TasksMeter.h"
# include "LoadAverageMeter.h"
# include "ClockMeter.h"
# include "HostnameMeter.h"
# include "UptimeMeter.h"
2015-07-13 21:53:46 +00:00
# include "DarwinProcessList.h"
2015-07-12 18:47:43 +00:00
2015-07-13 06:17:14 +00:00
# include <stdlib.h>
2015-07-12 18:47:43 +00:00
/*{
# include "Action.h"
2015-11-02 15:46:04 +00:00
# include "SignalsPanel.h"
2015-10-23 15:46:21 +00:00
# include "CPUMeter.h"
2015-07-12 18:47:43 +00:00
# include "BatteryMeter.h"
# include "DarwinProcess.h"
} */
ProcessField Platform_defaultFields [ ] = { PID , USER , PRIORITY , NICE , M_SIZE , M_RESIDENT , STATE , PERCENT_CPU , PERCENT_MEM , TIME , COMM , 0 } ;
2015-10-06 16:03:47 +00:00
SignalItem Platform_signals [ ] = {
{ . name = " 0 Cancel " , . number = 0 } ,
{ . name = " 1 SIGHUP " , . number = 1 } ,
{ . name = " 2 SIGINT " , . number = 2 } ,
{ . name = " 3 SIGQUIT " , . number = 3 } ,
{ . name = " 4 SIGILL " , . number = 4 } ,
{ . name = " 5 SIGTRAP " , . number = 5 } ,
{ . name = " 6 SIGABRT " , . number = 6 } ,
{ . name = " 6 SIGIOT " , . number = 6 } ,
{ . name = " 7 SIGEMT " , . number = 7 } ,
{ . name = " 8 SIGFPE " , . number = 8 } ,
{ . name = " 9 SIGKILL " , . number = 9 } ,
{ . name = " 10 SIGBUS " , . number = 10 } ,
{ . name = " 11 SIGSEGV " , . number = 11 } ,
{ . name = " 12 SIGSYS " , . number = 12 } ,
{ . name = " 13 SIGPIPE " , . number = 13 } ,
{ . name = " 14 SIGALRM " , . number = 14 } ,
{ . name = " 15 SIGTERM " , . number = 15 } ,
{ . name = " 16 SIGURG " , . number = 16 } ,
{ . name = " 17 SIGSTOP " , . number = 17 } ,
{ . name = " 18 SIGTSTP " , . number = 18 } ,
{ . name = " 19 SIGCONT " , . number = 19 } ,
{ . name = " 20 SIGCHLD " , . number = 20 } ,
{ . name = " 21 SIGTTIN " , . number = 21 } ,
{ . name = " 22 SIGTTOU " , . number = 22 } ,
{ . name = " 23 SIGIO " , . number = 23 } ,
{ . name = " 24 SIGXCPU " , . number = 24 } ,
{ . name = " 25 SIGXFSZ " , . number = 25 } ,
{ . name = " 26 SIGVTALRM " , . number = 26 } ,
{ . name = " 27 SIGPROF " , . number = 27 } ,
{ . name = " 28 SIGWINCH " , . number = 28 } ,
{ . name = " 29 SIGINFO " , . number = 29 } ,
{ . name = " 30 SIGUSR1 " , . number = 30 } ,
{ . name = " 31 SIGUSR2 " , . number = 31 } ,
} ;
unsigned int Platform_numberOfSignals = sizeof ( Platform_signals ) / sizeof ( SignalItem ) ;
2015-07-12 18:47:43 +00:00
ProcessFieldData Process_fields [ ] = {
[ 0 ] = { . name = " " , . title = NULL , . description = NULL , . flags = 0 , } ,
[ PID ] = { . name = " PID " , . title = " PID " , . description = " Process/thread ID " , . flags = 0 , } ,
[ COMM ] = { . name = " Command " , . title = " Command " , . description = " Command line " , . flags = 0 , } ,
[ STATE ] = { . name = " STATE " , . title = " S " , . description = " Process state (S sleeping, R running, D disk, Z zombie, T traced, W paging) " , . flags = 0 , } ,
[ PPID ] = { . name = " PPID " , . title = " PPID " , . description = " Parent process ID " , . flags = 0 , } ,
[ PGRP ] = { . name = " PGRP " , . title = " PGRP " , . description = " Process group ID " , . flags = 0 , } ,
[ SESSION ] = { . name = " SESSION " , . title = " SESN " , . description = " Process's session ID " , . flags = 0 , } ,
[ TTY_NR ] = { . name = " TTY_NR " , . title = " TTY " , . description = " Controlling terminal " , . flags = 0 , } ,
[ TPGID ] = { . name = " TPGID " , . title = " TPGID " , . description = " Process ID of the fg process group of the controlling terminal " , . flags = 0 , } ,
[ MINFLT ] = { . name = " MINFLT " , . title = " MINFLT " , . description = " Number of minor faults which have not required loading a memory page from disk " , . flags = 0 , } ,
[ MAJFLT ] = { . name = " MAJFLT " , . title = " MAJFLT " , . description = " Number of major faults which have required loading a memory page from disk " , . flags = 0 , } ,
[ PRIORITY ] = { . name = " PRIORITY " , . title = " PRI " , . description = " Kernel's internal priority for the process " , . flags = 0 , } ,
[ NICE ] = { . name = " NICE " , . title = " NI " , . description = " Nice value (the higher the value, the more it lets other processes take priority) " , . flags = 0 , } ,
[ STARTTIME ] = { . name = " STARTTIME " , . title = " START " , . description = " Time the process was started " , . flags = 0 , } ,
[ PROCESSOR ] = { . name = " PROCESSOR " , . title = " CPU " , . description = " Id of the CPU the process last executed on " , . flags = 0 , } ,
[ M_SIZE ] = { . name = " M_SIZE " , . title = " VIRT " , . description = " Total program size in virtual memory " , . flags = 0 , } ,
[ M_RESIDENT ] = { . name = " M_RESIDENT " , . title = " RES " , . description = " Resident set size, size of the text and data sections, plus stack usage " , . flags = 0 , } ,
[ ST_UID ] = { . name = " ST_UID " , . title = " UID " , . description = " User ID of the process owner " , . flags = 0 , } ,
[ PERCENT_CPU ] = { . name = " PERCENT_CPU " , . title = " CPU% " , . description = " Percentage of the CPU time the process used in the last sampling " , . flags = 0 , } ,
[ PERCENT_MEM ] = { . name = " PERCENT_MEM " , . title = " MEM% " , . description = " Percentage of the memory the process is using, based on resident memory size " , . flags = 0 , } ,
[ USER ] = { . name = " USER " , . title = " USER " , . description = " Username of the process owner (or user ID if name cannot be determined) " , . flags = 0 , } ,
[ TIME ] = { . name = " TIME " , . title = " TIME+ " , . description = " Total time the process has spent in user and system time " , . flags = 0 , } ,
[ NLWP ] = { . name = " NLWP " , . title = " NLWP " , . description = " Number of threads in the process " , . flags = 0 , } ,
[ TGID ] = { . name = " TGID " , . title = " TGID " , . description = " Thread group ID (i.e. process ID) " , . flags = 0 , } ,
[ 100 ] = { . name = " *** report bug! *** " , . title = NULL , . description = NULL , . flags = 0 , } ,
} ;
MeterClass * Platform_meterTypes [ ] = {
& CPUMeter_class ,
& ClockMeter_class ,
& LoadAverageMeter_class ,
& LoadMeter_class ,
& MemoryMeter_class ,
2015-11-16 17:32:22 +00:00
& SwapMeter_class ,
2015-07-12 18:47:43 +00:00
& TasksMeter_class ,
& BatteryMeter_class ,
& HostnameMeter_class ,
& UptimeMeter_class ,
& AllCPUsMeter_class ,
& AllCPUs2Meter_class ,
& LeftCPUsMeter_class ,
& RightCPUsMeter_class ,
& LeftCPUs2Meter_class ,
& RightCPUs2Meter_class ,
& BlankMeter_class ,
NULL
} ;
void Platform_setBindings ( Htop_Action * keys ) {
( void ) keys ;
}
int Platform_numberOfFields = 100 ;
int Platform_getUptime ( ) {
2015-08-19 16:56:46 +00:00
struct timeval bootTime , currTime ;
int mib [ 2 ] = { CTL_KERN , KERN_BOOTTIME } ;
size_t size = sizeof ( bootTime ) ;
2015-07-14 02:02:40 +00:00
2015-08-19 16:56:46 +00:00
int err = sysctl ( mib , 2 , & bootTime , & size , NULL , 0 ) ;
if ( err ) {
return - 1 ;
}
gettimeofday ( & currTime , NULL ) ;
2015-07-14 02:02:40 +00:00
2015-08-19 16:56:46 +00:00
return ( int ) difftime ( currTime . tv_sec , bootTime . tv_sec ) ;
2015-07-12 18:47:43 +00:00
}
void Platform_getLoadAverage ( double * one , double * five , double * fifteen ) {
2015-07-13 06:17:14 +00:00
double results [ 3 ] ;
if ( 3 = = getloadavg ( results , 3 ) ) {
* one = results [ 0 ] ;
* five = results [ 1 ] ;
* fifteen = results [ 2 ] ;
} else {
* one = 0 ;
* five = 0 ;
* fifteen = 0 ;
}
2015-07-12 18:47:43 +00:00
}
int Platform_getMaxPid ( ) {
2015-07-13 06:17:14 +00:00
/* http://opensource.apple.com/source/xnu/xnu-2782.1.97/bsd/sys/proc_internal.hh */
return 99999 ;
2015-07-12 18:47:43 +00:00
}
2015-08-20 03:32:47 +00:00
ProcessPidColumn Process_pidColumns [ ] = {
{ . id = PID , . label = " PID " } ,
{ . id = PPID , . label = " PPID " } ,
{ . id = TPGID , . label = " TPGID " } ,
{ . id = TGID , . label = " TGID " } ,
{ . id = PGRP , . label = " PGRP " } ,
{ . id = SESSION , . label = " SESN " } ,
{ . id = 0 , . label = NULL } ,
} ;
2015-07-12 18:47:43 +00:00
2015-10-23 15:46:21 +00:00
static double Platform_setCPUAverageValues ( Meter * mtr ) {
DarwinProcessList * dpl = ( DarwinProcessList * ) mtr - > pl ;
int cpus = dpl - > super . cpuCount ;
2015-10-25 03:28:29 +00:00
double sumNice = 0.0 ;
double sumNormal = 0.0 ;
double sumKernel = 0.0 ;
double sumPercent = 0.0 ;
2015-10-23 15:46:21 +00:00
for ( int i = 1 ; i < = cpus ; i + + ) {
sumPercent + = Platform_setCPUValues ( mtr , i ) ;
sumNice + = mtr - > values [ CPU_METER_NICE ] ;
sumNormal + = mtr - > values [ CPU_METER_NORMAL ] ;
sumKernel + = mtr - > values [ CPU_METER_KERNEL ] ;
}
mtr - > values [ CPU_METER_NICE ] = sumNice / cpus ;
mtr - > values [ CPU_METER_NORMAL ] = sumNormal / cpus ;
mtr - > values [ CPU_METER_KERNEL ] = sumKernel / cpus ;
return sumPercent / cpus ;
}
2015-07-13 21:53:46 +00:00
double Platform_setCPUValues ( Meter * mtr , int cpu ) {
2015-10-23 15:46:21 +00:00
if ( cpu = = 0 ) {
return Platform_setCPUAverageValues ( mtr ) ;
}
2015-08-19 16:56:46 +00:00
DarwinProcessList * dpl = ( DarwinProcessList * ) mtr - > pl ;
processor_cpu_load_info_t prev = & dpl - > prev_load [ cpu - 1 ] ;
processor_cpu_load_info_t curr = & dpl - > curr_load [ cpu - 1 ] ;
double total = 0 ;
/* Take the sums */
for ( size_t i = 0 ; i < CPU_STATE_MAX ; + + i ) {
total + = ( double ) curr - > cpu_ticks [ i ] - ( double ) prev - > cpu_ticks [ i ] ;
}
2015-07-12 18:47:43 +00:00
2015-08-19 16:56:46 +00:00
mtr - > values [ CPU_METER_NICE ]
= ( ( double ) curr - > cpu_ticks [ CPU_STATE_NICE ] - ( double ) prev - > cpu_ticks [ CPU_STATE_NICE ] ) * 100.0 / total ;
mtr - > values [ CPU_METER_NORMAL ]
= ( ( double ) curr - > cpu_ticks [ CPU_STATE_USER ] - ( double ) prev - > cpu_ticks [ CPU_STATE_USER ] ) * 100.0 / total ;
mtr - > values [ CPU_METER_KERNEL ]
= ( ( double ) curr - > cpu_ticks [ CPU_STATE_SYSTEM ] - ( double ) prev - > cpu_ticks [ CPU_STATE_SYSTEM ] ) * 100.0 / total ;
2015-07-14 02:02:40 +00:00
2015-08-19 16:56:46 +00:00
Meter_setItems ( mtr , 3 ) ;
2015-07-14 02:02:40 +00:00
2015-08-19 16:56:46 +00:00
/* Convert to percent and return */
total = mtr - > values [ CPU_METER_NICE ] + mtr - > values [ CPU_METER_NORMAL ] + mtr - > values [ CPU_METER_KERNEL ] ;
return MIN ( 100.0 , MAX ( 0.0 , total ) ) ;
}
void Platform_setMemoryValues ( Meter * mtr ) {
DarwinProcessList * dpl = ( DarwinProcessList * ) mtr - > pl ;
vm_statistics64_t vm = & dpl - > vm_stats ;
double page_K = ( double ) vm_page_size / ( double ) 1024 ;
mtr - > total = dpl - > host_info . max_mem / 1024 ;
mtr - > values [ 0 ] = ( double ) ( vm - > active_count + vm - > wire_count ) * page_K ;
mtr - > values [ 1 ] = ( double ) vm - > purgeable_count * page_K ;
mtr - > values [ 2 ] = ( double ) vm - > inactive_count * page_K ;
2015-07-12 18:47:43 +00:00
}
2015-11-16 17:32:22 +00:00
void Platform_setSwapValues ( Meter * mtr ) {
int mib [ 2 ] = { CTL_VM , VM_SWAPUSAGE } ;
struct xsw_usage swapused ;
size_t swlen = sizeof ( swapused ) ;
sysctl ( mib , 2 , & swapused , & swlen , NULL , 0 ) ;
2015-07-12 18:47:43 +00:00
2015-11-16 17:32:22 +00:00
mtr - > total = swapused . xsu_total / 1024 ;
mtr - > values [ 0 ] = swapused . xsu_used / 1024 ;
}
2015-12-03 21:16:10 +00:00
char * Platform_getProcessEnv ( pid_t pid ) {
char * env = NULL ;
int argmax ;
size_t bufsz = sizeof ( argmax ) ;
int mib [ 3 ] ;
mib [ 0 ] = CTL_KERN ;
mib [ 1 ] = KERN_ARGMAX ;
if ( sysctl ( mib , 2 , & argmax , & bufsz , 0 , 0 ) = = 0 ) {
char * buf = malloc ( argmax ) ;
if ( buf ) {
mib [ 0 ] = CTL_KERN ;
mib [ 1 ] = KERN_PROCARGS2 ;
mib [ 2 ] = pid ;
size_t bufsz = argmax ;
if ( sysctl ( mib , 3 , buf , & bufsz , 0 , 0 ) = = 0 ) {
if ( bufsz > sizeof ( int ) ) {
char * p = buf , * endp = buf + bufsz ;
int argc = * ( int * ) p ;
p + = sizeof ( int ) ;
// skip exe
p = strchr ( p , 0 ) + 1 ;
// skip padding
while ( ! * p & & p < endp )
+ + p ;
// skip argv
for ( ; argc - - & & p < endp ; p = strrchr ( p , 0 ) + 1 )
;
// skip padding
while ( ! * p & & p < endp )
+ + p ;
size_t size = endp - p ;
env = malloc ( size + 2 ) ;
if ( env ) {
memcpy ( env , p , size ) ;
env [ size ] = 0 ;
env [ size + 1 ] = 0 ;
}
}
}
free ( buf ) ;
}
}
return env ;
}