]> git.saurik.com Git - apple/system_cmds.git/blob - top.tproj/top.c
system_cmds-230.tar.gz
[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 #include <mach/shared_memory_server.h>
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>
86 #include <curses.h>
87 #include <sys/ioctl.h>
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 */
116 int wclear(WINDOW *win);
117 int wmove(WINDOW *win, int y, int x);
118 int wrefresh(WINDOW *win);
119 int endwin(void);
120 int werase(WINDOW *win);
121
122 int total_threads;
123 unsigned long long total_fw_private;
124
125 char bytesread[128];
126
127 host_cpu_load_info_data_t lastcounters, curcounters, startcounters;
128 double userticks, systicks, idleticks, totalticks;
129
130 struct timeval cur_tod;
131 struct timeval start_tod;
132 struct timeval last_tod;
133 struct timeval elapsed_tod;
134 int elapsed_milliseconds;
135 int newLINES = 0;
136 int Header_lines = HEADER_LINES;
137
138 int do_proc0_vm;
139 int sort_by_usage;
140 int wide_output;
141 int oneshot;
142 int logcnt;
143 int events_only;
144 int events_delta;
145 int events_accumulate;
146 long start_time = 0;
147
148
149 struct 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
158 struct io_stats i_net, o_net;
159 struct io_stats i_dsk, o_dsk;
160 struct io_stats i_vm, o_vm;
161
162
163 io_iterator_t drivelist = 0; /* needs release */
164 mach_port_t masterPort = 0;
165
166
167 struct 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
210 typedef struct proc_info *proc_info_t;
211
212 mach_port_t host_priv_port, host_port;
213
214 struct 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
228 struct object_info *shared_hash_table[OBJECT_TABLE_SIZE];
229
230 struct object_info *of_free_list = 0;
231
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
239 int
240 mach_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 */
255 char mach_state_table[] = "ZRUSITH?";
256
257 char * state_name[] = {
258 "zombie",
259 "running",
260 "stuck",
261 "sleeping",
262 "idle",
263 "stopped",
264 "halted",
265 "unknown",
266 };
267 int state_breakdown[STATE_MAX+1];
268
269
270 char *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
284 void 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
307 void
308 print_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
327 char *
328 digits(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
344 char *
345 mem_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
363 char *
364 offset_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
384 mach_port_t get_host_priv()
385 {
386 return(mach_host_self());
387 }
388
389 mach_port_t get_host_port()
390 {
391 return(mach_host_self());
392 }
393
394 void
395 shared_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
429 void
430 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)
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
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
451 if (address >= GLOBAL_SHARED_TEXT_SEGMENT && address < (GLOBAL_SHARED_DATA_SEGMENT + SHARED_DATA_REGION_SIZE)) {
452
453 *fw_private += info.private_pages_resident * vm_page_size;
454
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 }
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)
529 *vsize -= (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE);
530 }
531
532
533 void
534 pmem_fw_resident(unsigned int *num_fw, unsigned long long *vsize, unsigned int *code_size, unsigned int *data_size, unsigned int *linkedit_size)
535 { vm_address_t address = GLOBAL_SHARED_TEXT_SEGMENT;
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
545 while (address < (GLOBAL_SHARED_DATA_SEGMENT + SHARED_DATA_REGION_SIZE)) {
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
557 if (address >= (GLOBAL_SHARED_DATA_SEGMENT + SHARED_DATA_REGION_SIZE))
558 break;
559 if (address < GLOBAL_SHARED_DATA_SEGMENT) {
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
589 void
590 pmem_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
620 int
621 get_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
720 void 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
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
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
878 void leave() /* exit under normal conditions -- INT handler */
879 {
880 if (!oneshot) {
881 move(LINES - 1, 0);
882 refresh();
883 endwin();
884 }
885 exit(0);
886 }
887
888 void quit(status) /* exit under duress */
889 int status;
890 {
891 if (!oneshot)
892 endwin();
893 exit(status);
894 }
895
896 void 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
908 int 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
933 int nproc, total_procs, old_procs;
934 struct kinfo_proc *kbase, *kpb;
935 struct proc_info *proc, *pp, *oldproc;
936 struct proc_info **pref, **prefp;
937
938 int topn = 0;
939 int wanted_topn = 0;
940 vm_size_t pagesize;
941
942
943
944 void 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
989 void 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
1095 void 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
1147 kern_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
1160 updateCPU()
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
1196 main(argc, argv)
1197 int argc;
1198 char *argv[];
1199 {
1200 char *myname = "top";
1201 int ch;
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
1225 while ((ch = getopt(argc, argv, "uwks:edal:")) != EOF) {
1226 switch(ch) {
1227 case 's':
1228 delay = atoi(optarg);
1229 break;
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':
1251 logcnt = atoi(optarg);
1252 oneshot = 1;
1253 LINES = 80;
1254 COLS = 132;
1255 break;
1256 default:
1257 fprintf(stderr, "Usage: %s [-u] [-w] [-k] [-sn] [-e | -d | -a] [-ln] [number]\n", myname);
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 }
1270 }
1271
1272 argc -= optind;
1273 //argv += optind;
1274
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) */
1289 if (argc) {
1290 wanted_topn = topn = atoi(argv[optind]);
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) {
1309 initscr();
1310 cbreak();
1311 timeout(delay * 1000);
1312 noecho();
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) {
1371 newLINES = 0;
1372
1373 if (!oneshot) {
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 }
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 }
1396 }
1397 (void)screen_update();
1398
1399 if (!oneshot) {
1400 int c;
1401
1402 if ((c = getch()) != ERR && (char)c == 'q')
1403 leave();
1404 } else
1405 sleep(delay);
1406 }
1407 }
1408
1409 void 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;
1421 unsigned int total_memory_regions = 0;
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 }
1465
1466 if (events_only) {
1467 getNETWORKcounters();
1468 getDISKcounters();
1469 }
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
1663 active_resident_size = vm_stat.active_count * pagesize;
1664 inactive_resident_size = vm_stat.inactive_count * pagesize;
1665 wire_resident_size = vm_stat.wire_count * pagesize;
1666 total_resident_size = (vm_stat.active_count + vm_stat.inactive_count +
1667 vm_stat.wire_count) * pagesize;
1668 free_size = vm_stat.free_count * pagesize;
1669
1670 sprintf(tbuf, "PhysMem: ");
1671 clen = strlen(tbuf);
1672 sprintf(&tbuf[clen], "%s wired, ", mem_to_string(wire_resident_size));
1673 clen = clen + strlen(&tbuf[clen]);
1674 sprintf(&tbuf[clen], "%s active, ", mem_to_string(active_resident_size));
1675 clen = clen + strlen(&tbuf[clen]);
1676 sprintf(&tbuf[clen], "%s inactive, ", mem_to_string(inactive_resident_size));
1677 clen = clen + strlen(&tbuf[clen]);
1678 sprintf(&tbuf[clen], "%s used, ", mem_to_string(total_resident_size));
1679 clen = clen + strlen(&tbuf[clen]);
1680 sprintf(&tbuf[clen], "%s free\n", mem_to_string(free_size));
1681
1682 if (tbuf[COLS-2] != '\n') {
1683 tbuf[COLS-1] = '\n';
1684 tbuf[COLS] = 0;
1685 }
1686 if (!oneshot)
1687 printw(tbuf);
1688 else
1689 printf(tbuf);
1690 }
1691 } else {
1692 int i_io, o_io, i_kbytes, o_kbytes;
1693
1694 i_io = o_io = i_kbytes = o_kbytes = 0;
1695
1696 if (events_delta) {
1697 if (i_net.io_prev || o_net.io_prev) {
1698 i_io = i_net.io - i_net.io_prev;
1699 o_io = o_net.io - o_net.io_prev;
1700 i_kbytes = i_net.kbytes - i_net.kbytes_prev;
1701 o_kbytes = o_net.kbytes - o_net.kbytes_prev;
1702 }
1703 } else if (events_accumulate) {
1704 if (i_net.io_prev || o_net.io_prev) {
1705 i_net.io_accum += i_net.io - i_net.io_prev;
1706 o_net.io_accum += o_net.io - o_net.io_prev;
1707 i_net.kbytes_accum += i_net.kbytes - i_net.kbytes_prev;
1708 o_net.kbytes_accum += o_net.kbytes - o_net.kbytes_prev;
1709
1710 i_io = i_net.io_accum;
1711 o_io = o_net.io_accum;
1712 i_kbytes = i_net.kbytes_accum;
1713 o_kbytes = o_net.kbytes_accum;
1714 }
1715 } else {
1716 i_io = i_net.io;
1717 o_io = o_net.io;
1718 i_kbytes = i_net.kbytes;
1719 o_kbytes = o_net.kbytes;
1720 }
1721 sprintf(tbuf, "Networks:%10d ipkts/%dK", i_io, i_kbytes);
1722 clen = strlen(tbuf);
1723 memset(&tbuf[clen], ' ', 36 - clen);
1724 sprintf(&tbuf[36], "%10d opkts /%dK\n", o_io, o_kbytes);
1725
1726 i_net.io_prev = i_net.io;
1727 o_net.io_prev = o_net.io;
1728 i_net.kbytes_prev = i_net.kbytes;
1729 o_net.kbytes_prev = o_net.kbytes;
1730
1731 if (tbuf[COLS-2] != '\n') {
1732 tbuf[COLS-1] = '\n';
1733 tbuf[COLS] = 0;
1734 }
1735 if (!oneshot)
1736 printw(tbuf);
1737 else
1738 printf(tbuf);
1739
1740 i_io = o_io = i_kbytes = o_kbytes = 0;
1741
1742 if (events_delta) {
1743 if (i_dsk.io_prev || o_dsk.io_prev) {
1744 i_io = i_dsk.io - i_dsk.io_prev;
1745 o_io = o_dsk.io - o_dsk.io_prev;
1746 i_kbytes = i_dsk.kbytes - i_dsk.kbytes_prev;
1747 o_kbytes = o_dsk.kbytes - o_dsk.kbytes_prev;
1748 }
1749 } else if (events_accumulate) {
1750 if (i_dsk.io_prev || o_dsk.io_prev) {
1751 i_dsk.io_accum += i_dsk.io - i_dsk.io_prev;
1752 o_dsk.io_accum += o_dsk.io - o_dsk.io_prev;
1753 i_dsk.kbytes_accum += i_dsk.kbytes - i_dsk.kbytes_prev;
1754 o_dsk.kbytes_accum += o_dsk.kbytes - o_dsk.kbytes_prev;
1755
1756 i_io = i_dsk.io_accum;
1757 o_io = o_dsk.io_accum;
1758 i_kbytes = i_dsk.kbytes_accum;
1759 o_kbytes = o_dsk.kbytes_accum;
1760 }
1761 } else {
1762 i_io = i_dsk.io;
1763 o_io = o_dsk.io;
1764 i_kbytes = i_dsk.kbytes;
1765 o_kbytes = o_dsk.kbytes;
1766 }
1767 sprintf(tbuf, "Disks: %10d reads/%dK", i_io, i_kbytes);
1768 clen = strlen(tbuf);
1769 memset(&tbuf[clen], ' ', 36 - clen);
1770 sprintf(&tbuf[36], "%10d writes/%dK\n", o_io, o_kbytes);
1771
1772 i_dsk.io_prev = i_dsk.io;
1773 o_dsk.io_prev = o_dsk.io;
1774 i_dsk.kbytes_prev = i_dsk.kbytes;
1775 o_dsk.kbytes_prev = o_dsk.kbytes;
1776
1777 if (tbuf[COLS-2] != '\n') {
1778 tbuf[COLS-1] = '\n';
1779 tbuf[COLS] = 0;
1780 }
1781 if (!oneshot)
1782 printw(tbuf);
1783 else
1784 printf(tbuf);
1785 }
1786
1787 /* display paging statistics */
1788 if (events_only) {
1789 int pageins, pageouts;
1790
1791 pageins = pageouts = 0;
1792
1793 if (events_delta) {
1794 if (i_vm.io_prev || o_vm.io_prev) {
1795 pageins = vm_stat.pageins - i_vm.io_prev;
1796 pageouts = vm_stat.pageouts - o_vm.io_prev;
1797 }
1798 } else if (events_accumulate) {
1799 if (i_vm.io_prev || o_vm.io_prev) {
1800 i_vm.io_accum += vm_stat.pageins - i_vm.io_prev;
1801 o_vm.io_accum += vm_stat.pageouts - o_vm.io_prev;
1802
1803 pageins = i_vm.io_accum;
1804 pageouts = o_vm.io_accum;
1805 }
1806 } else {
1807 pageins = vm_stat.pageins;
1808 pageouts = vm_stat.pageouts;
1809 }
1810 sprintf(tbuf, "VM: %10d pageins", pageins);
1811 clen = strlen(tbuf);
1812 memset(&tbuf[clen], ' ', 36 - clen);
1813 sprintf(&tbuf[36], "%10d pageouts\n", pageouts);
1814 } else {
1815 sprintf(tbuf, "VM: %5.5s + ", mem_to_string(total_virtual_size));
1816 clen = strlen(tbuf);
1817 sprintf(&tbuf[clen], "%5.5s ", mem_to_string(total_fw_vsize));
1818 clen = clen + strlen(&tbuf[clen]);
1819 sprintf(&tbuf[clen], "%d(%d) pageins, ", vm_stat.pageins, vm_stat.pageins - (int)i_vm.io_prev);
1820 clen = clen + strlen(&tbuf[clen]);
1821 sprintf(&tbuf[clen], "%d(%d) pageouts\n", vm_stat.pageouts, vm_stat.pageouts - (int)o_vm.io_prev);
1822 }
1823 if (tbuf[COLS-2] != '\n') {
1824 tbuf[COLS-1] = '\n';
1825 tbuf[COLS] = 0;
1826 }
1827 if (!oneshot)
1828 printw(tbuf);
1829 else
1830 printf(tbuf);
1831
1832 i_vm.io_prev = vm_stat.pageins;
1833 o_vm.io_prev = vm_stat.pageouts;
1834
1835
1836 /* display the processes */
1837 if (topn > 0) {
1838 if (events_delta)
1839 sprintf(tbuf, "\n PID COMMAND %%%%CPU TIME FAULTS PGINS/COWS MSENT/MRCVD BSD/MACH CSW\n");
1840 else if (events_only)
1841 sprintf(tbuf, "\n PID COMMAND %%%%CPU TIME FAULTS PAGEINS COW_FAULTS MSGS_SENT MSGS_RCVD BSDSYSCALL MACHSYSCALL CSWITCH\n");
1842 else if (wide_output)
1843 sprintf(tbuf, "\n PID COMMAND %%%%CPU TIME #TH #PRTS(delta) #MREGS VPRVT RPRVT(delta) RSHRD(delta) RSIZE(delta) VSIZE(delta)\n");
1844 else
1845 sprintf(tbuf, "\n PID COMMAND %%%%CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE\n");
1846
1847
1848 if (tbuf[COLS] != '\n') {
1849 tbuf[COLS+1] = '\n';
1850 tbuf[COLS+2] = 0;
1851 }
1852 if (!oneshot)
1853 printw(tbuf);
1854 else
1855 printf(tbuf);
1856
1857 update_histdata();
1858
1859 /* sort */
1860 qsort((char *)pref,
1861 active_procs,
1862 sizeof(struct proc_info *),
1863 proc_compar);
1864
1865 /* now, show the top whatever */
1866 if (active_procs > topn)
1867 {
1868 /* adjust for too many processes */
1869 active_procs = topn;
1870 }
1871
1872 for (prefp = pref, i = 0; i < active_procs; prefp++, i++)
1873 {
1874 pp = *prefp;
1875
1876 sprintf(tbuf, "%5d", pp->pid); /* pid */
1877 clen = strlen(tbuf);
1878 sprintf(&tbuf[clen], " %-10.10s ", pp->command); /* command */
1879 clen = clen + strlen(&tbuf[clen]);
1880
1881 print_usage(&tbuf[clen], pp->cpu_usage);
1882 clen = clen + strlen(&tbuf[clen]);
1883
1884 sprintf(&tbuf[clen], " ");
1885 clen++;
1886
1887 print_time(&tbuf[clen], pp->total_time); /* cputime */
1888 clen = clen + strlen(&tbuf[clen]);
1889
1890
1891 if (events_only) {
1892 if (events_delta) {
1893 sprintf(&tbuf[clen], " %6d", pp->deltatei.faults);
1894 clen = clen + strlen(&tbuf[clen]);
1895 sprintf(&tbuf[clen], " %5d", pp->deltatei.pageins);
1896 clen = clen + strlen(&tbuf[clen]);
1897 sprintf(&tbuf[clen], "/%-4d", pp->deltatei.cow_faults);
1898 clen = clen + strlen(&tbuf[clen]);
1899 sprintf(&tbuf[clen], " %5d", pp->deltatei.messages_sent);
1900 clen = clen + strlen(&tbuf[clen]);
1901 sprintf(&tbuf[clen], "/%-4d", pp->deltatei.messages_received);
1902 clen = clen + strlen(&tbuf[clen]);
1903 sprintf(&tbuf[clen], " %5d", pp->deltatei.syscalls_unix);
1904 clen = clen + strlen(&tbuf[clen]);
1905 sprintf(&tbuf[clen], "/%-5d", pp->deltatei.syscalls_mach);
1906 clen = clen + strlen(&tbuf[clen]);
1907 sprintf(&tbuf[clen], "%6d", pp->deltatei.csw);
1908 clen = clen + strlen(&tbuf[clen]);
1909 } else if (events_accumulate) {
1910 sprintf(&tbuf[clen], " %-8d", pp->deltatei.faults);
1911 clen = clen + strlen(&tbuf[clen]);
1912 sprintf(&tbuf[clen], " %-8d", pp->deltatei.pageins);
1913 clen = clen + strlen(&tbuf[clen]);
1914 sprintf(&tbuf[clen], " %-10d", pp->deltatei.cow_faults);
1915 clen = clen + strlen(&tbuf[clen]);
1916 sprintf(&tbuf[clen], " %-10d", pp->deltatei.messages_sent);
1917 clen = clen + strlen(&tbuf[clen]);
1918 sprintf(&tbuf[clen], " %-10d", pp->deltatei.messages_received);
1919 clen = clen + strlen(&tbuf[clen]);
1920 sprintf(&tbuf[clen], " %-10d", pp->deltatei.syscalls_unix);
1921 clen = clen + strlen(&tbuf[clen]);
1922 sprintf(&tbuf[clen], " %-11d", pp->deltatei.syscalls_mach);
1923 clen = clen + strlen(&tbuf[clen]);
1924 sprintf(&tbuf[clen], " %-8d", pp->deltatei.csw);
1925 clen = clen + strlen(&tbuf[clen]);
1926 } else {
1927 sprintf(&tbuf[clen], " %-8d", pp->tei.faults);
1928 clen = clen + strlen(&tbuf[clen]);
1929 sprintf(&tbuf[clen], " %-8d", pp->tei.pageins);
1930 clen = clen + strlen(&tbuf[clen]);
1931 sprintf(&tbuf[clen], " %-10d", pp->tei.cow_faults);
1932 clen = clen + strlen(&tbuf[clen]);
1933 sprintf(&tbuf[clen], " %-10d", pp->tei.messages_sent);
1934 clen = clen + strlen(&tbuf[clen]);
1935 sprintf(&tbuf[clen], " %-10d", pp->tei.messages_received);
1936 clen = clen + strlen(&tbuf[clen]);
1937 sprintf(&tbuf[clen], " %-10d", pp->tei.syscalls_unix);
1938 clen = clen + strlen(&tbuf[clen]);
1939 sprintf(&tbuf[clen], " %-11d", pp->tei.syscalls_mach);
1940 clen = clen + strlen(&tbuf[clen]);
1941 sprintf(&tbuf[clen], " %-8d", pp->tei.csw);
1942 clen = clen + strlen(&tbuf[clen]);
1943 }
1944 } else {
1945
1946 sprintf(&tbuf[clen], " %3d", pp->num_threads); /* # of threads */
1947 clen = clen + strlen(&tbuf[clen]);
1948 sprintf(&tbuf[clen], " %5d", pp->num_ports); /* # of ports */
1949 clen = clen + strlen(&tbuf[clen]);
1950
1951 if (wide_output) {
1952 if (pp->dnum_ports)
1953 sprintf(&tbuf[clen], "(%5d)", pp->dnum_ports);
1954 else
1955 sprintf(&tbuf[clen], " ");
1956 clen = clen + strlen(&tbuf[clen]);
1957 }
1958 if (pp->pid || do_proc0_vm)
1959 sprintf(&tbuf[clen], " %4d", pp->obj_count);
1960 else
1961 sprintf(&tbuf[clen], " -");
1962 clen = clen + strlen(&tbuf[clen]);
1963
1964 if (wide_output) {
1965 if (pp->pid || do_proc0_vm) {
1966 sprintf(&tbuf[clen], " %5.5s", mem_to_string((unsigned long long)pp->vprivate)); /* res size */
1967 clen = clen + strlen(&tbuf[clen]);
1968 sprintf(&tbuf[clen], " %5.5s", mem_to_string((unsigned long long)pp->private)); /* res size */
1969 clen = clen + strlen(&tbuf[clen]);
1970
1971 if (pp->drprvt)
1972 sprintf(&tbuf[clen], "(%5.5s)", offset_to_string(pp->drprvt));
1973 else
1974 sprintf(&tbuf[clen], " ");
1975 } else
1976 sprintf(&tbuf[clen], " - - ");
1977 } else {
1978 if (pp->drprvt == 0)
1979 dp = " ";
1980 else if ((int)pp->drprvt > 0)
1981 dp = "+";
1982 else
1983 dp = "-";
1984
1985 if (pp->pid || do_proc0_vm)
1986 sprintf(&tbuf[clen], " %5.5s%s", mem_to_string((unsigned long long)pp->private), dp); /* res size */
1987 else
1988 sprintf(&tbuf[clen], " -");
1989 }
1990 clen = clen + strlen(&tbuf[clen]);
1991
1992 if (wide_output) {
1993 if (pp->pid || do_proc0_vm) {
1994 sprintf(&tbuf[clen], " %5.5s", mem_to_string((unsigned long long)pp->shared));
1995 clen = clen + strlen(&tbuf[clen]);
1996
1997 if (pp->drshrd)
1998 sprintf(&tbuf[clen], "(%5.5s)", offset_to_string(pp->drshrd));
1999 else
2000 sprintf(&tbuf[clen], " ");
2001 } else
2002 sprintf(&tbuf[clen], " - ");
2003 } else {
2004 if (pp->drshrd == 0)
2005 dp = " ";
2006 else if ((int)pp->drshrd > 0)
2007 dp = "+";
2008 else
2009 dp = "-";
2010
2011 if (pp->pid || do_proc0_vm)
2012 sprintf(&tbuf[clen], " %5.5s%s", mem_to_string((unsigned long long)pp->shared), dp);
2013 else
2014 sprintf(&tbuf[clen], " - ");
2015 }
2016 clen = clen + strlen(&tbuf[clen]);
2017
2018 if (wide_output) {
2019 sprintf(&tbuf[clen], " %5.5s", mem_to_string((unsigned long long)pp->resident_size)); /* res size */
2020 clen = clen + strlen(&tbuf[clen]);
2021
2022 if (pp->drsize)
2023 sprintf(&tbuf[clen], "(%5.5s)", offset_to_string(pp->drsize));
2024 else
2025 sprintf(&tbuf[clen], " ");
2026 } else {
2027 if (pp->drsize == 0)
2028 dp = " ";
2029 else if ((int)pp->drsize > 0)
2030 dp = "+";
2031 else
2032 dp = "-";
2033
2034 sprintf(&tbuf[clen], " %5.5s%s", mem_to_string((unsigned long long)pp->resident_size), dp); /* res size */
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->virtual_size)); /* size */
2040 clen = clen + strlen(&tbuf[clen]);
2041
2042 if (pp->rvsize)
2043 sprintf(&tbuf[clen], "(%5.5s)", offset_to_string(pp->rvsize));
2044 else
2045 sprintf(&tbuf[clen], " ");
2046 } else {
2047 if (pp->dvsize == 0)
2048 dp = " ";
2049 else if ((int)pp->dvsize > 0)
2050 dp = "+";
2051 else
2052 dp = "-";
2053
2054 sprintf(&tbuf[clen], " %5.5s%s", mem_to_string((unsigned long long)pp->virtual_size), dp); /* size */
2055 }
2056 clen = clen + strlen(&tbuf[clen]);
2057
2058 } /* else not events only */
2059
2060 sprintf(&tbuf[clen], "\n");
2061
2062 if (tbuf[COLS-1] != '\n') {
2063 tbuf[COLS] = '\n';
2064 tbuf[COLS+1] = 0;
2065 }
2066 if (!oneshot)
2067 printw(tbuf);
2068 else
2069 printf(tbuf);
2070 }
2071
2072 for (n = 0, prefp = pref; n < total_procs && i < topn; prefp++, n++)
2073 {
2074 pp = *prefp;
2075
2076 if (pp->has_idle_thread == TRUE) {
2077 sprintf(tbuf, "%5d", pp->pid);
2078 clen = strlen(tbuf);
2079 sprintf(&tbuf[clen], " %-10.10s ", "idle_thread");
2080 clen = clen + strlen(&tbuf[clen]);
2081
2082 print_usage(&tbuf[clen], pp->cpu_idle);
2083 clen = clen + strlen(&tbuf[clen]);
2084 sprintf(&tbuf[clen], " ");
2085 clen++;
2086 print_time(&tbuf[clen], pp->idle_time);
2087 clen = clen + strlen(&tbuf[clen]);
2088 sprintf(&tbuf[clen], "\n");
2089
2090 if (tbuf[COLS-1] != '\n') {
2091 tbuf[COLS] = '\n';
2092 tbuf[COLS+1] = 0;
2093 }
2094 if (!oneshot)
2095 printw(tbuf);
2096 else
2097 printf(tbuf);
2098 i++;
2099 }
2100 }
2101 }
2102 if (oneshot) {
2103 printf("\n");
2104
2105 if (--logcnt <= 0)
2106 leave();
2107 } else
2108 refresh();
2109 }
2110
2111
2112 void
2113 update_eventsdata()
2114 {
2115 /* unimplemented */
2116 }
2117
2118
2119 static struct nlist nl_net[] = {
2120 #define N_IFNET 0
2121 { "_ifnet" },
2122 { "" },
2123 };
2124
2125
2126
2127 /*
2128 * Read kernel memory, return 0 on success.
2129 */
2130 int
2131 kread(addr, buf, size)
2132 u_long addr;
2133 char *buf;
2134 int size;
2135 {
2136 static kvm_t *kvmd = 0;
2137
2138 if (kvmd == 0) {
2139 /*
2140 * XXX.
2141 */
2142 kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, buf);
2143 if (kvmd != NULL) {
2144 if (kvm_nlist(kvmd, nl_net) < 0)
2145 errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
2146
2147 if (nl_net[0].n_type == 0)
2148 errx(1, "no namelist");
2149 } else {
2150 return(-1);
2151 }
2152 }
2153 if (!buf)
2154 return (0);
2155 if (kvm_read(kvmd, addr, buf, size) != size) {
2156 warnx("%s", kvm_geterr(kvmd));
2157 return (-1);
2158 }
2159 return (0);
2160 }
2161
2162
2163 getNETWORKcounters()
2164 {
2165 struct ifnet ifnet;
2166 struct ifnethead ifnethead;
2167 u_long off;
2168
2169 if (nl_net[N_IFNET].n_value == 0)
2170 return;
2171 if (kread(nl_net[N_IFNET].n_value, (char *)&ifnethead, sizeof ifnethead))
2172 return;
2173
2174 i_net.io = 0;
2175 o_net.io = 0;
2176
2177 i_net.kbytes = 0;
2178 o_net.kbytes = 0;
2179
2180 for (off = (u_long)ifnethead.tqh_first; off; ) {
2181 char tname[16];
2182
2183 if (kread(off, (char *)&ifnet, sizeof ifnet))
2184 break;
2185 if (kread((u_long)ifnet.if_name, tname, 16))
2186 break;
2187
2188 if (strncmp(tname, "lo", 2)) {
2189 i_net.io += ifnet.if_ipackets;
2190 o_net.io += ifnet.if_opackets;
2191
2192 i_net.kbytes += ifnet.if_ibytes/1024;
2193 o_net.kbytes += ifnet.if_obytes/1024;
2194 }
2195 off = (u_long) ifnet.if_link.tqe_next;
2196 }
2197 return;
2198 }
2199
2200
2201 getDISKcounters()
2202 {
2203 io_registry_entry_t drive = 0; /* needs release */
2204 UInt64 totalReadBytes = 0;
2205 UInt64 totalReadCount = 0;
2206 UInt64 totalWriteBytes = 0;
2207 UInt64 totalWriteCount = 0;
2208
2209 kern_return_t status = 0;
2210
2211 while ( (drive = IOIteratorNext(drivelist)) )
2212 {
2213 CFNumberRef number = 0; /* don't release */
2214 CFDictionaryRef properties = 0; /* needs release */
2215 CFDictionaryRef statistics = 0; /* don't release */
2216 UInt64 value = 0;
2217
2218 /* Obtain the properties for this drive object */
2219
2220 status = IORegistryEntryCreateCFProperties (drive,
2221 (CFMutableDictionaryRef *) &properties,
2222 kCFAllocatorDefault,
2223 kNilOptions);
2224 if (properties) {
2225
2226 /* Obtain the statistics from the drive properties */
2227 statistics = (CFDictionaryRef) CFDictionaryGetValue(properties, CFSTR(kIOBlockStorageDriverStatisticsKey));
2228
2229 if (statistics) {
2230 /* Obtain the number of bytes read from the drive statistics */
2231 number = (CFNumberRef) CFDictionaryGetValue (statistics,
2232 CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey));
2233 if (number) {
2234 status = CFNumberGetValue(number, kCFNumberSInt64Type, &value);
2235 totalReadBytes += value;
2236 }
2237 /* Obtain the number of reads from the drive statistics */
2238 number = (CFNumberRef) CFDictionaryGetValue (statistics,
2239 CFSTR(kIOBlockStorageDriverStatisticsReadsKey));
2240 if (number) {
2241 status = CFNumberGetValue(number, kCFNumberSInt64Type, &value);
2242 totalReadCount += value;
2243 }
2244
2245 /* Obtain the number of writes from the drive statistics */
2246 number = (CFNumberRef) CFDictionaryGetValue (statistics,
2247 CFSTR(kIOBlockStorageDriverStatisticsWritesKey));
2248 if (number) {
2249 status = CFNumberGetValue(number, kCFNumberSInt64Type, &value);
2250 totalWriteCount += value;
2251 }
2252 /* Obtain the number of bytes written from the drive statistics */
2253 number = (CFNumberRef) CFDictionaryGetValue (statistics,
2254 CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey));
2255 if (number) {
2256 status = CFNumberGetValue(number, kCFNumberSInt64Type, &value);
2257 totalWriteBytes += value;
2258 }
2259 }
2260 /* Release resources */
2261
2262 CFRelease(properties); properties = 0;
2263 }
2264 IOObjectRelease(drive); drive = 0;
2265 }
2266 IOIteratorReset(drivelist);
2267
2268 i_dsk.io = (int)totalReadCount;
2269 o_dsk.io = (int)totalWriteCount;
2270 i_dsk.kbytes = (int)(totalReadBytes / 1024);
2271 o_dsk.kbytes = (int)(totalWriteBytes / 1024);
2272 }