MachVMMemory.cpp revision 3a54da4467c036cf6b8ed4afe5cdd9dd7409c2d5
124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===-- MachVMMemory.cpp ----------------------------------------*- C++ -*-===// 224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// The LLVM Compiler Infrastructure 424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// This file is distributed under the University of Illinois Open Source 624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// License. See LICENSE.TXT for details. 724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===----------------------------------------------------------------------===// 924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 1024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Created by Greg Clayton on 6/26/07. 1124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 1224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===----------------------------------------------------------------------===// 1324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 1424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "MachVMMemory.h" 1524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "MachVMRegion.h" 1624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "DNBLog.h" 1724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <mach/mach_vm.h> 18fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong#include <mach/shared_region.h> 19e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong#include <sys/sysctl.h> 2077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong#include <dlfcn.h> 2124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 2224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::MachVMMemory() : 2324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_page_size (kInvalidPageSize), 2424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err (0) 2524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 2624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 2724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 2824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::~MachVMMemory() 2924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 3024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 3124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 3224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnernub_size_t 33fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason MolendaMachVMMemory::PageSize(task_t task) 3424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 3524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_page_size == kInvalidPageSize) 3624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 37fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda#if defined (TASK_VM_INFO) && TASK_VM_INFO >= 22 38fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda if (task != TASK_NULL) 39fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda { 40fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda kern_return_t kr; 41fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda mach_msg_type_number_t info_count = TASK_VM_INFO_COUNT; 42fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda task_vm_info_data_t vm_info; 43fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda kr = task_info (task, TASK_VM_INFO, (task_info_t) &vm_info, &info_count); 44fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda if (kr == KERN_SUCCESS) 45fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda { 46dfb7c7f12cbefccf5f097ec90f6d157e2a32f35dJason Molenda DNBLogThreadedIf(LOG_TASK, "MachVMMemory::PageSize task_info returned page size of 0x%x", (int) vm_info.page_size); 47e255a7d13780e35b97e0f2954cba47cc9eaae7e0Jason Molenda m_page_size = vm_info.page_size; 48e255a7d13780e35b97e0f2954cba47cc9eaae7e0Jason Molenda return m_page_size; 49fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda } 5092748483a4c36e9bf2535abb863dbca1271053a1Jason Molenda else 5192748483a4c36e9bf2535abb863dbca1271053a1Jason Molenda { 5292748483a4c36e9bf2535abb863dbca1271053a1Jason Molenda DNBLogThreadedIf(LOG_TASK, "MachVMMemory::PageSize task_info call failed to get page size, TASK_VM_INFO %d, TASK_VM_INFO_COUNT %d, kern return %d", TASK_VM_INFO, TASK_VM_INFO_COUNT, kr); 5392748483a4c36e9bf2535abb863dbca1271053a1Jason Molenda } 54fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda } 55fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda#endif 5624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err = ::host_page_size( ::mach_host_self(), &m_page_size); 5724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_err.Fail()) 5824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_page_size = 0; 5924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 6024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return m_page_size; 6124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 6224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 6324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnernub_size_t 64fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason MolendaMachVMMemory::MaxBytesLeftInPage(task_t task, nub_addr_t addr, nub_size_t count) 6524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 66fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda const nub_size_t page_size = PageSize(task); 6724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (page_size > 0) 6824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 6924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_size_t page_offset = (addr % page_size); 7024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_size_t bytes_left_in_page = page_size - page_offset; 7124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (count > bytes_left_in_page) 7224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner count = bytes_left_in_page; 7324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 7424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return count; 7524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 7624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 771308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Claytonnub_bool_t 78a9385537809ef342c843c5ab972e513742652047Greg ClaytonMachVMMemory::GetMemoryRegionInfo(task_t task, nub_addr_t address, DNBRegionInfo *region_info) 79dc8ff30b6dbe28c851e99712e20c1358eca4709dJason Molenda{ 80dc8ff30b6dbe28c851e99712e20c1358eca4709dJason Molenda MachVMRegion vmRegion(task); 81dc8ff30b6dbe28c851e99712e20c1358eca4709dJason Molenda 82a9385537809ef342c843c5ab972e513742652047Greg Clayton if (vmRegion.GetRegionForAddress(address)) 83a9385537809ef342c843c5ab972e513742652047Greg Clayton { 84a9385537809ef342c843c5ab972e513742652047Greg Clayton region_info->addr = vmRegion.StartAddress(); 85a9385537809ef342c843c5ab972e513742652047Greg Clayton region_info->size = vmRegion.GetByteSize(); 86a9385537809ef342c843c5ab972e513742652047Greg Clayton region_info->permissions = vmRegion.GetDNBPermissions(); 87a9385537809ef342c843c5ab972e513742652047Greg Clayton } 881308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton else 891308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton { 901308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton region_info->addr = address; 911308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton region_info->size = 0; 921308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton if (vmRegion.GetError().Success()) 931308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton { 941308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // vmRegion.GetRegionForAddress() return false, indicating that "address" 951308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // wasn't in a valid region, but the "vmRegion" info was successfully 961308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // read from the task which means the info describes the next valid 971308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // region from which we can infer the size of this invalid region 981308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton mach_vm_address_t start_addr = vmRegion.StartAddress(); 991308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton if (address < start_addr) 1001308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton region_info->size = start_addr - address; 1011308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton } 1021308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // If we can't get any infor about the size from the next region, just fill 1031308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // 1 in as the byte size 1041308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton if (region_info->size == 0) 1051308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton region_info->size = 1; 1061308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton 1071308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton // Not readable, writeable or executable 1081308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton region_info->permissions = 0; 1091308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton } 1101308a9555ad586ff03c8f97bcfe7f3212d06bc86Greg Clayton return true; 111dc8ff30b6dbe28c851e99712e20c1358eca4709dJason Molenda} 112fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 113e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong// For integrated graphics chip, this makes the accounting info for 'wired' memory more like top. 114fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molendauint64_t 115fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason MolendaMachVMMemory::GetStolenPages(task_t task) 116e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong{ 117e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static uint64_t stolenPages = 0; 118e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static bool calculated = false; 119e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if (calculated) return stolenPages; 120e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 121e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static int mib_reserved[CTL_MAXNAME]; 122e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static int mib_unusable[CTL_MAXNAME]; 123e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static int mib_other[CTL_MAXNAME]; 124e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static size_t mib_reserved_len = 0; 125e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static size_t mib_unusable_len = 0; 126e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static size_t mib_other_len = 0; 127e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong int r; 128e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 129e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong /* This can be used for testing: */ 130e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong //tsamp->pages_stolen = (256 * 1024 * 1024ULL) / tsamp->pagesize; 131e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 132e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(0 == mib_reserved_len) 133e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 134e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib_reserved_len = CTL_MAXNAME; 135e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 136e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong r = sysctlnametomib("machdep.memmap.Reserved", mib_reserved, 137e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong &mib_reserved_len); 138e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 139e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(-1 == r) 140e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 141e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib_reserved_len = 0; 142e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return 0; 143e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 144e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 145e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib_unusable_len = CTL_MAXNAME; 146e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 147e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong r = sysctlnametomib("machdep.memmap.Unusable", mib_unusable, 148e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong &mib_unusable_len); 149e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 150e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(-1 == r) 151e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 152e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib_reserved_len = 0; 153e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return 0; 154e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 155e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 156e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 157e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib_other_len = CTL_MAXNAME; 158e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 159e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong r = sysctlnametomib("machdep.memmap.Other", mib_other, 160e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong &mib_other_len); 161e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 162e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(-1 == r) 163e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 164e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib_reserved_len = 0; 165e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return 0; 166e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 167e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 168e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 169e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(mib_reserved_len > 0 && mib_unusable_len > 0 && mib_other_len > 0) 170e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 171e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong uint64_t reserved = 0, unusable = 0, other = 0; 172e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong size_t reserved_len; 173e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong size_t unusable_len; 174e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong size_t other_len; 175e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 176e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong reserved_len = sizeof(reserved); 177e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong unusable_len = sizeof(unusable); 178e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong other_len = sizeof(other); 179e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 180e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong /* These are all declared as QUAD/uint64_t sysctls in the kernel. */ 181e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 182e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(-1 == sysctl(mib_reserved, mib_reserved_len, &reserved, 183e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong &reserved_len, NULL, 0)) 184e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 185e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return 0; 186e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 187e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 188e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(-1 == sysctl(mib_unusable, mib_unusable_len, &unusable, 189e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong &unusable_len, NULL, 0)) 190e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 191e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return 0; 192e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 193e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 194e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(-1 == sysctl(mib_other, mib_other_len, &other, 195e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong &other_len, NULL, 0)) 196e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 197e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return 0; 198e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 199e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 200e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(reserved_len == sizeof(reserved) 201e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong && unusable_len == sizeof(unusable) 202e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong && other_len == sizeof(other)) 203e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 204e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong uint64_t stolen = reserved + unusable + other; 205e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong uint64_t mb128 = 128 * 1024 * 1024ULL; 206e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 207e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if(stolen >= mb128) 208e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong { 209e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong stolen = (stolen & ~((128 * 1024 * 1024ULL) - 1)); // rounding down 21008f60c88b61c42c35abf3233f0cbe19d29fbe814Jason Molenda stolenPages = stolen / PageSize (task); 211e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 212e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 213e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong } 214e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 215e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong calculated = true; 216e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return stolenPages; 217e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong} 218e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 219e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ongstatic uint64_t GetPhysicalMemory() 220e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong{ 221e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong // This doesn't change often at all. No need to poll each time. 222e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static uint64_t physical_memory = 0; 223e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong static bool calculated = false; 224e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong if (calculated) return physical_memory; 225e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 226e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong int mib[2]; 227e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib[0] = CTL_HW; 228e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong mib[1] = HW_MEMSIZE; 229e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong size_t len = sizeof(physical_memory); 230e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong sysctl(mib, 2, &physical_memory, &len, NULL, 0); 231e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong return physical_memory; 232e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong} 233e45c499d61f372cc93abdacf3dbfa9466c412066Han Ming Ong 234fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong// rsize and dirty_size is not adjusted for dyld shared cache and multiple __LINKEDIT segment, as in vmmap. In practice, dirty_size doesn't differ much but rsize may. There is performance penalty for the adjustment. Right now, only use the dirty_size. 235fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molendavoid 236fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason MolendaMachVMMemory::GetRegionSizes(task_t task, mach_vm_size_t &rsize, mach_vm_size_t &dirty_size) 237fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong{ 238fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong mach_vm_address_t address = 0; 239fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong mach_vm_size_t size; 240fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong kern_return_t err = 0; 241fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong unsigned nestingDepth = 0; 242fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong mach_vm_size_t pages_resident = 0; 243fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong mach_vm_size_t pages_dirtied = 0; 244fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 245fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong while (1) 246fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 2472a647e4b0eb044cffab5c8c29b6af9ed52129544Han Ming Ong mach_msg_type_number_t count; 248fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong struct vm_region_submap_info_64 info; 249fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 250fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong count = VM_REGION_SUBMAP_INFO_COUNT_64; 251fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong err = mach_vm_region_recurse(task, &address, &size, &nestingDepth, (vm_region_info_t)&info, &count); 252fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong if (err == KERN_INVALID_ADDRESS) 253fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 254fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong // It seems like this is a good break too. 255fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong break; 256fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 257fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong else if (err) 258fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 259fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong mach_error("vm_region",err); 260fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong break; // reached last region 261fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 262fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 263fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong bool should_count = true; 264fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong if (info.is_submap) 265fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { // is it a submap? 266fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong nestingDepth++; 267fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong should_count = false; 268fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 269fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong else 270fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 271fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong // Don't count malloc stack logging data in the TOTAL VM usage lines. 272fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong if (info.user_tag == VM_MEMORY_ANALYSIS_TOOL) 273fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong should_count = false; 274190276872994426fb0398e1cf521748249b75875Han Ming Ong 275fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong address = address+size; 276fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 277fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 278fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong if (should_count) 279fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 280fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong pages_resident += info.pages_resident; 281fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong pages_dirtied += info.pages_dirtied; 282fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 283fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 284fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 28577d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong vm_size_t pagesize = PageSize (task); 2862a647e4b0eb044cffab5c8c29b6af9ed52129544Han Ming Ong rsize = pages_resident * pagesize; 2872a647e4b0eb044cffab5c8c29b6af9ed52129544Han Ming Ong dirty_size = pages_dirtied * pagesize; 288fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong} 289fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 290fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong// Test whether the virtual address is within the architecture's shared region. 291fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ongstatic bool InSharedRegion(mach_vm_address_t addr, cpu_type_t type) 292fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong{ 293559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_vm_address_t base = 0, size = 0; 294fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 295559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda switch(type) { 296559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case CPU_TYPE_ARM: 297559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda base = SHARED_REGION_BASE_ARM; 298559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda size = SHARED_REGION_SIZE_ARM; 299fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong break; 300fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 301559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case CPU_TYPE_X86_64: 302559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda base = SHARED_REGION_BASE_X86_64; 303559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda size = SHARED_REGION_SIZE_X86_64; 304fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong break; 305fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 306559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case CPU_TYPE_I386: 307559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda base = SHARED_REGION_BASE_I386; 308559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda size = SHARED_REGION_SIZE_I386; 309fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong break; 310fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 311559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda default: { 312fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong // Log error abut unknown CPU type 313fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong break; 314559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 315559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 316fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 317fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 318559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda return(addr >= base && addr < (base + size)); 319fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong} 320fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 321fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molendavoid 322fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason MolendaMachVMMemory::GetMemorySizes(task_t task, cpu_type_t cputype, nub_process_t pid, mach_vm_size_t &rprvt, mach_vm_size_t &vprvt) 323fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong{ 324fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong // Collecting some other info cheaply but not reporting for now. 325fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong mach_vm_size_t empty = 0; 326559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_vm_size_t fw_private = 0; 327fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 328559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_vm_size_t aliased = 0; 329fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong bool global_shared_text_data_mapped = false; 33077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong vm_size_t pagesize = PageSize (task); 3312a647e4b0eb044cffab5c8c29b6af9ed52129544Han Ming Ong 332559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda for (mach_vm_address_t addr=0, size=0; ; addr += size) 333fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 334559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda vm_region_top_info_data_t info; 335559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_msg_type_number_t count = VM_REGION_TOP_INFO_COUNT; 336559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_port_t object_name; 337fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 338559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda kern_return_t kr = mach_vm_region(task, &addr, &size, VM_REGION_TOP_INFO, (vm_region_info_t)&info, &count, &object_name); 339559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (kr != KERN_SUCCESS) break; 340559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda 341559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (InSharedRegion(addr, cputype)) 342fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 343559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // Private Shared 344559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda fw_private += info.private_pages_resident * pagesize; 345fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 346559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // Check if this process has the globally shared text and data regions mapped in. If so, set global_shared_text_data_mapped to TRUE and avoid checking again. 347559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (global_shared_text_data_mapped == FALSE && info.share_mode == SM_EMPTY) { 3482a647e4b0eb044cffab5c8c29b6af9ed52129544Han Ming Ong vm_region_basic_info_data_64_t b_info; 349559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_vm_address_t b_addr = addr; 350559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda mach_vm_size_t b_size = size; 351559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda count = VM_REGION_BASIC_INFO_COUNT_64; 352559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda 353559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda kr = mach_vm_region(task, &b_addr, &b_size, VM_REGION_BASIC_INFO, (vm_region_info_t)&b_info, &count, &object_name); 354559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (kr != KERN_SUCCESS) break; 355fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 356559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (b_info.reserved) { 357559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda global_shared_text_data_mapped = TRUE; 358559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 359559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 360559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda 361559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // Short circuit the loop if this isn't a shared private region, since that's the only region type we care about within the current address range. 362559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (info.share_mode != SM_PRIVATE) 363fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 364559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda continue; 365559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 366559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 367559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda 368559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // Update counters according to the region type. 369559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (info.share_mode == SM_COW && info.ref_count == 1) 370fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 371559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // Treat single reference SM_COW as SM_PRIVATE 372559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda info.share_mode = SM_PRIVATE; 373559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 374fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 375559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda switch (info.share_mode) 376fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 377559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case SM_LARGE_PAGE: 378559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // Treat SM_LARGE_PAGE the same as SM_PRIVATE 379559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // since they are not shareable and are wired. 380559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case SM_PRIVATE: 381559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda rprvt += info.private_pages_resident * pagesize; 382559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda rprvt += info.shared_pages_resident * pagesize; 383559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda vprvt += size; 384559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda break; 385559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda 386559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case SM_EMPTY: 387fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong empty += size; 388559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda break; 389559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda 390559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case SM_COW: 391559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda case SM_SHARED: 392fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 393559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (pid == 0) 394fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 395559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda // Treat kernel_task specially 396559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (info.share_mode == SM_COW) 397fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 398559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda rprvt += info.private_pages_resident * pagesize; 399559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda vprvt += size; 400559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 401559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda break; 402559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 403fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 404559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda if (info.share_mode == SM_COW) 405fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong { 406559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda rprvt += info.private_pages_resident * pagesize; 407559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda vprvt += info.private_pages_resident * pagesize; 408559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 409559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda break; 410fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong } 411559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda default: 412fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong // log that something is really bad. 413559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda break; 414559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 415559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda } 416fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 417559cf6e8b52b940f5f4362b32d628838d6301e2eJason Molenda rprvt += aliased; 418fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong} 419fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 42077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong#if defined (TASK_VM_INFO) && TASK_VM_INFO >= 22 42177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong 42277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong// cribbed from sysmond 42377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ongstatic uint64_t 42477d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming OngSumVMPurgeableInfo(const vm_purgeable_info_t info) 42577d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong{ 42677d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong uint64_t sum = 0; 42777d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong int i; 42877d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong 42977d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong for (i = 0; i < 8; i++) 43077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong { 43177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong sum += info->fifo_data[i].size; 43277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong } 43377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong sum += info->obsolete_data.size; 43477d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong for (i = 0; i < 8; i++) 43577d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong { 43677d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong sum += info->lifo_data[i].size; 43777d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong } 43877d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong 43977d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong return sum; 44077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong} 44177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong 44277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong#endif 44377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong 44477d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ongstatic void 44577d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming OngGetPurgeableAndAnonymous(task_t task, uint64_t &purgeable, uint64_t &anonymous) 44677d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong{ 44777d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong#if defined (TASK_VM_INFO) && TASK_VM_INFO >= 22 44877d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong 44977d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong kern_return_t kr; 45077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong task_purgable_info_t purgeable_info; 45177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong uint64_t purgeable_sum = 0; 45277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong mach_msg_type_number_t info_count; 45377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong task_vm_info_data_t vm_info; 45477d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong 4553a54da4467c036cf6b8ed4afe5cdd9dd7409c2d5Han Ming Ong typedef kern_return_t (*task_purgable_info_type) (task_t, task_purgable_info_t *); 4563a54da4467c036cf6b8ed4afe5cdd9dd7409c2d5Han Ming Ong task_purgable_info_type task_purgable_info_ptr = NULL; 4573a54da4467c036cf6b8ed4afe5cdd9dd7409c2d5Han Ming Ong task_purgable_info_ptr = (task_purgable_info_type)dlsym(RTLD_NEXT, "task_purgable_info"); 4583a54da4467c036cf6b8ed4afe5cdd9dd7409c2d5Han Ming Ong if (task_purgable_info_ptr != NULL) 45977d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong { 4603a54da4467c036cf6b8ed4afe5cdd9dd7409c2d5Han Ming Ong kr = (*task_purgable_info_ptr)(task, &purgeable_info); 46177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong if (kr == KERN_SUCCESS) { 46277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong purgeable_sum = SumVMPurgeableInfo(&purgeable_info); 46377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong purgeable = purgeable_sum; 46477d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong } 46577d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong } 46677d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong 46777d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong info_count = TASK_VM_INFO_COUNT; 46877d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong kr = task_info(task, TASK_VM_INFO, (task_info_t)&vm_info, &info_count); 46977d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong if (kr == KERN_SUCCESS) 47077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong { 47177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong if (purgeable_sum < vm_info.internal) 47277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong { 47377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong anonymous = vm_info.internal - purgeable_sum; 47477d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong } 47577d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong else 47677d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong { 47777d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong anonymous = 0; 47877d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong } 47977d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong } 4803a54da4467c036cf6b8ed4afe5cdd9dd7409c2d5Han Ming Ong 48177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong#endif 48277d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong} 48377d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong 484fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ongnub_bool_t 48577d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming OngMachVMMemory::GetMemoryProfile(DNBProfileDataScanType scanType, task_t task, struct task_basic_info ti, cpu_type_t cputype, nub_process_t pid, vm_statistics_data_t &vm_stats, uint64_t &physical_memory, mach_vm_size_t &rprvt, mach_vm_size_t &rsize, mach_vm_size_t &vprvt, mach_vm_size_t &vsize, mach_vm_size_t &dirty_size, mach_vm_size_t &purgeable, mach_vm_size_t &anonymous) 486fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong{ 487cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong if (scanType & eProfileHostMemory) 488cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong physical_memory = GetPhysicalMemory(); 489cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong 490cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong if (scanType & eProfileMemory) 491cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong { 492cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong static mach_port_t localHost = mach_host_self(); 493cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong mach_msg_type_number_t count = HOST_VM_INFO_COUNT; 494cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong host_statistics(localHost, HOST_VM_INFO, (host_info_t)&vm_stats, &count); 495fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda vm_stats.wire_count += GetStolenPages(task); 496fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 497cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong GetMemorySizes(task, cputype, pid, rprvt, vprvt); 498fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 499cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong rsize = ti.resident_size; 500cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong vsize = ti.virtual_size; 501a53a76965eb603afe5705c694ee8e3344f91cc61Han Ming Ong 502a53a76965eb603afe5705c694ee8e3344f91cc61Han Ming Ong if (scanType & eProfileMemoryDirtyPage) 503a53a76965eb603afe5705c694ee8e3344f91cc61Han Ming Ong { 504a53a76965eb603afe5705c694ee8e3344f91cc61Han Ming Ong // This uses vmmap strategy. We don't use the returned rsize for now. We prefer to match top's version since that's what we do for the rest of the metrics. 505a53a76965eb603afe5705c694ee8e3344f91cc61Han Ming Ong GetRegionSizes(task, rsize, dirty_size); 506a53a76965eb603afe5705c694ee8e3344f91cc61Han Ming Ong } 50777d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong 50877d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong if (scanType & eProfileMemoryAnonymous) 50977d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong { 51077d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong GetPurgeableAndAnonymous(task, purgeable, anonymous); 51177d340f114b99ec8e2f7a48cbb674c93e237022bHan Ming Ong } 512cec43ab7f30085ac7f65a26a58b956a69e363a3bHan Ming Ong } 513fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong 514fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong return true; 515fb9cee64303d36d6fe5d87e63dd8701d1ddb70a9Han Ming Ong} 516dc8ff30b6dbe28c851e99712e20c1358eca4709dJason Molenda 51724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnernub_size_t 51824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::Read(task_t task, nub_addr_t address, void *data, nub_size_t data_count) 51924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 52024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (data == NULL || data_count == 0) 52124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return 0; 52224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 52324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_size_t total_bytes_read = 0; 52424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_addr_t curr_addr = address; 52524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner uint8_t *curr_data = (uint8_t*)data; 52624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner while (total_bytes_read < data_count) 52724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 528fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda mach_vm_size_t curr_size = MaxBytesLeftInPage(task, curr_addr, data_count - total_bytes_read); 52924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner mach_msg_type_number_t curr_bytes_read = 0; 53024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner vm_offset_t vm_memory = NULL; 53124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err = ::mach_vm_read (task, curr_addr, curr_size, &vm_memory, &curr_bytes_read); 532d906b1b24a6c838d78039b399ee43dc57598ab52Jim Ingham 53355f768792c75eb5f9474edb09ca416c8737eeac0Jim Ingham if (DNBLogCheckLogBit(LOG_MEMORY)) 53424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err.LogThreaded("::mach_vm_read ( task = 0x%4.4x, addr = 0x%8.8llx, size = %llu, data => %8.8p, dataCnt => %i )", task, (uint64_t)curr_addr, (uint64_t)curr_size, vm_memory, curr_bytes_read); 53524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 53624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_err.Success()) 53724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 53824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (curr_bytes_read != curr_size) 53924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 54024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (DNBLogCheckLogBit(LOG_MEMORY)) 54124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err.LogThreaded("::mach_vm_read ( task = 0x%4.4x, addr = 0x%8.8llx, size = %llu, data => %8.8p, dataCnt=>%i ) only read %u of %llu bytes", task, (uint64_t)curr_addr, (uint64_t)curr_size, vm_memory, curr_bytes_read, curr_bytes_read, (uint64_t)curr_size); 54224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 54324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ::memcpy (curr_data, (void *)vm_memory, curr_bytes_read); 54424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ::vm_deallocate (mach_task_self (), vm_memory, curr_bytes_read); 54524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner total_bytes_read += curr_bytes_read; 54624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_addr += curr_bytes_read; 54724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_data += curr_bytes_read; 54824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 54924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 55024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 55124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 55224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 55324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 55424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return total_bytes_read; 55524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 55624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 55724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 55824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnernub_size_t 55924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::Write(task_t task, nub_addr_t address, const void *data, nub_size_t data_count) 56024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 56124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner MachVMRegion vmRegion(task); 56224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 56324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_size_t total_bytes_written = 0; 56424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_addr_t curr_addr = address; 56524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const uint8_t *curr_data = (const uint8_t*)data; 56624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 56724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 56824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner while (total_bytes_written < data_count) 56924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 57024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (vmRegion.GetRegionForAddress(curr_addr)) 57124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 57224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner mach_vm_size_t curr_data_count = data_count - total_bytes_written; 57324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner mach_vm_size_t region_bytes_left = vmRegion.BytesRemaining(curr_addr); 57424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (region_bytes_left == 0) 57524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 57624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 57724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 57824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (curr_data_count > region_bytes_left) 57924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_data_count = region_bytes_left; 58024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 58124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (vmRegion.SetProtections(curr_addr, curr_data_count, VM_PROT_READ | VM_PROT_WRITE)) 58224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 58324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_size_t bytes_written = WriteRegion(task, curr_addr, curr_data, curr_data_count); 58424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (bytes_written <= 0) 58524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 58624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Error should have already be posted by WriteRegion... 58724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 58824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 58924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 59024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 59124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner total_bytes_written += bytes_written; 59224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_addr += bytes_written; 59324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_data += bytes_written; 59424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 59524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 59624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 59724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 59824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner DNBLogThreadedIf(LOG_MEMORY_PROTECTIONS, "Failed to set read/write protections on region for address: [0x%8.8llx-0x%8.8llx)", (uint64_t)curr_addr, (uint64_t)(curr_addr + curr_data_count)); 59924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 60024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 60124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 60224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 60324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 60424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner DNBLogThreadedIf(LOG_MEMORY_PROTECTIONS, "Failed to get region for address: 0x%8.8llx", (uint64_t)address); 60524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 60624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 60724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 60824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 60924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return total_bytes_written; 61024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 61124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 61224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 61324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnernub_size_t 61424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerMachVMMemory::WriteRegion(task_t task, const nub_addr_t address, const void *data, const nub_size_t data_count) 61524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 61624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (data == NULL || data_count == 0) 61724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return 0; 61824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 61924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_size_t total_bytes_written = 0; 62024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_addr_t curr_addr = address; 62124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const uint8_t *curr_data = (const uint8_t*)data; 62224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner while (total_bytes_written < data_count) 62324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 624fb190f3e1ddbaf9fb72e15a96e103de2b9c0dc44Jason Molenda mach_msg_type_number_t curr_data_count = MaxBytesLeftInPage(task, curr_addr, data_count - total_bytes_written); 62524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err = ::mach_vm_write (task, curr_addr, (pointer_t) curr_data, curr_data_count); 62624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (DNBLogCheckLogBit(LOG_MEMORY) || m_err.Fail()) 62724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err.LogThreaded("::mach_vm_write ( task = 0x%4.4x, addr = 0x%8.8llx, data = %8.8p, dataCnt = %u )", task, (uint64_t)curr_addr, curr_data, curr_data_count); 62824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 62924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#if !defined (__i386__) && !defined (__x86_64__) 63024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner vm_machine_attribute_val_t mattr_value = MATTR_VAL_CACHE_FLUSH; 63124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 63224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err = ::vm_machine_attribute (task, curr_addr, curr_data_count, MATTR_CACHE, &mattr_value); 63324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (DNBLogCheckLogBit(LOG_MEMORY) || m_err.Fail()) 63424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_err.LogThreaded("::vm_machine_attribute ( task = 0x%4.4x, addr = 0x%8.8llx, size = %u, attr = MATTR_CACHE, mattr_value => MATTR_VAL_CACHE_FLUSH )", task, (uint64_t)curr_addr, curr_data_count); 63524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#endif 63624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 63724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_err.Success()) 63824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 63924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner total_bytes_written += curr_data_count; 64024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_addr += curr_data_count; 64124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner curr_data += curr_data_count; 64224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 64324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 64424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 64524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner break; 64624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 64724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 64824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return total_bytes_written; 64924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 650