blob: 31c874066b40262c4fcd5d1d99d81610c509f840 [file] [log] [blame]
Hisham Muhammadd6231ba2006-03-04 18:16:49 +00001/*
2htop - Process.c
Hisham Muhammad9b351402011-05-26 16:31:18 +00003(C) 2004-2011 Hisham H. Muhammad
Hisham Muhammadd6231ba2006-03-04 18:16:49 +00004Released under the GNU GPL, see the COPYING file
5in the source distribution for its full text.
6*/
7
Hisham Muhammadd6231ba2006-03-04 18:16:49 +00008#include "ProcessList.h"
9#include "Object.h"
10#include "CRT.h"
11#include "String.h"
12#include "Process.h"
Hisham Muhammad8fa33dc2008-03-09 02:33:23 +000013#include "RichString.h"
Hisham Muhammadec17b702011-09-24 00:30:47 +000014#include "Affinity.h"
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000015
16#include "debug.h"
17
18#include <stdio.h>
19#include <sys/time.h>
20#include <sys/resource.h>
21#include <sys/param.h>
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <unistd.h>
25#include <signal.h>
26#include <string.h>
27#include <stdbool.h>
28#include <pwd.h>
Hisham Muhammada7c2aed2007-11-08 23:23:01 +000029#include <sched.h>
Hisham Muhammaddc262f42010-03-29 18:36:11 +000030#include <time.h>
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000031
Hisham Muhammadec17b702011-09-24 00:30:47 +000032#ifdef HAVE_HWLOC
33#include <hwloc/linux.h>
Hisham Muhammad3b950e42009-03-11 13:15:43 +000034#endif
Hisham Muhammad4df76d12008-03-05 09:46:47 +000035
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000036// This works only with glibc 2.1+. On earlier versions
37// the behavior is similar to have a hardcoded page size.
Hisham Muhammad9710a432007-05-17 18:29:30 +000038#ifndef PAGE_SIZE
Hisham Muhammad3b950e42009-03-11 13:15:43 +000039#define PAGE_SIZE ( sysconf(_SC_PAGESIZE) )
Hisham Muhammad9710a432007-05-17 18:29:30 +000040#endif
Hisham Muhammad3b950e42009-03-11 13:15:43 +000041#define PAGE_SIZE_KB ( PAGE_SIZE / ONE_K )
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000042
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000043/*{
44
Hisham Muhammadd8e14802010-11-22 12:40:20 +000045#ifndef Process_isKernelThread
46#define Process_isKernelThread(_process) (_process->pgrp == 0)
47#endif
48
49#ifndef Process_isUserlandThread
50#define Process_isUserlandThread(_process) (_process->pid != _process->tgid)
51#endif
52
Hisham Muhammadef318932010-02-22 20:57:25 +000053#ifndef Process_isThread
Hisham Muhammadd8e14802010-11-22 12:40:20 +000054#define Process_isThread(_process) (Process_isUserlandThread(_process) || Process_isKernelThread(_process))
Hisham Muhammadef318932010-02-22 20:57:25 +000055#endif
56
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000057typedef enum ProcessField_ {
58 PID = 1, COMM, STATE, PPID, PGRP, SESSION, TTY_NR, TPGID, FLAGS, MINFLT, CMINFLT, MAJFLT, CMAJFLT, UTIME,
59 STIME, CUTIME, CSTIME, PRIORITY, NICE, ITREALVALUE, STARTTIME, VSIZE, RSS, RLIM, STARTCODE, ENDCODE,
60 STARTSTACK, KSTKESP, KSTKEIP, SIGNAL, BLOCKED, SSIGIGNORE, SIGCATCH, WCHAN, NSWAP, CNSWAP, EXIT_SIGNAL,
61 PROCESSOR, M_SIZE, M_RESIDENT, M_SHARE, M_TRS, M_DRS, M_LRS, M_DT, ST_UID, PERCENT_CPU, PERCENT_MEM,
Hisham Muhammadcf7fdcd2007-12-17 05:57:28 +000062 USER, TIME, NLWP, TGID,
Hisham Muhammad4c51ad02007-08-10 05:07:14 +000063 #ifdef HAVE_OPENVZ
Hisham Muhammadb93e5c02009-03-11 13:05:19 +000064 CTID, VPID,
Hisham Muhammad4c51ad02007-08-10 05:07:14 +000065 #endif
Hisham Muhammada5dfaa22008-09-23 04:31:13 +000066 #ifdef HAVE_VSERVER
67 VXID,
68 #endif
Hisham Muhammad12f4f092008-03-09 08:02:22 +000069 #ifdef HAVE_TASKSTATS
Hisham Muhammad2338ad52008-03-14 18:50:49 +000070 RCHAR, WCHAR, SYSCR, SYSCW, RBYTES, WBYTES, CNCLWB, IO_READ_RATE, IO_WRITE_RATE, IO_RATE,
Hisham Muhammad12f4f092008-03-09 08:02:22 +000071 #endif
Hisham Muhammad84ed4c02010-10-30 19:24:07 +000072 #ifdef HAVE_CGROUP
73 CGROUP,
74 #endif
Hisham Muhammad4c51ad02007-08-10 05:07:14 +000075 LAST_PROCESSFIELD
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000076} ProcessField;
77
78struct ProcessList_;
79
80typedef struct Process_ {
81 Object super;
82
83 struct ProcessList_ *pl;
84 bool updated;
85
Hisham Muhammad02a30bf2010-02-25 01:43:18 +000086 pid_t pid;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000087 char* comm;
88 int indent;
89 char state;
90 bool tag;
Hisham Muhammad9eb91212010-06-17 19:02:03 +000091 bool showChildren;
Hisham Muhammadd8e14802010-11-22 12:40:20 +000092 bool show;
Hisham Muhammad02a30bf2010-02-25 01:43:18 +000093 pid_t ppid;
Hisham Muhammada227b202007-04-05 19:53:23 +000094 unsigned int pgrp;
95 unsigned int session;
96 unsigned int tty_nr;
Hisham Muhammad02a30bf2010-02-25 01:43:18 +000097 pid_t tgid;
Hisham Muhammada7c2aed2007-11-08 23:23:01 +000098 int tpgid;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000099 unsigned long int flags;
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000100 #ifdef DEBUG
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000101 unsigned long int minflt;
102 unsigned long int cminflt;
103 unsigned long int majflt;
104 unsigned long int cmajflt;
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000105 #endif
Hisham Muhammad219bb9c2011-03-28 19:06:06 +0000106 unsigned long long int utime;
107 unsigned long long int stime;
108 unsigned long long int cutime;
109 unsigned long long int cstime;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000110 long int priority;
111 long int nice;
Hisham Muhammadd357c672007-05-21 19:10:53 +0000112 long int nlwp;
Hisham Muhammaddc262f42010-03-29 18:36:11 +0000113 char starttime_show[8];
114 time_t starttime_ctime;
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000115 #ifdef DEBUG
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000116 long int itrealvalue;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000117 unsigned long int vsize;
118 long int rss;
119 unsigned long int rlim;
120 unsigned long int startcode;
121 unsigned long int endcode;
122 unsigned long int startstack;
123 unsigned long int kstkesp;
124 unsigned long int kstkeip;
125 unsigned long int signal;
126 unsigned long int blocked;
127 unsigned long int sigignore;
128 unsigned long int sigcatch;
129 unsigned long int wchan;
130 unsigned long int nswap;
131 unsigned long int cnswap;
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000132 #endif
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000133 int exit_signal;
134 int processor;
135 int m_size;
136 int m_resident;
137 int m_share;
138 int m_trs;
139 int m_drs;
140 int m_lrs;
141 int m_dt;
142 uid_t st_uid;
143 float percent_cpu;
144 float percent_mem;
Hisham Muhammadeb2803c2006-07-12 01:35:59 +0000145 char* user;
Hisham Muhammad4c51ad02007-08-10 05:07:14 +0000146 #ifdef HAVE_OPENVZ
Hisham Muhammadb93e5c02009-03-11 13:05:19 +0000147 unsigned int ctid;
Hisham Muhammad4c51ad02007-08-10 05:07:14 +0000148 unsigned int vpid;
149 #endif
Hisham Muhammada5dfaa22008-09-23 04:31:13 +0000150 #ifdef HAVE_VSERVER
151 unsigned int vxid;
152 #endif
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000153 #ifdef HAVE_TASKSTATS
154 unsigned long long io_rchar;
155 unsigned long long io_wchar;
156 unsigned long long io_syscr;
157 unsigned long long io_syscw;
158 unsigned long long io_read_bytes;
159 unsigned long long io_write_bytes;
160 unsigned long long io_cancelled_write_bytes;
161 double io_rate_read_bps;
162 unsigned long long io_rate_read_time;
163 double io_rate_write_bps;
164 unsigned long long io_rate_write_time;
165 #endif
Hisham Muhammad84ed4c02010-10-30 19:24:07 +0000166 #ifdef HAVE_CGROUP
167 char* cgroup;
168 #endif
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000169} Process;
170
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000171}*/
172
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000173#ifdef DEBUG
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000174char* PROCESS_CLASS = "Process";
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000175#else
176#define PROCESS_CLASS NULL
177#endif
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000178
Hisham Muhammad02a30bf2010-02-25 01:43:18 +0000179const char *Process_fieldNames[] = {
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000180 "", "PID", "Command", "STATE", "PPID", "PGRP", "SESSION",
181 "TTY_NR", "TPGID", "FLAGS", "MINFLT", "CMINFLT", "MAJFLT", "CMAJFLT",
182 "UTIME", "STIME", "CUTIME", "CSTIME", "PRIORITY", "NICE", "ITREALVALUE",
183 "STARTTIME", "VSIZE", "RSS", "RLIM", "STARTCODE", "ENDCODE", "STARTSTACK",
184 "KSTKESP", "KSTKEIP", "SIGNAL", "BLOCKED", "SIGIGNORE", "SIGCATCH", "WCHAN",
185 "NSWAP", "CNSWAP", "EXIT_SIGNAL", "PROCESSOR", "M_SIZE", "M_RESIDENT", "M_SHARE",
186 "M_TRS", "M_DRS", "M_LRS", "M_DT", "ST_UID", "PERCENT_CPU", "PERCENT_MEM",
187 "USER", "TIME", "NLWP", "TGID",
Hisham Muhammad4c51ad02007-08-10 05:07:14 +0000188#ifdef HAVE_OPENVZ
Hisham Muhammadb93e5c02009-03-11 13:05:19 +0000189 "CTID", "VPID",
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000190#endif
Hisham Muhammada5dfaa22008-09-23 04:31:13 +0000191#ifdef HAVE_VSERVER
192 "VXID",
193#endif
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000194#ifdef HAVE_TASKSTATS
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000195 "RCHAR", "WCHAR", "SYSCR", "SYSCW", "RBYTES", "WBYTES", "CNCLWB",
196 "IO_READ_RATE", "IO_WRITE_RATE", "IO_RATE",
Hisham Muhammad4c51ad02007-08-10 05:07:14 +0000197#endif
Hisham Muhammad84ed4c02010-10-30 19:24:07 +0000198#ifdef HAVE_CGROUP
199 "CGROUP",
200#endif
Hisham Muhammad4c51ad02007-08-10 05:07:14 +0000201"*** report bug! ***"
Hisham Muhammad2f1f82e2006-06-06 20:41:01 +0000202};
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000203
Hisham Muhammad02a30bf2010-02-25 01:43:18 +0000204const char *Process_fieldTitles[] = {
Hisham Muhammad75080ce2011-09-29 18:40:23 +0000205 "", " PID ", "Command ", "S ", " PPID ", " PGRP ", " SESN ",
206 " TTY ", " TPGID ", "- ", "- ", "- ", "- ", "- ",
Hisham Muhammad3e265ce2011-09-08 04:21:31 +0000207 " UTIME+ ", " STIME+ ", " CUTIME+ ", " CSTIME+ ", "PRI ", " NI ", "- ",
Hisham Muhammaddc262f42010-03-29 18:36:11 +0000208 "START ", "- ", "- ", "- ", "- ", "- ", "- ",
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000209 "- ", "- ", "- ", "- ", "- ", "- ", "- ",
210 "- ", "- ", "- ", "CPU ", " VIRT ", " RES ", " SHR ",
211 " CODE ", " DATA ", " LIB ", " DIRTY ", " UID ", "CPU% ", "MEM% ",
Hisham Muhammad75080ce2011-09-29 18:40:23 +0000212 "USER ", " TIME+ ", "NLWP ", " TGID ",
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000213#ifdef HAVE_OPENVZ
Hisham Muhammadb93e5c02009-03-11 13:05:19 +0000214 " CTID ", " VPID ",
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000215#endif
Hisham Muhammada5dfaa22008-09-23 04:31:13 +0000216#ifdef HAVE_VSERVER
217 " VXID ",
218#endif
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000219#ifdef HAVE_TASKSTATS
Hisham Muhammad75080ce2011-09-29 18:40:23 +0000220 " RD_CHAR ", " WR_CHAR ", " RD_SYSC ", " WR_SYSC ", " IO_RBYTES ", " IO_WBYTES ", " IO_CANCEL ",
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000221 " IORR ", " IOWR ", " IO ",
222#endif
Hisham Muhammad84ed4c02010-10-30 19:24:07 +0000223#ifdef HAVE_CGROUP
224 " CGROUP ",
225#endif
226"*** report bug! ***"
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000227};
228
Hisham Muhammadeb2803c2006-07-12 01:35:59 +0000229static int Process_getuid = -1;
230
Hisham Muhammad75080ce2011-09-29 18:40:23 +0000231static char* Process_pidFormat = "%7u ";
232static char* Process_tpgidFormat = "%7u ";
233
234void Process_getMaxPid() {
235 FILE* file = fopen(PROCDIR "/sys/kernel/pid_max", "r");
236 if (!file) return;
237 int maxPid = 4194303;
Hisham Muhammadd1b1cbc2011-10-25 00:05:46 +0000238 fscanf(file, "%32d", &maxPid);
Hisham Muhammad75080ce2011-09-29 18:40:23 +0000239 fclose(file);
240 if (maxPid > 99999) {
241 Process_fieldTitles[PID] = " PID ";
242 Process_fieldTitles[PPID] = " PPID ";
243 Process_fieldTitles[TPGID] = " TPGID ";
244 Process_fieldTitles[TGID] = " TGID ";
245 Process_pidFormat = "%7u ";
246 Process_tpgidFormat = "%7d ";
247 } else {
248 Process_fieldTitles[PID] = " PID ";
249 Process_fieldTitles[PPID] = " PPID ";
250 Process_fieldTitles[TPGID] = "TPGID ";
251 Process_fieldTitles[TGID] = " TGID ";
252 Process_pidFormat = "%5u ";
253 Process_tpgidFormat = "%5d ";
254 }
255}
256
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000257#define ONE_K 1024
258#define ONE_M (ONE_K * ONE_K)
259#define ONE_G (ONE_M * ONE_K)
260
Hisham Muhammad9b351402011-05-26 16:31:18 +0000261static void Process_humanNumber(Process* this, RichString* str, unsigned long number) {
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000262 char buffer[11];
263 int len;
Hisham Muhammad6330ff32009-06-02 04:51:23 +0000264 if(number >= (10 * ONE_M)) {
Hisham Muhammad2960a812010-11-20 20:35:07 +0000265 if(number >= (100 * ONE_M)) {
266 len = snprintf(buffer, 10, "%4ldG ", number / ONE_M);
267 RichString_appendn(str, CRT_colors[LARGE_NUMBER], buffer, len);
268 } else {
269 len = snprintf(buffer, 10, "%3.1fG ", (float)number / ONE_M);
270 RichString_appendn(str, CRT_colors[LARGE_NUMBER], buffer, len);
271 }
272 } else if (number >= 100000) {
Hisham Muhammade3198ca2006-11-29 18:35:25 +0000273 len = snprintf(buffer, 10, "%4ldM ", number / ONE_K);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000274 int attr = this->pl->highlightMegabytes
275 ? CRT_colors[PROCESS_MEGABYTES]
276 : CRT_colors[PROCESS];
277 RichString_appendn(str, attr, buffer, len);
278 } else if (this->pl->highlightMegabytes && number >= 1000) {
Hisham Muhammade3198ca2006-11-29 18:35:25 +0000279 len = snprintf(buffer, 10, "%2ld", number/1000);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000280 RichString_appendn(str, CRT_colors[PROCESS_MEGABYTES], buffer, len);
281 number %= 1000;
Hisham Muhammade3198ca2006-11-29 18:35:25 +0000282 len = snprintf(buffer, 10, "%03ld ", number);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000283 RichString_appendn(str, CRT_colors[PROCESS], buffer, len);
284 } else {
Hisham Muhammade3198ca2006-11-29 18:35:25 +0000285 len = snprintf(buffer, 10, "%5ld ", number);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000286 RichString_appendn(str, CRT_colors[PROCESS], buffer, len);
287 }
288}
289
Hisham Muhammadd1b1cbc2011-10-25 00:05:46 +0000290static void Process_colorNumber(RichString* str, unsigned long long number) {
Hisham Muhammad9b351402011-05-26 16:31:18 +0000291 char buffer[14];
292 if (number > 10000000000) {
293 snprintf(buffer, 13, "%11lld ", number / 1000);
294 RichString_appendn(str, CRT_colors[LARGE_NUMBER], buffer, 5);
295 RichString_appendn(str, CRT_colors[PROCESS_MEGABYTES], buffer+5, 3);
296 RichString_appendn(str, CRT_colors[PROCESS], buffer+8, 4);
297 } else {
298 snprintf(buffer, 13, "%11lld ", number);
299 RichString_appendn(str, CRT_colors[LARGE_NUMBER], buffer, 2);
300 RichString_appendn(str, CRT_colors[PROCESS_MEGABYTES], buffer+2, 3);
301 RichString_appendn(str, CRT_colors[PROCESS], buffer+5, 3);
302 RichString_appendn(str, CRT_colors[PROCESS_SHADOW], buffer+8, 4);
303 }
304}
305
Hisham Muhammad2f1f82e2006-06-06 20:41:01 +0000306static double jiffy = 0.0;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000307
Hisham Muhammad219bb9c2011-03-28 19:06:06 +0000308static void Process_printTime(RichString* str, unsigned long long t) {
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000309 if(jiffy == 0.0) jiffy = sysconf(_SC_CLK_TCK);
310 double jiffytime = 1.0 / jiffy;
311
312 double realTime = t * jiffytime;
313 int iRealTime = (int) realTime;
314
315 int hours = iRealTime / 3600;
316 int minutes = (iRealTime / 60) % 60;
317 int seconds = iRealTime % 60;
318 int hundredths = (realTime - iRealTime) * 100;
319 char buffer[11];
320 if (hours) {
321 snprintf(buffer, 10, "%2dh", hours);
322 RichString_append(str, CRT_colors[LARGE_NUMBER], buffer);
323 snprintf(buffer, 10, "%02d:%02d ", minutes, seconds);
324 } else {
325 snprintf(buffer, 10, "%2d:%02d.%02d ", minutes, seconds, hundredths);
326 }
327 RichString_append(str, CRT_colors[DEFAULT_COLOR], buffer);
328}
329
Hisham Muhammad93f091c2008-03-08 23:39:48 +0000330static inline void Process_writeCommand(Process* this, int attr, int baseattr, RichString* str) {
Hisham Muhammadd8e14802010-11-22 12:40:20 +0000331 int start = RichString_size(str);
Hisham Muhammad8fa33dc2008-03-09 02:33:23 +0000332 RichString_append(str, attr, this->comm);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000333 if (this->pl->highlightBaseName) {
Hisham Muhammadd8e14802010-11-22 12:40:20 +0000334 int finish = RichString_size(str) - 1;
Hisham Muhammad8fa33dc2008-03-09 02:33:23 +0000335 int space = RichString_findChar(str, ' ', start);
336 if (space != -1)
337 finish = space - 1;
338 for (;;) {
339 int slash = RichString_findChar(str, '/', start);
340 if (slash == -1 || slash > finish)
341 break;
342 start = slash + 1;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000343 }
Hisham Muhammad8fa33dc2008-03-09 02:33:23 +0000344 RichString_setAttrn(str, baseattr, start, finish);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000345 }
346}
347
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000348static inline void Process_outputRate(Process* this, RichString* str, int attr, char* buffer, int n, double rate) {
349 rate = rate / 1024;
350 if (rate < 0.01)
351 snprintf(buffer, n, " 0 ");
352 else if (rate <= 10)
353 snprintf(buffer, n, "%5.2f ", rate);
354 else if (rate <= 100)
355 snprintf(buffer, n, "%5.1f ", rate);
356 else {
Hisham Muhammad9b351402011-05-26 16:31:18 +0000357 Process_humanNumber(this, str, rate);
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000358 return;
359 }
360 RichString_append(str, attr, buffer);
361}
362
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000363static void Process_writeField(Process* this, RichString* str, ProcessField field) {
Hisham Muhammadd8e14802010-11-22 12:40:20 +0000364 char buffer[128]; buffer[127] = '\0';
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000365 int attr = CRT_colors[DEFAULT_COLOR];
Hisham Muhammad93f091c2008-03-08 23:39:48 +0000366 int baseattr = CRT_colors[PROCESS_BASENAME];
Hisham Muhammadd8e14802010-11-22 12:40:20 +0000367 int n = sizeof(buffer) - 1;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000368
369 switch (field) {
Hisham Muhammad75080ce2011-09-29 18:40:23 +0000370 case PID: snprintf(buffer, n, Process_pidFormat, this->pid); break;
371 case PPID: snprintf(buffer, n, Process_pidFormat, this->ppid); break;
Hisham Muhammada227b202007-04-05 19:53:23 +0000372 case PGRP: snprintf(buffer, n, "%5u ", this->pgrp); break;
373 case SESSION: snprintf(buffer, n, "%5u ", this->session); break;
374 case TTY_NR: snprintf(buffer, n, "%5u ", this->tty_nr); break;
Hisham Muhammad75080ce2011-09-29 18:40:23 +0000375 case TGID: snprintf(buffer, n, Process_pidFormat, this->tgid); break;
376 case TPGID: snprintf(buffer, n, Process_tpgidFormat, this->tpgid); break;
Hisham Muhammada9c0ea32011-03-22 20:37:08 +0000377 case PROCESSOR: snprintf(buffer, n, "%3d ", ProcessList_cpuId(this->pl, this->processor)); break;
Hisham Muhammadd357c672007-05-21 19:10:53 +0000378 case NLWP: snprintf(buffer, n, "%4ld ", this->nlwp); break;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000379 case COMM: {
Hisham Muhammadef318932010-02-22 20:57:25 +0000380 if (this->pl->highlightThreads && Process_isThread(this)) {
Hisham Muhammad93f091c2008-03-08 23:39:48 +0000381 attr = CRT_colors[PROCESS_THREAD];
382 baseattr = CRT_colors[PROCESS_THREAD_BASENAME];
383 }
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000384 if (!this->pl->treeView || this->indent == 0) {
Hisham Muhammad93f091c2008-03-08 23:39:48 +0000385 Process_writeCommand(this, attr, baseattr, str);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000386 return;
387 } else {
388 char* buf = buffer;
389 int maxIndent = 0;
Hisham Muhammadca6b9232011-11-03 22:12:12 +0000390 const char **treeStr = this->pl->treeStr;
391 bool lastItem = (this->indent < 0);
392 int indent = (this->indent < 0 ? -this->indent : this->indent);
393 if (treeStr == NULL)
394 treeStr = ProcessList_treeStrAscii;
395
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000396 for (int i = 0; i < 32; i++)
Hisham Muhammadca6b9232011-11-03 22:12:12 +0000397 if (indent & (1 << i))
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000398 maxIndent = i+1;
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000399 for (int i = 0; i < maxIndent - 1; i++) {
Hisham Muhammadca6b9232011-11-03 22:12:12 +0000400 int written;
401 if (indent & (1 << i))
402 written = snprintf(buf, n, "%s ", treeStr[TREE_STR_VERT]);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000403 else
Hisham Muhammadca6b9232011-11-03 22:12:12 +0000404 written = snprintf(buf, n, " ");
405 buf += written;
406 n -= written;
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000407 }
Hisham Muhammadca6b9232011-11-03 22:12:12 +0000408 const char* draw = treeStr[lastItem ? (this->pl->direction == 1 ? TREE_STR_BEND : TREE_STR_TEND) : TREE_STR_RTEE];
409 snprintf(buf, n, "%s%s ", draw, this->showChildren ? treeStr[TREE_STR_SHUT] : treeStr[TREE_STR_OPEN] );
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000410 RichString_append(str, CRT_colors[PROCESS_TREE], buffer);
Hisham Muhammad93f091c2008-03-08 23:39:48 +0000411 Process_writeCommand(this, attr, baseattr, str);
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000412 return;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000413 }
414 }
415 case STATE: {
416 snprintf(buffer, n, "%c ", this->state);
417 attr = this->state == 'R'
418 ? CRT_colors[PROCESS_R_STATE]
419 : attr;
420 break;
421 }
422 case PRIORITY: {
423 if(this->priority == -100)
424 snprintf(buffer, n, " RT ");
425 else
426 snprintf(buffer, n, "%3ld ", this->priority);
427 break;
428 }
429 case NICE: {
430 snprintf(buffer, n, "%3ld ", this->nice);
431 attr = this->nice < 0 ? CRT_colors[PROCESS_HIGH_PRIORITY]
432 : this->nice > 0 ? CRT_colors[PROCESS_LOW_PRIORITY]
433 : attr;
434 break;
435 }
Hisham Muhammad9b351402011-05-26 16:31:18 +0000436 case M_DRS: Process_humanNumber(this, str, this->m_drs * PAGE_SIZE_KB); return;
437 case M_DT: Process_humanNumber(this, str, this->m_dt * PAGE_SIZE_KB); return;
438 case M_LRS: Process_humanNumber(this, str, this->m_lrs * PAGE_SIZE_KB); return;
439 case M_TRS: Process_humanNumber(this, str, this->m_trs * PAGE_SIZE_KB); return;
440 case M_SIZE: Process_humanNumber(this, str, this->m_size * PAGE_SIZE_KB); return;
441 case M_RESIDENT: Process_humanNumber(this, str, this->m_resident * PAGE_SIZE_KB); return;
442 case M_SHARE: Process_humanNumber(this, str, this->m_share * PAGE_SIZE_KB); return;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000443 case ST_UID: snprintf(buffer, n, "%4d ", this->st_uid); break;
444 case USER: {
Hisham Muhammad02a30bf2010-02-25 01:43:18 +0000445 if (Process_getuid != (int) this->st_uid)
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000446 attr = CRT_colors[PROCESS_SHADOW];
Hisham Muhammadeb2803c2006-07-12 01:35:59 +0000447 if (this->user) {
Hisham Muhammad9b351402011-05-26 16:31:18 +0000448 snprintf(buffer, n, "%-9s ", this->user);
Hisham Muhammadeb2803c2006-07-12 01:35:59 +0000449 } else {
Hisham Muhammad9b351402011-05-26 16:31:18 +0000450 snprintf(buffer, n, "%-9d ", this->st_uid);
Hisham Muhammadeb2803c2006-07-12 01:35:59 +0000451 }
Hisham Muhammad9b351402011-05-26 16:31:18 +0000452 if (buffer[9] != '\0') {
453 buffer[9] = ' ';
454 buffer[10] = '\0';
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000455 }
456 break;
457 }
458 case UTIME: Process_printTime(str, this->utime); return;
459 case STIME: Process_printTime(str, this->stime); return;
460 case CUTIME: Process_printTime(str, this->cutime); return;
461 case CSTIME: Process_printTime(str, this->cstime); return;
462 case TIME: Process_printTime(str, this->utime + this->stime); return;
463 case PERCENT_CPU: {
Hisham Muhammad93f091c2008-03-08 23:39:48 +0000464 if (this->percent_cpu > 999.9) {
465 snprintf(buffer, n, "%4d ", (unsigned int)this->percent_cpu);
466 } else if (this->percent_cpu > 99.9) {
467 snprintf(buffer, n, "%3d. ", (unsigned int)this->percent_cpu);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000468 } else {
469 snprintf(buffer, n, "%4.1f ", this->percent_cpu);
470 }
471 break;
472 }
473 case PERCENT_MEM: {
474 if (this->percent_mem > 99.9) {
475 snprintf(buffer, n, "100. ");
476 } else {
477 snprintf(buffer, n, "%4.1f ", this->percent_mem);
478 }
479 break;
480 }
Hisham Muhammaddc262f42010-03-29 18:36:11 +0000481 case STARTTIME: snprintf(buffer, n, "%s", this->starttime_show); break;
Hisham Muhammad4c51ad02007-08-10 05:07:14 +0000482 #ifdef HAVE_OPENVZ
Hisham Muhammadb93e5c02009-03-11 13:05:19 +0000483 case CTID: snprintf(buffer, n, "%5u ", this->ctid); break;
Hisham Muhammad4c51ad02007-08-10 05:07:14 +0000484 case VPID: snprintf(buffer, n, "%5u ", this->vpid); break;
485 #endif
Hisham Muhammada5dfaa22008-09-23 04:31:13 +0000486 #ifdef HAVE_VSERVER
487 case VXID: snprintf(buffer, n, "%5u ", this->vxid); break;
488 #endif
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000489 #ifdef HAVE_TASKSTATS
Hisham Muhammad75080ce2011-09-29 18:40:23 +0000490 case RCHAR: snprintf(buffer, n, "%12llu ", this->io_rchar); break;
491 case WCHAR: snprintf(buffer, n, "%12llu ", this->io_wchar); break;
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000492 case SYSCR: snprintf(buffer, n, "%10llu ", this->io_syscr); break;
493 case SYSCW: snprintf(buffer, n, "%10llu ", this->io_syscw); break;
Hisham Muhammadd1b1cbc2011-10-25 00:05:46 +0000494 case RBYTES: Process_colorNumber(str, this->io_read_bytes); return;
495 case WBYTES: Process_colorNumber(str, this->io_write_bytes); return;
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000496 case CNCLWB: snprintf(buffer, n, "%10llu ", this->io_cancelled_write_bytes); break;
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000497 case IO_READ_RATE: Process_outputRate(this, str, attr, buffer, n, this->io_rate_read_bps); return;
498 case IO_WRITE_RATE: Process_outputRate(this, str, attr, buffer, n, this->io_rate_write_bps); return;
499 case IO_RATE: Process_outputRate(this, str, attr, buffer, n, this->io_rate_read_bps + this->io_rate_write_bps); return;
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000500 #endif
Hisham Muhammad84ed4c02010-10-30 19:24:07 +0000501 #ifdef HAVE_CGROUP
502 case CGROUP: snprintf(buffer, n, "%-10s ", this->cgroup); break;
503 #endif
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000504
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000505 default:
506 snprintf(buffer, n, "- ");
507 }
508 RichString_append(str, attr, buffer);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000509}
510
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000511static void Process_display(Object* cast, RichString* out) {
512 Process* this = (Process*) cast;
513 ProcessField* fields = this->pl->fields;
Hisham Muhammadd8e14802010-11-22 12:40:20 +0000514 RichString_prune(out);
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000515 for (int i = 0; fields[i]; i++)
516 Process_writeField(this, out, fields[i]);
Hisham Muhammad02a30bf2010-02-25 01:43:18 +0000517 if (this->pl->shadowOtherUsers && (int)this->st_uid != Process_getuid)
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000518 RichString_setAttr(out, CRT_colors[PROCESS_SHADOW]);
519 if (this->tag == true)
520 RichString_setAttr(out, CRT_colors[PROCESS_TAG]);
Hisham Muhammada9c0ea32011-03-22 20:37:08 +0000521 assert(out->chlen > 0);
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000522}
523
524void Process_delete(Object* cast) {
525 Process* this = (Process*) cast;
526 assert (this != NULL);
527 if (this->comm) free(this->comm);
Hisham Muhammad84ed4c02010-10-30 19:24:07 +0000528#ifdef HAVE_CGROUP
529 if (this->cgroup) free(this->cgroup);
530#endif
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000531 free(this);
532}
533
534Process* Process_new(struct ProcessList_ *pl) {
535 Process* this = calloc(sizeof(Process), 1);
536 Object_setClass(this, PROCESS_CLASS);
537 ((Object*)this)->display = Process_display;
538 ((Object*)this)->delete = Process_delete;
539 this->pid = 0;
540 this->pl = pl;
541 this->tag = false;
Hisham Muhammad9eb91212010-06-17 19:02:03 +0000542 this->showChildren = true;
Hisham Muhammadd8e14802010-11-22 12:40:20 +0000543 this->show = true;
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000544 this->updated = false;
545 this->utime = 0;
546 this->stime = 0;
547 this->comm = NULL;
548 this->indent = 0;
Hisham Muhammad84ed4c02010-10-30 19:24:07 +0000549#ifdef HAVE_CGROUP
550 this->cgroup = NULL;
551#endif
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000552 if (Process_getuid == -1) Process_getuid = getuid();
553 return this;
554}
555
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000556void Process_toggleTag(Process* this) {
557 this->tag = this->tag == true ? false : true;
558}
559
560bool Process_setPriority(Process* this, int priority) {
561 int old_prio = getpriority(PRIO_PROCESS, this->pid);
562 int err = setpriority(PRIO_PROCESS, this->pid, priority);
563 if (err == 0 && old_prio != getpriority(PRIO_PROCESS, this->pid)) {
564 this->nice = priority;
565 }
566 return (err == 0);
567}
568
Hisham Muhammadec17b702011-09-24 00:30:47 +0000569#ifdef HAVE_HWLOC
570Affinity* Process_getAffinity(Process* this) {
571 hwloc_cpuset_t cpuset = hwloc_bitmap_alloc();
572 bool ok = (hwloc_linux_get_tid_cpubind(this->pl->topology, this->pid, cpuset) == 0);
573 Affinity* affinity = NULL;
574 if (ok) {
575 affinity = Affinity_new();
576 if (hwloc_bitmap_last(cpuset) == -1) {
577 for (int i = 0; i < this->pl->cpuCount; i++) {
578 Affinity_add(affinity, i);
579 }
580 } else {
581 unsigned int id;
582 hwloc_bitmap_foreach_begin(id, cpuset);
583 Affinity_add(affinity, id);
584 hwloc_bitmap_foreach_end();
585 }
586 }
587 hwloc_bitmap_free(cpuset);
588 return affinity;
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000589}
590
Hisham Muhammadec17b702011-09-24 00:30:47 +0000591bool Process_setAffinity(Process* this, Affinity* affinity) {
592 hwloc_cpuset_t cpuset = hwloc_bitmap_alloc();
593 for (int i = 0; i < affinity->used; i++) {
594 hwloc_bitmap_set(cpuset, affinity->cpus[i]);
595 }
596 bool ok = (hwloc_linux_set_tid_cpubind(this->pl->topology, this->pid, cpuset) == 0);
597 hwloc_bitmap_free(cpuset);
598 return ok;
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000599}
Hisham Muhammad3b950e42009-03-11 13:15:43 +0000600#endif
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000601
Hisham Muhammad02a30bf2010-02-25 01:43:18 +0000602void Process_sendSignal(Process* this, int sgn) {
603 kill(this->pid, sgn);
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000604}
605
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000606int Process_pidCompare(const void* v1, const void* v2) {
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000607 Process* p1 = (Process*)v1;
608 Process* p2 = (Process*)v2;
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000609 return (p1->pid - p2->pid);
610}
611
612int Process_compare(const void* v1, const void* v2) {
613 Process *p1, *p2;
614 ProcessList *pl = ((Process*)v1)->pl;
615 if (pl->direction == 1) {
616 p1 = (Process*)v1;
617 p2 = (Process*)v2;
618 } else {
619 p2 = (Process*)v1;
620 p1 = (Process*)v2;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000621 }
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000622 long long diff;
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000623 switch (pl->sortKey) {
624 case PID:
625 return (p1->pid - p2->pid);
626 case PPID:
627 return (p1->ppid - p2->ppid);
628 case USER:
Hisham Muhammad6330ff32009-06-02 04:51:23 +0000629 return strcmp(p1->user ? p1->user : "", p2->user ? p2->user : "");
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000630 case PRIORITY:
631 return (p1->priority - p2->priority);
Hisham Muhammad843aded2009-03-11 13:52:39 +0000632 case PROCESSOR:
633 return (p1->processor - p2->processor);
634 case SESSION:
635 return (p1->session - p2->session);
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000636 case STATE:
637 return (p1->state - p2->state);
638 case NICE:
639 return (p1->nice - p2->nice);
Hisham Muhammadf56c8012007-04-05 20:13:32 +0000640 case M_DRS:
641 return (p2->m_drs - p1->m_drs);
642 case M_DT:
643 return (p2->m_dt - p1->m_dt);
644 case M_LRS:
645 return (p2->m_lrs - p1->m_lrs);
646 case M_TRS:
647 return (p2->m_trs - p1->m_trs);
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000648 case M_SIZE:
649 return (p2->m_size - p1->m_size);
650 case M_RESIDENT:
651 return (p2->m_resident - p1->m_resident);
652 case M_SHARE:
653 return (p2->m_share - p1->m_share);
654 case PERCENT_CPU:
655 return (p2->percent_cpu > p1->percent_cpu ? 1 : -1);
656 case PERCENT_MEM:
657 return (p2->m_resident - p1->m_resident);
658 case UTIME:
659 return (p2->utime - p1->utime);
660 case STIME:
661 return (p2->stime - p1->stime);
662 case TIME:
663 return ((p2->utime+p2->stime) - (p1->utime+p1->stime));
664 case COMM:
665 return strcmp(p1->comm, p2->comm);
Hisham Muhammadd357c672007-05-21 19:10:53 +0000666 case NLWP:
667 return (p1->nlwp - p2->nlwp);
Hisham Muhammad8d0fff22010-03-29 18:44:14 +0000668 case STARTTIME: {
669 if (p1->starttime_ctime == p2->starttime_ctime)
670 return (p1->pid - p2->pid);
671 else
672 return (p1->starttime_ctime - p2->starttime_ctime);
673 }
Hisham Muhammad4c51ad02007-08-10 05:07:14 +0000674 #ifdef HAVE_OPENVZ
Hisham Muhammadb93e5c02009-03-11 13:05:19 +0000675 case CTID:
676 return (p1->ctid - p2->ctid);
Hisham Muhammad4c51ad02007-08-10 05:07:14 +0000677 case VPID:
678 return (p1->vpid - p2->vpid);
679 #endif
Hisham Muhammada5dfaa22008-09-23 04:31:13 +0000680 #ifdef HAVE_VSERVER
681 case VXID:
682 return (p1->vxid - p2->vxid);
683 #endif
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000684 #ifdef HAVE_TASKSTATS
685 case RCHAR: diff = p2->io_rchar - p1->io_rchar; goto test_diff;
686 case WCHAR: diff = p2->io_wchar - p1->io_wchar; goto test_diff;
687 case SYSCR: diff = p2->io_syscr - p1->io_syscr; goto test_diff;
688 case SYSCW: diff = p2->io_syscw - p1->io_syscw; goto test_diff;
689 case RBYTES: diff = p2->io_read_bytes - p1->io_read_bytes; goto test_diff;
690 case WBYTES: diff = p2->io_write_bytes - p1->io_write_bytes; goto test_diff;
691 case CNCLWB: diff = p2->io_cancelled_write_bytes - p1->io_cancelled_write_bytes; goto test_diff;
692 case IO_READ_RATE: diff = p2->io_rate_read_bps - p1->io_rate_read_bps; goto test_diff;
693 case IO_WRITE_RATE: diff = p2->io_rate_write_bps - p1->io_rate_write_bps; goto test_diff;
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000694 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;
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000695 #endif
Hisham Muhammad84ed4c02010-10-30 19:24:07 +0000696 #ifdef HAVE_CGROUP
697 case CGROUP:
698 return strcmp(p1->cgroup ? p1->cgroup : "", p2->cgroup ? p2->cgroup : "");
699 #endif
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000700
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000701 default:
702 return (p1->pid - p2->pid);
703 }
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000704 test_diff:
705 return (diff > 0) ? 1 : (diff < 0 ? -1 : 0);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000706}