diff options
-rw-r--r-- | base/process_util_win.cc | 37 | ||||
-rw-r--r-- | chrome/browser/memory_details.cc | 70 | ||||
-rw-r--r-- | chrome/browser/memory_details.h | 1 | ||||
-rw-r--r-- | chrome/browser/resources/about_memory.html | 3 |
4 files changed, 66 insertions, 45 deletions
diff --git a/base/process_util_win.cc b/base/process_util_win.cc index fc05664..45a23e8 100644 --- a/base/process_util_win.cc +++ b/base/process_util_win.cc @@ -524,21 +524,30 @@ void ProcessMetrics::GetCommittedKBytes(CommittedKBytes* usage) const { size_t committed_mapped = 0; size_t committed_image = 0; void* base_address = NULL; - while (VirtualQueryEx(process_, base_address, &mbi, - sizeof(MEMORY_BASIC_INFORMATION)) == - sizeof(MEMORY_BASIC_INFORMATION)) { - if (mbi.State == MEM_COMMIT) { - if (mbi.Type == MEM_PRIVATE) { - committed_private += mbi.RegionSize; - } else if (mbi.Type == MEM_MAPPED) { - committed_mapped += mbi.RegionSize; - } else if (mbi.Type == MEM_IMAGE) { - committed_image += mbi.RegionSize; - } else { - NOTREACHED(); - } + while (VirtualQueryEx(process_, base_address, &mbi, sizeof(mbi)) == + sizeof(mbi)) { + if (mbi.State == MEM_COMMIT) { + if (mbi.Type == MEM_PRIVATE) { + committed_private += mbi.RegionSize; + } else if (mbi.Type == MEM_MAPPED) { + committed_mapped += mbi.RegionSize; + } else if (mbi.Type == MEM_IMAGE) { + committed_image += mbi.RegionSize; + } else { + NOTREACHED(); } - base_address = (static_cast<BYTE*>(mbi.BaseAddress)) + mbi.RegionSize; + } + void* new_base = (static_cast<BYTE*>(mbi.BaseAddress)) + mbi.RegionSize; + // Avoid infinite loop by weird MEMORY_BASIC_INFORMATION. + // If we query 64bit processes in a 32bit process, VirtualQueryEx() + // returns such data. + if (new_base <= base_address) { + usage->image = 0; + usage->mapped = 0; + usage->priv = 0; + return; + } + base_address = new_base; } usage->image = committed_image / 1024; usage->mapped = committed_mapped / 1024; diff --git a/chrome/browser/memory_details.cc b/chrome/browser/memory_details.cc index a6dc4dc..362bedc 100644 --- a/chrome/browser/memory_details.cc +++ b/chrome/browser/memory_details.cc @@ -19,12 +19,14 @@ class RenderViewHostDelegate; // Template of static data we use for finding browser process information. // These entries must match the ordering for MemoryDetails::BrowserProcess. -static ProcessData g_process_template[] = { +static ProcessData + g_process_template[MemoryDetails::MAX_BROWSERS] = { { L"Chromium", L"chrome.exe", }, { L"IE", L"iexplore.exe", }, { L"Firefox", L"firefox.exe", }, { L"Opera", L"opera.exe", }, { L"Safari", L"safari.exe", }, + { L"IE (64bit)", L"iexplore.exe", }, }; @@ -89,41 +91,46 @@ void MemoryDetails::CollectProcessData( DCHECK(MessageLoop::current() == ChromeThread::GetMessageLoop(ChromeThread::FILE)); - int array_size = 32; - scoped_ptr_malloc<DWORD> process_list; - DWORD bytes_used = 0; - do { - array_size *= 2; - process_list.reset(static_cast<DWORD*>( - realloc(process_list.release(), sizeof(DWORD) * array_size))); - // EnumProcesses doesn't return an error if the array is too small. - // We have to check if the return buffer is full, and if so, call it - // again. See msdn docs for more info. - if (!EnumProcesses(process_list.get(), array_size * sizeof(DWORD), - &bytes_used)) { - LOG(ERROR) << "EnumProcesses failed: " << GetLastError(); - return; - } - } while (bytes_used == (array_size * sizeof(DWORD))); - - int num_processes = bytes_used / sizeof(DWORD); - // Clear old data. for (int index = 0; index < arraysize(g_process_template); index++) process_data_[index].processes.clear(); - for (int index = 0; index < num_processes; index++) { - int pid = process_list.get()[index]; - ScopedHandle handle(OpenProcess( + SYSTEM_INFO system_info; + GetNativeSystemInfo(&system_info); + bool is_64bit_os = + system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; + + ScopedHandle snapshot(::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)); + PROCESSENTRY32 process_entry = {sizeof(PROCESSENTRY32)}; + if (!snapshot.Get()) { + LOG(ERROR) << "CreateToolhelp32Snaphot failed: " << GetLastError(); + return; + } + if (!::Process32First(snapshot, &process_entry)) { + LOG(ERROR) << "Process32First failed: " << GetLastError(); + return; + } + do { + int pid = process_entry.th32ProcessID; + ScopedHandle handle(::OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid)); if (!handle.Get()) continue; - TCHAR name[MAX_PATH]; - if (!GetModuleBaseName(handle, NULL, name, MAX_PATH - 1)) - continue; + bool is_64bit_process = false; + // IsWow64Process() returns FALSE for a 32bit process on a 32bit OS. + // We need to check if the real OS is 64bit. + if (is_64bit_os) { + BOOL is_wow64 = FALSE; + // IsWow64Process() is supported by Windows XP SP2 or later. + IsWow64Process(handle, &is_wow64); + is_64bit_process = !is_wow64; + } for (int index2 = 0; index2 < arraysize(g_process_template); index2++) { - if (_wcsicmp(process_data_[index2].process_name, name) != 0) + if (_wcsicmp(process_data_[index2].process_name, + process_entry.szExeFile) != 0) continue; + if (index2 == IE_BROWSER && is_64bit_process) + continue; // Should use IE_64BIT_BROWSER // Get Memory Information. ProcessMemoryInformation info; info.pid = pid; @@ -138,9 +145,10 @@ void MemoryDetails::CollectProcessData( metrics->GetWorkingSetKBytes(&info.working_set); // Get Version Information. - if (index2 == 0) { // Chrome + TCHAR name[MAX_PATH]; + if (index2 == CHROME_BROWSER) { scoped_ptr<FileVersionInfo> version_info( - FileVersionInfo::CreateFileVersionInfoForCurrentModule()); + FileVersionInfo::CreateFileVersionInfoForCurrentModule()); if (version_info != NULL) info.version = version_info->file_version(); // Check if this is one of the child processes whose data we collected @@ -155,7 +163,7 @@ void MemoryDetails::CollectProcessData( } else if (GetModuleFileNameEx(handle, NULL, name, MAX_PATH - 1)) { std::wstring str_name(name); scoped_ptr<FileVersionInfo> version_info( - FileVersionInfo::CreateFileVersionInfo(str_name)); + FileVersionInfo::CreateFileVersionInfo(str_name)); if (version_info != NULL) { info.version = version_info->product_version(); info.product_name = version_info->product_name(); @@ -166,7 +174,7 @@ void MemoryDetails::CollectProcessData( process_data_[index2].processes.push_back(info); break; } - } + } while (::Process32Next(snapshot, &process_entry)); // Finally return to the browser thread. ui_loop_->PostTask(FROM_HERE, diff --git a/chrome/browser/memory_details.h b/chrome/browser/memory_details.h index 2725285..ddf5280 100644 --- a/chrome/browser/memory_details.h +++ b/chrome/browser/memory_details.h @@ -78,6 +78,7 @@ class MemoryDetails : public base::RefCountedThreadSafe<MemoryDetails> { FIREFOX_BROWSER, OPERA_BROWSER, SAFARI_BROWSER, + IE_64BIT_BROWSER, MAX_BROWSERS } BrowserProcess; diff --git a/chrome/browser/resources/about_memory.html b/chrome/browser/resources/about_memory.html index 0c31cdd..08f24ce 100644 --- a/chrome/browser/resources/about_memory.html +++ b/chrome/browser/resources/about_memory.html @@ -330,6 +330,9 @@ function reload() { function formatNumber(str) { str += ''; + if (str == '0') { + return 'N/A '; + } var x = str.split('.'); var x1 = x[0]; var x2 = x.length > 1 ? '.' + x[1] : ''; |