2 /* Author: Ben Gras <beng@few.vu.nl> 17 march 2006 */
5 #define _POSIX_SOURCE 1
22 #include <sys/ioc_tty.h>
23 #include <sys/times.h>
24 #include <sys/types.h>
26 #include <sys/select.h>
28 #include <minix/ipc.h>
29 #include <minix/com.h>
30 #include <minix/sysinfo.h>
31 #include <minix/config.h>
32 #include <minix/type.h>
33 #include <minix/const.h>
35 #include "../../kernel/arch/i386/include/archtypes.h"
36 #include "../../servers/pm/mproc.h"
37 #include "../../kernel/const.h"
38 #include "../../kernel/proc.h"
42 #define TC_BUFFER 1024 /* Size of termcap(3) buffer */
43 #define TC_STRINGS 200 /* Enough room for cm,cl,so,se */
48 int print_memory(struct pm_mem_info
*pmi
)
51 int largest_bytes
= 0, total_bytes
= 0;
52 for(h
= 0; h
< _NR_HOLES
; h
++) {
53 if(pmi
->pmi_holes
[h
].h_base
&& pmi
->pmi_holes
[h
].h_len
) {
55 bytes
= pmi
->pmi_holes
[h
].h_len
<< CLICK_SHIFT
;
56 if(bytes
> largest_bytes
) largest_bytes
= bytes
;
61 printf("Mem: %dK Free, %dK Contiguous Free\n",
62 total_bytes
/1024, largest_bytes
/1024);
68 int print_load(double *loads
, int nloads
)
71 printf("load averages: ");
72 for(i
= 0; i
< nloads
; i
++)
73 printf("%s %.2f", (i
> 0) ? "," : "", loads
[i
]);
78 #define PROCS (NR_PROCS+NR_TASKS)
80 int print_proc_summary(struct proc
*proc
)
82 int p
, alive
, running
, sleeping
;
84 alive
= running
= sleeping
= 0;
86 for(p
= 0; p
< PROCS
; p
++) {
87 if(p
- NR_TASKS
== IDLE
)
89 if(isemptyp(&proc
[p
]))
92 if(!proc_is_runnable(&proc
[p
]))
97 printf("%d processes: %d running, %d sleeping\n",
98 alive
, running
, sleeping
);
107 int cmp_ticks(const void *v1
, const void *v2
)
109 struct tp
*p1
= (struct tp
*) v1
, *p2
= (struct tp
*) v2
;
110 if(p1
->ticks
< p2
->ticks
)
112 if(p1
->ticks
> p2
->ticks
)
114 if(p1
->p
->p_nr
< p2
->p
->p_nr
)
116 if(p1
->p
->p_nr
> p2
->p
->p_nr
)
121 void print_procs(int maxlines
,
122 struct proc
*proc1
, struct proc
*proc2
, int dt
,
125 int p
, nprocs
, tot
=0;
126 int idleticks
= 0, kernelticks
= 0, systemticks
= 0;
130 for(p
= nprocs
= 0; p
< PROCS
; p
++) {
131 if(isemptyp(&proc2
[p
]))
133 tick_procs
[nprocs
].p
= proc2
+ p
;
134 if(proc1
[p
].p_endpoint
== proc2
[p
].p_endpoint
) {
135 tick_procs
[nprocs
].ticks
=
136 proc2
[p
].p_user_time
-proc1
[p
].p_user_time
;
138 tick_procs
[nprocs
].ticks
=
139 proc2
[p
].p_user_time
;
141 if(p
-NR_TASKS
== IDLE
) {
142 idleticks
= tick_procs
[nprocs
].ticks
;
146 /* Kernel task time, not counting IDLE */
147 if(proc2
[p
].p_nr
< 0)
148 kernelticks
+= tick_procs
[nprocs
].ticks
;
149 else if(mproc
[proc2
[p
].p_nr
].mp_procgrp
== 0)
150 systemticks
+= tick_procs
[nprocs
].ticks
;
154 qsort(tick_procs
, nprocs
, sizeof(tick_procs
[0]), cmp_ticks
);
156 printf("CPU states: %6.2f%% user, %6.2f%% system, %6.2f%% kernel, %6.2f%% idle",
157 100.0*(dt
-systemticks
-kernelticks
-idleticks
)/dt
,
158 100.0*systemticks
/dt
,
159 100.0*kernelticks
/dt
,
164 printf(" PID USERNAME PRI NICE SIZE STATE TIME CPU COMMAND\n");
166 for(p
= 0; p
< nprocs
; p
++) {
171 static struct passwd
*who
= NULL
;
172 static int last_who
= -1;
174 if(maxlines
-- <= 0) break;
176 pnr
= tick_procs
[p
].p
->p_nr
;
177 pr
= tick_procs
[p
].p
;
178 ticks
= pr
->p_user_time
;
180 printf("%5d ", mproc
[pnr
].mp_pid
);
181 euid
= mproc
[pnr
].mp_effuid
;
182 name
= mproc
[pnr
].mp_name
;
184 printf("[%3d] ", pnr
);
187 if(last_who
!= euid
|| !who
) {
188 who
= getpwuid(euid
);
192 if(who
&& who
->pw_name
) printf("%-8s ", who
->pw_name
);
193 else if(pnr
>= 0) printf("%8d ", mproc
[pnr
].mp_effuid
);
196 printf(" %2d ", pr
->p_priority
);
198 printf(" %3d ", mproc
[pnr
].mp_nice
);
201 ((pr
->p_memmap
[T
].mem_len
+
202 pr
->p_memmap
[D
].mem_len
) << CLICK_SHIFT
)/1024);
203 printf("%6s", pr
->p_rts_flags
? "" : "RUN");
204 printf(" %3d:%02d ", (ticks
/system_hz
/60), (ticks
/system_hz
)%60);
206 printf("%6.2f%% %s\n",
207 100.0*tick_procs
[p
].ticks
/dt
, name
);
214 double loads
[NLOADS
];
215 int nloads
, i
, p
, lines
= 0;
216 static struct proc prev_proc
[PROCS
], proc
[PROCS
];
217 struct winsize winsize
;
219 static struct pm_mem_info pmi;
221 static int prev_uptime
, uptime
;
222 static struct mproc mproc
[NR_PROCS
];
226 uptime
= times(&tms
);
228 if(ioctl(STDIN_FILENO
, TIOCGWINSZ
, &winsize
) != 0) {
229 perror("TIOCGWINSZ");
230 fprintf(stderr
, "TIOCGWINSZ failed\n");
235 if(getsysinfo(PM_PROC_NR
, SI_MEM_ALLOC
, &pmi
) < 0) {
236 fprintf(stderr
, "getsysinfo() for SI_MEM_ALLOC failed.\n");
242 if(getsysinfo(PM_PROC_NR
, SI_KPROC_TAB
, proc
) < 0) {
243 fprintf(stderr
, "getsysinfo() for SI_KPROC_TAB failed.\n");
247 if(getsysinfo(PM_PROC_NR
, SI_PROC_TAB
, mproc
) < 0) {
248 fprintf(stderr
, "getsysinfo() for SI_PROC_TAB failed.\n");
252 if((nloads
= getloadavg(loads
, NLOADS
)) != NLOADS
) {
253 fprintf(stderr
, "getloadavg() failed - %d loads\n", nloads
);
258 printf("%s", Tclr_all
);
260 lines
+= print_load(loads
, NLOADS
);
261 lines
+= print_proc_summary(proc
);
263 if(mem
) { lines
+= print_memory(&pmi
); }
266 if(winsize
.ws_row
> 0) r
= winsize
.ws_row
;
268 print_procs(r
- lines
- 2, prev_proc
,
269 proc
, uptime
-prev_uptime
, mproc
);
271 memcpy(prev_proc
, proc
, sizeof(prev_proc
));
272 prev_uptime
= uptime
;
278 static char buffer
[TC_BUFFER
], strings
[TC_STRINGS
];
279 char *s
= strings
, *v
;
283 if(!(term
= getenv("TERM"))) {
284 fprintf(stderr
, "No TERM set\n");
288 if ( tgetent( buffer
, term
) != 1 ) {
289 fprintf(stderr
, "tgetent failed for term %s\n", term
);
293 if ( (Tclr_all
= tgetstr( "cl", &s
)) == NULL
)
296 if((v
= tgetstr ("li", &s
)) != NULL
)
297 sscanf(v
, "%d", rows
);
298 if(*rows
< 1) *rows
= 24;
300 fprintf(stderr
, "initscr() failed\n");
307 void sigwinch(int sig
) { }
309 int main(int argc
, char *argv
[])
311 int r
, c
, s
= 0, orig
;
313 getsysinfo_up(PM_PROC_NR
, SIU_SYSTEMHZ
, sizeof(system_hz
), &system_hz
);
317 while((c
=getopt(argc
, argv
, "s:")) != EOF
) {
324 "Usage: %s [-s<secdelay>]\n", argv
[0]);
332 /* Catch window size changes so display is updated properly right away. */
333 signal(SIGWINCH
, sigwinch
);
344 FD_SET(STDIN_FILENO
, &fds
);
345 if((ns
=select(STDIN_FILENO
+1, &fds
, NULL
, NULL
, &tv
)) < 0
351 if(ns
> 0 && FD_ISSET(STDIN_FILENO
, &fds
)) {
353 if(read(STDIN_FILENO
, &c
, 1) == 1) {