]> git.saurik.com Git - apple/system_cmds.git/blame - top.tproj/top.c
system_cmds-230.7.tar.gz
[apple/system_cmds.git] / top.tproj / top.c
CommitLineData
1815bff5
A
1/*
2 * Top users display for Berkeley Unix
3 * Version 1.8
4 *
5 * This program may be freely redistributed to other Unix sites, but this
6 * entire comment MUST remain intact.
7 *
8 * Copyright (c) 1984, William LeFebvre, Rice University
9 *
10 * This program is designed to run on either Berkeley 4.1 or 4.2 Unix.
11 * Compile with the preprocessor constant "FOUR_ONE" set to get an
12 * executable that will run on Berkeley 4.1 Unix.
13 *
14 * The Sun kernel uses scaled integers instead of floating point so compile
15 * with the preprocessor variable "SUN" to get an executable that will run
16 * on Sun Unix version 1.1 or later.
17 *
18 * Fixes and enhancements since version 1.5:
19 *
20 * Jonathon Feiber at sun:
21 * added "#ifdef SUN" code to make top work on a Sun,
22 * fixed race bug in getkval for getting user structure,
23 * efficiency improvements: added register variables and
24 * removed the function hashit
25 *
26 * added real and virtual memory status line
27 *
28 * added second "key" to the qsort comparisn function "proc_compar"
29 * which sorts by on cpu ticks if percentage is equal
30 *
31 **********************************************************************
32 * HISTORY
33 * 22-Apr-99 Avadis Tevanian (avie) at Apple
34 * Another rewrite for Mach 3.0
35 *
36 * 21-Apr-90 Avadis Tevanian (avie) at NeXT
37 * Completely rewritten again for processor sets.
38 *
39 * 6-May-88 David Golub (dbg) at Carnegie-Mellon University
40 * Completely rewritten for MACH. This version will NOT run on any
41 * other version of BSD.
42 *
43 */
44
45#define Default_TOPN 16 /* default number of lines */
46#define Default_DELAY 1 /* default delay interval */
47#define IOKIT 1 /* for io_name_t in device_types.h */
48
49#include <mach/mach.h>
50#include <stdlib.h>
51#include <stdio.h>
52#include <signal.h>
53#include <strings.h>
54#include <nlist.h>
55#include <fcntl.h>
56#include <string.h>
57
58#include <sys/types.h>
59#include <sys/param.h>
60#include <sys/sysctl.h>
61#include <sys/time.h>
62
63#include <mach/bootstrap.h>
64#include <mach/host_info.h>
65#include <mach/mach_error.h>
66#include <mach/mach_types.h>
67#include <mach/message.h>
68#include <mach/vm_region.h>
69#include <mach/vm_map.h>
70#include <mach/vm_types.h>
71#include <mach/vm_prot.h>
b51d5b5f 72#include <mach/shared_memory_server.h>
1815bff5
A
73
74#include <device/device_types.h>
75#include <CoreFoundation/CoreFoundation.h>
76#include <IOKit/IOKitLib.h>
77#include <IOKit/storage/IOBlockStorageDriver.h>
78
79#include <kvm.h>
80#include <sys/socket.h>
81#include <net/if.h>
82#include <net/if_var.h>
83
84#include <libc.h>
85#include <termios.h>
b51d5b5f
A
86#include <curses.h>
87#include <sys/ioctl.h>
1815bff5
A
88
89/* Number of lines of header information on the standard screen */
90#define HEADER_LINES 8
91
92#define sec_to_minutes(t) ((t) / 60)
93#define sec_to_seconds(t) ((t) % 60)
94#define usec_to_100ths(t) ((t) / 10000)
95
96#ifndef TH_USAGE_SCALE
97#define TH_USAGE_SCALE 1000
98#endif TH_USAGE_SCALE
99#define usage_to_percent(u) ((u*100)/TH_USAGE_SCALE)
100#define usage_to_tenths(u) (((u*1000)/TH_USAGE_SCALE) % 10)
101
102
103#define time_value_sub(tvp, uvp, vvp) \
104 do { \
105 (vvp)->seconds = (tvp)->seconds - (uvp)->seconds; \
106 (vvp)->microseconds = (tvp)->microseconds - (uvp)->microseconds; \
107 if ((vvp)->microseconds < 0) { \
108 (vvp)->seconds--; \
109 (vvp)->microseconds += 1000000; \
110 } \
111 } while (0)
112
113
114
115/* From libcurses */
116int wclear(WINDOW *win);
117int wmove(WINDOW *win, int y, int x);
118int wrefresh(WINDOW *win);
119int endwin(void);
120int werase(WINDOW *win);
121
122int total_threads;
123unsigned long long total_fw_private;
124
1815bff5
A
125char bytesread[128];
126
127host_cpu_load_info_data_t lastcounters, curcounters, startcounters;
128double userticks, systicks, idleticks, totalticks;
129
130struct timeval cur_tod;
131struct timeval start_tod;
132struct timeval last_tod;
133struct timeval elapsed_tod;
134int elapsed_milliseconds;
135int newLINES = 0;
136int Header_lines = HEADER_LINES;
137
138int do_proc0_vm;
139int sort_by_usage;
140int wide_output;
141int oneshot;
142int logcnt;
143int events_only;
144int events_delta;
145int events_accumulate;
146long start_time = 0;
147
148
149struct io_stats {
150 UInt64 io_accum;
151 UInt64 io_prev;
152 UInt64 io;
153 UInt64 kbytes_accum;
154 UInt64 kbytes_prev;
155 UInt64 kbytes;
156};
157
158struct io_stats i_net, o_net;
159struct io_stats i_dsk, o_dsk;
160struct io_stats i_vm, o_vm;
161
162
163io_iterator_t drivelist = 0; /* needs release */
164mach_port_t masterPort = 0;
165
166
167struct proc_info {
168 uid_t uid;
169 short pid;
170 short ppid;
171 short pgrp;
172 int status;
173 int flag;
174
175 int state;
176 int pri;
177 int base_pri;
178 boolean_t all_swapped;
179 boolean_t has_idle_thread;
180 time_value_t total_time;
181 time_value_t idle_time;
182 time_value_t beg_total_time;
183 time_value_t beg_idle_time;
184
185 vm_size_t virtual_size;
186 vm_size_t resident_size;
187 vm_size_t orig_virtual_size;
188 vm_offset_t drsize, dvsize;
189 vm_offset_t drprvt, drshrd;
190 vm_offset_t rvsize;
191 unsigned int shared;
192 unsigned int private;
193 unsigned int vprivate;
194 int obj_count;
195 int cpu_usage;
196 int cpu_idle;
197
198 char command[20];
199
200 int num_ports;
201 int orig_num_ports;
202 int dnum_ports;
203 int num_threads;
204 thread_basic_info_t threads; /* array */
205 task_events_info_data_t tei;
206 task_events_info_data_t deltatei;
207 task_events_info_data_t accumtei;
208};
209
210typedef struct proc_info *proc_info_t;
211
212mach_port_t host_priv_port, host_port;
213
214struct object_info {
215 int id;
216 int pid;
217 int share_type;
218 int resident_page_count;
219 int ref_count;
220 int task_ref_count;
221 int size;
222 struct object_info *next;
223};
224
225#define OBJECT_TABLE_SIZE 537
226#define OT_HASH(object) (((unsigned)object)%OBJECT_TABLE_SIZE)
227
228struct object_info *shared_hash_table[OBJECT_TABLE_SIZE];
229
230struct object_info *of_free_list = 0;
231
1815bff5
A
232/*
233 * Translate thread state to a number in an ordered scale.
234 * When collapsing all the threads' states to one for the
235 * entire task, the lower-numbered state dominates.
236 */
237#define STATE_MAX 7
238
239int
240mach_state_order(s, sleep_time)
241 int s;
242 long sleep_time;
243 {
244 switch (s) {
245 case TH_STATE_RUNNING: return(1);
246 case TH_STATE_UNINTERRUPTIBLE:
247 return(2);
248 case TH_STATE_WAITING: return((sleep_time > 20) ? 4 : 3);
249 case TH_STATE_STOPPED: return(5);
250 case TH_STATE_HALTED: return(6);
251 default: return(7);
252 }
253}
254 /*01234567 */
255char mach_state_table[] = "ZRUSITH?";
256
257char * state_name[] = {
258 "zombie",
259 "running",
260 "stuck",
261 "sleeping",
262 "idle",
263 "stopped",
264 "halted",
265 "unknown",
266};
267int state_breakdown[STATE_MAX+1];
268
269
270char *state_to_string(pi)
271 proc_info_t pi;
272{
273 static char s[5]; /* STATIC! */
274
275 s[0] = mach_state_table[pi->state];
276 s[1] = (pi->all_swapped) ? 'W' : ' ';
277 s[2] = (pi->base_pri > 50) ? 'N' :
278 (pi->base_pri < 40) ? '<' : ' ';
279 s[3] = ' ';
280 s[4] = '\0';
281 return(s);
282}
283
284void print_time(char *p, time_value_t t)
285{
286 long seconds, useconds, minutes, hours;
287
288 seconds = t.seconds;
289 useconds = t.microseconds;
290 minutes = seconds / 60;
291 hours = minutes / 60;
292
293 if (minutes < 100) { // up to 100 minutes
294 sprintf(p, "%2ld:%02ld.%02ld", minutes, seconds % 60,
295 usec_to_100ths(useconds));
296 }
297 else if (hours < 100) { // up to 100 hours
298 sprintf(p, "%2ld:%02ld:%02ld", hours, minutes % 60,
299 seconds % 60);
300 }
301 else {
302 sprintf(p, "%4ld hrs", hours);
303 }
304}
305
306
307void
308print_usage(char *p, int cpu_usage)
309{
310 int left_of_decimal;
311 int right_of_decimal;
312
313 if (elapsed_milliseconds) {
314 left_of_decimal = (cpu_usage * 100) / elapsed_milliseconds;
315
316 right_of_decimal = (((cpu_usage * 100) - (left_of_decimal * elapsed_milliseconds)) * 10) /
317 elapsed_milliseconds;
318 } else {
319 left_of_decimal = 0;
320 right_of_decimal = 0;
321 }
322 sprintf(p, "%3d.%01d%%%%", left_of_decimal, right_of_decimal); /* %cpu */
323}
324
325
326
327char *
328digits(n)
329 float n;
330{
331 static char tmp[10]; /* STATIC! */
332
333 if ((n > 0) && (n < 10))
334 sprintf(tmp, "%4.2f", n);
335 else if ((n > 0) && (n < 100))
336 sprintf(tmp, "%4.1f", n);
337 else if ((n < 0) && (n > -10))
338 sprintf(tmp, "%4.1f", n);
339 else
340 sprintf(tmp, "%4.0f", n);
341 return(tmp);
342}
343
344char *
345mem_to_string(n)
346 unsigned long long n;
347{
348 static char s[10]; /* STATIC! */
349
350 /* convert to kilobytes */
351 n /= 1024;
352
353 if (n > 1024*1024)
354 sprintf(s, "%sG", digits(((float)n)/(1024.0*1024.0)));
355 else if (n > 1024)
356 sprintf(s, "%sM", digits((float)n/(1024.0)));
357 else
358 sprintf(s, "%dK", (int)n);
359
360 return(s);
361}
362
363char *
364offset_to_string(n)
365 int n;
366{
367 static char s[10]; /* STATIC! */
368 int an;
369
370 /* convert to kilobytes */
371 n /= 1024;
372 an = abs(n);
373
374 if (an > 1024*1024)
375 sprintf(s, "%sG", digits(((float)n)/(1024.0*1024.0)));
376 else if (an > 1024)
377 sprintf(s, "%sM", digits((float)n/(1024.0)));
378 else
379 sprintf(s, "%dK", n);
380
381 return(s);
382}
383
384mach_port_t get_host_priv()
385{
386 return(mach_host_self());
387}
388
389mach_port_t get_host_port()
390{
391 return(mach_host_self());
392}
393
394void
395shared_hash_enter(int obj_id, int share_type, int resident_page_count, int ref_count, int size, int pid)
396{
397 register struct object_info **bucket;
398 register struct object_info *of;
399
400 of = shared_hash_table[OT_HASH(obj_id/OBJECT_TABLE_SIZE)];
401 while (of) {
402 if (of->id == obj_id) {
403 of->size += size;
404 of->task_ref_count++;
405 of->pid = pid;
406 return;
407 }
408 of = of->next;
409 }
410 bucket = &shared_hash_table[OT_HASH(obj_id/OBJECT_TABLE_SIZE)];
411
412 if (of = of_free_list)
413 of_free_list = of->next;
414 else
415 of = (struct object_info *) malloc(sizeof(*of));
416
417 of->resident_page_count = resident_page_count;
418 of->id = obj_id;
419 of->share_type = share_type;
420 of->ref_count = ref_count;
421 of->task_ref_count = 1;
422 of->pid = pid;
423 of->size = size;
424
425 of->next = *bucket;
426 *bucket = of;
427}
428
429void
430pmem_doit(task_port_t task, int pid, int *shared, int *private, int *aliased, int *obj_count, int *vprivate, vm_size_t *vsize, unsigned long long *fw_private)
431{
432 vm_address_t address = 0;
433 kern_return_t err = 0;
434 register int i;
435 int split = 0;
436
437 *obj_count = *aliased = *shared = *private = *vprivate = 0;
438
439 while (1) {
440 mach_port_t object_name;
441 vm_region_top_info_data_t info;
442 mach_msg_type_number_t count;
443 vm_size_t size;
444
1815bff5
A
445 count = VM_REGION_TOP_INFO_COUNT;
446
447 if (err = vm_region(task, &address, &size, VM_REGION_TOP_INFO, (vm_region_info_t)&info,
448 &count, &object_name))
449 break;
450
b51d5b5f 451 if (address >= GLOBAL_SHARED_TEXT_SEGMENT && address < (GLOBAL_SHARED_DATA_SEGMENT + SHARED_DATA_REGION_SIZE)) {
1815bff5
A
452
453 *fw_private += info.private_pages_resident * vm_page_size;
454
1c51fdde
A
455 if ( !split && info.share_mode == SM_EMPTY) {
456 vm_region_basic_info_data_64_t b_info;
457
458 count = VM_REGION_BASIC_INFO_COUNT_64;
459 if (err = vm_region_64(task, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)&b_info,
460 &count, &object_name))
461 break;
462
463 if (b_info.reserved)
464 split = 1;
465 }
1815bff5
A
466 if (info.share_mode != SM_PRIVATE) {
467 address += size;
468 continue;
469 }
470 }
471 address += size;
472
473 *obj_count += 1;
474
475 switch (info.share_mode) {
476
477 case SM_PRIVATE:
478 *private += info.private_pages_resident * vm_page_size;
479 *vprivate += size;
480 break;
481
482 case SM_COW:
483 if (info.ref_count == 1)
484 info.share_mode = SM_PRIVATE;
485 if (pid && info.share_mode == SM_COW)
486 shared_hash_enter(info.obj_id, SM_COW, info.shared_pages_resident,
487 info.ref_count, size, pid);
488 if (info.share_mode == SM_PRIVATE)
489 *private += info.shared_pages_resident * vm_page_size;
490 *private += info.private_pages_resident * vm_page_size;
491
492 if (info.share_mode == SM_PRIVATE)
493 *vprivate += size;
494 else
495 *vprivate += info.private_pages_resident * vm_page_size;
496 break;
497
498 case SM_SHARED:
499 if (pid)
500 shared_hash_enter(info.obj_id, SM_SHARED, info.shared_pages_resident,
501 info.ref_count, size, pid);
502 break;
503 }
504 }
505 for (i = 0; i < OBJECT_TABLE_SIZE; i++) {
506 register struct object_info *sl;
507
508 sl = shared_hash_table[i];
509
510 while (sl) {
511 if (sl->pid == pid) {
512 if (sl->share_type == SM_SHARED) {
513 if (sl->ref_count == sl->task_ref_count) {
514 sl->share_type = SM_PRIVATE_ALIASED;
515
516 *aliased += sl->resident_page_count * vm_page_size;
517 *vprivate += sl->size;
518 }
519 }
520 if (sl->share_type != SM_PRIVATE_ALIASED)
521 *shared += sl->resident_page_count * vm_page_size;
522 }
523 sl->task_ref_count = 0;
524
525 sl = sl->next;
526 }
527 }
528 if (split)
b51d5b5f 529 *vsize -= (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE);
1815bff5
A
530}
531
532
533void
534pmem_fw_resident(unsigned int *num_fw, unsigned long long *vsize, unsigned int *code_size, unsigned int *data_size, unsigned int *linkedit_size)
b51d5b5f 535{ vm_address_t address = GLOBAL_SHARED_TEXT_SEGMENT;
1815bff5
A
536 kern_return_t err = 0;
537 int state = 0;
538
539 *vsize = 0;
540 *num_fw = 0;
541 *code_size = 0;
542 *data_size = 0;
543 *linkedit_size = 0;
544
b51d5b5f 545 while (address < (GLOBAL_SHARED_DATA_SEGMENT + SHARED_DATA_REGION_SIZE)) {
1815bff5
A
546 vm_region_submap_info_data_64_t s_info;
547 mach_msg_type_number_t count;
548 vm_size_t size;
549 int nesting_depth;
550
551 nesting_depth = 1;
552 count = VM_REGION_SUBMAP_INFO_COUNT_64;
553
554 if (err = vm_region_recurse_64(mach_task_self(), &address, &size, &nesting_depth, (vm_region_info_t)&s_info, &count))
555 break;
556
b51d5b5f 557 if (address >= (GLOBAL_SHARED_DATA_SEGMENT + SHARED_DATA_REGION_SIZE))
1815bff5 558 break;
b51d5b5f 559 if (address < GLOBAL_SHARED_DATA_SEGMENT) {
1815bff5
A
560
561 if (s_info.share_mode == SM_SHARED || s_info.share_mode == SM_COW) {
562 if (s_info.max_protection & VM_PROT_EXECUTE) {
563 *code_size += (s_info.pages_resident * vm_page_size);
564
565 if (state == 0)
566 *num_fw += 1;
567 state = 1;
568
569 } else {
570 *linkedit_size += (s_info.pages_resident * vm_page_size);
571
572 state = 0;
573 }
574 }
575
576 } else {
577 if (s_info.share_mode == SM_SHARED || s_info.share_mode == SM_COW || s_info.share_mode == SM_TRUESHARED)
578 *data_size += (s_info.pages_resident * vm_page_size);
579 }
580 *vsize += size;
581
582 address += size;
583 }
584}
585
586
587
588
589void
590pmem_shared_resident(unsigned long long *total, int *number)
591{ register int i;
592 register int total_size;
593 register int total_num;
594 register struct object_info *sl, *next;
595
596 total_size = total_num = 0;
597
598 for (i = 0; i < OBJECT_TABLE_SIZE; i++) {
599 sl = shared_hash_table[i];
600 shared_hash_table[i] = 0;
601
602 while (sl) {
603 if (sl->share_type != SM_PRIVATE_ALIASED) {
604 total_size += sl->resident_page_count;
605 total_num++;
606 }
607 next = sl->next;
608
609 sl->next = of_free_list;
610 of_free_list = sl;
611
612 sl = next;
613 }
614 }
615 *number = total_num;
616 *total = total_size * vm_page_size;
617}
618
619
620int
621get_real_command_name(int pid, char *cbuf, int csize)
622{
623 /*
624 * Get command and arguments.
625 */
626 volatile int *ip, *savedip;
627 volatile char *cp;
628 char c;
629 char *end_argc;
630 int mib[4];
631 char *arguments;
632 int arguments_size = 4096;
633 volatile unsigned int *valuep;
634 unsigned int value;
635 int blahlen=0, skiplen=0;
636
637 /*
638 * A sysctl() is made to find out the full path that the command
639 * was called with.
640 */
641 mib[0] = CTL_KERN;
642 mib[1] = KERN_PROCARGS;
643 mib[2] = pid;
644 mib[3] = 0;
645
646 arguments = (char *) malloc(arguments_size);
647 if (sysctl(mib, 3, arguments, (size_t *)&arguments_size, NULL, 0) < 0) {
648 free(arguments);
649 return(0);
650 }
651 end_argc = &arguments[arguments_size];
652
653 ip = (int *)end_argc;
654 ip -= 2; /* last arg word and .long 0 */
655 while (*--ip) {
656 if (ip == (int *)arguments) {
657 free(arguments);
658 return(0);
659 }
660 }
661 savedip = ip;
662 savedip++;
663 cp = (char *)savedip;
664 while (*--ip) {
665 if (ip == (int *)arguments) {
666 free(arguments);
667 return(0);
668 }
669 }
670 ip++;
671 valuep = (unsigned int *)ip;
672 value = *valuep;
673
674 if ((value & 0xbfff0000) == 0xbfff0000) {
675 ip++; ip++;
676 valuep = ip;
677 blahlen = strlen((char *)ip);
678 skiplen = (blahlen +3 ) /4 ;
679 valuep += skiplen;
680 cp = (char *)valuep;
681 while (!*cp)
682 cp++;
683 savedip = (int *)cp;
684 }
685 for (cp = (char *)savedip; cp < (end_argc-1); cp++) {
686 c = *cp & 0177;
687
688 if (c == 0)
689 break;
690 }
691 *cp = 0;
692
693 if (cp > (char *)savedip)
694 cp--;
695
696 while (cp > (char *)savedip) {
697 if (*cp == '/') {
698 cp++;
699 break;
700 }
701 cp--;
702 }
703 if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') {
704 /*
705 * Not enough information
706 */
707 free(arguments);
708 return(0);
709 }
710 (void) strncpy(cbuf, (char *)cp, csize);
711 cbuf[csize] = '\0';
712
713 free(arguments);
714 return(1);
715}
716
717
718/* All of this should come out of the process manager... */
719
720void get_proc_info(kpb, pi)
721 struct kinfo_proc *kpb;
722 struct proc_info *pi;
723{
724 task_port_t task;
725 mach_port_array_t names, types;
726 unsigned int ncnt, tcnt;
727
728 pi->uid = kpb->kp_eproc.e_ucred.cr_uid;
729 pi->pid = kpb->kp_proc.p_pid;
730 pi->ppid = kpb->kp_eproc.e_ppid;
731 pi->pgrp = kpb->kp_eproc.e_pgid;
732 pi->status = kpb->kp_proc.p_stat;
733 pi->flag = kpb->kp_proc.p_flag;
734
735 /*
736 * Find the other stuff
737 */
738 if (task_for_pid(mach_task_self(), pi->pid, &task) != KERN_SUCCESS) {
739 pi->status = SZOMB;
740 }
741
742 else {
743 task_basic_info_data_t ti;
744 unsigned int count;
745 unsigned int aliased;
746 thread_array_t thread_table;
747 unsigned int table_size;
748 thread_basic_info_t thi;
749 thread_basic_info_data_t thi_data;
750 int i, t_state;
751
752 count = TASK_BASIC_INFO_COUNT;
753 if (task_info(task, TASK_BASIC_INFO, (task_info_t)&ti,
754 &count) != KERN_SUCCESS) {
755 pi->status = SZOMB;
756 } else {
757 pi->virtual_size = ti.virtual_size;
758
759 pi->resident_size = ti.resident_size;
760
761 if ((pi->pid || do_proc0_vm) && (!events_only)) {
762 pmem_doit(task, pi->pid, &pi->shared, &pi->private, &aliased, &pi->obj_count, &pi->vprivate, &pi->virtual_size, &total_fw_private);
763 pi->private += aliased;
764 } else {
765 pi->shared = 0;
766 pi->private = 0;
767 pi->vprivate = 0;
768 pi->obj_count = 0;
769 }
770 pi->orig_virtual_size = pi->virtual_size;
771 pi->total_time = ti.user_time;
772 time_value_add(&pi->total_time, &ti.system_time);
773
774 pi->idle_time.seconds = 0;
775 pi->idle_time.microseconds = 0;
776
777 if (task_threads(task, &thread_table, &table_size) != KERN_SUCCESS)
778 pi->status = SZOMB;
779 else {
780 pi->state = STATE_MAX;
781 pi->pri = 255;
782 pi->base_pri = 255;
783 pi->all_swapped = TRUE;
784 pi->has_idle_thread = FALSE;
785
786 thi = &thi_data;
787
788 pi->num_threads = table_size;
789 total_threads += table_size;
790
791 for (i = 0; i < table_size; i++) {
792 count = THREAD_BASIC_INFO_COUNT;
793 if (thread_info(thread_table[i], THREAD_BASIC_INFO,
794 (thread_info_t)thi, &count) == KERN_SUCCESS) {
795
796 if (thi->flags & TH_FLAGS_IDLE) {
797 pi->has_idle_thread = TRUE;
798
799 time_value_add(&pi->idle_time,
800 &thi->user_time);
801 time_value_add(&pi->idle_time,
802 &thi->system_time);
803 } else {
804 time_value_add(&pi->total_time,
805 &thi->user_time);
806 time_value_add(&pi->total_time,
807 &thi->system_time);
808 }
809 t_state = mach_state_order(thi->run_state,
810 thi->sleep_time);
811 if (t_state < pi->state)
812 pi->state = t_state;
813// update priority info based on schedule policy
814// if (thi->cur_priority < pi->pri)
815// pi->pri = thi->cur_priority;
816// if (thi->base_priority < pi->base_pri)
817// pi->base_pri = thi->base_priority;
818 if ((thi->flags & TH_FLAGS_SWAPPED) == 0)
819 pi->all_swapped = FALSE;
820
821 }
822 if (task != mach_task_self()) {
823 mach_port_deallocate(mach_task_self(),
824 thread_table[i]);
825 }
826 }
827 (void) vm_deallocate(mach_task_self(), (vm_offset_t)thread_table,
828 table_size * sizeof(*thread_table));
829
1c51fdde
A
830 if (!events_only) {
831 if (mach_port_names(task, &names, &ncnt,
832 &types, &tcnt) == KERN_SUCCESS) {
833 pi->num_ports = ncnt;
834 pi->orig_num_ports = ncnt;
835 (void) vm_deallocate(mach_task_self(),
836 (vm_offset_t) names,
837 ncnt * sizeof(*names));
838 (void) vm_deallocate(mach_task_self(),
839 (vm_offset_t) types,
840 tcnt * sizeof(*types));
841 } else {
842 pi->num_ports = -1;
843 }
844 } else
845 pi->num_ports = 0;
846
1815bff5
A
847 if (events_only) {
848 task_events_info_data_t tei;
849
850 count = TASK_EVENTS_INFO_COUNT;
851 if (task_info(task, TASK_EVENTS_INFO, (task_info_t)&tei,
852 &count) != KERN_SUCCESS) {
853 pi->status = SZOMB;
854 } else {
855 pi->tei = tei;
856
857 }
858 }
859 }
860 }
861 if (task != mach_task_self()) {
862 mach_port_deallocate(mach_task_self(), task);
863 }
864 }
865 if ( strncmp (kpb->kp_proc.p_comm, "LaunchCFMA", 10) ||
866 !get_real_command_name(pi->pid, pi->command, sizeof(kpb->kp_proc.p_comm)-1)) {
867 (void) strncpy(pi->command, kpb->kp_proc.p_comm,
868 sizeof(kpb->kp_proc.p_comm)-1);
869 pi->command[sizeof(kpb->kp_proc.p_comm)-1] = '\0';
870 }
871}
872
873
874/*
875 * signal handlers
876 */
877
878void leave() /* exit under normal conditions -- INT handler */
879{
880 if (!oneshot) {
881 move(LINES - 1, 0);
882 refresh();
883 endwin();
1815bff5
A
884 }
885 exit(0);
886}
887
888void quit(status) /* exit under duress */
889 int status;
890{
b51d5b5f 891 if (!oneshot)
1815bff5 892 endwin();
1815bff5
A
893 exit(status);
894}
895
896void sigwinch()
897{
898 newLINES = 1;
899}
900
901
902/*
903 * comparison function for "qsort"
904 * Do first order sort based on cpu percentage computed by kernel and
905 * second order sort based on total time for the process.
906 */
907
908int proc_compar(p1, p2)
909 register struct proc_info **p1;
910 register struct proc_info **p2;
911{
912 if (sort_by_usage) {
913 if ((*p1)->cpu_usage < (*p2)->cpu_usage)
914 return(1);
915 else if ((*p1)->cpu_usage > (*p2)->cpu_usage)
916 return(-1);
917 else {
918 if ((*p1)->total_time.seconds < (*p2)->total_time.seconds)
919 return(1);
920 else
921 return(-1);
922 }
923 }
924 else {
925 if ((*p1)->pid < (*p2)->pid)
926 return(1);
927 else
928 return(-1);
929 }
930}
931
932
933int nproc, total_procs, old_procs;
934struct kinfo_proc *kbase, *kpb;
935struct proc_info *proc, *pp, *oldproc;
936struct proc_info **pref, **prefp;
937
938int topn = 0;
939int wanted_topn = 0;
940vm_size_t pagesize;
941
942
943
944void grab_task(task)
945 task_t task;
946{
947 int pid;
948 size_t size;
949 kern_return_t ret;
950 struct kinfo_proc ki;
951 int mib[4];
952
953 ret = pid_for_task(task, &pid);
954 if (ret != KERN_SUCCESS)
955 return;
956 size = sizeof(ki);
957 mib[0] = CTL_KERN;
958 mib[1] = KERN_PROC;
959 mib[2] = KERN_PROC_PID;
960 mib[3] = pid;
961
962 if (sysctl(mib, 4, &ki, &size, NULL, 0) < 0) {
963 perror("failure calling sysctl");
964 exit(1);
965 }
966 if (ki.kp_proc.p_stat == 0) {
967 state_breakdown[0]++;
968 return;
969 }
970 if (total_procs == nproc) {
971 nproc *= 2;
972 kbase = (struct kinfo_proc *) realloc(kbase,
973 nproc*sizeof(struct kinfo_proc));
974 bzero(&kbase[total_procs], total_procs*sizeof(struct kinfo_proc));
975 proc = (struct proc_info *) realloc(proc,
976 nproc*sizeof(struct proc_info));
977 bzero(&proc[total_procs], total_procs*sizeof(struct proc_info));
978 oldproc = (struct proc_info *) realloc(oldproc,
979 nproc*sizeof(struct proc_info));
980 bzero(&oldproc[total_procs], total_procs*sizeof(struct proc_info));
981 pref = (struct proc_info **) realloc(pref,
982 nproc*sizeof(struct proc_info *));
983 bzero(&pref[total_procs], total_procs*sizeof(struct proc_info *));
984 }
985 kbase[total_procs] = ki;
986 total_procs++;
987}
988
989void update_histdata()
990{
991 struct proc_info *pp, *oldp;
992 int i, j, pid;
993 time_value_t elapsed_time;
994
995 i = 0;
996 pp = proc;
997
998 // XXX use linear search since list is usually small
999
1000 while (i < total_procs) {
1001 j = 0;
1002 oldp = oldproc;
1003 pid = pp->pid;
1004
1005 while (j < old_procs) {
1006 if (oldp->pid == pid) {
1007 pp->drprvt = pp->private - oldp->private;
1008 pp->drshrd = pp->shared - oldp->shared;
1009 pp->drsize = pp->resident_size - oldp->resident_size;
1010 pp->dvsize = pp->virtual_size - oldp->virtual_size;
1011
1012 pp->rvsize = pp->virtual_size - oldp->orig_virtual_size;
1013 pp->orig_virtual_size = oldp->orig_virtual_size;
1014
1015 pp->dnum_ports = pp->num_ports - oldp->orig_num_ports;
1016 pp->orig_num_ports = oldp->orig_num_ports;
1017
1018 if (pp->has_idle_thread == TRUE) {
1019 if (events_accumulate) {
1020 time_value_sub(&pp->idle_time, &oldp->beg_idle_time, &elapsed_time);
1021 pp->beg_idle_time = oldp->beg_idle_time;
1022 pp->idle_time = elapsed_time;
1023 } else
1024 time_value_sub(&pp->idle_time, &oldp->idle_time, &elapsed_time);
1025
1026 pp->cpu_idle = (elapsed_time.seconds * 1000) + (elapsed_time.microseconds / 1000);
1027 }
1028 if (events_accumulate) {
1029 time_value_sub(&pp->total_time, &oldp->beg_total_time, &elapsed_time);
1030 pp->beg_total_time = oldp->beg_total_time;
1031 pp->total_time = elapsed_time;
1032 } else
1033 time_value_sub(&pp->total_time, &oldp->total_time, &elapsed_time);
1034
1035 pp->cpu_usage = (elapsed_time.seconds * 1000) + (elapsed_time.microseconds / 1000);
1036
1037 if (events_delta)
1038 {
1039 pp->deltatei.pageins = pp->tei.pageins - oldp->tei.pageins;
1040 pp->deltatei.faults = pp->tei.faults - oldp->tei.faults;
1041 pp->deltatei.cow_faults = pp->tei.cow_faults - oldp->tei.cow_faults;
1042 pp->deltatei.messages_sent = pp->tei.messages_sent - oldp->tei.messages_sent;
1043 pp->deltatei.messages_received = pp->tei.messages_received - oldp->tei.messages_received;
1044 pp->deltatei.syscalls_unix = pp->tei.syscalls_unix - oldp->tei.syscalls_unix;
1045 pp->deltatei.syscalls_mach = pp->tei.syscalls_mach - oldp->tei.syscalls_mach;
1046 pp->deltatei.csw = pp->tei.csw - oldp->tei.csw;
1047 }
1048 if (events_accumulate)
1049 {
1050 pp->deltatei.pageins = pp->tei.pageins - oldp->accumtei.pageins;
1051 pp->deltatei.faults = pp->tei.faults - oldp->accumtei.faults;
1052 pp->deltatei.cow_faults = pp->tei.cow_faults - oldp->accumtei.cow_faults;
1053 pp->deltatei.messages_sent = pp->tei.messages_sent - oldp->accumtei.messages_sent;
1054 pp->deltatei.messages_received = pp->tei.messages_received - oldp->accumtei.messages_received;
1055 pp->deltatei.syscalls_unix = pp->tei.syscalls_unix - oldp->accumtei.syscalls_unix;
1056 pp->deltatei.syscalls_mach = pp->tei.syscalls_mach - oldp->accumtei.syscalls_mach;
1057 pp->deltatei.csw = pp->tei.csw - oldp->accumtei.csw;
1058
1059 pp->accumtei = oldp->accumtei;
1060 }
1061 break;
1062 }
1063 j++;
1064 oldp++;
1065 }
1066 if (j >= old_procs) {
1067 if (events_accumulate) {
1068 pp->accumtei = pp->tei;
1069 pp->beg_total_time = pp->total_time;
1070 pp->beg_idle_time = pp->idle_time;
1071
1072 pp->idle_time.seconds = 0;
1073 pp->idle_time.microseconds = 0;
1074 pp->total_time.seconds = 0;
1075 pp->total_time.microseconds = 0;
1076 }
1077 bzero(&pp->deltatei, sizeof (task_events_info_data_t));
1078
1079 pp->drprvt = 0;
1080 pp->drshrd = 0;
1081 pp->drsize = 0;
1082 pp->dvsize = 0;
1083 pp->rvsize = 0;
1084 pp->dnum_ports = 0;
1085 pp->cpu_usage = 0;
1086 pp->cpu_idle = 0;
1087 }
1088 i++;
1089 pp++;
1090 }
1091 bcopy(proc, oldproc, total_procs*sizeof(struct proc_info));
1092 old_procs = total_procs;
1093}
1094
1095void read_proc_table()
1096{
1097 mach_port_t host;
1098 processor_set_t *psets;
1099 task_t *tasks;
1100 unsigned int pcount, tcount;
1101 kern_return_t ret;
1102 processor_set_t p;
1103 int i, j;
1104
1105 total_procs = 0;
1106 total_threads = 0;
1107
1108 host = host_priv_port;
1109
1110 if (host == MACH_PORT_NULL) {
1111 printf("Insufficient privileges.\n");
1112 exit(0);
1113 }
1114 ret = host_processor_sets(host, &psets, &pcount);
1115 if (ret != KERN_SUCCESS) {
1116 mach_error("host_processor_sets", ret);
1117 exit(0);
1118 }
1119 for (i = 0; i < pcount; i++) {
1120 ret = host_processor_set_priv(host, psets[i], &p);
1121 if (ret != KERN_SUCCESS) {
1122 mach_error("host_processor_set_priv", ret);
1123 exit(0);
1124 }
1125
1126 ret = processor_set_tasks(p, &tasks, &tcount);
1127 if (ret != KERN_SUCCESS) {
1128 mach_error("processor_set_tasks", ret);
1129 exit(0);
1130 }
1131 for (j = 0; j < tcount; j++) {
1132 grab_task(tasks[j]);
1133 // don't delete our own task port
1134 if (tasks[j] != mach_task_self())
1135 mach_port_deallocate(mach_task_self(),
1136 tasks[j]);
1137 }
1138 vm_deallocate(mach_task_self(), (vm_address_t)tasks,
1139 tcount * sizeof(task_t));
1140 mach_port_deallocate(mach_task_self(), p);
1141 mach_port_deallocate(mach_task_self(), psets[i]);
1142 }
1143 vm_deallocate(mach_task_self(), (vm_address_t)psets,
1144 pcount * sizeof(processor_set_t));
1145}
1146
1147kern_return_t getCPU(cpucounters)
1148 host_cpu_load_info_t cpucounters;
1149{
1150 mach_msg_type_number_t count;
1151 kern_return_t kr;
1152
1153 count = HOST_CPU_LOAD_INFO_COUNT;
1154 kr = host_statistics (host_priv_port, HOST_CPU_LOAD_INFO,
1155 (host_info_t)cpucounters, &count);
1156
1157 return(kr);
1158}
1159
1160updateCPU()
1161{
1162
1163 if (events_accumulate) {
1164 userticks = curcounters.cpu_ticks[CPU_STATE_USER]-
1165 startcounters.cpu_ticks[CPU_STATE_USER];
1166
1167 systicks = curcounters.cpu_ticks[CPU_STATE_SYSTEM]-
1168 startcounters.cpu_ticks[CPU_STATE_SYSTEM];
1169
1170 idleticks = curcounters.cpu_ticks[CPU_STATE_IDLE]-
1171 startcounters.cpu_ticks[CPU_STATE_IDLE];
1172 } else if (events_only && !events_delta) {
1173
1174 userticks = curcounters.cpu_ticks[CPU_STATE_USER];
1175
1176 systicks = curcounters.cpu_ticks[CPU_STATE_SYSTEM];
1177
1178 idleticks = curcounters.cpu_ticks[CPU_STATE_IDLE];
1179 } else {
1180 userticks = curcounters.cpu_ticks[CPU_STATE_USER]-
1181 lastcounters.cpu_ticks[CPU_STATE_USER];
1182
1183 systicks = curcounters.cpu_ticks[CPU_STATE_SYSTEM]-
1184 lastcounters.cpu_ticks[CPU_STATE_SYSTEM];
1185
1186 idleticks = curcounters.cpu_ticks[CPU_STATE_IDLE]-
1187 lastcounters.cpu_ticks[CPU_STATE_IDLE];
1188
1189 lastcounters = curcounters;
1190 }
1191 totalticks = userticks + systicks + idleticks;
1192}
1193
1194
1195
1196main(argc, argv)
1197 int argc;
1198 char *argv[];
1199{
1200 char *myname = "top";
1c51fdde 1201 int ch;
1815bff5
A
1202 int delay = Default_DELAY;
1203 kern_return_t error;
1204
1205 void screen_update();
1206
1207 /* get our name */
1208 if (argc > 0) {
1209 if ((myname = rindex(argv[0], '/')) == 0) {
1210 myname = argv[0];
1211 }
1212 else {
1213 myname++;
1214 }
1215 }
1216
1217 /* check for options */
1218 sort_by_usage = 0;
1219 wide_output = 0;
1220 do_proc0_vm = 0;
1221 events_only = 0;
1222 events_delta = 0;
1223 events_accumulate = 0;
1224
1c51fdde
A
1225 while ((ch = getopt(argc, argv, "uwks:edal:")) != EOF) {
1226 switch(ch) {
1815bff5 1227 case 's':
1c51fdde
A
1228 delay = atoi(optarg);
1229 break;
1815bff5
A
1230 case 'u':
1231 sort_by_usage = 1;
1232 break;
1233 case 'w':
1234 wide_output = 1;
1235 break;
1236 case 'k':
1237 do_proc0_vm = 1;
1238 break;
1239 case 'e':
1240 events_only = 1;
1241 break;
1242 case 'd':
1243 events_only = 1;
1244 events_delta = 1;
1245 break;
1246 case 'a':
1247 events_only = 1;
1248 events_accumulate = 1;
1249 break;
1250 case 'l':
1c51fdde 1251 logcnt = atoi(optarg);
1815bff5
A
1252 oneshot = 1;
1253 LINES = 80;
1254 COLS = 132;
1255 break;
1256 default:
1c51fdde 1257 fprintf(stderr, "Usage: %s [-u] [-w] [-k] [-sn] [-e | -d | -a] [-ln] [number]\n", myname);
1815bff5
A
1258 fprintf(stderr, " -u enables sort by usage\n");
1259 fprintf(stderr, " -w enables wide output of additional info\n");
1260 fprintf(stderr, " -k generate vm info for kernel(proc 0)... expensive\n");
1261 fprintf(stderr, " -sn change sample rate to every n seconds\n");
1262 fprintf(stderr, " -e switch to events info counter mode\n");
1263 fprintf(stderr, " -d switch to events info counter delta mode\n");
1264 fprintf(stderr, " -a switch to events info counter accumulate mode\n");
1265 fprintf(stderr, " -ln log n samples\n");
1266 fprintf(stderr, " number limit number of processes monitored\n");
1267
1268 exit(1);
1269 }
1815bff5 1270 }
1c51fdde
A
1271
1272 argc -= optind;
1273 //argv += optind;
1274
1815bff5
A
1275 if (events_only)
1276 {
1277 if ( wide_output || do_proc0_vm)
1278 {
1279 fprintf(stderr, " The -w and -k flag have no effect in event mode.\n");
1280 wide_output = 0;
1281 do_proc0_vm = 0;
1282 }
1283 }
1284
1285 host_priv_port = get_host_priv();
1286 host_port = get_host_port();
1287
1288 /* get count of top processes to display (if any) */
1c51fdde
A
1289 if (argc) {
1290 wanted_topn = topn = atoi(argv[optind]);
1815bff5
A
1291 } else
1292 wanted_topn = -1;
1293
1294 /* allocate space for proc structure array and array of pointers */
1295 nproc = 50; /* starting point */
1296 kbase = (struct kinfo_proc *) malloc(nproc*sizeof(struct kinfo_proc));
1297 bzero(kbase, nproc*sizeof(struct kinfo_proc));
1298 proc = (struct proc_info *) malloc(nproc*sizeof(struct proc_info));
1299 bzero(proc, nproc*sizeof(struct proc_info));
1300 oldproc = (struct proc_info *) malloc(nproc*sizeof(struct proc_info));
1301 bzero(oldproc, nproc*sizeof(struct proc_info));
1302 pref = (struct proc_info **) malloc(nproc*sizeof(struct proc_info *));
1303 bzero(pref, nproc*sizeof(struct proc_info *));
1304
1305 (void) host_page_size(host_port, &pagesize);
1306 /* initializes curses and screen (last) */
1307
1308 if (!oneshot) {
1815bff5 1309 initscr();
b51d5b5f
A
1310 cbreak();
1311 timeout(delay * 1000);
1312 noecho();
1815bff5
A
1313 erase();
1314 clear();
1315 refresh();
1316 }
1317 /* set up signal handlers */
1318 signal(SIGINT, leave);
1319 signal(SIGQUIT, leave);
1320 signal(SIGWINCH, sigwinch);
1321
1322 /* can only display (LINES - Header_lines) processes */
1323 if (topn > LINES - Header_lines) {
1324 if (!oneshot)
1325 printw("Warning: this terminal can only display %d processes...\n",
1326 LINES - Header_lines);
1327 else
1328 printf("Warning: this terminal can only display %d processes...\n",
1329 LINES - Header_lines);
1330
1331 if (!oneshot)
1332 refresh();
1333 sleep(2);
1334 topn = LINES - Header_lines;
1335 if (!oneshot)
1336 clear();
1337 }
1338 if (topn == 0) { // use default
1339 // leave one blank line at bottom
1340
1341 topn = LINES - Header_lines - 1;
1342 }
1343
1344 /* prime the pump for gathering networking stats */
1345 kread(0, 0, 0);
1346
1347 /**************************************************/
1348 /* get ports and services for drive stats */
1349 /* Obtain the I/O Kit communication handle */
1350
1351 error = IOMasterPort(bootstrap_port, &masterPort);
1352
1353 /* Obtain the list of all drive objects */
1354
1355 error = IOServiceGetMatchingServices(masterPort,
1356 IOServiceMatching("IOBlockStorageDriver"),
1357 &drivelist);
1358 getCPU(&lastcounters);
1359 startcounters = lastcounters;
1360
1361 gettimeofday(&cur_tod, NULL);
1362 start_tod = cur_tod;
1363 elapsed_milliseconds = -1;
1364
1365 /* main loop */
1366
1367 while (1) {
1368 int n;
1369
1370 if (newLINES) {
b51d5b5f 1371 newLINES = 0;
1815bff5
A
1372
1373 if (!oneshot) {
b51d5b5f
A
1374 struct winsize size;
1375
1376 if (ioctl(1, TIOCGWINSZ, &size) != -1) {
1377 resizeterm(size.ws_row, size.ws_col);
1378 erase();
1379 clear();
1380 }
1815bff5
A
1381 }
1382 n = LINES - Header_lines;
1383
1384 if (topn >= n)
1385 topn = n;
1386 else {
1387 if (wanted_topn == -1)
1388 topn = n;
1389 else if (topn < wanted_topn) {
1390 if (wanted_topn < n)
1391 topn = wanted_topn;
1392 else
1393 topn = n;
1394 }
1395 }
1815bff5
A
1396 }
1397 (void)screen_update();
1398
1399 if (!oneshot) {
b51d5b5f 1400 int c;
1815bff5 1401
b51d5b5f
A
1402 if ((c = getch()) != ERR && (char)c == 'q')
1403 leave();
1815bff5
A
1404 } else
1405 sleep(delay);
1406 }
1407}
1408
1409void screen_update()
1410{
1411 char c;
1412 int i, n, mpid;
1413 int active_procs;
1414 int avenrun[3];
1415 long curr_time;
1416 long elapsed_secs;
1417 unsigned long long total_fw_vsize;
1418 unsigned long long total_virtual_size;
1419 unsigned long long total_private_size;
1420 unsigned long long total_shared_size;
1c51fdde 1421 unsigned int total_memory_regions = 0;
1815bff5
A
1422 unsigned int total_shared_objects;
1423 unsigned int total_fw_code_size;
1424 unsigned int total_fw_data_size;
1425 unsigned int total_fw_linkedit_size;
1426 unsigned int total_frameworks;
1427 vm_statistics_data_t vm_stat;
1428 struct host_load_info load_data;
1429 int host_count;
1430 kern_return_t error;
1431 char tbuf[256];
1432 char *dp;
1433 int clen;
1434
1435 bzero((char *)state_breakdown, sizeof(state_breakdown));
1436
1437 if (!oneshot) {
1438 /* clear for new display */
1439 erase();
1440 }
1441 /* read all of the process information */
1442 read_proc_table();
1443
1444 /* get the load averages */
1445 host_count = sizeof(load_data)/sizeof(integer_t);
1446 error = host_statistics(host_priv_port, HOST_LOAD_INFO,
1447 (host_info_t)&load_data, &host_count);
1448 if (error != KERN_SUCCESS) {
1449 mach_error("host_statistics", error);
1450 exit(EXIT_FAILURE);
1451 }
1452
1453 avenrun[0] = load_data.avenrun[0];
1454 avenrun[1] = load_data.avenrun[1];
1455 avenrun[2] = load_data.avenrun[2];
1456
1457 /* get total - systemwide main memory usage structure */
1458 host_count = sizeof(vm_stat)/sizeof(integer_t);
1459 error = host_statistics(host_priv_port, HOST_VM_INFO,
1460 (host_info_t)&vm_stat, &host_count);
1461 if (error != KERN_SUCCESS) {
1462 mach_error("host_info", error);
1463 exit(EXIT_FAILURE);
1464 }
1c51fdde
A
1465
1466 if (events_only) {
1467 getNETWORKcounters();
1468 getDISKcounters();
1469 }
1815bff5
A
1470 /* count up process states and get pointers to interesting procs */
1471
1472 mpid = 0;
1473 active_procs = 0;
1474 total_virtual_size = 0;
1475 total_private_size = 0;
1476 total_fw_private = 0;
1477
1478 prefp = pref;
1479 for (kpb = kbase, pp = proc, i = 0;
1480 i < total_procs;
1481 kpb++, pp++, i++) {
1482
1483 /* place pointers to each valid proc structure in pref[] */
1484 get_proc_info(kpb, pp);
1485
1486 if (kpb->kp_proc.p_stat != 0) {
1487 *prefp++ = pp;
1488 active_procs++;
1489 if (pp->pid > mpid)
1490 mpid = pp->pid;
1491
1492 if ((unsigned int)pp->state > (unsigned int)STATE_MAX)
1493 pp->state = STATE_MAX;
1494 state_breakdown[pp->state]++;
1495 total_virtual_size += pp->virtual_size;
1496 total_private_size += pp->private;
1497 total_memory_regions += pp->obj_count;
1498 }
1499 else
1500 state_breakdown[0]++;
1501 }
1502 /* get the cpu counters */
1503 getCPU(&curcounters);
1504 updateCPU();
1505
1506 if (elapsed_milliseconds != -1) {
1507 last_tod = cur_tod;
1508 gettimeofday(&cur_tod, NULL);
1509
1510 if (events_accumulate)
1511 timersub(&cur_tod, &start_tod, &elapsed_tod);
1512 else
1513 timersub(&cur_tod, &last_tod, &elapsed_tod);
1514
1515 elapsed_milliseconds = (elapsed_tod.tv_sec * 1000) + (elapsed_tod.tv_usec / 1000);
1516 } else
1517 elapsed_milliseconds = 0;
1518
1519 if (!events_only) {
1520 pmem_fw_resident(&total_frameworks, &total_fw_vsize, &total_fw_code_size, &total_fw_data_size, &total_fw_linkedit_size);
1521
1522 pmem_shared_resident(&total_shared_size, &total_shared_objects);
1523 }
1524 if (!oneshot)
1525 move(0,0);
1526
1527 /* display process state breakdown */
1528 sprintf(tbuf, "Processes: %d total", total_procs);
1529 clen = strlen(tbuf);
1530
1531
1532 for (i = 0; i <= STATE_MAX; i++) {
1533 if (state_breakdown[i] != 0) {
1534 sprintf(&tbuf[clen], ", %d %s%s",
1535 state_breakdown[i],
1536 state_name[i],
1537 (i == 0 && state_breakdown[0] > 1) ? "s" : ""
1538 );
1539
1540 clen = clen + strlen(&tbuf[clen]);
1541 }
1542 }
1543 sprintf(&tbuf[clen], "... %d threads", total_threads);
1544
1545 clen = clen + strlen(&tbuf[clen]);
1546 /*
1547 * Display the current time.
1548 * "ctime" always returns a string that looks like this:
1549 *
1550 * Sun Sep 16 01:03:52 1973
1551 * 012345678901234567890123
1552 * 1 2
1553 *
1554 * We want indices 11 thru 18 (length 8).
1555 */
1556 curr_time = time((long *)0);
1557
1558 if (start_time == 0)
1559 start_time = curr_time;
1560
1561 memset(&tbuf[clen], ' ', 111 - clen);
1562
1563 if (wide_output)
1564 clen = 118 - 8;
1565 else if (events_accumulate)
1566 clen = 103 - 8;
1567 else if (events_only && !events_delta)
1568 clen = 115 - 8;
1569 else
1570 clen = 79 - 8;
1571
1572 sprintf(&tbuf[clen], "%-8.8s", &(ctime(&curr_time)[11]));
1573 clen = clen + strlen(&tbuf[clen]);
1574
1575 if (events_accumulate) {
1576 int hours;
1577 int minutes;
1578
1579 elapsed_secs = curr_time - start_time;
1580 minutes = elapsed_secs / 60;
1581 hours = minutes / 60;
1582
1583 sprintf(&tbuf[clen], " %3ld:%02ld:%02ld\n", hours, minutes % 60, elapsed_secs % 60);
1584 } else {
1585 sprintf(&tbuf[clen], "\n");
1586 }
1587
1588 if (tbuf[COLS-2] != '\n') {
1589 tbuf[COLS-1] = '\n';
1590 tbuf[COLS] = 0;
1591 }
1592 if (!oneshot)
1593 printw(tbuf);
1594 else
1595 printf(tbuf);
1596
1597 /* display the load averages */
1598 sprintf(tbuf, "Load Avg");
1599 clen = strlen(tbuf);
1600
1601 for (i = 0; i < 3; i++) {
1602 sprintf(&tbuf[clen], "%s %4.2f", i == 0 ? ": " : ",",
1603 (double)avenrun[i] / LOAD_SCALE);
1604 clen = clen + strlen(&tbuf[clen]);
1605 }
1606 if (totalticks) {
1607 sprintf(&tbuf[clen], " CPU usage: %.1f%%%% user, %.1f%%%% sys, %.1f%%%% idle\n",
1608 (100*userticks)/totalticks, (100*systicks)/totalticks, (100*idleticks)/totalticks);
1609 clen = clen + strlen(&tbuf[clen]);
1610 }
1611 if (tbuf[COLS-2] != '\n') {
1612 tbuf[COLS-1] = '\n';
1613 tbuf[COLS] = 0;
1614 }
1615 if (!oneshot)
1616 printw(tbuf);
1617 else
1618 printf(tbuf);
1619
1620 if (!events_only) {
1621 sprintf(tbuf, "SharedLibs: num = %4d, ", total_frameworks);
1622 clen = strlen(tbuf);
1623 sprintf(&tbuf[clen], "resident = %s code, ", mem_to_string((unsigned long long)total_fw_code_size));
1624 clen = clen + strlen(&tbuf[clen]);
1625 sprintf(&tbuf[clen], "%s data, ", mem_to_string((unsigned long long)total_fw_data_size));
1626 clen = clen + strlen(&tbuf[clen]);
1627 sprintf(&tbuf[clen], "%s LinkEdit\n", mem_to_string((unsigned long long)total_fw_linkedit_size));
1628
1629 if (tbuf[COLS-2] != '\n') {
1630 tbuf[COLS-1] = '\n';
1631 tbuf[COLS] = 0;
1632 }
1633 if (!oneshot)
1634 printw(tbuf);
1635 else
1636 printf(tbuf);
1637
1638 sprintf(tbuf, "MemRegions: num = %4d, ", total_memory_regions);
1639 clen = strlen(tbuf);
1640 sprintf(&tbuf[clen], "resident = %s + ", mem_to_string(total_private_size - total_fw_private));
1641 clen = clen + strlen(&tbuf[clen]);
1642 sprintf(&tbuf[clen], "%s private, ", mem_to_string(total_fw_private));
1643 clen = clen + strlen(&tbuf[clen]);
1644 sprintf(&tbuf[clen], "%s shared\n", mem_to_string(total_shared_size));
1645
1646 if (tbuf[COLS-2] != '\n') {
1647 tbuf[COLS-1] = '\n';
1648 tbuf[COLS] = 0;
1649 }
1650 if (!oneshot)
1651 printw(tbuf);
1652 else
1653 printf(tbuf);
1654
1655 /* display main memory statistics */
1656 {
1657 unsigned long long total_resident_size,
1658 active_resident_size,
1659 inactive_resident_size,
1660 wire_resident_size,
1661 free_size;
1662
756446ec
A
1663 active_resident_size = (unsigned long long) vm_stat.active_count * (unsigned long long) pagesize;
1664 inactive_resident_size = (unsigned long long) vm_stat.inactive_count * (unsigned long long) pagesize;
1665 wire_resident_size = (unsigned long long) vm_stat.wire_count * (unsigned long long) pagesize;
1666 total_resident_size = (unsigned long long) (vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count) * (unsigned long long) pagesize;
1667 free_size = (unsigned long long) vm_stat.free_count * (unsigned long long) pagesize;
1815bff5
A
1668
1669 sprintf(tbuf, "PhysMem: ");
1670 clen = strlen(tbuf);
1671 sprintf(&tbuf[clen], "%s wired, ", mem_to_string(wire_resident_size));
1672 clen = clen + strlen(&tbuf[clen]);
1673 sprintf(&tbuf[clen], "%s active, ", mem_to_string(active_resident_size));
1674 clen = clen + strlen(&tbuf[clen]);
1675 sprintf(&tbuf[clen], "%s inactive, ", mem_to_string(inactive_resident_size));
1676 clen = clen + strlen(&tbuf[clen]);
1677 sprintf(&tbuf[clen], "%s used, ", mem_to_string(total_resident_size));
1678 clen = clen + strlen(&tbuf[clen]);
1679 sprintf(&tbuf[clen], "%s free\n", mem_to_string(free_size));
1680
1681 if (tbuf[COLS-2] != '\n') {
1682 tbuf[COLS-1] = '\n';
1683 tbuf[COLS] = 0;
1684 }
1685 if (!oneshot)
1686 printw(tbuf);
1687 else
1688 printf(tbuf);
1689 }
1690 } else {
1691 int i_io, o_io, i_kbytes, o_kbytes;
1692
1693 i_io = o_io = i_kbytes = o_kbytes = 0;
1694
1695 if (events_delta) {
1696 if (i_net.io_prev || o_net.io_prev) {
1697 i_io = i_net.io - i_net.io_prev;
1698 o_io = o_net.io - o_net.io_prev;
1699 i_kbytes = i_net.kbytes - i_net.kbytes_prev;
1700 o_kbytes = o_net.kbytes - o_net.kbytes_prev;
1701 }
1702 } else if (events_accumulate) {
1703 if (i_net.io_prev || o_net.io_prev) {
1704 i_net.io_accum += i_net.io - i_net.io_prev;
1705 o_net.io_accum += o_net.io - o_net.io_prev;
1706 i_net.kbytes_accum += i_net.kbytes - i_net.kbytes_prev;
1707 o_net.kbytes_accum += o_net.kbytes - o_net.kbytes_prev;
1708
1709 i_io = i_net.io_accum;
1710 o_io = o_net.io_accum;
1711 i_kbytes = i_net.kbytes_accum;
1712 o_kbytes = o_net.kbytes_accum;
1713 }
1714 } else {
1715 i_io = i_net.io;
1716 o_io = o_net.io;
1717 i_kbytes = i_net.kbytes;
1718 o_kbytes = o_net.kbytes;
1719 }
1c51fdde 1720 sprintf(tbuf, "Networks:%10d ipkts/%dK", i_io, i_kbytes);
1815bff5
A
1721 clen = strlen(tbuf);
1722 memset(&tbuf[clen], ' ', 36 - clen);
1723 sprintf(&tbuf[36], "%10d opkts /%dK\n", o_io, o_kbytes);
1724
1725 i_net.io_prev = i_net.io;
1726 o_net.io_prev = o_net.io;
1727 i_net.kbytes_prev = i_net.kbytes;
1728 o_net.kbytes_prev = o_net.kbytes;
1729
1730 if (tbuf[COLS-2] != '\n') {
1731 tbuf[COLS-1] = '\n';
1732 tbuf[COLS] = 0;
1733 }
1734 if (!oneshot)
1735 printw(tbuf);
1736 else
1737 printf(tbuf);
1738
1739 i_io = o_io = i_kbytes = o_kbytes = 0;
1740
1741 if (events_delta) {
1742 if (i_dsk.io_prev || o_dsk.io_prev) {
1743 i_io = i_dsk.io - i_dsk.io_prev;
1744 o_io = o_dsk.io - o_dsk.io_prev;
1745 i_kbytes = i_dsk.kbytes - i_dsk.kbytes_prev;
1746 o_kbytes = o_dsk.kbytes - o_dsk.kbytes_prev;
1747 }
1748 } else if (events_accumulate) {
1749 if (i_dsk.io_prev || o_dsk.io_prev) {
1750 i_dsk.io_accum += i_dsk.io - i_dsk.io_prev;
1751 o_dsk.io_accum += o_dsk.io - o_dsk.io_prev;
1752 i_dsk.kbytes_accum += i_dsk.kbytes - i_dsk.kbytes_prev;
1753 o_dsk.kbytes_accum += o_dsk.kbytes - o_dsk.kbytes_prev;
1754
1755 i_io = i_dsk.io_accum;
1756 o_io = o_dsk.io_accum;
1757 i_kbytes = i_dsk.kbytes_accum;
1758 o_kbytes = o_dsk.kbytes_accum;
1759 }
1760 } else {
1761 i_io = i_dsk.io;
1762 o_io = o_dsk.io;
1763 i_kbytes = i_dsk.kbytes;
1764 o_kbytes = o_dsk.kbytes;
1765 }
1c51fdde 1766 sprintf(tbuf, "Disks: %10d reads/%dK", i_io, i_kbytes);
1815bff5
A
1767 clen = strlen(tbuf);
1768 memset(&tbuf[clen], ' ', 36 - clen);
1769 sprintf(&tbuf[36], "%10d writes/%dK\n", o_io, o_kbytes);
1770
1771 i_dsk.io_prev = i_dsk.io;
1772 o_dsk.io_prev = o_dsk.io;
1773 i_dsk.kbytes_prev = i_dsk.kbytes;
1774 o_dsk.kbytes_prev = o_dsk.kbytes;
1775
1776 if (tbuf[COLS-2] != '\n') {
1777 tbuf[COLS-1] = '\n';
1778 tbuf[COLS] = 0;
1779 }
1780 if (!oneshot)
1781 printw(tbuf);
1782 else
1783 printf(tbuf);
1784 }
1785
1786 /* display paging statistics */
1787 if (events_only) {
1788 int pageins, pageouts;
1789
1790 pageins = pageouts = 0;
1791
1792 if (events_delta) {
1793 if (i_vm.io_prev || o_vm.io_prev) {
1794 pageins = vm_stat.pageins - i_vm.io_prev;
1795 pageouts = vm_stat.pageouts - o_vm.io_prev;
1796 }
1797 } else if (events_accumulate) {
1798 if (i_vm.io_prev || o_vm.io_prev) {
1799 i_vm.io_accum += vm_stat.pageins - i_vm.io_prev;
1800 o_vm.io_accum += vm_stat.pageouts - o_vm.io_prev;
1801
1802 pageins = i_vm.io_accum;
1803 pageouts = o_vm.io_accum;
1804 }
1805 } else {
1806 pageins = vm_stat.pageins;
1807 pageouts = vm_stat.pageouts;
1808 }
1c51fdde 1809 sprintf(tbuf, "VM: %10d pageins", pageins);
1815bff5
A
1810 clen = strlen(tbuf);
1811 memset(&tbuf[clen], ' ', 36 - clen);
1812 sprintf(&tbuf[36], "%10d pageouts\n", pageouts);
1813 } else {
1814 sprintf(tbuf, "VM: %5.5s + ", mem_to_string(total_virtual_size));
1815 clen = strlen(tbuf);
1816 sprintf(&tbuf[clen], "%5.5s ", mem_to_string(total_fw_vsize));
1817 clen = clen + strlen(&tbuf[clen]);
1818 sprintf(&tbuf[clen], "%d(%d) pageins, ", vm_stat.pageins, vm_stat.pageins - (int)i_vm.io_prev);
1819 clen = clen + strlen(&tbuf[clen]);
1820 sprintf(&tbuf[clen], "%d(%d) pageouts\n", vm_stat.pageouts, vm_stat.pageouts - (int)o_vm.io_prev);
1821 }
1822 if (tbuf[COLS-2] != '\n') {
1823 tbuf[COLS-1] = '\n';
1824 tbuf[COLS] = 0;
1825 }
1826 if (!oneshot)
1827 printw(tbuf);
1828 else
1829 printf(tbuf);
1830
1831 i_vm.io_prev = vm_stat.pageins;
1832 o_vm.io_prev = vm_stat.pageouts;
1833
1834
1835 /* display the processes */
1836 if (topn > 0) {
1837 if (events_delta)
1838 sprintf(tbuf, "\n PID COMMAND %%%%CPU TIME FAULTS PGINS/COWS MSENT/MRCVD BSD/MACH CSW\n");
1839 else if (events_only)
1840 sprintf(tbuf, "\n PID COMMAND %%%%CPU TIME FAULTS PAGEINS COW_FAULTS MSGS_SENT MSGS_RCVD BSDSYSCALL MACHSYSCALL CSWITCH\n");
1841 else if (wide_output)
1842 sprintf(tbuf, "\n PID COMMAND %%%%CPU TIME #TH #PRTS(delta) #MREGS VPRVT RPRVT(delta) RSHRD(delta) RSIZE(delta) VSIZE(delta)\n");
1843 else
1844 sprintf(tbuf, "\n PID COMMAND %%%%CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE\n");
1845
1846
1847 if (tbuf[COLS] != '\n') {
1848 tbuf[COLS+1] = '\n';
1849 tbuf[COLS+2] = 0;
1850 }
1851 if (!oneshot)
1852 printw(tbuf);
1853 else
1854 printf(tbuf);
1855
1856 update_histdata();
1857
1858 /* sort */
1859 qsort((char *)pref,
1860 active_procs,
1861 sizeof(struct proc_info *),
1862 proc_compar);
1863
1864 /* now, show the top whatever */
1865 if (active_procs > topn)
1866 {
1867 /* adjust for too many processes */
1868 active_procs = topn;
1869 }
1870
1871 for (prefp = pref, i = 0; i < active_procs; prefp++, i++)
1872 {
1873 pp = *prefp;
1874
1875 sprintf(tbuf, "%5d", pp->pid); /* pid */
1876 clen = strlen(tbuf);
1877 sprintf(&tbuf[clen], " %-10.10s ", pp->command); /* command */
1878 clen = clen + strlen(&tbuf[clen]);
1879
1880 print_usage(&tbuf[clen], pp->cpu_usage);
1881 clen = clen + strlen(&tbuf[clen]);
1882
1883 sprintf(&tbuf[clen], " ");
1884 clen++;
1885
1886 print_time(&tbuf[clen], pp->total_time); /* cputime */
1887 clen = clen + strlen(&tbuf[clen]);
1888
1889
1890 if (events_only) {
1891 if (events_delta) {
1892 sprintf(&tbuf[clen], " %6d", pp->deltatei.faults);
1893 clen = clen + strlen(&tbuf[clen]);
1894 sprintf(&tbuf[clen], " %5d", pp->deltatei.pageins);
1895 clen = clen + strlen(&tbuf[clen]);
1896 sprintf(&tbuf[clen], "/%-4d", pp->deltatei.cow_faults);
1897 clen = clen + strlen(&tbuf[clen]);
1898 sprintf(&tbuf[clen], " %5d", pp->deltatei.messages_sent);
1899 clen = clen + strlen(&tbuf[clen]);
1900 sprintf(&tbuf[clen], "/%-4d", pp->deltatei.messages_received);
1901 clen = clen + strlen(&tbuf[clen]);
1902 sprintf(&tbuf[clen], " %5d", pp->deltatei.syscalls_unix);
1903 clen = clen + strlen(&tbuf[clen]);
1904 sprintf(&tbuf[clen], "/%-5d", pp->deltatei.syscalls_mach);
1905 clen = clen + strlen(&tbuf[clen]);
1906 sprintf(&tbuf[clen], "%6d", pp->deltatei.csw);
1907 clen = clen + strlen(&tbuf[clen]);
1908 } else if (events_accumulate) {
1909 sprintf(&tbuf[clen], " %-8d", pp->deltatei.faults);
1910 clen = clen + strlen(&tbuf[clen]);
1911 sprintf(&tbuf[clen], " %-8d", pp->deltatei.pageins);
1912 clen = clen + strlen(&tbuf[clen]);
1913 sprintf(&tbuf[clen], " %-10d", pp->deltatei.cow_faults);
1914 clen = clen + strlen(&tbuf[clen]);
1915 sprintf(&tbuf[clen], " %-10d", pp->deltatei.messages_sent);
1916 clen = clen + strlen(&tbuf[clen]);
1917 sprintf(&tbuf[clen], " %-10d", pp->deltatei.messages_received);
1918 clen = clen + strlen(&tbuf[clen]);
1919 sprintf(&tbuf[clen], " %-10d", pp->deltatei.syscalls_unix);
1920 clen = clen + strlen(&tbuf[clen]);
1921 sprintf(&tbuf[clen], " %-11d", pp->deltatei.syscalls_mach);
1922 clen = clen + strlen(&tbuf[clen]);
1923 sprintf(&tbuf[clen], " %-8d", pp->deltatei.csw);
1924 clen = clen + strlen(&tbuf[clen]);
1925 } else {
1926 sprintf(&tbuf[clen], " %-8d", pp->tei.faults);
1927 clen = clen + strlen(&tbuf[clen]);
1928 sprintf(&tbuf[clen], " %-8d", pp->tei.pageins);
1929 clen = clen + strlen(&tbuf[clen]);
1930 sprintf(&tbuf[clen], " %-10d", pp->tei.cow_faults);
1931 clen = clen + strlen(&tbuf[clen]);
1932 sprintf(&tbuf[clen], " %-10d", pp->tei.messages_sent);
1933 clen = clen + strlen(&tbuf[clen]);
1934 sprintf(&tbuf[clen], " %-10d", pp->tei.messages_received);
1935 clen = clen + strlen(&tbuf[clen]);
1936 sprintf(&tbuf[clen], " %-10d", pp->tei.syscalls_unix);
1937 clen = clen + strlen(&tbuf[clen]);
1938 sprintf(&tbuf[clen], " %-11d", pp->tei.syscalls_mach);
1939 clen = clen + strlen(&tbuf[clen]);
1940 sprintf(&tbuf[clen], " %-8d", pp->tei.csw);
1941 clen = clen + strlen(&tbuf[clen]);
1942 }
1943 } else {
1944
1945 sprintf(&tbuf[clen], " %3d", pp->num_threads); /* # of threads */
1946 clen = clen + strlen(&tbuf[clen]);
1947 sprintf(&tbuf[clen], " %5d", pp->num_ports); /* # of ports */
1948 clen = clen + strlen(&tbuf[clen]);
1949
1950 if (wide_output) {
1951 if (pp->dnum_ports)
1952 sprintf(&tbuf[clen], "(%5d)", pp->dnum_ports);
1953 else
1954 sprintf(&tbuf[clen], " ");
1955 clen = clen + strlen(&tbuf[clen]);
1956 }
1957 if (pp->pid || do_proc0_vm)
1958 sprintf(&tbuf[clen], " %4d", pp->obj_count);
1959 else
1960 sprintf(&tbuf[clen], " -");
1961 clen = clen + strlen(&tbuf[clen]);
1962
1963 if (wide_output) {
1964 if (pp->pid || do_proc0_vm) {
1965 sprintf(&tbuf[clen], " %5.5s", mem_to_string((unsigned long long)pp->vprivate)); /* res size */
1966 clen = clen + strlen(&tbuf[clen]);
1967 sprintf(&tbuf[clen], " %5.5s", mem_to_string((unsigned long long)pp->private)); /* res size */
1968 clen = clen + strlen(&tbuf[clen]);
1969
1970 if (pp->drprvt)
1971 sprintf(&tbuf[clen], "(%5.5s)", offset_to_string(pp->drprvt));
1972 else
1973 sprintf(&tbuf[clen], " ");
1974 } else
1975 sprintf(&tbuf[clen], " - - ");
1976 } else {
1977 if (pp->drprvt == 0)
1978 dp = " ";
1979 else if ((int)pp->drprvt > 0)
1980 dp = "+";
1981 else
1982 dp = "-";
1983
1984 if (pp->pid || do_proc0_vm)
1985 sprintf(&tbuf[clen], " %5.5s%s", mem_to_string((unsigned long long)pp->private), dp); /* res size */
1986 else
1987 sprintf(&tbuf[clen], " -");
1988 }
1989 clen = clen + strlen(&tbuf[clen]);
1990
1991 if (wide_output) {
1992 if (pp->pid || do_proc0_vm) {
1993 sprintf(&tbuf[clen], " %5.5s", mem_to_string((unsigned long long)pp->shared));
1994 clen = clen + strlen(&tbuf[clen]);
1995
1996 if (pp->drshrd)
1997 sprintf(&tbuf[clen], "(%5.5s)", offset_to_string(pp->drshrd));
1998 else
1999 sprintf(&tbuf[clen], " ");
2000 } else
2001 sprintf(&tbuf[clen], " - ");
2002 } else {
2003 if (pp->drshrd == 0)
2004 dp = " ";
2005 else if ((int)pp->drshrd > 0)
2006 dp = "+";
2007 else
2008 dp = "-";
2009
2010 if (pp->pid || do_proc0_vm)
2011 sprintf(&tbuf[clen], " %5.5s%s", mem_to_string((unsigned long long)pp->shared), dp);
2012 else
2013 sprintf(&tbuf[clen], " - ");
2014 }
2015 clen = clen + strlen(&tbuf[clen]);
2016
2017 if (wide_output) {
2018 sprintf(&tbuf[clen], " %5.5s", mem_to_string((unsigned long long)pp->resident_size)); /* res size */
2019 clen = clen + strlen(&tbuf[clen]);
2020
2021 if (pp->drsize)
2022 sprintf(&tbuf[clen], "(%5.5s)", offset_to_string(pp->drsize));
2023 else
2024 sprintf(&tbuf[clen], " ");
2025 } else {
2026 if (pp->drsize == 0)
2027 dp = " ";
2028 else if ((int)pp->drsize > 0)
2029 dp = "+";
2030 else
2031 dp = "-";
2032
2033 sprintf(&tbuf[clen], " %5.5s%s", mem_to_string((unsigned long long)pp->resident_size), dp); /* res size */
2034 }
2035 clen = clen + strlen(&tbuf[clen]);
2036
2037 if (wide_output) {
2038 sprintf(&tbuf[clen], " %5.5s", mem_to_string((unsigned long long)pp->virtual_size)); /* size */
2039 clen = clen + strlen(&tbuf[clen]);
2040
2041 if (pp->rvsize)
2042 sprintf(&tbuf[clen], "(%5.5s)", offset_to_string(pp->rvsize));
2043 else
2044 sprintf(&tbuf[clen], " ");
2045 } else {
2046 if (pp->dvsize == 0)
2047 dp = " ";
2048 else if ((int)pp->dvsize > 0)
2049 dp = "+";
2050 else
2051 dp = "-";
2052
2053 sprintf(&tbuf[clen], " %5.5s%s", mem_to_string((unsigned long long)pp->virtual_size), dp); /* size */
2054 }
2055 clen = clen + strlen(&tbuf[clen]);
2056
2057 } /* else not events only */
2058
2059 sprintf(&tbuf[clen], "\n");
2060
2061 if (tbuf[COLS-1] != '\n') {
2062 tbuf[COLS] = '\n';
2063 tbuf[COLS+1] = 0;
2064 }
2065 if (!oneshot)
2066 printw(tbuf);
2067 else
2068 printf(tbuf);
2069 }
2070
2071 for (n = 0, prefp = pref; n < total_procs && i < topn; prefp++, n++)
2072 {
2073 pp = *prefp;
2074
2075 if (pp->has_idle_thread == TRUE) {
2076 sprintf(tbuf, "%5d", pp->pid);
2077 clen = strlen(tbuf);
2078 sprintf(&tbuf[clen], " %-10.10s ", "idle_thread");
2079 clen = clen + strlen(&tbuf[clen]);
2080
2081 print_usage(&tbuf[clen], pp->cpu_idle);
2082 clen = clen + strlen(&tbuf[clen]);
2083 sprintf(&tbuf[clen], " ");
2084 clen++;
2085 print_time(&tbuf[clen], pp->idle_time);
2086 clen = clen + strlen(&tbuf[clen]);
2087 sprintf(&tbuf[clen], "\n");
2088
2089 if (tbuf[COLS-1] != '\n') {
2090 tbuf[COLS] = '\n';
2091 tbuf[COLS+1] = 0;
2092 }
2093 if (!oneshot)
2094 printw(tbuf);
2095 else
2096 printf(tbuf);
2097 i++;
2098 }
2099 }
2100 }
2101 if (oneshot) {
2102 printf("\n");
2103
2104 if (--logcnt <= 0)
2105 leave();
2106 } else
2107 refresh();
2108}
2109
2110
2111void
2112update_eventsdata()
2113{
2114 /* unimplemented */
2115}
2116
2117
2118static struct nlist nl_net[] = {
2119#define N_IFNET 0
2120 { "_ifnet" },
2121 { "" },
2122};
2123
2124
2125
2126/*
2127 * Read kernel memory, return 0 on success.
2128 */
2129int
2130kread(addr, buf, size)
2131 u_long addr;
2132 char *buf;
2133 int size;
2134{
2135 static kvm_t *kvmd = 0;
2136
2137 if (kvmd == 0) {
2138 /*
2139 * XXX.
2140 */
2141 kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, buf);
2142 if (kvmd != NULL) {
2143 if (kvm_nlist(kvmd, nl_net) < 0)
2144 errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
2145
2146 if (nl_net[0].n_type == 0)
2147 errx(1, "no namelist");
2148 } else {
2149 return(-1);
2150 }
2151 }
2152 if (!buf)
2153 return (0);
2154 if (kvm_read(kvmd, addr, buf, size) != size) {
2155 warnx("%s", kvm_geterr(kvmd));
2156 return (-1);
2157 }
2158 return (0);
2159}
2160
2161
2162getNETWORKcounters()
2163{
2164 struct ifnet ifnet;
2165 struct ifnethead ifnethead;
2166 u_long off;
2167
2168 if (nl_net[N_IFNET].n_value == 0)
2169 return;
2170 if (kread(nl_net[N_IFNET].n_value, (char *)&ifnethead, sizeof ifnethead))
2171 return;
2172
1c51fdde
A
2173 i_net.io = 0;
2174 o_net.io = 0;
2175
2176 i_net.kbytes = 0;
2177 o_net.kbytes = 0;
2178
1815bff5 2179 for (off = (u_long)ifnethead.tqh_first; off; ) {
1c51fdde 2180 char tname[16];
1815bff5
A
2181
2182 if (kread(off, (char *)&ifnet, sizeof ifnet))
2183 break;
2184 if (kread((u_long)ifnet.if_name, tname, 16))
2185 break;
1815bff5 2186
1c51fdde
A
2187 if (strncmp(tname, "lo", 2)) {
2188 i_net.io += ifnet.if_ipackets;
2189 o_net.io += ifnet.if_opackets;
1815bff5 2190
1c51fdde
A
2191 i_net.kbytes += ifnet.if_ibytes/1024;
2192 o_net.kbytes += ifnet.if_obytes/1024;
1815bff5
A
2193 }
2194 off = (u_long) ifnet.if_link.tqe_next;
2195 }
2196 return;
2197}
2198
2199
2200getDISKcounters()
2201{
2202 io_registry_entry_t drive = 0; /* needs release */
2203 UInt64 totalReadBytes = 0;
2204 UInt64 totalReadCount = 0;
2205 UInt64 totalWriteBytes = 0;
2206 UInt64 totalWriteCount = 0;
2207
2208 kern_return_t status = 0;
2209
2210 while ( (drive = IOIteratorNext(drivelist)) )
2211 {
2212 CFNumberRef number = 0; /* don't release */
2213 CFDictionaryRef properties = 0; /* needs release */
2214 CFDictionaryRef statistics = 0; /* don't release */
2215 UInt64 value = 0;
2216
2217 /* Obtain the properties for this drive object */
2218
2219 status = IORegistryEntryCreateCFProperties (drive,
2220 (CFMutableDictionaryRef *) &properties,
2221 kCFAllocatorDefault,
2222 kNilOptions);
b51d5b5f 2223 if (properties) {
1815bff5 2224
b51d5b5f
A
2225 /* Obtain the statistics from the drive properties */
2226 statistics = (CFDictionaryRef) CFDictionaryGetValue(properties, CFSTR(kIOBlockStorageDriverStatisticsKey));
1815bff5 2227
b51d5b5f 2228 if (statistics) {
1815bff5
A
2229 /* Obtain the number of bytes read from the drive statistics */
2230 number = (CFNumberRef) CFDictionaryGetValue (statistics,
2231 CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey));
2232 if (number) {
2233 status = CFNumberGetValue(number, kCFNumberSInt64Type, &value);
2234 totalReadBytes += value;
2235 }
2236 /* Obtain the number of reads from the drive statistics */
2237 number = (CFNumberRef) CFDictionaryGetValue (statistics,
2238 CFSTR(kIOBlockStorageDriverStatisticsReadsKey));
2239 if (number) {
2240 status = CFNumberGetValue(number, kCFNumberSInt64Type, &value);
2241 totalReadCount += value;
2242 }
2243
2244 /* Obtain the number of writes from the drive statistics */
2245 number = (CFNumberRef) CFDictionaryGetValue (statistics,
2246 CFSTR(kIOBlockStorageDriverStatisticsWritesKey));
2247 if (number) {
2248 status = CFNumberGetValue(number, kCFNumberSInt64Type, &value);
2249 totalWriteCount += value;
2250 }
2251 /* Obtain the number of bytes written from the drive statistics */
2252 number = (CFNumberRef) CFDictionaryGetValue (statistics,
2253 CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey));
2254 if (number) {
2255 status = CFNumberGetValue(number, kCFNumberSInt64Type, &value);
2256 totalWriteBytes += value;
2257 }
b51d5b5f
A
2258 }
2259 /* Release resources */
1815bff5 2260
b51d5b5f
A
2261 CFRelease(properties); properties = 0;
2262 }
1815bff5
A
2263 IOObjectRelease(drive); drive = 0;
2264 }
2265 IOIteratorReset(drivelist);
2266
2267 i_dsk.io = (int)totalReadCount;
2268 o_dsk.io = (int)totalWriteCount;
2269 i_dsk.kbytes = (int)(totalReadBytes / 1024);
2270 o_dsk.kbytes = (int)(totalWriteBytes / 1024);
2271}