blob: ac02de02b8828ad9111fa0c8e4eb5cfc0526ab55 [file] [log] [blame]
Hisham Muhammadd6231ba2006-03-04 18:16:49 +00001/*
2htop - Process.c
Hisham Muhammad130938f2006-03-23 18:55:29 +00003(C) 2004-2006 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
8#define _GNU_SOURCE
9#include "ProcessList.h"
10#include "Object.h"
11#include "CRT.h"
12#include "String.h"
13#include "Process.h"
Hisham Muhammad8fa33dc2008-03-09 02:33:23 +000014#include "RichString.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 Muhammadd6231ba2006-03-04 18:16:49 +000030
Hisham Muhammad3b950e42009-03-11 13:15:43 +000031#ifdef HAVE_PLPA
Hisham Muhammad4df76d12008-03-05 09:46:47 +000032#include <plpa.h>
Hisham Muhammad3b950e42009-03-11 13:15:43 +000033#endif
Hisham Muhammad4df76d12008-03-05 09:46:47 +000034
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000035// This works only with glibc 2.1+. On earlier versions
36// the behavior is similar to have a hardcoded page size.
Hisham Muhammad9710a432007-05-17 18:29:30 +000037#ifndef PAGE_SIZE
Hisham Muhammad3b950e42009-03-11 13:15:43 +000038#define PAGE_SIZE ( sysconf(_SC_PAGESIZE) )
Hisham Muhammad9710a432007-05-17 18:29:30 +000039#endif
Hisham Muhammad3b950e42009-03-11 13:15:43 +000040#define PAGE_SIZE_KB ( PAGE_SIZE / ONE_K )
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000041
42#define PROCESS_COMM_LEN 300
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000043
44/*{
45
Hisham Muhammadef318932010-02-22 20:57:25 +000046#ifndef Process_isThread
47#define Process_isThread(_process) (_process->pid != _process->tgid || _process->m_size == 0)
48#endif
49
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000050typedef enum ProcessField_ {
51 PID = 1, COMM, STATE, PPID, PGRP, SESSION, TTY_NR, TPGID, FLAGS, MINFLT, CMINFLT, MAJFLT, CMAJFLT, UTIME,
52 STIME, CUTIME, CSTIME, PRIORITY, NICE, ITREALVALUE, STARTTIME, VSIZE, RSS, RLIM, STARTCODE, ENDCODE,
53 STARTSTACK, KSTKESP, KSTKEIP, SIGNAL, BLOCKED, SSIGIGNORE, SIGCATCH, WCHAN, NSWAP, CNSWAP, EXIT_SIGNAL,
54 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 +000055 USER, TIME, NLWP, TGID,
Hisham Muhammad4c51ad02007-08-10 05:07:14 +000056 #ifdef HAVE_OPENVZ
Hisham Muhammadb93e5c02009-03-11 13:05:19 +000057 CTID, VPID,
Hisham Muhammad4c51ad02007-08-10 05:07:14 +000058 #endif
Hisham Muhammada5dfaa22008-09-23 04:31:13 +000059 #ifdef HAVE_VSERVER
60 VXID,
61 #endif
Hisham Muhammad12f4f092008-03-09 08:02:22 +000062 #ifdef HAVE_TASKSTATS
Hisham Muhammad2338ad52008-03-14 18:50:49 +000063 RCHAR, WCHAR, SYSCR, SYSCW, RBYTES, WBYTES, CNCLWB, IO_READ_RATE, IO_WRITE_RATE, IO_RATE,
Hisham Muhammad12f4f092008-03-09 08:02:22 +000064 #endif
Hisham Muhammad4c51ad02007-08-10 05:07:14 +000065 LAST_PROCESSFIELD
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000066} ProcessField;
67
68struct ProcessList_;
69
70typedef struct Process_ {
71 Object super;
72
73 struct ProcessList_ *pl;
74 bool updated;
75
Hisham Muhammad02a30bf2010-02-25 01:43:18 +000076 pid_t pid;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000077 char* comm;
78 int indent;
79 char state;
80 bool tag;
Hisham Muhammad02a30bf2010-02-25 01:43:18 +000081 pid_t ppid;
Hisham Muhammada227b202007-04-05 19:53:23 +000082 unsigned int pgrp;
83 unsigned int session;
84 unsigned int tty_nr;
Hisham Muhammad02a30bf2010-02-25 01:43:18 +000085 pid_t tgid;
Hisham Muhammada7c2aed2007-11-08 23:23:01 +000086 int tpgid;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000087 unsigned long int flags;
Hisham Muhammad5d48ab82006-07-11 06:13:32 +000088 #ifdef DEBUG
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000089 unsigned long int minflt;
90 unsigned long int cminflt;
91 unsigned long int majflt;
92 unsigned long int cmajflt;
Hisham Muhammad5d48ab82006-07-11 06:13:32 +000093 #endif
Hisham Muhammadd6231ba2006-03-04 18:16:49 +000094 unsigned long int utime;
95 unsigned long int stime;
96 long int cutime;
97 long int cstime;
98 long int priority;
99 long int nice;
Hisham Muhammadd357c672007-05-21 19:10:53 +0000100 long int nlwp;
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000101 #ifdef DEBUG
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000102 long int itrealvalue;
103 unsigned long int starttime;
104 unsigned long int vsize;
105 long int rss;
106 unsigned long int rlim;
107 unsigned long int startcode;
108 unsigned long int endcode;
109 unsigned long int startstack;
110 unsigned long int kstkesp;
111 unsigned long int kstkeip;
112 unsigned long int signal;
113 unsigned long int blocked;
114 unsigned long int sigignore;
115 unsigned long int sigcatch;
116 unsigned long int wchan;
117 unsigned long int nswap;
118 unsigned long int cnswap;
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000119 #endif
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000120 int exit_signal;
121 int processor;
122 int m_size;
123 int m_resident;
124 int m_share;
125 int m_trs;
126 int m_drs;
127 int m_lrs;
128 int m_dt;
129 uid_t st_uid;
130 float percent_cpu;
131 float percent_mem;
Hisham Muhammadeb2803c2006-07-12 01:35:59 +0000132 char* user;
Hisham Muhammad4c51ad02007-08-10 05:07:14 +0000133 #ifdef HAVE_OPENVZ
Hisham Muhammadb93e5c02009-03-11 13:05:19 +0000134 unsigned int ctid;
Hisham Muhammad4c51ad02007-08-10 05:07:14 +0000135 unsigned int vpid;
136 #endif
Hisham Muhammada5dfaa22008-09-23 04:31:13 +0000137 #ifdef HAVE_VSERVER
138 unsigned int vxid;
139 #endif
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000140 #ifdef HAVE_TASKSTATS
141 unsigned long long io_rchar;
142 unsigned long long io_wchar;
143 unsigned long long io_syscr;
144 unsigned long long io_syscw;
145 unsigned long long io_read_bytes;
146 unsigned long long io_write_bytes;
147 unsigned long long io_cancelled_write_bytes;
148 double io_rate_read_bps;
149 unsigned long long io_rate_read_time;
150 double io_rate_write_bps;
151 unsigned long long io_rate_write_time;
152 #endif
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000153} Process;
154
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000155}*/
156
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000157#ifdef DEBUG
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000158char* PROCESS_CLASS = "Process";
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000159#else
160#define PROCESS_CLASS NULL
161#endif
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000162
Hisham Muhammad02a30bf2010-02-25 01:43:18 +0000163const char *Process_fieldNames[] = {
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000164 "", "PID", "Command", "STATE", "PPID", "PGRP", "SESSION",
165 "TTY_NR", "TPGID", "FLAGS", "MINFLT", "CMINFLT", "MAJFLT", "CMAJFLT",
166 "UTIME", "STIME", "CUTIME", "CSTIME", "PRIORITY", "NICE", "ITREALVALUE",
167 "STARTTIME", "VSIZE", "RSS", "RLIM", "STARTCODE", "ENDCODE", "STARTSTACK",
168 "KSTKESP", "KSTKEIP", "SIGNAL", "BLOCKED", "SIGIGNORE", "SIGCATCH", "WCHAN",
169 "NSWAP", "CNSWAP", "EXIT_SIGNAL", "PROCESSOR", "M_SIZE", "M_RESIDENT", "M_SHARE",
170 "M_TRS", "M_DRS", "M_LRS", "M_DT", "ST_UID", "PERCENT_CPU", "PERCENT_MEM",
171 "USER", "TIME", "NLWP", "TGID",
Hisham Muhammad4c51ad02007-08-10 05:07:14 +0000172#ifdef HAVE_OPENVZ
Hisham Muhammadb93e5c02009-03-11 13:05:19 +0000173 "CTID", "VPID",
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000174#endif
Hisham Muhammada5dfaa22008-09-23 04:31:13 +0000175#ifdef HAVE_VSERVER
176 "VXID",
177#endif
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000178#ifdef HAVE_TASKSTATS
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000179 "RCHAR", "WCHAR", "SYSCR", "SYSCW", "RBYTES", "WBYTES", "CNCLWB",
180 "IO_READ_RATE", "IO_WRITE_RATE", "IO_RATE",
Hisham Muhammad4c51ad02007-08-10 05:07:14 +0000181#endif
182"*** report bug! ***"
Hisham Muhammad2f1f82e2006-06-06 20:41:01 +0000183};
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000184
Hisham Muhammad02a30bf2010-02-25 01:43:18 +0000185const char *Process_fieldTitles[] = {
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000186 "", " PID ", "Command ", "S ", " PPID ", " PGRP ", " SESN ",
187 " TTY ", "TPGID ", "- ", "- ", "- ", "- ", "- ",
188 " UTIME+ ", " STIME+ ", "- ", "- ", "PRI ", " NI ", "- ",
189 "- ", "- ", "- ", "- ", "- ", "- ", "- ",
190 "- ", "- ", "- ", "- ", "- ", "- ", "- ",
191 "- ", "- ", "- ", "CPU ", " VIRT ", " RES ", " SHR ",
192 " CODE ", " DATA ", " LIB ", " DIRTY ", " UID ", "CPU% ", "MEM% ",
193 "USER ", " TIME+ ", "NLWP ", " TGID ",
194#ifdef HAVE_OPENVZ
Hisham Muhammadb93e5c02009-03-11 13:05:19 +0000195 " CTID ", " VPID ",
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000196#endif
Hisham Muhammada5dfaa22008-09-23 04:31:13 +0000197#ifdef HAVE_VSERVER
198 " VXID ",
199#endif
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000200#ifdef HAVE_TASKSTATS
Hisham Muhammad02a30bf2010-02-25 01:43:18 +0000201 " RD_CHAR ", " WR_CHAR ", " RD_SYSC ", " WR_SYSC ", " IO_RBYTES ", " IO_WBYTES ", " IO_CANCEL ",
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000202 " IORR ", " IOWR ", " IO ",
203#endif
204};
205
Hisham Muhammadeb2803c2006-07-12 01:35:59 +0000206static int Process_getuid = -1;
207
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000208#define ONE_K 1024
209#define ONE_M (ONE_K * ONE_K)
210#define ONE_G (ONE_M * ONE_K)
211
Hisham Muhammad6b6b4372006-11-20 16:42:03 +0000212static void Process_printLargeNumber(Process* this, RichString *str, unsigned long number) {
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000213 char buffer[11];
214 int len;
Hisham Muhammad6330ff32009-06-02 04:51:23 +0000215 if(number >= (10 * ONE_M)) {
216 len = snprintf(buffer, 10, "%3.1fG ", (float)number / ONE_M);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000217 RichString_appendn(str, CRT_colors[LARGE_NUMBER], buffer, len);
218 } else if(number >= (100000)) {
Hisham Muhammade3198ca2006-11-29 18:35:25 +0000219 len = snprintf(buffer, 10, "%4ldM ", number / ONE_K);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000220 int attr = this->pl->highlightMegabytes
221 ? CRT_colors[PROCESS_MEGABYTES]
222 : CRT_colors[PROCESS];
223 RichString_appendn(str, attr, buffer, len);
224 } else if (this->pl->highlightMegabytes && number >= 1000) {
Hisham Muhammade3198ca2006-11-29 18:35:25 +0000225 len = snprintf(buffer, 10, "%2ld", number/1000);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000226 RichString_appendn(str, CRT_colors[PROCESS_MEGABYTES], buffer, len);
227 number %= 1000;
Hisham Muhammade3198ca2006-11-29 18:35:25 +0000228 len = snprintf(buffer, 10, "%03ld ", number);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000229 RichString_appendn(str, CRT_colors[PROCESS], buffer, len);
230 } else {
Hisham Muhammade3198ca2006-11-29 18:35:25 +0000231 len = snprintf(buffer, 10, "%5ld ", number);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000232 RichString_appendn(str, CRT_colors[PROCESS], buffer, len);
233 }
234}
235
Hisham Muhammad2f1f82e2006-06-06 20:41:01 +0000236static double jiffy = 0.0;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000237
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000238static void Process_printTime(RichString* str, unsigned long t) {
239 if(jiffy == 0.0) jiffy = sysconf(_SC_CLK_TCK);
240 double jiffytime = 1.0 / jiffy;
241
242 double realTime = t * jiffytime;
243 int iRealTime = (int) realTime;
244
245 int hours = iRealTime / 3600;
246 int minutes = (iRealTime / 60) % 60;
247 int seconds = iRealTime % 60;
248 int hundredths = (realTime - iRealTime) * 100;
249 char buffer[11];
250 if (hours) {
251 snprintf(buffer, 10, "%2dh", hours);
252 RichString_append(str, CRT_colors[LARGE_NUMBER], buffer);
253 snprintf(buffer, 10, "%02d:%02d ", minutes, seconds);
254 } else {
255 snprintf(buffer, 10, "%2d:%02d.%02d ", minutes, seconds, hundredths);
256 }
257 RichString_append(str, CRT_colors[DEFAULT_COLOR], buffer);
258}
259
Hisham Muhammad93f091c2008-03-08 23:39:48 +0000260static inline void Process_writeCommand(Process* this, int attr, int baseattr, RichString* str) {
Hisham Muhammad8fa33dc2008-03-09 02:33:23 +0000261 int start = str->len;
262 RichString_append(str, attr, this->comm);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000263 if (this->pl->highlightBaseName) {
Hisham Muhammad8fa33dc2008-03-09 02:33:23 +0000264 int finish = str->len - 1;
265 int space = RichString_findChar(str, ' ', start);
266 if (space != -1)
267 finish = space - 1;
268 for (;;) {
269 int slash = RichString_findChar(str, '/', start);
270 if (slash == -1 || slash > finish)
271 break;
272 start = slash + 1;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000273 }
Hisham Muhammad8fa33dc2008-03-09 02:33:23 +0000274 RichString_setAttrn(str, baseattr, start, finish);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000275 }
276}
277
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000278static inline void Process_outputRate(Process* this, RichString* str, int attr, char* buffer, int n, double rate) {
279 rate = rate / 1024;
280 if (rate < 0.01)
281 snprintf(buffer, n, " 0 ");
282 else if (rate <= 10)
283 snprintf(buffer, n, "%5.2f ", rate);
284 else if (rate <= 100)
285 snprintf(buffer, n, "%5.1f ", rate);
286 else {
287 Process_printLargeNumber(this, str, rate);
288 return;
289 }
290 RichString_append(str, attr, buffer);
291}
292
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000293static void Process_writeField(Process* this, RichString* str, ProcessField field) {
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000294 char buffer[PROCESS_COMM_LEN];
295 int attr = CRT_colors[DEFAULT_COLOR];
Hisham Muhammad93f091c2008-03-08 23:39:48 +0000296 int baseattr = CRT_colors[PROCESS_BASENAME];
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000297 int n = PROCESS_COMM_LEN;
298
299 switch (field) {
Hisham Muhammada227b202007-04-05 19:53:23 +0000300 case PID: snprintf(buffer, n, "%5u ", this->pid); break;
301 case PPID: snprintf(buffer, n, "%5u ", this->ppid); break;
302 case PGRP: snprintf(buffer, n, "%5u ", this->pgrp); break;
303 case SESSION: snprintf(buffer, n, "%5u ", this->session); break;
304 case TTY_NR: snprintf(buffer, n, "%5u ", this->tty_nr); break;
Hisham Muhammada7c2aed2007-11-08 23:23:01 +0000305 case TGID: snprintf(buffer, n, "%5u ", this->tgid); break;
306 case TPGID: snprintf(buffer, n, "%5d ", this->tpgid); break;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000307 case PROCESSOR: snprintf(buffer, n, "%3d ", this->processor+1); break;
Hisham Muhammadd357c672007-05-21 19:10:53 +0000308 case NLWP: snprintf(buffer, n, "%4ld ", this->nlwp); break;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000309 case COMM: {
Hisham Muhammadef318932010-02-22 20:57:25 +0000310 if (this->pl->highlightThreads && Process_isThread(this)) {
Hisham Muhammad93f091c2008-03-08 23:39:48 +0000311 attr = CRT_colors[PROCESS_THREAD];
312 baseattr = CRT_colors[PROCESS_THREAD_BASENAME];
313 }
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000314 if (!this->pl->treeView || this->indent == 0) {
Hisham Muhammad93f091c2008-03-08 23:39:48 +0000315 Process_writeCommand(this, attr, baseattr, str);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000316 return;
317 } else {
318 char* buf = buffer;
319 int maxIndent = 0;
320 for (int i = 0; i < 32; i++)
321 if (this->indent & (1 << i))
322 maxIndent = i+1;
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000323 for (int i = 0; i < maxIndent - 1; i++) {
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000324 if (this->indent & (1 << i))
325 snprintf(buf, n, " | ");
326 else
327 snprintf(buf, n, " ");
328 buf += 4;
329 n -= 4;
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000330 }
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000331 if (this->pl->direction == 1)
332 snprintf(buf, n, " `- ");
333 else
334 snprintf(buf, n, " ,- ");
335 RichString_append(str, CRT_colors[PROCESS_TREE], buffer);
Hisham Muhammad93f091c2008-03-08 23:39:48 +0000336 Process_writeCommand(this, attr, baseattr, str);
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000337 return;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000338 }
339 }
340 case STATE: {
341 snprintf(buffer, n, "%c ", this->state);
342 attr = this->state == 'R'
343 ? CRT_colors[PROCESS_R_STATE]
344 : attr;
345 break;
346 }
347 case PRIORITY: {
348 if(this->priority == -100)
349 snprintf(buffer, n, " RT ");
350 else
351 snprintf(buffer, n, "%3ld ", this->priority);
352 break;
353 }
354 case NICE: {
355 snprintf(buffer, n, "%3ld ", this->nice);
356 attr = this->nice < 0 ? CRT_colors[PROCESS_HIGH_PRIORITY]
357 : this->nice > 0 ? CRT_colors[PROCESS_LOW_PRIORITY]
358 : attr;
359 break;
360 }
Hisham Muhammad3b950e42009-03-11 13:15:43 +0000361 case M_DRS: Process_printLargeNumber(this, str, this->m_drs * PAGE_SIZE_KB); return;
362 case M_DT: Process_printLargeNumber(this, str, this->m_dt * PAGE_SIZE_KB); return;
363 case M_LRS: Process_printLargeNumber(this, str, this->m_lrs * PAGE_SIZE_KB); return;
364 case M_TRS: Process_printLargeNumber(this, str, this->m_trs * PAGE_SIZE_KB); return;
365 case M_SIZE: Process_printLargeNumber(this, str, this->m_size * PAGE_SIZE_KB); return;
366 case M_RESIDENT: Process_printLargeNumber(this, str, this->m_resident * PAGE_SIZE_KB); return;
367 case M_SHARE: Process_printLargeNumber(this, str, this->m_share * PAGE_SIZE_KB); return;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000368 case ST_UID: snprintf(buffer, n, "%4d ", this->st_uid); break;
369 case USER: {
Hisham Muhammad02a30bf2010-02-25 01:43:18 +0000370 if (Process_getuid != (int) this->st_uid)
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000371 attr = CRT_colors[PROCESS_SHADOW];
Hisham Muhammadeb2803c2006-07-12 01:35:59 +0000372 if (this->user) {
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000373 snprintf(buffer, n, "%-8s ", this->user);
Hisham Muhammadeb2803c2006-07-12 01:35:59 +0000374 } else {
375 snprintf(buffer, n, "%-8d ", this->st_uid);
376 }
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000377 if (buffer[8] != '\0') {
378 buffer[8] = ' ';
379 buffer[9] = '\0';
380 }
381 break;
382 }
383 case UTIME: Process_printTime(str, this->utime); return;
384 case STIME: Process_printTime(str, this->stime); return;
385 case CUTIME: Process_printTime(str, this->cutime); return;
386 case CSTIME: Process_printTime(str, this->cstime); return;
387 case TIME: Process_printTime(str, this->utime + this->stime); return;
388 case PERCENT_CPU: {
Hisham Muhammad93f091c2008-03-08 23:39:48 +0000389 if (this->percent_cpu > 999.9) {
390 snprintf(buffer, n, "%4d ", (unsigned int)this->percent_cpu);
391 } else if (this->percent_cpu > 99.9) {
392 snprintf(buffer, n, "%3d. ", (unsigned int)this->percent_cpu);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000393 } else {
394 snprintf(buffer, n, "%4.1f ", this->percent_cpu);
395 }
396 break;
397 }
398 case PERCENT_MEM: {
399 if (this->percent_mem > 99.9) {
400 snprintf(buffer, n, "100. ");
401 } else {
402 snprintf(buffer, n, "%4.1f ", this->percent_mem);
403 }
404 break;
405 }
Hisham Muhammad4c51ad02007-08-10 05:07:14 +0000406 #ifdef HAVE_OPENVZ
Hisham Muhammadb93e5c02009-03-11 13:05:19 +0000407 case CTID: snprintf(buffer, n, "%5u ", this->ctid); break;
Hisham Muhammad4c51ad02007-08-10 05:07:14 +0000408 case VPID: snprintf(buffer, n, "%5u ", this->vpid); break;
409 #endif
Hisham Muhammada5dfaa22008-09-23 04:31:13 +0000410 #ifdef HAVE_VSERVER
411 case VXID: snprintf(buffer, n, "%5u ", this->vxid); break;
412 #endif
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000413 #ifdef HAVE_TASKSTATS
414 case RCHAR: snprintf(buffer, n, "%10llu ", this->io_rchar); break;
415 case WCHAR: snprintf(buffer, n, "%10llu ", this->io_wchar); break;
416 case SYSCR: snprintf(buffer, n, "%10llu ", this->io_syscr); break;
417 case SYSCW: snprintf(buffer, n, "%10llu ", this->io_syscw); break;
418 case RBYTES: snprintf(buffer, n, "%10llu ", this->io_read_bytes); break;
419 case WBYTES: snprintf(buffer, n, "%10llu ", this->io_write_bytes); break;
420 case CNCLWB: snprintf(buffer, n, "%10llu ", this->io_cancelled_write_bytes); break;
Hisham Muhammad2338ad52008-03-14 18:50:49 +0000421 case IO_READ_RATE: Process_outputRate(this, str, attr, buffer, n, this->io_rate_read_bps); return;
422 case IO_WRITE_RATE: Process_outputRate(this, str, attr, buffer, n, this->io_rate_write_bps); return;
423 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 +0000424 #endif
425
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000426 default:
427 snprintf(buffer, n, "- ");
428 }
429 RichString_append(str, attr, buffer);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000430}
431
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000432static void Process_display(Object* cast, RichString* out) {
433 Process* this = (Process*) cast;
434 ProcessField* fields = this->pl->fields;
435 RichString_init(out);
436 for (int i = 0; fields[i]; i++)
437 Process_writeField(this, out, fields[i]);
Hisham Muhammad02a30bf2010-02-25 01:43:18 +0000438 if (this->pl->shadowOtherUsers && (int)this->st_uid != Process_getuid)
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000439 RichString_setAttr(out, CRT_colors[PROCESS_SHADOW]);
440 if (this->tag == true)
441 RichString_setAttr(out, CRT_colors[PROCESS_TAG]);
442 assert(out->len > 0);
443}
444
445void Process_delete(Object* cast) {
446 Process* this = (Process*) cast;
447 assert (this != NULL);
448 if (this->comm) free(this->comm);
449 free(this);
450}
451
452Process* Process_new(struct ProcessList_ *pl) {
453 Process* this = calloc(sizeof(Process), 1);
454 Object_setClass(this, PROCESS_CLASS);
455 ((Object*)this)->display = Process_display;
456 ((Object*)this)->delete = Process_delete;
457 this->pid = 0;
458 this->pl = pl;
459 this->tag = false;
460 this->updated = false;
461 this->utime = 0;
462 this->stime = 0;
463 this->comm = NULL;
464 this->indent = 0;
465 if (Process_getuid == -1) Process_getuid = getuid();
466 return this;
467}
468
469Process* Process_clone(Process* this) {
Hisham Muhammad02a30bf2010-02-25 01:43:18 +0000470 Process* copy = malloc(sizeof(Process));
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000471 #if HAVE_TASKSTATS
472 this->io_rchar = 0;
473 this->io_wchar = 0;
474 this->io_syscr = 0;
475 this->io_syscw = 0;
476 this->io_read_bytes = 0;
477 this->io_rate_read_bps = 0;
478 this->io_rate_read_time = 0;
479 this->io_write_bytes = 0;
480 this->io_rate_write_bps = 0;
481 this->io_rate_write_time = 0;
482 this->io_cancelled_write_bytes = 0;
483 #endif
Hisham Muhammad02a30bf2010-02-25 01:43:18 +0000484 memcpy(copy, this, sizeof(Process));
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000485 this->comm = NULL;
486 this->pid = 0;
Hisham Muhammad02a30bf2010-02-25 01:43:18 +0000487 return copy;
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000488}
489
490void Process_toggleTag(Process* this) {
491 this->tag = this->tag == true ? false : true;
492}
493
494bool Process_setPriority(Process* this, int priority) {
495 int old_prio = getpriority(PRIO_PROCESS, this->pid);
496 int err = setpriority(PRIO_PROCESS, this->pid, priority);
497 if (err == 0 && old_prio != getpriority(PRIO_PROCESS, this->pid)) {
498 this->nice = priority;
499 }
500 return (err == 0);
501}
502
Hisham Muhammad3b950e42009-03-11 13:15:43 +0000503#ifdef HAVE_PLPA
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000504unsigned long Process_getAffinity(Process* this) {
505 unsigned long mask = 0;
506 plpa_sched_getaffinity(this->pid, sizeof(unsigned long), (plpa_cpu_set_t*) &mask);
507 return mask;
508}
509
510bool Process_setAffinity(Process* this, unsigned long mask) {
511 return (plpa_sched_setaffinity(this->pid, sizeof(unsigned long), (plpa_cpu_set_t*) &mask) == 0);
512}
Hisham Muhammad3b950e42009-03-11 13:15:43 +0000513#endif
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000514
Hisham Muhammad02a30bf2010-02-25 01:43:18 +0000515void Process_sendSignal(Process* this, int sgn) {
516 kill(this->pid, sgn);
Hisham Muhammadda23c8c2008-03-09 08:58:38 +0000517}
518
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000519int Process_pidCompare(const void* v1, const void* v2) {
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000520 Process* p1 = (Process*)v1;
521 Process* p2 = (Process*)v2;
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000522 return (p1->pid - p2->pid);
523}
524
525int Process_compare(const void* v1, const void* v2) {
526 Process *p1, *p2;
527 ProcessList *pl = ((Process*)v1)->pl;
528 if (pl->direction == 1) {
529 p1 = (Process*)v1;
530 p2 = (Process*)v2;
531 } else {
532 p2 = (Process*)v1;
533 p1 = (Process*)v2;
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000534 }
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000535 long long diff;
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000536 switch (pl->sortKey) {
537 case PID:
538 return (p1->pid - p2->pid);
539 case PPID:
540 return (p1->ppid - p2->ppid);
541 case USER:
Hisham Muhammad6330ff32009-06-02 04:51:23 +0000542 return strcmp(p1->user ? p1->user : "", p2->user ? p2->user : "");
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000543 case PRIORITY:
544 return (p1->priority - p2->priority);
Hisham Muhammad843aded2009-03-11 13:52:39 +0000545 case PROCESSOR:
546 return (p1->processor - p2->processor);
547 case SESSION:
548 return (p1->session - p2->session);
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000549 case STATE:
550 return (p1->state - p2->state);
551 case NICE:
552 return (p1->nice - p2->nice);
Hisham Muhammadf56c8012007-04-05 20:13:32 +0000553 case M_DRS:
554 return (p2->m_drs - p1->m_drs);
555 case M_DT:
556 return (p2->m_dt - p1->m_dt);
557 case M_LRS:
558 return (p2->m_lrs - p1->m_lrs);
559 case M_TRS:
560 return (p2->m_trs - p1->m_trs);
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000561 case M_SIZE:
562 return (p2->m_size - p1->m_size);
563 case M_RESIDENT:
564 return (p2->m_resident - p1->m_resident);
565 case M_SHARE:
566 return (p2->m_share - p1->m_share);
567 case PERCENT_CPU:
568 return (p2->percent_cpu > p1->percent_cpu ? 1 : -1);
569 case PERCENT_MEM:
570 return (p2->m_resident - p1->m_resident);
571 case UTIME:
572 return (p2->utime - p1->utime);
573 case STIME:
574 return (p2->stime - p1->stime);
575 case TIME:
576 return ((p2->utime+p2->stime) - (p1->utime+p1->stime));
577 case COMM:
578 return strcmp(p1->comm, p2->comm);
Hisham Muhammadd357c672007-05-21 19:10:53 +0000579 case NLWP:
580 return (p1->nlwp - p2->nlwp);
Hisham Muhammad4c51ad02007-08-10 05:07:14 +0000581 #ifdef HAVE_OPENVZ
Hisham Muhammadb93e5c02009-03-11 13:05:19 +0000582 case CTID:
583 return (p1->ctid - p2->ctid);
Hisham Muhammad4c51ad02007-08-10 05:07:14 +0000584 case VPID:
585 return (p1->vpid - p2->vpid);
586 #endif
Hisham Muhammada5dfaa22008-09-23 04:31:13 +0000587 #ifdef HAVE_VSERVER
588 case VXID:
589 return (p1->vxid - p2->vxid);
590 #endif
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000591 #ifdef HAVE_TASKSTATS
592 case RCHAR: diff = p2->io_rchar - p1->io_rchar; goto test_diff;
593 case WCHAR: diff = p2->io_wchar - p1->io_wchar; goto test_diff;
594 case SYSCR: diff = p2->io_syscr - p1->io_syscr; goto test_diff;
595 case SYSCW: diff = p2->io_syscw - p1->io_syscw; goto test_diff;
596 case RBYTES: diff = p2->io_read_bytes - p1->io_read_bytes; goto test_diff;
597 case WBYTES: diff = p2->io_write_bytes - p1->io_write_bytes; goto test_diff;
598 case CNCLWB: diff = p2->io_cancelled_write_bytes - p1->io_cancelled_write_bytes; goto test_diff;
599 case IO_READ_RATE: diff = p2->io_rate_read_bps - p1->io_rate_read_bps; goto test_diff;
600 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 +0000601 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 +0000602 #endif
603
Hisham Muhammad5d48ab82006-07-11 06:13:32 +0000604 default:
605 return (p1->pid - p2->pid);
606 }
Hisham Muhammad12f4f092008-03-09 08:02:22 +0000607 test_diff:
608 return (diff > 0) ? 1 : (diff < 0 ? -1 : 0);
Hisham Muhammadd6231ba2006-03-04 18:16:49 +0000609}