summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHan Ming Ong <hanming@apple.com>2012-11-27 19:21:03 +0000
committerHan Ming Ong <hanming@apple.com>2012-11-27 19:21:03 +0000
commit8594ae85d5134489b8ab904ed4dbc846a722d2be (patch)
tree8a39ca7944090e619ee583c28f934b3612fa2062
parent5cb8cfae1e8e53d0f0154ba663c2cfb6fa0ca83b (diff)
downloadbcm5719-llvm-8594ae85d5134489b8ab904ed4dbc846a722d2be.tar.gz
bcm5719-llvm-8594ae85d5134489b8ab904ed4dbc846a722d2be.zip
<rdar://problem/12759744> Provide physical memory distribution as part of profile data
Make use of unix system calls to provide physical memory usage profile data. llvm-svn: 168720
-rw-r--r--lldb/tools/debugserver/source/MacOSX/MachTask.cpp24
-rw-r--r--lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp129
-rw-r--r--lldb/tools/debugserver/source/MacOSX/MachVMMemory.h2
3 files changed, 146 insertions, 9 deletions
diff --git a/lldb/tools/debugserver/source/MacOSX/MachTask.cpp b/lldb/tools/debugserver/source/MacOSX/MachTask.cpp
index 6f6f1430981..836cd3ff0e4 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachTask.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/MachTask.cpp
@@ -231,7 +231,7 @@ MachTask::GetMemoryRegionInfo (nub_addr_t addr, DNBRegionInfo *region_info)
(r)->tv_usec = (a)->microseconds; \
} while (0)
-// todo: make use of existing MachThread, if there is already one?
+// We should consider moving this into each MacThread.
static void update_used_time(task_t task, int &num_threads, uint64_t **threads_id, uint64_t **threads_used_usec, struct timeval &current_used_time)
{
kern_return_t kr;
@@ -296,11 +296,6 @@ MachTask::GetProfileDataAsCString ()
int num_threads = 0;
uint64_t *threads_used_usec = NULL;
uint64_t *threads_id = NULL;
- mach_vm_size_t rprvt = 0;
- mach_vm_size_t rsize = 0;
- mach_vm_size_t vprvt = 0;
- mach_vm_size_t vsize = 0;
- mach_vm_size_t dirty_size = 0;
// Get current used time.
struct timeval current_used_time;
@@ -318,7 +313,14 @@ MachTask::GetProfileDataAsCString ()
elapsed_usec = current_elapsed_time.tv_sec * 1000000ULL + current_elapsed_time.tv_usec;
}
- if (m_vm_memory.GetMemoryProfile(task, task_info, m_process->GetCPUType(), m_process->ProcessID(), rprvt, rsize, vprvt, vsize, dirty_size))
+ struct vm_statistics vm_stats;
+ uint64_t physical_memory;
+ mach_vm_size_t rprvt = 0;
+ mach_vm_size_t rsize = 0;
+ mach_vm_size_t vprvt = 0;
+ mach_vm_size_t vsize = 0;
+ mach_vm_size_t dirty_size = 0;
+ if (m_vm_memory.GetMemoryProfile(task, task_info, m_process->GetCPUType(), m_process->ProcessID(), vm_stats, physical_memory, rprvt, rsize, vprvt, vsize, dirty_size))
{
std::ostringstream profile_data_stream;
@@ -332,6 +334,14 @@ MachTask::GetProfileDataAsCString ()
}
profile_data_stream << ';';
+ profile_data_stream << "wired:" << vm_stats.wire_count * vm_page_size << ';';
+ profile_data_stream << "active:" << vm_stats.active_count * vm_page_size << ';';
+ profile_data_stream << "inactive:" << vm_stats.inactive_count * vm_page_size << ';';
+ uint64_t total_used_count = vm_stats.wire_count + vm_stats.inactive_count + vm_stats.active_count;
+ profile_data_stream << "used:" << total_used_count * vm_page_size << ';';
+ profile_data_stream << "free:" << vm_stats.free_count * vm_page_size << ';';
+ profile_data_stream << "total:" << physical_memory << ';';
+
profile_data_stream << "rprvt:" << rprvt << ';';
profile_data_stream << "rsize:" << rsize << ';';
profile_data_stream << "vprvt:" << vprvt << ';';
diff --git a/lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp b/lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
index b92f92c3e22..d13cbfe0131 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
@@ -16,6 +16,7 @@
#include "DNBLog.h"
#include <mach/mach_vm.h>
#include <mach/shared_region.h>
+#include <sys/sysctl.h>
MachVMMemory::MachVMMemory() :
m_page_size (kInvalidPageSize),
@@ -89,6 +90,126 @@ MachVMMemory::GetMemoryRegionInfo(task_t task, nub_addr_t address, DNBRegionInfo
return true;
}
+// For integrated graphics chip, this makes the accounting info for 'wired' memory more like top.
+static uint64_t GetStolenPages()
+{
+ static uint64_t stolenPages = 0;
+ static bool calculated = false;
+ if (calculated) return stolenPages;
+
+ static int mib_reserved[CTL_MAXNAME];
+ static int mib_unusable[CTL_MAXNAME];
+ static int mib_other[CTL_MAXNAME];
+ static size_t mib_reserved_len = 0;
+ static size_t mib_unusable_len = 0;
+ static size_t mib_other_len = 0;
+ int r;
+
+ /* This can be used for testing: */
+ //tsamp->pages_stolen = (256 * 1024 * 1024ULL) / tsamp->pagesize;
+
+ if(0 == mib_reserved_len)
+ {
+ mib_reserved_len = CTL_MAXNAME;
+
+ r = sysctlnametomib("machdep.memmap.Reserved", mib_reserved,
+ &mib_reserved_len);
+
+ if(-1 == r)
+ {
+ mib_reserved_len = 0;
+ return 0;
+ }
+
+ mib_unusable_len = CTL_MAXNAME;
+
+ r = sysctlnametomib("machdep.memmap.Unusable", mib_unusable,
+ &mib_unusable_len);
+
+ if(-1 == r)
+ {
+ mib_reserved_len = 0;
+ return 0;
+ }
+
+
+ mib_other_len = CTL_MAXNAME;
+
+ r = sysctlnametomib("machdep.memmap.Other", mib_other,
+ &mib_other_len);
+
+ if(-1 == r)
+ {
+ mib_reserved_len = 0;
+ return 0;
+ }
+ }
+
+ if(mib_reserved_len > 0 && mib_unusable_len > 0 && mib_other_len > 0)
+ {
+ uint64_t reserved = 0, unusable = 0, other = 0;
+ size_t reserved_len;
+ size_t unusable_len;
+ size_t other_len;
+
+ reserved_len = sizeof(reserved);
+ unusable_len = sizeof(unusable);
+ other_len = sizeof(other);
+
+ /* These are all declared as QUAD/uint64_t sysctls in the kernel. */
+
+ if(-1 == sysctl(mib_reserved, mib_reserved_len, &reserved,
+ &reserved_len, NULL, 0))
+ {
+ return 0;
+ }
+
+ if(-1 == sysctl(mib_unusable, mib_unusable_len, &unusable,
+ &unusable_len, NULL, 0))
+ {
+ return 0;
+ }
+
+ if(-1 == sysctl(mib_other, mib_other_len, &other,
+ &other_len, NULL, 0))
+ {
+ return 0;
+ }
+
+ if(reserved_len == sizeof(reserved)
+ && unusable_len == sizeof(unusable)
+ && other_len == sizeof(other))
+ {
+ uint64_t stolen = reserved + unusable + other;
+ uint64_t mb128 = 128 * 1024 * 1024ULL;
+
+ if(stolen >= mb128)
+ {
+ stolen = (stolen & ~((128 * 1024 * 1024ULL) - 1)); // rounding down
+ stolenPages = stolen/vm_page_size;
+ }
+ }
+ }
+
+ calculated = true;
+ return stolenPages;
+}
+
+static uint64_t GetPhysicalMemory()
+{
+ // This doesn't change often at all. No need to poll each time.
+ static uint64_t physical_memory = 0;
+ static bool calculated = false;
+ if (calculated) return physical_memory;
+
+ int mib[2];
+ mib[0] = CTL_HW;
+ mib[1] = HW_MEMSIZE;
+ size_t len = sizeof(physical_memory);
+ sysctl(mib, 2, &physical_memory, &len, NULL, 0);
+ return physical_memory;
+}
+
// 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.
static void GetRegionSizes(task_t task, mach_vm_size_t &rsize, mach_vm_size_t &dirty_size)
{
@@ -276,8 +397,14 @@ static void GetMemorySizes(task_t task, cpu_type_t cputype, nub_process_t pid, m
}
nub_bool_t
-MachVMMemory::GetMemoryProfile(task_t task, struct task_basic_info ti, cpu_type_t cputype, nub_process_t pid, 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)
+MachVMMemory::GetMemoryProfile(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)
{
+ static mach_port_t localHost = mach_host_self();
+ mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
+ host_statistics(localHost, HOST_VM_INFO, (host_info_t)&vm_stats, &count);
+ vm_stats.wire_count += GetStolenPages();
+ physical_memory = GetPhysicalMemory();
+
// 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.
GetRegionSizes(task, rsize, dirty_size);
diff --git a/lldb/tools/debugserver/source/MacOSX/MachVMMemory.h b/lldb/tools/debugserver/source/MacOSX/MachVMMemory.h
index cbb0224a93c..2a8f3d13c84 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachVMMemory.h
+++ b/lldb/tools/debugserver/source/MacOSX/MachVMMemory.h
@@ -28,7 +28,7 @@ public:
nub_size_t Write(task_t task, nub_addr_t address, const void *data, nub_size_t data_count);
nub_size_t PageSize();
nub_bool_t GetMemoryRegionInfo(task_t task, nub_addr_t address, DNBRegionInfo *region_info);
- nub_bool_t GetMemoryProfile(task_t task, struct task_basic_info ti, cpu_type_t cputype, nub_process_t pid, 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);
+ nub_bool_t GetMemoryProfile(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);
protected:
nub_size_t MaxBytesLeftInPage(nub_addr_t addr, nub_size_t count);
OpenPOWER on IntegriCloud