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