2014-11-24 20:55:49 +00:00
/*
htop - LinuxProcess . c
( C ) 2014 Hisham H . Muhammad
2020-08-19 23:35:24 +00:00
( C ) 2020 Red Hat , Inc . All Rights Reserved .
2020-10-05 07:51:32 +00:00
Released under the GNU GPLv2 , see the COPYING file
2014-11-24 20:55:49 +00:00
in the source distribution for its full text .
*/
2021-04-29 18:13:36 +00:00
# include "linux/LinuxProcess.h"
2014-11-24 21:22:50 +00:00
2021-04-29 15:12:43 +00:00
# include <assert.h>
2020-09-19 11:55:23 +00:00
# include <math.h>
# include <stdio.h>
2015-02-20 16:52:10 +00:00
# include <stdlib.h>
2020-12-06 14:22:41 +00:00
# include <string.h>
2020-09-19 11:55:23 +00:00
# include <syscall.h>
# include <unistd.h>
# include "CRT.h"
2020-11-18 13:26:30 +00:00
# include "Macros.h"
2020-09-19 11:55:23 +00:00
# include "Process.h"
# include "ProvideCurses.h"
2020-11-18 13:26:30 +00:00
# include "RichString.h"
2020-09-19 11:55:23 +00:00
# include "XUtils.h"
2021-04-29 18:13:36 +00:00
# include "linux/IOPriority.h"
2014-11-24 20:55:49 +00:00
2020-10-14 18:21:09 +00:00
2020-07-10 00:35:32 +00:00
/* semi-global */
2020-12-10 00:57:48 +00:00
int pageSize ;
int pageSizeKB ;
2018-08-19 04:29:03 +00:00
2020-10-17 10:54:45 +00:00
/* Used to identify kernel threads in Comm and Exe columns */
static const char * const kthreadID = " KTHREAD " ;
2020-12-15 18:44:52 +00:00
const ProcessFieldData Process_fields [ LAST_PROCESSFIELD ] = {
2015-03-16 04:43:04 +00:00
[ 0 ] = { . name = " " , . title = NULL , . description = NULL , . flags = 0 , } ,
2020-12-15 18:44:52 +00:00
[ PID ] = { . name = " PID " , . title = " PID " , . description = " Process/thread ID " , . flags = 0 , . pidColumn = true , } ,
2015-03-16 04:43:04 +00:00
[ COMM ] = { . name = " Command " , . title = " Command " , . description = " Command line " , . flags = 0 , } ,
2018-01-14 09:08:20 +00:00
[ STATE ] = { . name = " STATE " , . title = " S " , . description = " Process state (S sleeping, R running, D disk, Z zombie, T traced, W paging, I idle) " , . flags = 0 , } ,
2020-12-15 18:44:52 +00:00
[ PPID ] = { . name = " PPID " , . title = " PPID " , . description = " Parent process ID " , . flags = 0 , . pidColumn = true , } ,
[ PGRP ] = { . name = " PGRP " , . title = " PGRP " , . description = " Process group ID " , . flags = 0 , . pidColumn = true , } ,
[ SESSION ] = { . name = " SESSION " , . title = " SID " , . description = " Process's session ID " , . flags = 0 , . pidColumn = true , } ,
2021-03-21 18:40:56 +00:00
[ TTY ] = { . name = " TTY " , . title = " TTY " , . description = " Controlling terminal " , . flags = 0 , } ,
2020-12-15 18:44:52 +00:00
[ TPGID ] = { . name = " TPGID " , . title = " TPGID " , . description = " Process ID of the fg process group of the controlling terminal " , . flags = 0 , . pidColumn = true , } ,
2021-01-21 13:27:23 +00:00
[ MINFLT ] = { . name = " MINFLT " , . title = " MINFLT " , . description = " Number of minor faults which have not required loading a memory page from disk " , . flags = 0 , . defaultSortDesc = true , } ,
[ CMINFLT ] = { . name = " CMINFLT " , . title = " CMINFLT " , . description = " Children processes' minor faults " , . flags = 0 , . defaultSortDesc = true , } ,
2021-01-21 19:57:34 +00:00
[ MAJFLT ] = { . name = " MAJFLT " , . title = " MAJFLT " , . description = " Number of major faults which have required loading a memory page from disk " , . flags = 0 , . defaultSortDesc = true , } ,
[ CMAJFLT ] = { . name = " CMAJFLT " , . title = " CMAJFLT " , . description = " Children processes' major faults " , . flags = 0 , . defaultSortDesc = true , } ,
[ UTIME ] = { . name = " UTIME " , . title = " UTIME+ " , . description = " User CPU time - time the process spent executing in user mode " , . flags = 0 , . defaultSortDesc = true , } ,
[ STIME ] = { . name = " STIME " , . title = " STIME+ " , . description = " System CPU time - time the kernel spent running system calls for this process " , . flags = 0 , . defaultSortDesc = true , } ,
[ CUTIME ] = { . name = " CUTIME " , . title = " CUTIME+ " , . description = " Children processes' user CPU time " , . flags = 0 , . defaultSortDesc = true , } ,
[ CSTIME ] = { . name = " CSTIME " , . title = " CSTIME+ " , . description = " Children processes' system CPU time " , . flags = 0 , . defaultSortDesc = true , } ,
2015-03-16 04:43:04 +00:00
[ 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 , } ,
2021-01-21 13:27:23 +00:00
[ M_VIRT ] = { . name = " M_VIRT " , . title = " VIRT " , . description = " Total program size in virtual memory " , . flags = 0 , . defaultSortDesc = true , } ,
[ M_RESIDENT ] = { . name = " M_RESIDENT " , . title = " RES " , . description = " Resident set size, size of the text and data sections, plus stack usage " , . flags = 0 , . defaultSortDesc = true , } ,
[ M_SHARE ] = { . name = " M_SHARE " , . title = " SHR " , . description = " Size of the process's shared pages " , . flags = 0 , . defaultSortDesc = true , } ,
[ M_TRS ] = { . name = " M_TRS " , . title = " CODE " , . description = " Size of the text segment of the process " , . flags = 0 , . defaultSortDesc = true , } ,
[ M_DRS ] = { . name = " M_DRS " , . title = " DATA " , . description = " Size of the data segment plus stack usage of the process " , . flags = 0 , . defaultSortDesc = true , } ,
[ M_LRS ] = { . name = " M_LRS " , . title = " LIB " , . description = " The library size of the process (calculated from memory maps) " , . flags = PROCESS_FLAG_LINUX_LRS_FIX , . defaultSortDesc = true , } ,
[ M_DT ] = { . name = " M_DT " , . title = " DIRTY " , . description = " Size of the dirty pages of the process (unused since Linux 2.6; always 0) " , . flags = 0 , . defaultSortDesc = true , } ,
2018-10-07 09:16:12 +00:00
[ ST_UID ] = { . name = " ST_UID " , . title = " UID " , . description = " User ID of the process owner " , . flags = 0 , } ,
2021-01-21 13:27:23 +00:00
[ PERCENT_CPU ] = { . name = " PERCENT_CPU " , . title = " CPU% " , . description = " Percentage of the CPU time the process used in the last sampling " , . flags = 0 , . defaultSortDesc = true , } ,
[ PERCENT_NORM_CPU ] = { . name = " PERCENT_NORM_CPU " , . title = " NCPU% " , . description = " Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count) " , . flags = 0 , . defaultSortDesc = true , } ,
[ PERCENT_MEM ] = { . name = " PERCENT_MEM " , . title = " MEM% " , . description = " Percentage of the memory the process is using, based on resident memory size " , . flags = 0 , . defaultSortDesc = true , } ,
2015-03-16 04:43:04 +00:00
[ USER ] = { . name = " USER " , . title = " USER " , . description = " Username of the process owner (or user ID if name cannot be determined) " , . flags = 0 , } ,
2021-01-21 13:27:23 +00:00
[ TIME ] = { . name = " TIME " , . title = " TIME+ " , . description = " Total time the process has spent in user and system time " , . flags = 0 , . defaultSortDesc = true , } ,
[ NLWP ] = { . name = " NLWP " , . title = " NLWP " , . description = " Number of threads in the process " , . flags = 0 , . defaultSortDesc = true , } ,
2020-12-15 18:44:52 +00:00
[ TGID ] = { . name = " TGID " , . title = " TGID " , . description = " Thread group ID (i.e. process ID) " , . flags = 0 , . pidColumn = true , } ,
2015-03-15 23:29:13 +00:00
# ifdef HAVE_OPENVZ
2020-09-30 21:46:52 +00:00
[ CTID ] = { . name = " CTID " , . title = " CTID " , . description = " OpenVZ container ID (a.k.a. virtual environment ID) " , . flags = PROCESS_FLAG_LINUX_OPENVZ , } ,
2020-12-15 18:44:52 +00:00
[ VPID ] = { . name = " VPID " , . title = " VPID " , . description = " OpenVZ process ID " , . flags = PROCESS_FLAG_LINUX_OPENVZ , . pidColumn = true , } ,
2015-03-15 23:29:13 +00:00
# endif
# ifdef HAVE_VSERVER
2015-03-16 04:43:04 +00:00
[ VXID ] = { . name = " VXID " , . title = " VXID " , . description = " VServer process ID " , . flags = PROCESS_FLAG_LINUX_VSERVER , } ,
2015-03-15 23:29:13 +00:00
# endif
2021-01-27 14:11:48 +00:00
[ RCHAR ] = { . name = " RCHAR " , . title = " RCHAR " , . description = " Number of bytes the process has read " , . flags = PROCESS_FLAG_IO , . defaultSortDesc = true , } ,
[ WCHAR ] = { . name = " WCHAR " , . title = " WCHAR " , . description = " Number of bytes the process has written " , . flags = PROCESS_FLAG_IO , . defaultSortDesc = true , } ,
[ SYSCR ] = { . name = " SYSCR " , . title = " READ_SYSC " , . description = " Number of read(2) syscalls for the process " , . flags = PROCESS_FLAG_IO , . defaultSortDesc = true , } ,
[ SYSCW ] = { . name = " SYSCW " , . title = " WRITE_SYSC " , . description = " Number of write(2) syscalls for the process " , . flags = PROCESS_FLAG_IO , . defaultSortDesc = true , } ,
[ RBYTES ] = { . name = " RBYTES " , . title = " IO_R " , . description = " Bytes of read(2) I/O for the process " , . flags = PROCESS_FLAG_IO , . defaultSortDesc = true , } ,
[ WBYTES ] = { . name = " WBYTES " , . title = " IO_W " , . description = " Bytes of write(2) I/O for the process " , . flags = PROCESS_FLAG_IO , . defaultSortDesc = true , } ,
[ CNCLWB ] = { . name = " CNCLWB " , . title = " IO_C " , . description = " Bytes of cancelled write(2) I/O " , . flags = PROCESS_FLAG_IO , . defaultSortDesc = true , } ,
2021-04-26 15:57:47 +00:00
[ IO_READ_RATE ] = { . name = " IO_READ_RATE " , . title = " DISK READ " , . description = " The I/O rate of read(2) in bytes per second for the process " , . flags = PROCESS_FLAG_IO , . defaultSortDesc = true , } ,
2021-01-21 19:57:34 +00:00
[ IO_WRITE_RATE ] = { . name = " IO_WRITE_RATE " , . title = " DISK WRITE " , . description = " The I/O rate of write(2) in bytes per second for the process " , . flags = PROCESS_FLAG_IO , . defaultSortDesc = true , } ,
[ IO_RATE ] = { . name = " IO_RATE " , . title = " DISK R/W " , . description = " Total I/O rate in bytes per second " , . flags = PROCESS_FLAG_IO , . defaultSortDesc = true , } ,
2015-03-16 04:43:04 +00:00
[ CGROUP ] = { . name = " CGROUP " , . title = " CGROUP " , . description = " Which cgroup the process is in " , . flags = PROCESS_FLAG_LINUX_CGROUP , } ,
2021-01-21 19:57:34 +00:00
[ OOM ] = { . name = " OOM " , . title = " OOM " , . description = " OOM (Out-of-Memory) killer score " , . flags = PROCESS_FLAG_LINUX_OOM , . defaultSortDesc = true , } ,
2015-03-16 04:43:04 +00:00
[ IO_PRIORITY ] = { . name = " IO_PRIORITY " , . title = " IO " , . description = " I/O priority " , . flags = PROCESS_FLAG_LINUX_IOPRIO , } ,
2017-12-04 02:15:29 +00:00
# ifdef HAVE_DELAYACCT
2021-01-21 19:57:34 +00:00
[ PERCENT_CPU_DELAY ] = { . name = " PERCENT_CPU_DELAY " , . title = " CPUD% " , . description = " CPU delay % " , . flags = PROCESS_FLAG_LINUX_DELAYACCT , . defaultSortDesc = true , } ,
[ PERCENT_IO_DELAY ] = { . name = " PERCENT_IO_DELAY " , . title = " IOD% " , . description = " Block I/O delay % " , . flags = PROCESS_FLAG_LINUX_DELAYACCT , . defaultSortDesc = true , } ,
[ PERCENT_SWAP_DELAY ] = { . name = " PERCENT_SWAP_DELAY " , . title = " SWAPD% " , . description = " Swapin delay % " , . flags = PROCESS_FLAG_LINUX_DELAYACCT , . defaultSortDesc = true , } ,
2017-12-04 02:15:29 +00:00
# endif
2021-02-02 07:57:21 +00:00
[ M_PSS ] = { . name = " M_PSS " , . title = " PSS " , . description = " proportional set size, same as M_RESIDENT but each page is divided by the number of processes sharing it " , . flags = PROCESS_FLAG_LINUX_SMAPS , . defaultSortDesc = true , } ,
2021-01-21 19:57:34 +00:00
[ M_SWAP ] = { . name = " M_SWAP " , . title = " SWAP " , . description = " Size of the process's swapped pages " , . flags = PROCESS_FLAG_LINUX_SMAPS , . defaultSortDesc = true , } ,
2021-02-02 07:57:21 +00:00
[ M_PSSWP ] = { . name = " M_PSSWP " , . title = " PSSWP " , . description = " shows proportional swap share of this mapping, unlike \" Swap \" , this does not take into account swapped out page of underlying shmem objects " , . flags = PROCESS_FLAG_LINUX_SMAPS , . defaultSortDesc = true , } ,
2021-01-21 19:57:34 +00:00
[ CTXT ] = { . name = " CTXT " , . title = " CTXT " , . description = " Context switches (incremental sum of voluntary_ctxt_switches and nonvoluntary_ctxt_switches) " , . flags = PROCESS_FLAG_LINUX_CTXT , . defaultSortDesc = true , } ,
2020-09-28 10:06:13 +00:00
[ SECATTR ] = { . name = " SECATTR " , . title = " Security Attribute " , . description = " Security attribute of the process (e.g. SELinux or AppArmor) " , . flags = PROCESS_FLAG_LINUX_SECATTR , } ,
2020-10-17 10:54:45 +00:00
[ PROC_COMM ] = { . name = " COMM " , . title = " COMM " , . description = " comm string of the process from /proc/[pid]/comm " , . flags = 0 , } ,
[ PROC_EXE ] = { . name = " EXE " , . title = " EXE " , . description = " Basename of exe of the process from /proc/[pid]/exe " , . flags = 0 , } ,
2020-11-26 16:51:54 +00:00
[ CWD ] = { . name = " CWD " , . title = " CWD " , . description = " The current working directory of the process " , . flags = PROCESS_FLAG_LINUX_CWD , } ,
2015-03-15 23:29:13 +00:00
} ;
2020-10-21 19:26:05 +00:00
Process * LinuxProcess_new ( const Settings * settings ) {
2016-02-02 14:53:02 +00:00
LinuxProcess * this = xCalloc ( 1 , sizeof ( LinuxProcess ) ) ;
2015-04-01 02:23:10 +00:00
Object_setClass ( this , Class ( LinuxProcess ) ) ;
2015-02-20 16:52:10 +00:00
Process_init ( & this - > super , settings ) ;
2020-10-21 19:26:05 +00:00
return & this - > super ;
2015-02-20 16:52:10 +00:00
}
2015-03-16 04:43:04 +00:00
void Process_delete ( Object * cast ) {
2015-03-08 22:45:56 +00:00
LinuxProcess * this = ( LinuxProcess * ) cast ;
2015-02-20 16:52:10 +00:00
Process_done ( ( Process * ) cast ) ;
2015-03-16 04:43:04 +00:00
free ( this - > cgroup ) ;
2020-09-30 21:46:52 +00:00
# ifdef HAVE_OPENVZ
free ( this - > ctid ) ;
2015-03-16 04:43:04 +00:00
# endif
2020-11-26 16:51:54 +00:00
free ( this - > cwd ) ;
2020-09-28 10:06:13 +00:00
free ( this - > secattr ) ;
2015-02-20 16:52:10 +00:00
free ( this ) ;
}
2014-11-24 20:55:49 +00:00
/*
[ 1 ] Note that before kernel 2.6 .26 a process that has not asked for
an io priority formally uses " none " as scheduling class , but the
io scheduler will treat such processes as if it were in the best
effort class . The priority within the best effort class will be
dynamically derived from the cpu nice level of the process :
io_priority = ( cpu_nice + 20 ) / 5. - - From ionice ( 1 ) man page
*/
2020-10-27 20:26:39 +00:00
static int LinuxProcess_effectiveIOPriority ( const LinuxProcess * this ) {
2020-11-01 00:09:51 +00:00
if ( IOPriority_class ( this - > ioPriority ) = = IOPRIO_CLASS_NONE ) {
2020-10-27 20:26:39 +00:00
return IOPriority_tuple ( IOPRIO_CLASS_BE , ( this - > super . nice + 20 ) / 5 ) ;
2020-11-01 00:09:51 +00:00
}
2020-10-27 20:26:39 +00:00
return this - > ioPriority ;
}
2014-11-24 20:55:49 +00:00
2020-12-15 18:44:44 +00:00
# ifdef __ANDROID__
# define SYS_ioprio_get __NR_ioprio_get
# define SYS_ioprio_set __NR_ioprio_set
# endif
2014-11-24 21:22:50 +00:00
IOPriority LinuxProcess_updateIOPriority ( LinuxProcess * this ) {
2016-02-14 14:05:35 +00:00
IOPriority ioprio = 0 ;
// Other OSes masquerading as Linux (NetBSD?) don't have this syscall
# ifdef SYS_ioprio_get
ioprio = syscall ( SYS_ioprio_get , IOPRIO_WHO_PROCESS , this - > super . pid ) ;
# endif
2014-11-24 20:55:49 +00:00
this - > ioPriority = ioprio ;
return ioprio ;
}
2020-10-27 10:46:29 +00:00
bool LinuxProcess_setIOPriority ( Process * this , Arg ioprio ) {
2016-02-14 14:05:35 +00:00
// Other OSes masquerading as Linux (NetBSD?) don't have this syscall
# ifdef SYS_ioprio_set
2020-10-27 10:46:29 +00:00
syscall ( SYS_ioprio_set , IOPRIO_WHO_PROCESS , this - > pid , ioprio . i ) ;
2016-02-14 14:05:35 +00:00
# endif
2020-10-27 10:46:29 +00:00
return ( LinuxProcess_updateIOPriority ( ( LinuxProcess * ) this ) = = ioprio . i ) ;
2014-11-24 20:55:49 +00:00
}
2017-12-04 02:15:29 +00:00
# ifdef HAVE_DELAYACCT
2020-11-19 13:43:04 +00:00
static void LinuxProcess_printDelay ( float delay_percent , char * buffer , int n ) {
2020-10-31 21:14:27 +00:00
if ( isnan ( delay_percent ) ) {
xSnprintf ( buffer , n , " N/A " ) ;
} else {
xSnprintf ( buffer , n , " %4.1f " , delay_percent ) ;
}
2017-12-04 02:15:29 +00:00
}
# endif
2020-10-17 10:54:45 +00:00
static void LinuxProcess_writeCommandField ( const Process * this , RichString * str , char * buffer , int n , int attr ) {
/* This code is from Process_writeField for COMM, but we invoke
* LinuxProcess_writeCommand to display
* / proc / pid / exe ( or its basename ) │ / proc / pid / comm │ / proc / pid / cmdline */
int baseattr = CRT_colors [ PROCESS_BASENAME ] ;
if ( this - > settings - > highlightThreads & & Process_isThread ( this ) ) {
attr = CRT_colors [ PROCESS_THREAD ] ;
baseattr = CRT_colors [ PROCESS_THREAD_BASENAME ] ;
}
if ( ! this - > settings - > treeView | | this - > indent = = 0 ) {
2021-04-10 11:31:39 +00:00
Process_writeCommand ( this , attr , baseattr , str ) ;
2020-10-17 10:54:45 +00:00
} else {
char * buf = buffer ;
int maxIndent = 0 ;
bool lastItem = ( this - > indent < 0 ) ;
int indent = ( this - > indent < 0 ? - this - > indent : this - > indent ) ;
int vertLen = strlen ( CRT_treeStr [ TREE_STR_VERT ] ) ;
for ( int i = 0 ; i < 32 ; i + + ) {
if ( indent & ( 1U < < i ) ) {
maxIndent = i + 1 ;
}
}
for ( int i = 0 ; i < maxIndent - 1 ; i + + ) {
if ( indent & ( 1 < < i ) ) {
if ( buf - buffer + ( vertLen + 3 ) > n ) {
break ;
}
buf = stpcpy ( buf , CRT_treeStr [ TREE_STR_VERT ] ) ;
buf = stpcpy ( buf , " " ) ;
} else {
if ( buf - buffer + 4 > n ) {
break ;
}
buf = stpcpy ( buf , " " ) ;
}
}
2020-12-08 20:24:19 +00:00
2020-10-17 10:54:45 +00:00
n - = ( buf - buffer ) ;
2020-12-08 20:24:19 +00:00
const char * draw = CRT_treeStr [ lastItem ? TREE_STR_BEND : TREE_STR_RTEE ] ;
2020-10-17 10:54:45 +00:00
xSnprintf ( buf , n , " %s%s " , draw , this - > showChildren ? CRT_treeStr [ TREE_STR_SHUT ] : CRT_treeStr [ TREE_STR_OPEN ] ) ;
2020-12-04 13:44:57 +00:00
RichString_appendWide ( str , CRT_colors [ PROCESS_TREE ] , buffer ) ;
2021-04-10 11:31:39 +00:00
Process_writeCommand ( this , attr , baseattr , str ) ;
2020-10-17 10:54:45 +00:00
}
}
2020-11-04 16:46:14 +00:00
static void LinuxProcess_writeField ( const Process * this , RichString * str , ProcessField field ) {
2020-10-21 19:26:01 +00:00
const LinuxProcess * lp = ( const LinuxProcess * ) this ;
2015-03-16 04:43:04 +00:00
bool coloring = this - > settings - > highlightMegabytes ;
2014-11-24 21:22:50 +00:00
char buffer [ 256 ] ; buffer [ 255 ] = ' \0 ' ;
int attr = CRT_colors [ DEFAULT_COLOR ] ;
2020-11-24 17:37:13 +00:00
size_t n = sizeof ( buffer ) - 1 ;
2020-12-15 18:44:48 +00:00
switch ( field ) {
2021-04-14 18:16:16 +00:00
case CMINFLT : Process_printCount ( str , lp - > cminflt , coloring ) ; return ;
case CMAJFLT : Process_printCount ( str , lp - > cmajflt , coloring ) ; return ;
2021-04-26 15:57:47 +00:00
case M_DRS : Process_printBytes ( str , lp - > m_drs * pageSize , coloring ) ; return ;
case M_DT : Process_printBytes ( str , lp - > m_dt * pageSize , coloring ) ; return ;
2020-11-26 18:56:10 +00:00
case M_LRS :
if ( lp - > m_lrs ) {
2021-04-26 15:57:47 +00:00
Process_printBytes ( str , lp - > m_lrs * pageSize , coloring ) ;
2020-11-26 18:56:10 +00:00
return ;
}
attr = CRT_colors [ PROCESS_SHADOW ] ;
xSnprintf ( buffer , n , " N/A " ) ;
break ;
2021-04-26 15:57:47 +00:00
case M_TRS : Process_printBytes ( str , lp - > m_trs * pageSize , coloring ) ; return ;
case M_SHARE : Process_printBytes ( str , lp - > m_share * pageSize , coloring ) ; return ;
2021-04-14 18:16:16 +00:00
case M_PSS : Process_printKBytes ( str , lp - > m_pss , coloring ) ; return ;
case M_SWAP : Process_printKBytes ( str , lp - > m_swap , coloring ) ; return ;
case M_PSSWP : Process_printKBytes ( str , lp - > m_psswp , coloring ) ; return ;
case UTIME : Process_printTime ( str , lp - > utime , coloring ) ; return ;
case STIME : Process_printTime ( str , lp - > stime , coloring ) ; return ;
case CUTIME : Process_printTime ( str , lp - > cutime , coloring ) ; return ;
case CSTIME : Process_printTime ( str , lp - > cstime , coloring ) ; return ;
2021-04-26 15:57:47 +00:00
case RCHAR : Process_printBytes ( str , lp - > io_rchar , coloring ) ; return ;
case WCHAR : Process_printBytes ( str , lp - > io_wchar , coloring ) ; return ;
2021-04-14 18:16:16 +00:00
case SYSCR : Process_printCount ( str , lp - > io_syscr , coloring ) ; return ;
case SYSCW : Process_printCount ( str , lp - > io_syscw , coloring ) ; return ;
2021-04-26 15:57:47 +00:00
case RBYTES : Process_printBytes ( str , lp - > io_read_bytes , coloring ) ; return ;
case WBYTES : Process_printBytes ( str , lp - > io_write_bytes , coloring ) ; return ;
case CNCLWB : Process_printBytes ( str , lp - > io_cancelled_write_bytes , coloring ) ; return ;
2021-04-14 18:16:16 +00:00
case IO_READ_RATE : Process_printRate ( str , lp - > io_rate_read_bps , coloring ) ; return ;
case IO_WRITE_RATE : Process_printRate ( str , lp - > io_rate_write_bps , coloring ) ; return ;
2016-02-20 04:22:57 +00:00
case IO_RATE : {
2021-02-28 20:43:53 +00:00
double totalRate ;
2020-10-31 19:52:20 +00:00
if ( ! isnan ( lp - > io_rate_read_bps ) & & ! isnan ( lp - > io_rate_write_bps ) )
2020-09-07 09:53:58 +00:00
totalRate = lp - > io_rate_read_bps + lp - > io_rate_write_bps ;
2020-10-31 19:52:20 +00:00
else if ( ! isnan ( lp - > io_rate_read_bps ) )
2020-09-07 09:53:58 +00:00
totalRate = lp - > io_rate_read_bps ;
2020-10-31 19:52:20 +00:00
else if ( ! isnan ( lp - > io_rate_write_bps ) )
2020-09-07 09:53:58 +00:00
totalRate = lp - > io_rate_write_bps ;
else
totalRate = NAN ;
2021-04-14 18:16:16 +00:00
Process_printRate ( str , totalRate , coloring ) ; return ;
2016-02-20 04:22:57 +00:00
}
2015-03-16 04:43:04 +00:00
# ifdef HAVE_OPENVZ
2020-09-30 21:46:52 +00:00
case CTID : xSnprintf ( buffer , n , " %-8s " , lp - > ctid ? lp - > ctid : " " ) ; break ;
2020-12-15 18:44:52 +00:00
case VPID : xSnprintf ( buffer , n , " %*d " , Process_pidDigits , lp - > vpid ) ; break ;
2015-03-16 04:43:04 +00:00
# endif
# ifdef HAVE_VSERVER
2017-07-27 19:07:50 +00:00
case VXID : xSnprintf ( buffer , n , " %5u " , lp - > vxid ) ; break ;
2015-03-16 04:43:04 +00:00
# endif
2020-09-21 11:47:39 +00:00
case CGROUP : xSnprintf ( buffer , n , " %-10s " , lp - > cgroup ? lp - > cgroup : " " ) ; break ;
2020-08-28 12:24:40 +00:00
case OOM : xSnprintf ( buffer , n , " %4u " , lp - > oom ) ; break ;
2014-11-24 20:55:49 +00:00
case IO_PRIORITY : {
2015-01-22 01:27:31 +00:00
int klass = IOPriority_class ( lp - > ioPriority ) ;
2014-11-24 20:55:49 +00:00
if ( klass = = IOPRIO_CLASS_NONE ) {
// see note [1] above
2017-07-27 19:07:50 +00:00
xSnprintf ( buffer , n , " B%1d " , ( int ) ( this - > nice + 20 ) / 5 ) ;
2014-11-24 20:55:49 +00:00
} else if ( klass = = IOPRIO_CLASS_BE ) {
2017-07-27 19:07:50 +00:00
xSnprintf ( buffer , n , " B%1d " , IOPriority_data ( lp - > ioPriority ) ) ;
2014-11-24 20:55:49 +00:00
} else if ( klass = = IOPRIO_CLASS_RT ) {
attr = CRT_colors [ PROCESS_HIGH_PRIORITY ] ;
2017-07-27 19:07:50 +00:00
xSnprintf ( buffer , n , " R%1d " , IOPriority_data ( lp - > ioPriority ) ) ;
2017-07-05 18:18:02 +00:00
} else if ( klass = = IOPRIO_CLASS_IDLE ) {
2019-10-31 16:39:12 +00:00
attr = CRT_colors [ PROCESS_LOW_PRIORITY ] ;
2017-07-27 19:07:50 +00:00
xSnprintf ( buffer , n , " id " ) ;
2014-11-24 20:55:49 +00:00
} else {
2017-07-27 19:07:50 +00:00
xSnprintf ( buffer , n , " ?? " ) ;
2014-11-24 20:55:49 +00:00
}
break ;
}
2017-12-04 02:15:29 +00:00
# ifdef HAVE_DELAYACCT
case PERCENT_CPU_DELAY : LinuxProcess_printDelay ( lp - > cpu_delay_percent , buffer , n ) ; break ;
case PERCENT_IO_DELAY : LinuxProcess_printDelay ( lp - > blkio_delay_percent , buffer , n ) ; break ;
case PERCENT_SWAP_DELAY : LinuxProcess_printDelay ( lp - > swapin_delay_percent , buffer , n ) ; break ;
# endif
2020-09-11 13:02:00 +00:00
case CTXT :
2020-11-01 00:09:51 +00:00
if ( lp - > ctxt_diff > 1000 ) {
2020-09-11 13:02:00 +00:00
attr | = A_BOLD ;
2020-11-01 00:09:51 +00:00
}
2020-09-11 13:02:00 +00:00
xSnprintf ( buffer , n , " %5lu " , lp - > ctxt_diff ) ;
break ;
2020-09-28 10:06:13 +00:00
case SECATTR : snprintf ( buffer , n , " %-30s " , lp - > secattr ? lp - > secattr : " ? " ) ; break ;
2020-10-17 10:54:45 +00:00
case COMM : {
2021-04-10 09:10:50 +00:00
if ( ( Process_isUserlandThread ( this ) & & this - > settings - > showThreadNames ) | | ! this - > mergedCommand . str ) {
2020-10-17 10:54:45 +00:00
Process_writeField ( this , str , field ) ;
} else {
LinuxProcess_writeCommandField ( this , str , buffer , n , attr ) ;
}
return ;
}
case PROC_COMM : {
2021-01-10 14:57:46 +00:00
const char * procComm ;
2021-01-30 14:31:59 +00:00
if ( this - > procComm ) {
2020-10-17 10:54:45 +00:00
attr = CRT_colors [ Process_isUserlandThread ( this ) ? PROCESS_THREAD_COMM : PROCESS_COMM ] ;
2021-01-30 14:31:59 +00:00
procComm = this - > procComm ;
2020-10-17 10:54:45 +00:00
} else {
2020-11-20 18:57:12 +00:00
attr = CRT_colors [ PROCESS_SHADOW ] ;
2021-04-10 12:08:26 +00:00
procComm = Process_isKernelThread ( this ) ? kthreadID : " N/A " ;
2020-10-17 10:54:45 +00:00
}
2021-01-10 14:57:46 +00:00
/* 15 being (TASK_COMM_LEN - 1) */
Process_printLeftAlignedField ( str , attr , procComm , 15 ) ;
return ;
2020-10-17 10:54:45 +00:00
}
case PROC_EXE : {
2021-01-10 14:57:46 +00:00
const char * procExe ;
2021-01-30 14:31:59 +00:00
if ( this - > procExe ) {
2020-10-17 10:54:45 +00:00
attr = CRT_colors [ Process_isUserlandThread ( this ) ? PROCESS_THREAD_BASENAME : PROCESS_BASENAME ] ;
2021-02-01 21:37:41 +00:00
if ( this - > procExeDeleted )
2020-11-23 21:55:56 +00:00
attr = CRT_colors [ FAILED_READ ] ;
2021-02-01 22:23:10 +00:00
procExe = this - > procExe + this - > procExeBasenameOffset ;
2020-10-17 10:54:45 +00:00
} else {
2020-11-20 18:57:12 +00:00
attr = CRT_colors [ PROCESS_SHADOW ] ;
2021-04-10 12:08:26 +00:00
procExe = Process_isKernelThread ( this ) ? kthreadID : " N/A " ;
2020-10-17 10:54:45 +00:00
}
2021-01-10 14:57:46 +00:00
Process_printLeftAlignedField ( str , attr , procExe , 15 ) ;
return ;
2020-10-17 10:54:45 +00:00
}
2021-01-10 14:57:46 +00:00
case CWD : {
const char * cwd ;
2020-11-26 16:51:54 +00:00
if ( ! lp - > cwd ) {
attr = CRT_colors [ PROCESS_SHADOW ] ;
2021-01-10 14:57:46 +00:00
cwd = " N/A " ;
2020-11-26 16:51:54 +00:00
} else if ( String_startsWith ( lp - > cwd , " /proc/ " ) & & strstr ( lp - > cwd , " (deleted) " ) ! = NULL ) {
attr = CRT_colors [ PROCESS_SHADOW ] ;
2021-01-10 14:57:46 +00:00
cwd = " main thread terminated " ;
2020-11-26 16:51:54 +00:00
} else {
2021-01-10 14:57:46 +00:00
cwd = lp - > cwd ;
2020-11-26 16:51:54 +00:00
}
2021-01-10 14:57:46 +00:00
Process_printLeftAlignedField ( str , attr , cwd , 25 ) ;
return ;
}
2014-11-24 20:55:49 +00:00
default :
2020-09-28 10:17:52 +00:00
Process_writeField ( this , str , field ) ;
2015-01-22 01:27:31 +00:00
return ;
2014-11-24 20:55:49 +00:00
}
2021-04-14 18:55:48 +00:00
RichString_appendAscii ( str , attr , buffer ) ;
2014-11-24 20:55:49 +00:00
}
2021-01-27 14:11:48 +00:00
static double adjustNaN ( double num ) {
if ( isnan ( num ) )
return - 0.0005 ;
return num ;
}
2020-12-23 12:02:32 +00:00
static int LinuxProcess_compareByKey ( const Process * v1 , const Process * v2 , ProcessField key ) {
2020-12-17 23:09:55 +00:00
const LinuxProcess * p1 = ( const LinuxProcess * ) v1 ;
const LinuxProcess * p2 = ( const LinuxProcess * ) v2 ;
2020-11-04 16:46:24 +00:00
2020-12-15 18:44:48 +00:00
switch ( key ) {
2015-03-16 04:43:04 +00:00
case M_DRS :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > m_drs , p2 - > m_drs ) ;
2015-03-16 04:43:04 +00:00
case M_DT :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > m_dt , p2 - > m_dt ) ;
2015-03-16 04:43:04 +00:00
case M_LRS :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > m_lrs , p2 - > m_lrs ) ;
2015-03-16 04:43:04 +00:00
case M_TRS :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > m_trs , p2 - > m_trs ) ;
2015-03-16 04:43:04 +00:00
case M_SHARE :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > m_share , p2 - > m_share ) ;
2018-10-09 19:49:29 +00:00
case M_PSS :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > m_pss , p2 - > m_pss ) ;
2018-10-09 19:49:29 +00:00
case M_SWAP :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > m_swap , p2 - > m_swap ) ;
2018-10-09 19:49:29 +00:00
case M_PSSWP :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > m_psswp , p2 - > m_psswp ) ;
2020-11-04 16:46:24 +00:00
case UTIME :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > utime , p2 - > utime ) ;
2020-11-04 16:46:24 +00:00
case CUTIME :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > cutime , p2 - > cutime ) ;
2020-11-04 16:46:24 +00:00
case STIME :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > stime , p2 - > stime ) ;
2020-11-04 16:46:24 +00:00
case CSTIME :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > cstime , p2 - > cstime ) ;
2020-11-04 16:46:24 +00:00
case RCHAR :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > io_rchar , p2 - > io_rchar ) ;
2020-11-04 16:46:24 +00:00
case WCHAR :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > io_wchar , p2 - > io_wchar ) ;
2020-11-04 16:46:24 +00:00
case SYSCR :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > io_syscr , p2 - > io_syscr ) ;
2020-11-04 16:46:24 +00:00
case SYSCW :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > io_syscw , p2 - > io_syscw ) ;
2020-11-04 16:46:24 +00:00
case RBYTES :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > io_read_bytes , p2 - > io_read_bytes ) ;
2020-11-04 16:46:24 +00:00
case WBYTES :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > io_write_bytes , p2 - > io_write_bytes ) ;
2020-11-04 16:46:24 +00:00
case CNCLWB :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > io_cancelled_write_bytes , p2 - > io_cancelled_write_bytes ) ;
2020-11-04 16:46:24 +00:00
case IO_READ_RATE :
2021-01-27 14:11:48 +00:00
return SPACESHIP_NUMBER ( adjustNaN ( p1 - > io_rate_read_bps ) , adjustNaN ( p2 - > io_rate_read_bps ) ) ;
2020-11-04 16:46:24 +00:00
case IO_WRITE_RATE :
2021-01-27 14:11:48 +00:00
return SPACESHIP_NUMBER ( adjustNaN ( p1 - > io_rate_write_bps ) , adjustNaN ( p2 - > io_rate_write_bps ) ) ;
2020-11-04 16:46:24 +00:00
case IO_RATE :
2021-01-27 14:11:48 +00:00
return SPACESHIP_NUMBER ( adjustNaN ( p1 - > io_rate_read_bps ) + adjustNaN ( p1 - > io_rate_write_bps ) , adjustNaN ( p2 - > io_rate_read_bps ) + adjustNaN ( p2 - > io_rate_write_bps ) ) ;
2015-03-16 04:43:04 +00:00
# ifdef HAVE_OPENVZ
case CTID :
2020-11-04 16:46:24 +00:00
return SPACESHIP_NULLSTR ( p1 - > ctid , p2 - > ctid ) ;
2015-03-16 04:43:04 +00:00
case VPID :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > vpid , p2 - > vpid ) ;
2015-03-16 04:43:04 +00:00
# endif
# ifdef HAVE_VSERVER
case VXID :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > vxid , p2 - > vxid ) ;
2015-03-16 04:43:04 +00:00
# endif
case CGROUP :
2020-11-04 16:46:24 +00:00
return SPACESHIP_NULLSTR ( p1 - > cgroup , p2 - > cgroup ) ;
2015-03-16 04:43:04 +00:00
case OOM :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > oom , p2 - > oom ) ;
2017-12-04 02:15:29 +00:00
# ifdef HAVE_DELAYACCT
case PERCENT_CPU_DELAY :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > cpu_delay_percent , p2 - > cpu_delay_percent ) ;
2017-12-04 02:15:29 +00:00
case PERCENT_IO_DELAY :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > blkio_delay_percent , p2 - > blkio_delay_percent ) ;
2017-12-04 02:15:29 +00:00
case PERCENT_SWAP_DELAY :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > swapin_delay_percent , p2 - > swapin_delay_percent ) ;
2017-12-04 02:15:29 +00:00
# endif
2014-11-24 20:55:49 +00:00
case IO_PRIORITY :
2020-11-04 16:46:24 +00:00
return SPACESHIP_NUMBER ( LinuxProcess_effectiveIOPriority ( p1 ) , LinuxProcess_effectiveIOPriority ( p2 ) ) ;
2020-09-11 13:02:00 +00:00
case CTXT :
2021-01-21 13:27:23 +00:00
return SPACESHIP_NUMBER ( p1 - > ctxt_diff , p2 - > ctxt_diff ) ;
2020-09-28 10:06:13 +00:00
case SECATTR :
2020-11-04 16:46:24 +00:00
return SPACESHIP_NULLSTR ( p1 - > secattr , p2 - > secattr ) ;
2020-10-17 10:54:45 +00:00
case PROC_COMM : {
2021-04-10 12:08:26 +00:00
const char * comm1 = v1 - > procComm ? v1 - > procComm : ( Process_isKernelThread ( v1 ) ? kthreadID : " " ) ;
const char * comm2 = v2 - > procComm ? v2 - > procComm : ( Process_isKernelThread ( v2 ) ? kthreadID : " " ) ;
2020-10-17 10:54:45 +00:00
return strcmp ( comm1 , comm2 ) ;
}
case PROC_EXE : {
2021-04-10 12:08:26 +00:00
const char * exe1 = v1 - > procExe ? ( v1 - > procExe + v1 - > procExeBasenameOffset ) : ( Process_isKernelThread ( v1 ) ? kthreadID : " " ) ;
const char * exe2 = v2 - > procExe ? ( v2 - > procExe + v2 - > procExeBasenameOffset ) : ( Process_isKernelThread ( v2 ) ? kthreadID : " " ) ;
2020-10-17 10:54:45 +00:00
return strcmp ( exe1 , exe2 ) ;
}
2020-11-26 16:51:54 +00:00
case CWD :
return SPACESHIP_NULLSTR ( p1 - > cwd , p2 - > cwd ) ;
2014-11-24 20:55:49 +00:00
default :
2020-12-18 21:12:26 +00:00
return Process_compareByKey_Base ( v1 , v2 , key ) ;
2014-11-24 20:55:49 +00:00
}
2015-03-16 04:43:04 +00:00
}
2020-11-04 16:46:14 +00:00
const ProcessClass LinuxProcess_class = {
. super = {
. extends = Class ( Process ) ,
. display = Process_display ,
. delete = Process_delete ,
2020-12-17 23:09:55 +00:00
. compare = Process_compare
2020-11-04 16:46:14 +00:00
} ,
2020-10-17 10:54:45 +00:00
. writeField = LinuxProcess_writeField ,
2020-12-17 23:09:55 +00:00
. compareByKey = LinuxProcess_compareByKey
2020-11-04 16:46:14 +00:00
} ;