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 .
2014-11-24 20:55:49 +00:00
Released under the GNU GPL , see the COPYING file
in the source distribution for its full text .
*/
# include "Process.h"
2014-11-24 21:22:50 +00:00
# include "ProcessList.h"
# include "LinuxProcess.h"
2015-03-15 23:29:13 +00:00
# include "Platform.h"
2014-11-24 21:22:50 +00:00
# include "CRT.h"
2015-02-20 16:52:10 +00:00
# include <stdlib.h>
2014-11-24 21:22:50 +00:00
# include <unistd.h>
2015-03-16 04:43:04 +00:00
# include <string.h>
2014-11-24 21:22:50 +00:00
# include <sys/syscall.h>
2018-08-19 04:29:03 +00:00
# include <time.h>
2014-11-24 20:55:49 +00:00
/*{
2015-03-15 23:29:13 +00:00
# define PROCESS_FLAG_LINUX_IOPRIO 0x0100
# define PROCESS_FLAG_LINUX_OPENVZ 0x0200
# define PROCESS_FLAG_LINUX_VSERVER 0x0400
# define PROCESS_FLAG_LINUX_CGROUP 0x0800
2015-04-09 18:41:21 +00:00
# define PROCESS_FLAG_LINUX_OOM 0x1000
2018-10-09 19:49:29 +00:00
# define PROCESS_FLAG_LINUX_SMAPS 0x2000
2015-03-15 23:29:13 +00:00
2015-03-16 04:43:04 +00:00
typedef enum UnsupportedProcessFields {
FLAGS = 9 ,
ITREALVALUE = 20 ,
VSIZE = 22 ,
RSS = 23 ,
RLIM = 24 ,
STARTCODE = 25 ,
ENDCODE = 26 ,
STARTSTACK = 27 ,
KSTKESP = 28 ,
KSTKEIP = 29 ,
SIGNAL = 30 ,
BLOCKED = 31 ,
SSIGIGNORE = 32 ,
SIGCATCH = 33 ,
WCHAN = 34 ,
NSWAP = 35 ,
CNSWAP = 36 ,
EXIT_SIGNAL = 37 ,
} UnsupportedProcessField ;
2015-03-15 23:29:13 +00:00
typedef enum LinuxProcessFields {
2015-03-16 04:43:04 +00:00
CMINFLT = 11 ,
CMAJFLT = 13 ,
UTIME = 14 ,
STIME = 15 ,
CUTIME = 16 ,
CSTIME = 17 ,
M_SHARE = 41 ,
M_TRS = 42 ,
M_DRS = 43 ,
M_LRS = 44 ,
M_DT = 45 ,
2015-03-15 23:29:13 +00:00
# ifdef HAVE_OPENVZ
2015-03-16 04:43:04 +00:00
CTID = 100 ,
VPID = 101 ,
2015-03-15 23:29:13 +00:00
# endif
# ifdef HAVE_VSERVER
2015-03-16 04:43:04 +00:00
VXID = 102 ,
2015-03-15 23:29:13 +00:00
# endif
# ifdef HAVE_TASKSTATS
2015-03-16 04:43:04 +00:00
RCHAR = 103 ,
WCHAR = 104 ,
SYSCR = 105 ,
SYSCW = 106 ,
RBYTES = 107 ,
WBYTES = 108 ,
CNCLWB = 109 ,
IO_READ_RATE = 110 ,
IO_WRITE_RATE = 111 ,
IO_RATE = 112 ,
2015-03-15 23:29:13 +00:00
# endif
# ifdef HAVE_CGROUP
2015-03-16 04:43:04 +00:00
CGROUP = 113 ,
2015-03-15 23:29:13 +00:00
# endif
2015-03-16 04:43:04 +00:00
OOM = 114 ,
IO_PRIORITY = 115 ,
2017-12-04 02:15:29 +00:00
# ifdef HAVE_DELAYACCT
PERCENT_CPU_DELAY = 116 ,
PERCENT_IO_DELAY = 117 ,
PERCENT_SWAP_DELAY = 118 ,
# endif
2018-10-09 19:49:29 +00:00
M_PSS = 119 ,
M_SWAP = 120 ,
M_PSSWP = 121 ,
LAST_PROCESSFIELD = 122 ,
2015-03-15 23:29:13 +00:00
} LinuxProcessField ;
2014-11-24 21:22:50 +00:00
# include "IOPriority.h"
2014-11-24 20:55:49 +00:00
typedef struct LinuxProcess_ {
Process super ;
2018-03-25 18:26:05 +00:00
bool isKernelThread ;
2014-11-24 20:55:49 +00:00
IOPriority ioPriority ;
2015-03-16 04:43:04 +00:00
unsigned long int cminflt ;
unsigned long int cmajflt ;
unsigned long long int utime ;
unsigned long long int stime ;
unsigned long long int cutime ;
unsigned long long int cstime ;
long m_share ;
2018-10-09 19:49:29 +00:00
long m_pss ;
long m_swap ;
long m_psswp ;
2015-03-16 04:43:04 +00:00
long m_trs ;
long m_drs ;
long m_lrs ;
long m_dt ;
2018-08-19 04:29:03 +00:00
unsigned long long starttime ;
2015-03-16 04:43:04 +00:00
# ifdef HAVE_TASKSTATS
unsigned long long io_rchar ;
unsigned long long io_wchar ;
unsigned long long io_syscr ;
unsigned long long io_syscw ;
unsigned long long io_read_bytes ;
unsigned long long io_write_bytes ;
unsigned long long io_cancelled_write_bytes ;
unsigned long long io_rate_read_time ;
2019-10-31 16:39:12 +00:00
unsigned long long io_rate_write_time ;
2015-03-16 04:43:04 +00:00
double io_rate_read_bps ;
double io_rate_write_bps ;
# endif
# ifdef HAVE_OPENVZ
unsigned int ctid ;
unsigned int vpid ;
# endif
# ifdef HAVE_VSERVER
unsigned int vxid ;
# endif
# ifdef HAVE_CGROUP
char * cgroup ;
# endif
unsigned int oom ;
2016-10-01 06:09:04 +00:00
char * ttyDevice ;
2017-12-04 02:15:29 +00:00
# ifdef HAVE_DELAYACCT
unsigned long long int delay_read_time ;
unsigned long long cpu_delay_total ;
unsigned long long blkio_delay_total ;
unsigned long long swapin_delay_total ;
float cpu_delay_percent ;
float blkio_delay_percent ;
float swapin_delay_percent ;
# endif
2014-11-24 20:55:49 +00:00
} LinuxProcess ;
2015-03-16 04:43:04 +00:00
# ifndef Process_isKernelThread
2018-05-23 02:09:20 +00:00
# define Process_isKernelThread(_process) (((LinuxProcess*)(_process))->isKernelThread)
2015-03-16 04:43:04 +00:00
# endif
# ifndef Process_isUserlandThread
# define Process_isUserlandThread(_process) (_process->pid != _process->tgid)
# endif
2015-02-20 16:52:10 +00:00
2014-11-24 20:55:49 +00:00
} */
2020-07-10 00:35:32 +00:00
/* semi-global */
long long btime ;
2018-08-19 04:29:03 +00:00
2015-03-15 23:29:13 +00:00
ProcessFieldData Process_fields [ ] = {
2015-03-16 04:43:04 +00:00
[ 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 , } ,
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 , } ,
2015-03-16 04:43:04 +00:00
[ PPID ] = { . name = " PPID " , . title = " PPID " , . description = " Parent process ID " , . flags = 0 , } ,
[ PGRP ] = { . name = " PGRP " , . title = " PGRP " , . description = " Process group ID " , . flags = 0 , } ,
2017-02-04 23:10:29 +00:00
[ SESSION ] = { . name = " SESSION " , . title = " SID " , . description = " Process's session ID " , . flags = 0 , } ,
2016-10-01 06:09:04 +00:00
[ TTY_NR ] = { . name = " TTY_NR " , . title = " TTY " , . description = " Controlling terminal " , . flags = 0 , } ,
2015-03-16 04:43:04 +00:00
[ TPGID ] = { . name = " TPGID " , . title = " TPGID " , . description = " Process ID of the fg process group of the controlling terminal " , . flags = 0 , } ,
[ FLAGS ] = { . name = " FLAGS " , . title = NULL , . description = NULL , . flags = 0 , } ,
[ MINFLT ] = { . name = " MINFLT " , . title = " MINFLT " , . description = " Number of minor faults which have not required loading a memory page from disk " , . flags = 0 , } ,
[ CMINFLT ] = { . name = " CMINFLT " , . title = " CMINFLT " , . description = " Children processes' minor faults " , . flags = 0 , } ,
[ MAJFLT ] = { . name = " MAJFLT " , . title = " MAJFLT " , . description = " Number of major faults which have required loading a memory page from disk " , . flags = 0 , } ,
[ CMAJFLT ] = { . name = " CMAJFLT " , . title = " CMAJFLT " , . description = " Children processes' major faults " , . flags = 0 , } ,
[ UTIME ] = { . name = " UTIME " , . title = " UTIME+ " , . description = " User CPU time - time the process spent executing in user mode " , . flags = 0 , } ,
[ STIME ] = { . name = " STIME " , . title = " STIME+ " , . description = " System CPU time - time the kernel spent running system calls for this process " , . flags = 0 , } ,
[ CUTIME ] = { . name = " CUTIME " , . title = " CUTIME+ " , . description = " Children processes' user CPU time " , . flags = 0 , } ,
[ CSTIME ] = { . name = " CSTIME " , . title = " CSTIME+ " , . description = " Children processes' system CPU time " , . 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 , } ,
[ ITREALVALUE ] = { . name = " ITREALVALUE " , . title = NULL , . description = NULL , . flags = 0 , } ,
[ STARTTIME ] = { . name = " STARTTIME " , . title = " START " , . description = " Time the process was started " , . flags = 0 , } ,
[ VSIZE ] = { . name = " VSIZE " , . title = NULL , . description = NULL , . flags = 0 , } ,
[ RSS ] = { . name = " RSS " , . title = NULL , . description = NULL , . flags = 0 , } ,
[ RLIM ] = { . name = " RLIM " , . title = NULL , . description = NULL , . flags = 0 , } ,
[ STARTCODE ] = { . name = " STARTCODE " , . title = NULL , . description = NULL , . flags = 0 , } ,
[ ENDCODE ] = { . name = " ENDCODE " , . title = NULL , . description = NULL , . flags = 0 , } ,
[ STARTSTACK ] = { . name = " STARTSTACK " , . title = NULL , . description = NULL , . flags = 0 , } ,
[ KSTKESP ] = { . name = " KSTKESP " , . title = NULL , . description = NULL , . flags = 0 , } ,
[ KSTKEIP ] = { . name = " KSTKEIP " , . title = NULL , . description = NULL , . flags = 0 , } ,
[ SIGNAL ] = { . name = " SIGNAL " , . title = NULL , . description = NULL , . flags = 0 , } ,
[ BLOCKED ] = { . name = " BLOCKED " , . title = NULL , . description = NULL , . flags = 0 , } ,
[ SSIGIGNORE ] = { . name = " SIGIGNORE " , . title = NULL , . description = NULL , . flags = 0 , } ,
[ SIGCATCH ] = { . name = " SIGCATCH " , . title = NULL , . description = NULL , . flags = 0 , } ,
[ WCHAN ] = { . name = " WCHAN " , . title = NULL , . description = NULL , . flags = 0 , } ,
[ NSWAP ] = { . name = " NSWAP " , . title = NULL , . description = NULL , . flags = 0 , } ,
[ CNSWAP ] = { . name = " CNSWAP " , . title = NULL , . description = NULL , . flags = 0 , } ,
[ EXIT_SIGNAL ] = { . name = " EXIT_SIGNAL " , . title = NULL , . description = NULL , . 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 , } ,
[ M_SHARE ] = { . name = " M_SHARE " , . title = " SHR " , . description = " Size of the process's shared pages " , . flags = 0 , } ,
[ M_TRS ] = { . name = " M_TRS " , . title = " CODE " , . description = " Size of the text segment of the process " , . flags = 0 , } ,
[ M_DRS ] = { . name = " M_DRS " , . title = " DATA " , . description = " Size of the data segment plus stack usage of the process " , . flags = 0 , } ,
[ M_LRS ] = { . name = " M_LRS " , . title = " LIB " , . description = " The library size of the process " , . flags = 0 , } ,
[ M_DT ] = { . name = " M_DT " , . title = " DIRTY " , . description = " Size of the dirty pages of the process " , . flags = 0 , } ,
2018-10-07 09:16:12 +00:00
[ ST_UID ] = { . name = " ST_UID " , . title = " UID " , . description = " User ID of the process owner " , . flags = 0 , } ,
2015-03-16 04:43:04 +00:00
[ 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 , } ,
2015-03-15 23:29:13 +00:00
# ifdef HAVE_OPENVZ
2015-03-16 04:43:04 +00:00
[ CTID ] = { . name = " CTID " , . title = " CTID " , . description = " OpenVZ container ID (a.k.a. virtual environment ID) " , . flags = PROCESS_FLAG_LINUX_OPENVZ , } ,
[ VPID ] = { . name = " VPID " , . title = " VPID " , . description = " OpenVZ process ID " , . flags = PROCESS_FLAG_LINUX_OPENVZ , } ,
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
# ifdef HAVE_TASKSTATS
2015-03-16 04:43:04 +00:00
[ RCHAR ] = { . name = " RCHAR " , . title = " RD_CHAR " , . description = " Number of bytes the process has read " , . flags = PROCESS_FLAG_IO , } ,
[ WCHAR ] = { . name = " WCHAR " , . title = " WR_CHAR " , . description = " Number of bytes the process has written " , . flags = PROCESS_FLAG_IO , } ,
[ SYSCR ] = { . name = " SYSCR " , . title = " RD_SYSC " , . description = " Number of read(2) syscalls for the process " , . flags = PROCESS_FLAG_IO , } ,
[ SYSCW ] = { . name = " SYSCW " , . title = " WR_SYSC " , . description = " Number of write(2) syscalls for the process " , . flags = PROCESS_FLAG_IO , } ,
[ RBYTES ] = { . name = " RBYTES " , . title = " IO_RBYTES " , . description = " Bytes of read(2) I/O for the process " , . flags = PROCESS_FLAG_IO , } ,
[ WBYTES ] = { . name = " WBYTES " , . title = " IO_WBYTES " , . description = " Bytes of write(2) I/O for the process " , . flags = PROCESS_FLAG_IO , } ,
[ CNCLWB ] = { . name = " CNCLWB " , . title = " IO_CANCEL " , . description = " Bytes of cancelled write(2) I/O " , . flags = PROCESS_FLAG_IO , } ,
[ 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 , } ,
[ 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 , } ,
[ IO_RATE ] = { . name = " IO_RATE " , . title = " DISK R/W " , . description = " Total I/O rate in bytes per second " , . flags = PROCESS_FLAG_IO , } ,
2015-03-15 23:29:13 +00:00
# endif
# ifdef HAVE_CGROUP
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 , } ,
2015-03-15 23:29:13 +00:00
# endif
2015-04-09 18:41:21 +00:00
[ OOM ] = { . name = " OOM " , . title = " OOM " , . description = " OOM (Out-of-Memory) killer score " , . flags = PROCESS_FLAG_LINUX_OOM , } ,
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
[ PERCENT_CPU_DELAY ] = { . name = " PERCENT_CPU_DELAY " , . title = " CPUD% " , . description = " CPU delay % " , . flags = 0 , } ,
[ PERCENT_IO_DELAY ] = { . name = " PERCENT_IO_DELAY " , . title = " IOD% " , . description = " Block I/O delay % " , . flags = 0 , } ,
[ PERCENT_SWAP_DELAY ] = { . name = " PERCENT_SWAP_DELAY " , . title = " SWAPD% " , . description = " Swapin delay % " , . flags = 0 , } ,
# endif
2018-10-09 19:49:29 +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 , } ,
[ M_SWAP ] = { . name = " M_SWAP " , . title = " SWAP " , . description = " Size of the process's swapped pages " , . flags = PROCESS_FLAG_LINUX_SMAPS , } ,
[ 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 , } ,
2015-03-16 04:43:04 +00:00
[ LAST_PROCESSFIELD ] = { . name = " *** report bug! *** " , . title = NULL , . description = NULL , . flags = 0 , } ,
2015-03-15 23:29:13 +00:00
} ;
2015-08-20 03:32:47 +00:00
ProcessPidColumn Process_pidColumns [ ] = {
{ . id = PID , . label = " PID " } ,
{ . id = PPID , . label = " PPID " } ,
# ifdef HAVE_OPENVZ
{ . id = VPID , . label = " VPID " } ,
# endif
{ . id = TPGID , . label = " TPGID " } ,
{ . id = TGID , . label = " TGID " } ,
{ . id = PGRP , . label = " PGRP " } ,
2017-01-31 23:03:55 +00:00
{ . id = SESSION , . label = " SID " } ,
2015-08-20 03:32:47 +00:00
{ . id = OOM , . label = " OOM " } ,
{ . id = 0 , . label = NULL } ,
} ;
2015-03-15 23:29:13 +00:00
2015-04-01 02:23:10 +00:00
ProcessClass LinuxProcess_class = {
. super = {
. extends = Class ( Process ) ,
. display = Process_display ,
. delete = Process_delete ,
. compare = LinuxProcess_compare
} ,
. writeField = ( Process_WriteField ) LinuxProcess_writeField ,
} ;
2015-02-20 16:52:10 +00:00
LinuxProcess * LinuxProcess_new ( 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 ) ;
return this ;
}
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
# ifdef HAVE_CGROUP
free ( this - > cgroup ) ;
# endif
2016-10-01 06:09:04 +00:00
free ( this - > ttyDevice ) ;
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
*/
2014-11-24 21:22:50 +00:00
# define LinuxProcess_effectiveIOPriority(p_) (IOPriority_class(p_->ioPriority) == IOPRIO_CLASS_NONE ? IOPriority_tuple(IOPRIO_CLASS_BE, (p_->super.nice + 20) / 5) : p_->ioPriority)
2014-11-24 20:55:49 +00:00
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-08-19 23:35:24 +00:00
bool LinuxProcess_setIOPriority ( LinuxProcess * 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-08-19 23:35:24 +00:00
syscall ( SYS_ioprio_set , IOPRIO_WHO_PROCESS , this - > super . pid , ioprio . i ) ;
2016-02-14 14:05:35 +00:00
# endif
2020-08-19 23:35:24 +00:00
return ( LinuxProcess_updateIOPriority ( this ) = = ioprio . i ) ;
2014-11-24 20:55:49 +00:00
}
2017-12-04 02:15:29 +00:00
# ifdef HAVE_DELAYACCT
void LinuxProcess_printDelay ( float delay_percent , char * buffer , int n ) {
if ( delay_percent = = - 1LL ) {
xSnprintf ( buffer , n , " N/A " ) ;
} else {
xSnprintf ( buffer , n , " %4.1f " , delay_percent ) ;
}
}
# endif
2015-04-02 04:57:37 +00:00
void LinuxProcess_writeField ( Process * this , RichString * str , ProcessField field ) {
2015-01-22 01:27:31 +00:00
LinuxProcess * lp = ( 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 ] ;
int n = sizeof ( buffer ) - 1 ;
2015-03-16 04:43:04 +00:00
switch ( ( int ) field ) {
2016-10-01 06:09:04 +00:00
case TTY_NR : {
if ( lp - > ttyDevice ) {
2017-07-27 19:07:50 +00:00
xSnprintf ( buffer , n , " %-9s " , lp - > ttyDevice + 5 /* skip "/dev/" */ ) ;
2016-10-01 06:09:04 +00:00
} else {
attr = CRT_colors [ PROCESS_SHADOW ] ;
2017-07-27 19:07:50 +00:00
xSnprintf ( buffer , n , " ? " ) ;
2016-10-01 06:09:04 +00:00
}
break ;
}
2015-03-16 04:43:04 +00:00
case CMINFLT : Process_colorNumber ( str , lp - > cminflt , coloring ) ; return ;
case CMAJFLT : Process_colorNumber ( str , lp - > cmajflt , coloring ) ; return ;
case M_DRS : Process_humanNumber ( str , lp - > m_drs * PAGE_SIZE_KB , coloring ) ; return ;
case M_DT : Process_humanNumber ( str , lp - > m_dt * PAGE_SIZE_KB , coloring ) ; return ;
case M_LRS : Process_humanNumber ( str , lp - > m_lrs * PAGE_SIZE_KB , coloring ) ; return ;
case M_TRS : Process_humanNumber ( str , lp - > m_trs * PAGE_SIZE_KB , coloring ) ; return ;
case M_SHARE : Process_humanNumber ( str , lp - > m_share * PAGE_SIZE_KB , coloring ) ; return ;
2018-10-09 19:49:29 +00:00
case M_PSS : Process_humanNumber ( str , lp - > m_pss , coloring ) ; return ;
case M_SWAP : Process_humanNumber ( str , lp - > m_swap , coloring ) ; return ;
case M_PSSWP : Process_humanNumber ( str , lp - > m_psswp , coloring ) ; return ;
2015-03-16 04:43:04 +00:00
case UTIME : Process_printTime ( str , lp - > utime ) ; return ;
case STIME : Process_printTime ( str , lp - > stime ) ; return ;
case CUTIME : Process_printTime ( str , lp - > cutime ) ; return ;
case CSTIME : Process_printTime ( str , lp - > cstime ) ; return ;
2018-08-19 04:29:03 +00:00
case STARTTIME : {
struct tm date ;
time_t starttimewall = btime + ( lp - > starttime / sysconf ( _SC_CLK_TCK ) ) ;
( void ) localtime_r ( & starttimewall , & date ) ;
strftime ( buffer , n , ( ( starttimewall > time ( NULL ) - 86400 ) ? " %R " : " %b%d " ) , & date ) ;
break ;
}
2015-03-16 04:43:04 +00:00
# ifdef HAVE_TASKSTATS
case RCHAR : Process_colorNumber ( str , lp - > io_rchar , coloring ) ; return ;
case WCHAR : Process_colorNumber ( str , lp - > io_wchar , coloring ) ; return ;
case SYSCR : Process_colorNumber ( str , lp - > io_syscr , coloring ) ; return ;
case SYSCW : Process_colorNumber ( str , lp - > io_syscw , coloring ) ; return ;
case RBYTES : Process_colorNumber ( str , lp - > io_read_bytes , coloring ) ; return ;
case WBYTES : Process_colorNumber ( str , lp - > io_write_bytes , coloring ) ; return ;
case CNCLWB : Process_colorNumber ( str , lp - > io_cancelled_write_bytes , coloring ) ; return ;
case IO_READ_RATE : Process_outputRate ( str , buffer , n , lp - > io_rate_read_bps , coloring ) ; return ;
case IO_WRITE_RATE : Process_outputRate ( str , buffer , n , lp - > io_rate_write_bps , coloring ) ; return ;
2016-02-20 04:22:57 +00:00
case IO_RATE : {
double totalRate = ( lp - > io_rate_read_bps ! = - 1 )
? ( lp - > io_rate_read_bps + lp - > io_rate_write_bps )
: - 1 ;
Process_outputRate ( str , buffer , n , totalRate , coloring ) ; return ;
}
2015-03-16 04:43:04 +00:00
# endif
# ifdef HAVE_OPENVZ
2017-07-27 19:07:50 +00:00
case CTID : xSnprintf ( buffer , n , " %7u " , lp - > ctid ) ; break ;
case VPID : xSnprintf ( buffer , n , Process_pidFormat , 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
# ifdef HAVE_CGROUP
2017-07-27 19:07:50 +00:00
case CGROUP : xSnprintf ( buffer , n , " %-10s " , lp - > cgroup ) ; break ;
2015-03-16 04:43:04 +00:00
# endif
2017-07-27 19:07:50 +00:00
case OOM : xSnprintf ( buffer , n , Process_pidFormat , 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
2014-11-24 20:55:49 +00:00
default :
2015-04-01 02:23:10 +00:00
Process_writeField ( ( Process * ) this , str , field ) ;
2015-01-22 01:27:31 +00:00
return ;
2014-11-24 20:55:49 +00:00
}
RichString_append ( str , attr , buffer ) ;
}
long LinuxProcess_compare ( const void * v1 , const void * v2 ) {
LinuxProcess * p1 , * p2 ;
2015-01-22 01:27:31 +00:00
Settings * settings = ( ( Process * ) v1 ) - > settings ;
if ( settings - > direction = = 1 ) {
2014-11-24 20:55:49 +00:00
p1 = ( LinuxProcess * ) v1 ;
p2 = ( LinuxProcess * ) v2 ;
} else {
p2 = ( LinuxProcess * ) v1 ;
p1 = ( LinuxProcess * ) v2 ;
}
2015-03-16 04:43:04 +00:00
long long diff ;
switch ( ( int ) settings - > sortKey ) {
case M_DRS :
return ( p2 - > m_drs - p1 - > m_drs ) ;
case M_DT :
return ( p2 - > m_dt - p1 - > m_dt ) ;
case M_LRS :
return ( p2 - > m_lrs - p1 - > m_lrs ) ;
case M_TRS :
return ( p2 - > m_trs - p1 - > m_trs ) ;
case M_SHARE :
return ( p2 - > m_share - p1 - > m_share ) ;
2018-10-09 19:49:29 +00:00
case M_PSS :
return ( p2 - > m_pss - p1 - > m_pss ) ;
case M_SWAP :
return ( p2 - > m_swap - p1 - > m_swap ) ;
case M_PSSWP :
return ( p2 - > m_psswp - p1 - > m_psswp ) ;
2015-03-16 04:43:04 +00:00
case UTIME : diff = p2 - > utime - p1 - > utime ; goto test_diff ;
case CUTIME : diff = p2 - > cutime - p1 - > cutime ; goto test_diff ;
case STIME : diff = p2 - > stime - p1 - > stime ; goto test_diff ;
2015-07-23 11:24:39 +00:00
case CSTIME : diff = p2 - > cstime - p1 - > cstime ; goto test_diff ;
2018-08-19 04:29:03 +00:00
case STARTTIME : {
if ( p1 - > starttime = = p2 - > starttime )
return ( p1 - > super . pid - p2 - > super . pid ) ;
else
return ( p1 - > starttime - p2 - > starttime ) ;
}
2015-03-16 04:43:04 +00:00
# ifdef HAVE_TASKSTATS
case RCHAR : diff = p2 - > io_rchar - p1 - > io_rchar ; goto test_diff ;
case WCHAR : diff = p2 - > io_wchar - p1 - > io_wchar ; goto test_diff ;
case SYSCR : diff = p2 - > io_syscr - p1 - > io_syscr ; goto test_diff ;
case SYSCW : diff = p2 - > io_syscw - p1 - > io_syscw ; goto test_diff ;
case RBYTES : diff = p2 - > io_read_bytes - p1 - > io_read_bytes ; goto test_diff ;
case WBYTES : diff = p2 - > io_write_bytes - p1 - > io_write_bytes ; goto test_diff ;
case CNCLWB : diff = p2 - > io_cancelled_write_bytes - p1 - > io_cancelled_write_bytes ; goto test_diff ;
case IO_READ_RATE : diff = p2 - > io_rate_read_bps - p1 - > io_rate_read_bps ; goto test_diff ;
case IO_WRITE_RATE : diff = p2 - > io_rate_write_bps - p1 - > io_rate_write_bps ; goto test_diff ;
case IO_RATE : diff = ( p2 - > io_rate_read_bps + p2 - > io_rate_write_bps ) - ( p1 - > io_rate_read_bps + p1 - > io_rate_write_bps ) ; goto test_diff ;
# endif
# ifdef HAVE_OPENVZ
case CTID :
2015-04-09 18:41:21 +00:00
return ( p2 - > ctid - p1 - > ctid ) ;
2015-03-16 04:43:04 +00:00
case VPID :
2015-04-09 18:41:21 +00:00
return ( p2 - > vpid - p1 - > vpid ) ;
2015-03-16 04:43:04 +00:00
# endif
# ifdef HAVE_VSERVER
case VXID :
2015-04-09 18:41:21 +00:00
return ( p2 - > vxid - p1 - > vxid ) ;
2015-03-16 04:43:04 +00:00
# endif
# ifdef HAVE_CGROUP
case CGROUP :
return strcmp ( p1 - > cgroup ? p1 - > cgroup : " " , p2 - > cgroup ? p2 - > cgroup : " " ) ;
# endif
case OOM :
2015-04-09 18:41:21 +00:00
return ( p2 - > oom - p1 - > oom ) ;
2017-12-04 02:15:29 +00:00
# ifdef HAVE_DELAYACCT
case PERCENT_CPU_DELAY :
return ( p2 - > cpu_delay_percent > p1 - > cpu_delay_percent ? 1 : - 1 ) ;
case PERCENT_IO_DELAY :
return ( p2 - > blkio_delay_percent > p1 - > blkio_delay_percent ? 1 : - 1 ) ;
case PERCENT_SWAP_DELAY :
return ( p2 - > swapin_delay_percent > p1 - > swapin_delay_percent ? 1 : - 1 ) ;
# endif
2014-11-24 20:55:49 +00:00
case IO_PRIORITY :
2014-11-24 21:22:50 +00:00
return LinuxProcess_effectiveIOPriority ( p1 ) - LinuxProcess_effectiveIOPriority ( p2 ) ;
2014-11-24 20:55:49 +00:00
default :
2015-04-01 02:23:10 +00:00
return Process_compare ( v1 , v2 ) ;
2014-11-24 20:55:49 +00:00
}
2015-03-16 04:43:04 +00:00
test_diff :
return ( diff > 0 ) ? 1 : ( diff < 0 ? - 1 : 0 ) ;
}
bool Process_isThread ( Process * this ) {
return ( Process_isUserlandThread ( this ) | | Process_isKernelThread ( this ) ) ;
2014-11-24 20:55:49 +00:00
}