[Lldb-commits] [lldb] r168720 - in /lldb/trunk/tools/debugserver/source/MacOSX: MachTask.cpp MachVMMemory.cpp MachVMMemory.h

Han Ming Ong hanming at apple.com
Tue Nov 27 11:21:03 PST 2012


Author: hanming
Date: Tue Nov 27 13:21:03 2012
New Revision: 168720

URL: http://llvm.org/viewvc/llvm-project?rev=168720&view=rev
Log:
<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.

Modified:
    lldb/trunk/tools/debugserver/source/MacOSX/MachTask.cpp
    lldb/trunk/tools/debugserver/source/MacOSX/MachVMMemory.cpp
    lldb/trunk/tools/debugserver/source/MacOSX/MachVMMemory.h

Modified: lldb/trunk/tools/debugserver/source/MacOSX/MachTask.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/MachTask.cpp?rev=168720&r1=168719&r2=168720&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/MachTask.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/MachTask.cpp Tue Nov 27 13:21:03 2012
@@ -231,7 +231,7 @@
 (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 @@
     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 @@
         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 @@
         }
         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 << ';';

Modified: lldb/trunk/tools/debugserver/source/MacOSX/MachVMMemory.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/MachVMMemory.cpp?rev=168720&r1=168719&r2=168720&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/MachVMMemory.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/MachVMMemory.cpp Tue Nov 27 13:21:03 2012
@@ -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 @@
     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 @@
 }
 
 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);
     

Modified: lldb/trunk/tools/debugserver/source/MacOSX/MachVMMemory.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/MachVMMemory.h?rev=168720&r1=168719&r2=168720&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/MachVMMemory.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/MachVMMemory.h Tue Nov 27 13:21:03 2012
@@ -28,7 +28,7 @@
     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);





More information about the lldb-commits mailing list