2 * Top users display for Berkeley Unix
5 * This program may be freely redistributed to other Unix sites, but this
6 * entire comment MUST remain intact.
8 * Copyright (c) 1984, William LeFebvre, Rice University
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.
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.
18 * Fixes and enhancements since version 1.5:
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
26 * added real and virtual memory status line
28 * added second "key" to the qsort comparisn function "proc_compar"
29 * which sorts by on cpu ticks if percentage is equal
31 **********************************************************************
33 * 22-Apr-99 Avadis Tevanian (avie) at Apple
34 * Another rewrite for Mach 3.0
36 * 21-Apr-90 Avadis Tevanian (avie) at NeXT
37 * Completely rewritten again for processor sets.
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.
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 */
49 #include <mach/mach.h>
58 #include <sys/types.h>
59 #include <sys/param.h>
60 #include <sys/sysctl.h>
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>
74 #include <device/device_types.h>
75 #include <CoreFoundation/CoreFoundation.h>
76 #include <IOKit/IOKitLib.h>
77 #include <IOKit/storage/IOBlockStorageDriver.h>
80 #include <sys/socket.h>
82 #include <net/if_var.h>
87 #include <sys/ioctl.h>
89 /* Number of lines of header information on the standard screen */
90 #define HEADER_LINES 8
92 #define sec_to_minutes(t) ((t) / 60)
93 #define sec_to_seconds(t) ((t) % 60)
94 #define usec_to_100ths(t) ((t) / 10000)
96 #ifndef TH_USAGE_SCALE
97 #define TH_USAGE_SCALE 1000
99 #define usage_to_percent(u) ((u*100)/TH_USAGE_SCALE)
100 #define usage_to_tenths(u) (((u*1000)/TH_USAGE_SCALE) % 10)
103 #define time_value_sub(tvp, uvp, vvp) \
105 (vvp)->seconds = (tvp)->seconds - (uvp)->seconds; \
106 (vvp)->microseconds = (tvp)->microseconds - (uvp)->microseconds; \
107 if ((vvp)->microseconds < 0) { \
109 (vvp)->microseconds += 1000000; \
116 int wclear(WINDOW
*win
);
117 int wmove(WINDOW
*win
, int y
, int x
);
118 int wrefresh(WINDOW
*win
);
120 int werase(WINDOW
*win
);
123 unsigned long long total_fw_private
;
127 host_cpu_load_info_data_t lastcounters
, curcounters
, startcounters
;
128 double userticks
, systicks
, idleticks
, totalticks
;
130 struct timeval cur_tod
;
131 struct timeval start_tod
;
132 struct timeval last_tod
;
133 struct timeval elapsed_tod
;
134 int elapsed_milliseconds
;
136 int Header_lines
= HEADER_LINES
;
145 int events_accumulate
;
158 struct io_stats i_net
, o_net
;
159 struct io_stats i_dsk
, o_dsk
;
160 struct io_stats i_vm
, o_vm
;
163 io_iterator_t drivelist
= 0; /* needs release */
164 mach_port_t masterPort
= 0;
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
;
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
;
192 unsigned int private;
193 unsigned int vprivate
;
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
;
210 typedef struct proc_info
*proc_info_t
;
212 mach_port_t host_priv_port
, host_port
;
218 int resident_page_count
;
222 struct object_info
*next
;
225 #define OBJECT_TABLE_SIZE 537
226 #define OT_HASH(object) (((unsigned)object)%OBJECT_TABLE_SIZE)
228 struct object_info
*shared_hash_table
[OBJECT_TABLE_SIZE
];
230 struct object_info
*of_free_list
= 0;
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.
240 mach_state_order(s
, sleep_time
)
245 case TH_STATE_RUNNING
: return(1);
246 case TH_STATE_UNINTERRUPTIBLE
:
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);
255 char mach_state_table
[] = "ZRUSITH?";
257 char * state_name
[] = {
267 int state_breakdown
[STATE_MAX
+1];
270 char *state_to_string(pi
)
273 static char s
[5]; /* STATIC! */
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) ? '<' : ' ';
284 void print_time(char *p
, time_value_t t
)
286 long seconds
, useconds
, minutes
, hours
;
289 useconds
= t
.microseconds
;
290 minutes
= seconds
/ 60;
291 hours
= minutes
/ 60;
293 if (minutes
< 100) { // up to 100 minutes
294 sprintf(p
, "%2ld:%02ld.%02ld", minutes
, seconds
% 60,
295 usec_to_100ths(useconds
));
297 else if (hours
< 100) { // up to 100 hours
298 sprintf(p
, "%2ld:%02ld:%02ld", hours
, minutes
% 60,
302 sprintf(p
, "%4ld hrs", hours
);
308 print_usage(char *p
, int cpu_usage
)
311 int right_of_decimal
;
313 if (elapsed_milliseconds
) {
314 left_of_decimal
= (cpu_usage
* 100) / elapsed_milliseconds
;
316 right_of_decimal
= (((cpu_usage
* 100) - (left_of_decimal
* elapsed_milliseconds
)) * 10) /
317 elapsed_milliseconds
;
320 right_of_decimal
= 0;
322 sprintf(p
, "%3d.%01d%%%%", left_of_decimal
, right_of_decimal
); /* %cpu */
331 static char tmp
[10]; /* STATIC! */
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
);
340 sprintf(tmp
, "%4.0f", n
);
346 unsigned long long n
;
348 static char s
[10]; /* STATIC! */
350 /* convert to kilobytes */
354 sprintf(s
, "%sG", digits(((float)n
)/(1024.0*1024.0)));
356 sprintf(s
, "%sM", digits((float)n
/(1024.0)));
358 sprintf(s
, "%dK", (int)n
);
367 static char s
[10]; /* STATIC! */
370 /* convert to kilobytes */
375 sprintf(s
, "%sG", digits(((float)n
)/(1024.0*1024.0)));
377 sprintf(s
, "%sM", digits((float)n
/(1024.0)));
379 sprintf(s
, "%dK", n
);
384 mach_port_t
get_host_priv()
386 return(mach_host_self());
389 mach_port_t
get_host_port()
391 return(mach_host_self());
395 shared_hash_enter(int obj_id
, int share_type
, int resident_page_count
, int ref_count
, int size
, int pid
)
397 register struct object_info
**bucket
;
398 register struct object_info
*of
;
400 of
= shared_hash_table
[OT_HASH(obj_id
/OBJECT_TABLE_SIZE
)];
402 if (of
->id
== obj_id
) {
404 of
->task_ref_count
++;
410 bucket
= &shared_hash_table
[OT_HASH(obj_id
/OBJECT_TABLE_SIZE
)];
412 if (of
= of_free_list
)
413 of_free_list
= of
->next
;
415 of
= (struct object_info
*) malloc(sizeof(*of
));
417 of
->resident_page_count
= resident_page_count
;
419 of
->share_type
= share_type
;
420 of
->ref_count
= ref_count
;
421 of
->task_ref_count
= 1;
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
)
432 vm_address_t address
= 0;
433 kern_return_t err
= 0;
437 *obj_count
= *aliased
= *shared
= *private = *vprivate
= 0;
440 mach_port_t object_name
;
441 vm_region_top_info_data_t info
;
442 mach_msg_type_number_t count
;
445 count
= VM_REGION_TOP_INFO_COUNT
;
447 if (err
= vm_region(task
, &address
, &size
, VM_REGION_TOP_INFO
, (vm_region_info_t
)&info
,
448 &count
, &object_name
))
451 if (address
>= GLOBAL_SHARED_TEXT_SEGMENT
&& address
< (GLOBAL_SHARED_DATA_SEGMENT
+ SHARED_DATA_REGION_SIZE
)) {
453 *fw_private
+= info
.private_pages_resident
* vm_page_size
;
455 if ( !split
&& info
.share_mode
== SM_EMPTY
) {
456 vm_region_basic_info_data_64_t b_info
;
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
))
466 if (info
.share_mode
!= SM_PRIVATE
) {
475 switch (info
.share_mode
) {
478 *private += info
.private_pages_resident
* vm_page_size
;
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
;
492 if (info
.share_mode
== SM_PRIVATE
)
495 *vprivate
+= info
.private_pages_resident
* vm_page_size
;
500 shared_hash_enter(info
.obj_id
, SM_SHARED
, info
.shared_pages_resident
,
501 info
.ref_count
, size
, pid
);
505 for (i
= 0; i
< OBJECT_TABLE_SIZE
; i
++) {
506 register struct object_info
*sl
;
508 sl
= shared_hash_table
[i
];
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
;
516 *aliased
+= sl
->resident_page_count
* vm_page_size
;
517 *vprivate
+= sl
->size
;
520 if (sl
->share_type
!= SM_PRIVATE_ALIASED
)
521 *shared
+= sl
->resident_page_count
* vm_page_size
;
523 sl
->task_ref_count
= 0;
529 *vsize
-= (SHARED_TEXT_REGION_SIZE
+ SHARED_DATA_REGION_SIZE
);
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;
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
;
552 count
= VM_REGION_SUBMAP_INFO_COUNT_64
;
554 if (err
= vm_region_recurse_64(mach_task_self(), &address
, &size
, &nesting_depth
, (vm_region_info_t
)&s_info
, &count
))
557 if (address
>= (GLOBAL_SHARED_DATA_SEGMENT
+ SHARED_DATA_REGION_SIZE
))
559 if (address
< GLOBAL_SHARED_DATA_SEGMENT
) {
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
);
570 *linkedit_size
+= (s_info
.pages_resident
* vm_page_size
);
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
);
590 pmem_shared_resident(unsigned long long *total
, int *number
)
592 register int total_size
;
593 register int total_num
;
594 register struct object_info
*sl
, *next
;
596 total_size
= total_num
= 0;
598 for (i
= 0; i
< OBJECT_TABLE_SIZE
; i
++) {
599 sl
= shared_hash_table
[i
];
600 shared_hash_table
[i
] = 0;
603 if (sl
->share_type
!= SM_PRIVATE_ALIASED
) {
604 total_size
+= sl
->resident_page_count
;
609 sl
->next
= of_free_list
;
616 *total
= total_size
* vm_page_size
;
621 get_real_command_name(int pid
, char *cbuf
, int csize
)
624 * Get command and arguments.
626 volatile int *ip
, *savedip
;
632 int arguments_size
= 4096;
633 volatile unsigned int *valuep
;
635 int blahlen
=0, skiplen
=0;
638 * A sysctl() is made to find out the full path that the command
642 mib
[1] = KERN_PROCARGS
;
646 arguments
= (char *) malloc(arguments_size
);
647 if (sysctl(mib
, 3, arguments
, (size_t *)&arguments_size
, NULL
, 0) < 0) {
651 end_argc
= &arguments
[arguments_size
];
653 ip
= (int *)end_argc
;
654 ip
-= 2; /* last arg word and .long 0 */
656 if (ip
== (int *)arguments
) {
663 cp
= (char *)savedip
;
665 if (ip
== (int *)arguments
) {
671 valuep
= (unsigned int *)ip
;
674 if ((value
& 0xbfff0000) == 0xbfff0000) {
677 blahlen
= strlen((char *)ip
);
678 skiplen
= (blahlen
+3 ) /4 ;
685 for (cp
= (char *)savedip
; cp
< (end_argc
-1); cp
++) {
693 if (cp
> (char *)savedip
)
696 while (cp
> (char *)savedip
) {
703 if (cp
[0] == '-' || cp
[0] == '?' || cp
[0] <= ' ') {
705 * Not enough information
710 (void) strncpy(cbuf
, (char *)cp
, csize
);
718 /* All of this should come out of the process manager... */
720 void get_proc_info(kpb
, pi
)
721 struct kinfo_proc
*kpb
;
722 struct proc_info
*pi
;
725 mach_port_array_t names
, types
;
726 unsigned int ncnt
, tcnt
;
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
;
736 * Find the other stuff
738 if (task_for_pid(mach_task_self(), pi
->pid
, &task
) != KERN_SUCCESS
) {
743 task_basic_info_data_t ti
;
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
;
752 count
= TASK_BASIC_INFO_COUNT
;
753 if (task_info(task
, TASK_BASIC_INFO
, (task_info_t
)&ti
,
754 &count
) != KERN_SUCCESS
) {
757 pi
->virtual_size
= ti
.virtual_size
;
759 pi
->resident_size
= ti
.resident_size
;
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
;
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
);
774 pi
->idle_time
.seconds
= 0;
775 pi
->idle_time
.microseconds
= 0;
777 if (task_threads(task
, &thread_table
, &table_size
) != KERN_SUCCESS
)
780 pi
->state
= STATE_MAX
;
783 pi
->all_swapped
= TRUE
;
784 pi
->has_idle_thread
= FALSE
;
788 pi
->num_threads
= table_size
;
789 total_threads
+= table_size
;
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
) {
796 if (thi
->flags
& TH_FLAGS_IDLE
) {
797 pi
->has_idle_thread
= TRUE
;
799 time_value_add(&pi
->idle_time
,
801 time_value_add(&pi
->idle_time
,
804 time_value_add(&pi
->total_time
,
806 time_value_add(&pi
->total_time
,
809 t_state
= mach_state_order(thi
->run_state
,
811 if (t_state
< pi
->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
;
822 if (task
!= mach_task_self()) {
823 mach_port_deallocate(mach_task_self(),
827 (void) vm_deallocate(mach_task_self(), (vm_offset_t
)thread_table
,
828 table_size
* sizeof(*thread_table
));
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(),
837 ncnt
* sizeof(*names
));
838 (void) vm_deallocate(mach_task_self(),
840 tcnt
* sizeof(*types
));
848 task_events_info_data_t tei
;
850 count
= TASK_EVENTS_INFO_COUNT
;
851 if (task_info(task
, TASK_EVENTS_INFO
, (task_info_t
)&tei
,
852 &count
) != KERN_SUCCESS
) {
861 if (task
!= mach_task_self()) {
862 mach_port_deallocate(mach_task_self(), task
);
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';
878 void leave() /* exit under normal conditions -- INT handler */
888 void quit(status
) /* exit under duress */
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.
908 int proc_compar(p1
, p2
)
909 register struct proc_info
**p1
;
910 register struct proc_info
**p2
;
913 if ((*p1
)->cpu_usage
< (*p2
)->cpu_usage
)
915 else if ((*p1
)->cpu_usage
> (*p2
)->cpu_usage
)
918 if ((*p1
)->total_time
.seconds
< (*p2
)->total_time
.seconds
)
925 if ((*p1
)->pid
< (*p2
)->pid
)
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
;
950 struct kinfo_proc ki
;
953 ret
= pid_for_task(task
, &pid
);
954 if (ret
!= KERN_SUCCESS
)
959 mib
[2] = KERN_PROC_PID
;
962 if (sysctl(mib
, 4, &ki
, &size
, NULL
, 0) < 0) {
963 perror("failure calling sysctl");
966 if (ki
.kp_proc
.p_stat
== 0) {
967 state_breakdown
[0]++;
970 if (total_procs
== nproc
) {
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
*));
985 kbase
[total_procs
] = ki
;
989 void update_histdata()
991 struct proc_info
*pp
, *oldp
;
993 time_value_t elapsed_time
;
998 // XXX use linear search since list is usually small
1000 while (i
< total_procs
) {
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
;
1012 pp
->rvsize
= pp
->virtual_size
- oldp
->orig_virtual_size
;
1013 pp
->orig_virtual_size
= oldp
->orig_virtual_size
;
1015 pp
->dnum_ports
= pp
->num_ports
- oldp
->orig_num_ports
;
1016 pp
->orig_num_ports
= oldp
->orig_num_ports
;
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
;
1024 time_value_sub(&pp
->idle_time
, &oldp
->idle_time
, &elapsed_time
);
1026 pp
->cpu_idle
= (elapsed_time
.seconds
* 1000) + (elapsed_time
.microseconds
/ 1000);
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
;
1033 time_value_sub(&pp
->total_time
, &oldp
->total_time
, &elapsed_time
);
1035 pp
->cpu_usage
= (elapsed_time
.seconds
* 1000) + (elapsed_time
.microseconds
/ 1000);
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
;
1048 if (events_accumulate
)
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
;
1059 pp
->accumtei
= oldp
->accumtei
;
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
;
1072 pp
->idle_time
.seconds
= 0;
1073 pp
->idle_time
.microseconds
= 0;
1074 pp
->total_time
.seconds
= 0;
1075 pp
->total_time
.microseconds
= 0;
1077 bzero(&pp
->deltatei
, sizeof (task_events_info_data_t
));
1091 bcopy(proc
, oldproc
, total_procs
*sizeof(struct proc_info
));
1092 old_procs
= total_procs
;
1095 void read_proc_table()
1098 processor_set_t
*psets
;
1100 unsigned int pcount
, tcount
;
1108 host
= host_priv_port
;
1110 if (host
== MACH_PORT_NULL
) {
1111 printf("Insufficient privileges.\n");
1114 ret
= host_processor_sets(host
, &psets
, &pcount
);
1115 if (ret
!= KERN_SUCCESS
) {
1116 mach_error("host_processor_sets", ret
);
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
);
1126 ret
= processor_set_tasks(p
, &tasks
, &tcount
);
1127 if (ret
!= KERN_SUCCESS
) {
1128 mach_error("processor_set_tasks", ret
);
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(),
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
]);
1143 vm_deallocate(mach_task_self(), (vm_address_t
)psets
,
1144 pcount
* sizeof(processor_set_t
));
1147 kern_return_t
getCPU(cpucounters
)
1148 host_cpu_load_info_t cpucounters
;
1150 mach_msg_type_number_t count
;
1153 count
= HOST_CPU_LOAD_INFO_COUNT
;
1154 kr
= host_statistics (host_priv_port
, HOST_CPU_LOAD_INFO
,
1155 (host_info_t
)cpucounters
, &count
);
1163 if (events_accumulate
) {
1164 userticks
= curcounters
.cpu_ticks
[CPU_STATE_USER
]-
1165 startcounters
.cpu_ticks
[CPU_STATE_USER
];
1167 systicks
= curcounters
.cpu_ticks
[CPU_STATE_SYSTEM
]-
1168 startcounters
.cpu_ticks
[CPU_STATE_SYSTEM
];
1170 idleticks
= curcounters
.cpu_ticks
[CPU_STATE_IDLE
]-
1171 startcounters
.cpu_ticks
[CPU_STATE_IDLE
];
1172 } else if (events_only
&& !events_delta
) {
1174 userticks
= curcounters
.cpu_ticks
[CPU_STATE_USER
];
1176 systicks
= curcounters
.cpu_ticks
[CPU_STATE_SYSTEM
];
1178 idleticks
= curcounters
.cpu_ticks
[CPU_STATE_IDLE
];
1180 userticks
= curcounters
.cpu_ticks
[CPU_STATE_USER
]-
1181 lastcounters
.cpu_ticks
[CPU_STATE_USER
];
1183 systicks
= curcounters
.cpu_ticks
[CPU_STATE_SYSTEM
]-
1184 lastcounters
.cpu_ticks
[CPU_STATE_SYSTEM
];
1186 idleticks
= curcounters
.cpu_ticks
[CPU_STATE_IDLE
]-
1187 lastcounters
.cpu_ticks
[CPU_STATE_IDLE
];
1189 lastcounters
= curcounters
;
1191 totalticks
= userticks
+ systicks
+ idleticks
;
1200 char *myname
= "top";
1202 int delay
= Default_DELAY
;
1203 kern_return_t error
;
1205 void screen_update();
1209 if ((myname
= rindex(argv
[0], '/')) == 0) {
1217 /* check for options */
1223 events_accumulate
= 0;
1225 while ((ch
= getopt(argc
, argv
, "uwks:edal:")) != EOF
) {
1228 delay
= atoi(optarg
);
1248 events_accumulate
= 1;
1251 logcnt
= atoi(optarg
);
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");
1277 if ( wide_output
|| do_proc0_vm
)
1279 fprintf(stderr
, " The -w and -k flag have no effect in event mode.\n");
1285 host_priv_port
= get_host_priv();
1286 host_port
= get_host_port();
1288 /* get count of top processes to display (if any) */
1290 wanted_topn
= topn
= atoi(argv
[optind
]);
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
*));
1305 (void) host_page_size(host_port
, &pagesize
);
1306 /* initializes curses and screen (last) */
1311 timeout(delay
* 1000);
1317 /* set up signal handlers */
1318 signal(SIGINT
, leave
);
1319 signal(SIGQUIT
, leave
);
1320 signal(SIGWINCH
, sigwinch
);
1322 /* can only display (LINES - Header_lines) processes */
1323 if (topn
> LINES
- Header_lines
) {
1325 printw("Warning: this terminal can only display %d processes...\n",
1326 LINES
- Header_lines
);
1328 printf("Warning: this terminal can only display %d processes...\n",
1329 LINES
- Header_lines
);
1334 topn
= LINES
- Header_lines
;
1338 if (topn
== 0) { // use default
1339 // leave one blank line at bottom
1341 topn
= LINES
- Header_lines
- 1;
1344 /* prime the pump for gathering networking stats */
1347 /**************************************************/
1348 /* get ports and services for drive stats */
1349 /* Obtain the I/O Kit communication handle */
1351 error
= IOMasterPort(bootstrap_port
, &masterPort
);
1353 /* Obtain the list of all drive objects */
1355 error
= IOServiceGetMatchingServices(masterPort
,
1356 IOServiceMatching("IOBlockStorageDriver"),
1358 getCPU(&lastcounters
);
1359 startcounters
= lastcounters
;
1361 gettimeofday(&cur_tod
, NULL
);
1362 start_tod
= cur_tod
;
1363 elapsed_milliseconds
= -1;
1374 struct winsize size
;
1376 if (ioctl(1, TIOCGWINSZ
, &size
) != -1) {
1377 resizeterm(size
.ws_row
, size
.ws_col
);
1382 n
= LINES
- Header_lines
;
1387 if (wanted_topn
== -1)
1389 else if (topn
< wanted_topn
) {
1390 if (wanted_topn
< n
)
1397 (void)screen_update();
1402 if ((c
= getch()) != ERR
&& (char)c
== 'q')
1409 void screen_update()
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
;
1430 kern_return_t error
;
1435 bzero((char *)state_breakdown
, sizeof(state_breakdown
));
1438 /* clear for new display */
1441 /* read all of the process information */
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
);
1453 avenrun
[0] = load_data
.avenrun
[0];
1454 avenrun
[1] = load_data
.avenrun
[1];
1455 avenrun
[2] = load_data
.avenrun
[2];
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
);
1467 getNETWORKcounters();
1470 /* count up process states and get pointers to interesting procs */
1474 total_virtual_size
= 0;
1475 total_private_size
= 0;
1476 total_fw_private
= 0;
1479 for (kpb
= kbase
, pp
= proc
, i
= 0;
1483 /* place pointers to each valid proc structure in pref[] */
1484 get_proc_info(kpb
, pp
);
1486 if (kpb
->kp_proc
.p_stat
!= 0) {
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
;
1500 state_breakdown
[0]++;
1502 /* get the cpu counters */
1503 getCPU(&curcounters
);
1506 if (elapsed_milliseconds
!= -1) {
1508 gettimeofday(&cur_tod
, NULL
);
1510 if (events_accumulate
)
1511 timersub(&cur_tod
, &start_tod
, &elapsed_tod
);
1513 timersub(&cur_tod
, &last_tod
, &elapsed_tod
);
1515 elapsed_milliseconds
= (elapsed_tod
.tv_sec
* 1000) + (elapsed_tod
.tv_usec
/ 1000);
1517 elapsed_milliseconds
= 0;
1520 pmem_fw_resident(&total_frameworks
, &total_fw_vsize
, &total_fw_code_size
, &total_fw_data_size
, &total_fw_linkedit_size
);
1522 pmem_shared_resident(&total_shared_size
, &total_shared_objects
);
1527 /* display process state breakdown */
1528 sprintf(tbuf
, "Processes: %d total", total_procs
);
1529 clen
= strlen(tbuf
);
1532 for (i
= 0; i
<= STATE_MAX
; i
++) {
1533 if (state_breakdown
[i
] != 0) {
1534 sprintf(&tbuf
[clen
], ", %d %s%s",
1537 (i
== 0 && state_breakdown
[0] > 1) ? "s" : ""
1540 clen
= clen
+ strlen(&tbuf
[clen
]);
1543 sprintf(&tbuf
[clen
], "... %d threads", total_threads
);
1545 clen
= clen
+ strlen(&tbuf
[clen
]);
1547 * Display the current time.
1548 * "ctime" always returns a string that looks like this:
1550 * Sun Sep 16 01:03:52 1973
1551 * 012345678901234567890123
1554 * We want indices 11 thru 18 (length 8).
1556 curr_time
= time((long *)0);
1558 if (start_time
== 0)
1559 start_time
= curr_time
;
1561 memset(&tbuf
[clen
], ' ', 111 - clen
);
1565 else if (events_accumulate
)
1567 else if (events_only
&& !events_delta
)
1572 sprintf(&tbuf
[clen
], "%-8.8s", &(ctime(&curr_time
)[11]));
1573 clen
= clen
+ strlen(&tbuf
[clen
]);
1575 if (events_accumulate
) {
1579 elapsed_secs
= curr_time
- start_time
;
1580 minutes
= elapsed_secs
/ 60;
1581 hours
= minutes
/ 60;
1583 sprintf(&tbuf
[clen
], " %3ld:%02ld:%02ld\n", hours
, minutes
% 60, elapsed_secs
% 60);
1585 sprintf(&tbuf
[clen
], "\n");
1588 if (tbuf
[COLS
-2] != '\n') {
1589 tbuf
[COLS
-1] = '\n';
1597 /* display the load averages */
1598 sprintf(tbuf
, "Load Avg");
1599 clen
= strlen(tbuf
);
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
]);
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
]);
1611 if (tbuf
[COLS
-2] != '\n') {
1612 tbuf
[COLS
-1] = '\n';
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
));
1629 if (tbuf
[COLS
-2] != '\n') {
1630 tbuf
[COLS
-1] = '\n';
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
));
1646 if (tbuf
[COLS
-2] != '\n') {
1647 tbuf
[COLS
-1] = '\n';
1655 /* display main memory statistics */
1657 unsigned long long total_resident_size
,
1658 active_resident_size
,
1659 inactive_resident_size
,
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
;
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
));
1682 if (tbuf
[COLS
-2] != '\n') {
1683 tbuf
[COLS
-1] = '\n';
1692 int i_io
, o_io
, i_kbytes
, o_kbytes
;
1694 i_io
= o_io
= i_kbytes
= o_kbytes
= 0;
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
;
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
;
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
;
1718 i_kbytes
= i_net
.kbytes
;
1719 o_kbytes
= o_net
.kbytes
;
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
);
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
;
1731 if (tbuf
[COLS
-2] != '\n') {
1732 tbuf
[COLS
-1] = '\n';
1740 i_io
= o_io
= i_kbytes
= o_kbytes
= 0;
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
;
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
;
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
;
1764 i_kbytes
= i_dsk
.kbytes
;
1765 o_kbytes
= o_dsk
.kbytes
;
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
);
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
;
1777 if (tbuf
[COLS
-2] != '\n') {
1778 tbuf
[COLS
-1] = '\n';
1787 /* display paging statistics */
1789 int pageins
, pageouts
;
1791 pageins
= pageouts
= 0;
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
;
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
;
1803 pageins
= i_vm
.io_accum
;
1804 pageouts
= o_vm
.io_accum
;
1807 pageins
= vm_stat
.pageins
;
1808 pageouts
= vm_stat
.pageouts
;
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
);
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
);
1823 if (tbuf
[COLS
-2] != '\n') {
1824 tbuf
[COLS
-1] = '\n';
1832 i_vm
.io_prev
= vm_stat
.pageins
;
1833 o_vm
.io_prev
= vm_stat
.pageouts
;
1836 /* display the processes */
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");
1845 sprintf(tbuf
, "\n PID COMMAND %%%%CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE\n");
1848 if (tbuf
[COLS
] != '\n') {
1849 tbuf
[COLS
+1] = '\n';
1862 sizeof(struct proc_info
*),
1865 /* now, show the top whatever */
1866 if (active_procs
> topn
)
1868 /* adjust for too many processes */
1869 active_procs
= topn
;
1872 for (prefp
= pref
, i
= 0; i
< active_procs
; prefp
++, i
++)
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
]);
1881 print_usage(&tbuf
[clen
], pp
->cpu_usage
);
1882 clen
= clen
+ strlen(&tbuf
[clen
]);
1884 sprintf(&tbuf
[clen
], " ");
1887 print_time(&tbuf
[clen
], pp
->total_time
); /* cputime */
1888 clen
= clen
+ strlen(&tbuf
[clen
]);
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
]);
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
]);
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
]);
1953 sprintf(&tbuf
[clen
], "(%5d)", pp
->dnum_ports
);
1955 sprintf(&tbuf
[clen
], " ");
1956 clen
= clen
+ strlen(&tbuf
[clen
]);
1958 if (pp
->pid
|| do_proc0_vm
)
1959 sprintf(&tbuf
[clen
], " %4d", pp
->obj_count
);
1961 sprintf(&tbuf
[clen
], " -");
1962 clen
= clen
+ strlen(&tbuf
[clen
]);
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
]);
1972 sprintf(&tbuf
[clen
], "(%5.5s)", offset_to_string(pp
->drprvt
));
1974 sprintf(&tbuf
[clen
], " ");
1976 sprintf(&tbuf
[clen
], " - - ");
1978 if (pp
->drprvt
== 0)
1980 else if ((int)pp
->drprvt
> 0)
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 */
1988 sprintf(&tbuf
[clen
], " -");
1990 clen
= clen
+ strlen(&tbuf
[clen
]);
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
]);
1998 sprintf(&tbuf
[clen
], "(%5.5s)", offset_to_string(pp
->drshrd
));
2000 sprintf(&tbuf
[clen
], " ");
2002 sprintf(&tbuf
[clen
], " - ");
2004 if (pp
->drshrd
== 0)
2006 else if ((int)pp
->drshrd
> 0)
2011 if (pp
->pid
|| do_proc0_vm
)
2012 sprintf(&tbuf
[clen
], " %5.5s%s", mem_to_string((unsigned long long)pp
->shared
), dp
);
2014 sprintf(&tbuf
[clen
], " - ");
2016 clen
= clen
+ strlen(&tbuf
[clen
]);
2019 sprintf(&tbuf
[clen
], " %5.5s", mem_to_string((unsigned long long)pp
->resident_size
)); /* res size */
2020 clen
= clen
+ strlen(&tbuf
[clen
]);
2023 sprintf(&tbuf
[clen
], "(%5.5s)", offset_to_string(pp
->drsize
));
2025 sprintf(&tbuf
[clen
], " ");
2027 if (pp
->drsize
== 0)
2029 else if ((int)pp
->drsize
> 0)
2034 sprintf(&tbuf
[clen
], " %5.5s%s", mem_to_string((unsigned long long)pp
->resident_size
), dp
); /* res size */
2036 clen
= clen
+ strlen(&tbuf
[clen
]);
2039 sprintf(&tbuf
[clen
], " %5.5s", mem_to_string((unsigned long long)pp
->virtual_size
)); /* size */
2040 clen
= clen
+ strlen(&tbuf
[clen
]);
2043 sprintf(&tbuf
[clen
], "(%5.5s)", offset_to_string(pp
->rvsize
));
2045 sprintf(&tbuf
[clen
], " ");
2047 if (pp
->dvsize
== 0)
2049 else if ((int)pp
->dvsize
> 0)
2054 sprintf(&tbuf
[clen
], " %5.5s%s", mem_to_string((unsigned long long)pp
->virtual_size
), dp
); /* size */
2056 clen
= clen
+ strlen(&tbuf
[clen
]);
2058 } /* else not events only */
2060 sprintf(&tbuf
[clen
], "\n");
2062 if (tbuf
[COLS
-1] != '\n') {
2072 for (n
= 0, prefp
= pref
; n
< total_procs
&& i
< topn
; prefp
++, n
++)
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
]);
2082 print_usage(&tbuf
[clen
], pp
->cpu_idle
);
2083 clen
= clen
+ strlen(&tbuf
[clen
]);
2084 sprintf(&tbuf
[clen
], " ");
2086 print_time(&tbuf
[clen
], pp
->idle_time
);
2087 clen
= clen
+ strlen(&tbuf
[clen
]);
2088 sprintf(&tbuf
[clen
], "\n");
2090 if (tbuf
[COLS
-1] != '\n') {
2119 static struct nlist nl_net
[] = {
2128 * Read kernel memory, return 0 on success.
2131 kread(addr
, buf
, size
)
2136 static kvm_t
*kvmd
= 0;
2142 kvmd
= kvm_openfiles(NULL
, NULL
, NULL
, O_RDONLY
, buf
);
2144 if (kvm_nlist(kvmd
, nl_net
) < 0)
2145 errx(1, "kvm_nlist: %s", kvm_geterr(kvmd
));
2147 if (nl_net
[0].n_type
== 0)
2148 errx(1, "no namelist");
2155 if (kvm_read(kvmd
, addr
, buf
, size
) != size
) {
2156 warnx("%s", kvm_geterr(kvmd
));
2163 getNETWORKcounters()
2166 struct ifnethead ifnethead
;
2169 if (nl_net
[N_IFNET
].n_value
== 0)
2171 if (kread(nl_net
[N_IFNET
].n_value
, (char *)&ifnethead
, sizeof ifnethead
))
2180 for (off
= (u_long
)ifnethead
.tqh_first
; off
; ) {
2183 if (kread(off
, (char *)&ifnet
, sizeof ifnet
))
2185 if (kread((u_long
)ifnet
.if_name
, tname
, 16))
2188 if (strncmp(tname
, "lo", 2)) {
2189 i_net
.io
+= ifnet
.if_ipackets
;
2190 o_net
.io
+= ifnet
.if_opackets
;
2192 i_net
.kbytes
+= ifnet
.if_ibytes
/1024;
2193 o_net
.kbytes
+= ifnet
.if_obytes
/1024;
2195 off
= (u_long
) ifnet
.if_link
.tqe_next
;
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;
2209 kern_return_t status
= 0;
2211 while ( (drive
= IOIteratorNext(drivelist
)) )
2213 CFNumberRef number
= 0; /* don't release */
2214 CFDictionaryRef properties
= 0; /* needs release */
2215 CFDictionaryRef statistics
= 0; /* don't release */
2218 /* Obtain the properties for this drive object */
2220 status
= IORegistryEntryCreateCFProperties (drive
,
2221 (CFMutableDictionaryRef
*) &properties
,
2222 kCFAllocatorDefault
,
2226 /* Obtain the statistics from the drive properties */
2227 statistics
= (CFDictionaryRef
) CFDictionaryGetValue(properties
, CFSTR(kIOBlockStorageDriverStatisticsKey
));
2230 /* Obtain the number of bytes read from the drive statistics */
2231 number
= (CFNumberRef
) CFDictionaryGetValue (statistics
,
2232 CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey
));
2234 status
= CFNumberGetValue(number
, kCFNumberSInt64Type
, &value
);
2235 totalReadBytes
+= value
;
2237 /* Obtain the number of reads from the drive statistics */
2238 number
= (CFNumberRef
) CFDictionaryGetValue (statistics
,
2239 CFSTR(kIOBlockStorageDriverStatisticsReadsKey
));
2241 status
= CFNumberGetValue(number
, kCFNumberSInt64Type
, &value
);
2242 totalReadCount
+= value
;
2245 /* Obtain the number of writes from the drive statistics */
2246 number
= (CFNumberRef
) CFDictionaryGetValue (statistics
,
2247 CFSTR(kIOBlockStorageDriverStatisticsWritesKey
));
2249 status
= CFNumberGetValue(number
, kCFNumberSInt64Type
, &value
);
2250 totalWriteCount
+= value
;
2252 /* Obtain the number of bytes written from the drive statistics */
2253 number
= (CFNumberRef
) CFDictionaryGetValue (statistics
,
2254 CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey
));
2256 status
= CFNumberGetValue(number
, kCFNumberSInt64Type
, &value
);
2257 totalWriteBytes
+= value
;
2260 /* Release resources */
2262 CFRelease(properties
); properties
= 0;
2264 IOObjectRelease(drive
); drive
= 0;
2266 IOIteratorReset(drivelist
);
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);