// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/trace_event/process_memory_totals_dump_provider.h" #include "base/process/process_metrics.h" #include "base/trace_event/process_memory_dump.h" #include "base/trace_event/process_memory_totals.h" #if defined(OS_LINUX) || defined(OS_ANDROID) #include #include "base/files/file_util.h" namespace { bool kernel_supports_rss_peak_reset = true; const char kClearPeakRssCommand[] = "5"; } #endif namespace base { namespace trace_event { // static uint64 ProcessMemoryTotalsDumpProvider::rss_bytes_for_testing = 0; namespace { ProcessMetrics* CreateProcessMetricsForCurrentProcess() { #if !defined(OS_MACOSX) || defined(OS_IOS) return ProcessMetrics::CreateProcessMetrics(GetCurrentProcessHandle()); #else return ProcessMetrics::CreateProcessMetrics(GetCurrentProcessHandle(), NULL); #endif } } // namespace // static ProcessMemoryTotalsDumpProvider* ProcessMemoryTotalsDumpProvider::GetInstance() { return Singleton< ProcessMemoryTotalsDumpProvider, LeakySingletonTraits>::get(); } ProcessMemoryTotalsDumpProvider::ProcessMemoryTotalsDumpProvider() : process_metrics_(CreateProcessMetricsForCurrentProcess()) { } ProcessMemoryTotalsDumpProvider::~ProcessMemoryTotalsDumpProvider() { } // Called at trace dump point time. Creates a snapshot the memory counters for // the current process. bool ProcessMemoryTotalsDumpProvider::OnMemoryDump(ProcessMemoryDump* pmd) { const uint64 rss_bytes = rss_bytes_for_testing ? rss_bytes_for_testing : process_metrics_->GetWorkingSetSize(); uint64 peak_rss_bytes = 0; #if !defined(OS_IOS) peak_rss_bytes = process_metrics_->GetPeakWorkingSetSize(); #if defined(OS_LINUX) || defined(OS_ANDROID) if (kernel_supports_rss_peak_reset) { // TODO(ssid): Fix crbug.com/461788 to write to the file from sandboxed // processes. int clear_refs_fd = open("/proc/self/clear_refs", O_WRONLY); if (clear_refs_fd > 0 && WriteFileDescriptor(clear_refs_fd, kClearPeakRssCommand, sizeof(kClearPeakRssCommand))) { pmd->process_totals()->set_is_peak_rss_resetable(true); } else { kernel_supports_rss_peak_reset = false; } close(clear_refs_fd); } #endif // defined(OS_LINUX) || defined(OS_ANDROID) #endif // !defined(OS_IOS) if (rss_bytes > 0) { pmd->process_totals()->set_resident_set_bytes(rss_bytes); pmd->process_totals()->set_peak_resident_set_bytes(peak_rss_bytes); pmd->set_has_process_totals(); return true; } return false; } } // namespace trace_event } // namespace base