2 * Copyright (c) 1999-2016 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
29 typedef char *kobject_description_t
[512];
30 #include <mach/mach.h>
31 #include <mach/mach_types.h>
32 #include <mach/task.h>
34 #include <mach/vm_purgable.h>
36 #define USAGE "Usage: vm_purgeable_stat [-a | -p <pid> | -s <interval>]\n"
37 #define PRIV_ERR_MSG "The option specified needs root priveleges."
38 #define PROC_NAME_LEN 256
40 #define PURGEABLE_PRIO_LEVELS VM_VOLATILE_GROUP_SHIFT
42 static inline int purge_info_size_adjust(uint64_t size
);
43 static inline char purge_info_unit(uint64_t size
);
44 void print_header(int summary_view
);
45 int get_system_tasks(task_array_t
*tasks
, mach_msg_type_number_t
*count
);
46 int get_task_from_pid(int pid
, task_t
*task
);
47 void print_purge_info_task(task_t task
, int pid
);
48 void print_purge_info_task_array(task_array_t tasks
, mach_msg_type_number_t count
);
49 void print_purge_info_summary(int sleep_duration
);
51 static inline int purge_info_size_adjust(uint64_t size
)
58 static inline char purge_info_unit(uint64_t size
)
60 char sizes
[] = {'B', 'K', 'M', 'G', 'T'};
70 void print_header(int summary_view
)
73 printf("%20s ", "Process-Name");
75 printf("%9s %9s %9s %9s %9s %9s %9s %9s %9s %9s %9s %9s %9s %9s %9s %9s %9s\n",
76 "FIFO-P0", "FIFO-P1", "FIFO-P2", "FIFO-P3",
77 "FIFO-P4", "FIFO-P5", "FIFO-P6", "FIFO-P7",
79 "LIFO-P0", "LIFO-P1", "LIFO-P2", "LIFO-P3",
80 "LIFO-P4", "LIFO-P5", "LIFO-P6", "LIFO-P7"
84 int get_task_from_pid(int pid
, task_t
*task
)
88 fprintf(stderr
, "%s\n", PRIV_ERR_MSG
);
91 kr
= task_for_pid(mach_task_self(), pid
, task
);
92 if (kr
!= KERN_SUCCESS
) {
93 fprintf(stderr
, "Failed to get task port for pid: %d\n", pid
);
99 int get_system_tasks(task_array_t
*tasks
, mach_msg_type_number_t
*count
)
101 processor_set_name_array_t psets
;
102 mach_msg_type_number_t psetCount
;
103 mach_port_t pset_priv
;
106 if (geteuid() != 0) {
107 fprintf(stderr
, "%s\n", PRIV_ERR_MSG
);
111 ret
= host_processor_sets(mach_host_self(), &psets
, &psetCount
);
112 if (ret
!= KERN_SUCCESS
) {
113 fprintf(stderr
, "host_processor_sets() failed: %s\n", mach_error_string(ret
));
116 if (psetCount
!= 1) {
117 fprintf(stderr
, "Assertion Failure: pset count greater than one (%d)\n", psetCount
);
121 /* convert the processor-set-name port to a privileged port */
122 ret
= host_processor_set_priv(mach_host_self(), psets
[0], &pset_priv
);
123 if (ret
!= KERN_SUCCESS
) {
124 fprintf(stderr
, "host_processor_set_priv() failed: %s\n", mach_error_string(ret
));
127 mach_port_deallocate(mach_task_self(), psets
[0]);
128 vm_deallocate(mach_task_self(), (vm_address_t
)psets
, (vm_size_t
)psetCount
* sizeof(mach_port_t
));
130 /* convert the processor-set-priv to a list of tasks for the processor set */
131 ret
= processor_set_tasks(pset_priv
, tasks
, count
);
132 if (ret
!= KERN_SUCCESS
) {
133 fprintf(stderr
, "processor_set_tasks() failed: %s\n", mach_error_string(ret
));
136 mach_port_deallocate(mach_task_self(), pset_priv
);
140 void print_purge_info_task(task_t task
, int pid
)
142 task_purgable_info_t info
;
145 char pname
[PROC_NAME_LEN
];
147 kr
= task_purgable_info(task
, &info
);
148 if (kr
!= KERN_SUCCESS
) {
149 fprintf(stderr
, "(pid: %d) task_purgable_info() failed: %s\n", pid
, mach_error_string(kr
));
152 if (0 == proc_name(pid
, pname
, PROC_NAME_LEN
))
153 strncpy(pname
, "Unknown", 7);
155 printf("%20s ", pname
);
156 for (i
=0; i
<PURGEABLE_PRIO_LEVELS
; i
++)
157 printf("%4u/%3d%c ", (unsigned)info
.fifo_data
[i
].count
, purge_info_size_adjust(info
.fifo_data
[i
].size
), purge_info_unit(info
.fifo_data
[i
].size
));
158 printf("%4u/%3d%c ", (unsigned)info
.obsolete_data
.count
, purge_info_size_adjust(info
.obsolete_data
.size
), purge_info_unit(info
.obsolete_data
.size
));
159 for (i
=0; i
<PURGEABLE_PRIO_LEVELS
; i
++)
160 printf("%4u/%3d%c ", (unsigned)info
.lifo_data
[i
].count
, purge_info_size_adjust(info
.lifo_data
[i
].size
), purge_info_unit(info
.lifo_data
[i
].size
));
165 void print_purge_info_task_array(task_array_t tasks
, mach_msg_type_number_t count
)
170 for (i
=0; i
<count
; i
++) {
171 if (KERN_SUCCESS
!= pid_for_task(tasks
[i
], &pid
))
173 print_purge_info_task(tasks
[i
], pid
);
178 void print_purge_info_summary(int sleep_duration
)
180 host_purgable_info_data_t info
;
181 mach_msg_type_number_t count
;
182 kern_return_t result
;
186 count
= HOST_VM_PURGABLE_COUNT
;
187 result
= host_info(mach_host_self(), HOST_VM_PURGABLE
, (host_info_t
)&info
, &count
);
188 if (result
!= KERN_SUCCESS
)
190 for (i
=0; i
<PURGEABLE_PRIO_LEVELS
; i
++)
191 printf("%4u/%3d%c ", (unsigned)info
.fifo_data
[i
].count
, purge_info_size_adjust(info
.fifo_data
[i
].size
), purge_info_unit(info
.fifo_data
[i
].size
));
192 printf("%4u/%3d%c ", (unsigned)info
.obsolete_data
.count
, purge_info_size_adjust(info
.obsolete_data
.size
), purge_info_unit(info
.obsolete_data
.size
));
193 for (i
=0; i
<PURGEABLE_PRIO_LEVELS
; i
++)
194 printf("%4u/%3d%c ", (unsigned)info
.lifo_data
[i
].count
, purge_info_size_adjust(info
.lifo_data
[i
].size
), purge_info_unit(info
.lifo_data
[i
].size
));
196 sleep(sleep_duration
);
201 int main(int argc
, char *argv
[])
209 mach_msg_type_number_t taskCount
;
213 ch
= getopt(argc
, argv
, "ahp:s:");
219 if (get_system_tasks(&tasks
, &taskCount
) < 0)
222 print_purge_info_task_array(tasks
, taskCount
);
226 pid
= (int)strtol(optarg
, NULL
, 10);
229 if (get_task_from_pid(pid
, &task
) < 0)
232 print_purge_info_task(task
, pid
);
235 sleep_duration
= (int)strtol(optarg
, NULL
, 10);
236 if (sleep_duration
< 0)
239 print_purge_info_summary(sleep_duration
);