/* * Copyright (c) 1999-2016 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights * Reserved. This file contains Original Code and/or Modifications of * Original Code as defined in and that are subject to the Apple Public * Source License Version 1.0 (the 'License'). You may not use this file * except in compliance with the License. Please obtain a copy of the * License at http://www.apple.com/publicsource and read it before using * this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License." * * @APPLE_LICENSE_HEADER_END@ */ #include #include #include #include typedef char *kobject_description_t[512]; #include #include #include #include #include #define USAGE "Usage: vm_purgeable_stat [-a | -p | -s ]\n" #define PRIV_ERR_MSG "The option specified needs root priveleges." #define PROC_NAME_LEN 256 #define KB 1024 #define PURGEABLE_PRIO_LEVELS VM_VOLATILE_GROUP_SHIFT static inline int purge_info_size_adjust(uint64_t size); static inline char purge_info_unit(uint64_t size); void print_header(int summary_view); int get_system_tasks(task_array_t *tasks, mach_msg_type_number_t *count); int get_task_from_pid(int pid, task_t *task); void print_purge_info_task(task_t task, int pid); void print_purge_info_task_array(task_array_t tasks, mach_msg_type_number_t count); void print_purge_info_summary(int sleep_duration); static inline int purge_info_size_adjust(uint64_t size) { while(size > KB) size /= KB; return (int)size; } static inline char purge_info_unit(uint64_t size) { char sizes[] = {'B', 'K', 'M', 'G', 'T'}; int index = 0; while(size > KB) { index++; size /= KB; } return sizes[index]; } void print_header(int summary_view) { if (!summary_view) printf("%20s ", "Process-Name"); printf("%9s %9s %9s %9s %9s %9s %9s %9s %9s %9s %9s %9s %9s %9s %9s %9s %9s\n", "FIFO-P0", "FIFO-P1", "FIFO-P2", "FIFO-P3", "FIFO-P4", "FIFO-P5", "FIFO-P6", "FIFO-P7", "OBSOLETE", "LIFO-P0", "LIFO-P1", "LIFO-P2", "LIFO-P3", "LIFO-P4", "LIFO-P5", "LIFO-P6", "LIFO-P7" ); } int get_task_from_pid(int pid, task_t *task) { kern_return_t kr; if (geteuid() != 0) { fprintf(stderr, "%s\n", PRIV_ERR_MSG); return -1; } kr = task_for_pid(mach_task_self(), pid, task); if (kr != KERN_SUCCESS) { fprintf(stderr, "Failed to get task port for pid: %d\n", pid); return -1; } return 0; } int get_system_tasks(task_array_t *tasks, mach_msg_type_number_t *count) { processor_set_name_array_t psets; mach_msg_type_number_t psetCount; mach_port_t pset_priv; kern_return_t ret; if (geteuid() != 0) { fprintf(stderr, "%s\n", PRIV_ERR_MSG); return -1; } ret = host_processor_sets(mach_host_self(), &psets, &psetCount); if (ret != KERN_SUCCESS) { fprintf(stderr, "host_processor_sets() failed: %s\n", mach_error_string(ret)); return -1; } if (psetCount != 1) { fprintf(stderr, "Assertion Failure: pset count greater than one (%d)\n", psetCount); return -1; } /* convert the processor-set-name port to a privileged port */ ret = host_processor_set_priv(mach_host_self(), psets[0], &pset_priv); if (ret != KERN_SUCCESS) { fprintf(stderr, "host_processor_set_priv() failed: %s\n", mach_error_string(ret)); return -1; } mach_port_deallocate(mach_task_self(), psets[0]); vm_deallocate(mach_task_self(), (vm_address_t)psets, (vm_size_t)psetCount * sizeof(mach_port_t)); /* convert the processor-set-priv to a list of tasks for the processor set */ ret = processor_set_tasks(pset_priv, tasks, count); if (ret != KERN_SUCCESS) { fprintf(stderr, "processor_set_tasks() failed: %s\n", mach_error_string(ret)); return -1; } mach_port_deallocate(mach_task_self(), pset_priv); return 0; } void print_purge_info_task(task_t task, int pid) { task_purgable_info_t info; kern_return_t kr; int i; char pname[PROC_NAME_LEN]; kr = task_purgable_info(task, &info); if (kr != KERN_SUCCESS) { fprintf(stderr, "(pid: %d) task_purgable_info() failed: %s\n", pid, mach_error_string(kr)); return; } if (0 == proc_name(pid, pname, PROC_NAME_LEN)) strncpy(pname, "Unknown", 7); pname[20] = 0; printf("%20s ", pname); for (i=0; i