1 // Copyright 2023 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_METRICS_HISTOGRAM_SHARED_MEMORY_H_ 6 #define BASE_METRICS_HISTOGRAM_SHARED_MEMORY_H_ 7 8 #include <optional> 9 #include <string_view> 10 11 #include "base/base_export.h" 12 #include "base/command_line.h" 13 #include "base/feature_list.h" 14 #include "base/memory/unsafe_shared_memory_region.h" 15 #include "base/metrics/persistent_memory_allocator.h" 16 #include "base/process/launch.h" 17 #include "build/build_config.h" 18 19 #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) 20 #include "base/files/platform_file.h" 21 #include "base/posix/global_descriptors.h" 22 #endif 23 24 #if !BUILDFLAG(USE_BLINK) 25 #error "This is only intended for platforms that use blink." 26 #endif 27 28 namespace base { 29 30 BASE_EXPORT BASE_DECLARE_FEATURE(kPassHistogramSharedMemoryOnLaunch); 31 32 // Helper structure to create and return a shared memory region and a histogram 33 // allocator over top of it. Once returned it is expected that the caller will 34 // move both the memory regions and the allocator out of the struct and into 35 // it's own appropriate state variables. Note that the memory region must 36 // outlive the allocator. 37 struct BASE_EXPORT HistogramSharedMemory { 38 HistogramSharedMemory() = delete; 39 ~HistogramSharedMemory() = delete; 40 HistogramSharedMemory(HistogramSharedMemory&) = delete; 41 HistogramSharedMemory(HistogramSharedMemory&&) = delete; 42 HistogramSharedMemory& operator=(HistogramSharedMemory&) = delete; 43 HistogramSharedMemory& operator=(HistogramSharedMemory&&) = delete; 44 45 // Configuration with which to create a histogram shared memory region and 46 // allocator. Note the expectation that this be initialized with static 47 // data for the allocator name (i.e., a string literal or static constant 48 // character array). 49 struct BASE_EXPORT Config { 50 const int process_type; // See: content/public/common/process_type.h 51 const std::string_view allocator_name; 52 const size_t memory_size_bytes; 53 }; 54 55 // Temporary structure used to return the shared memory region and allocator 56 // created by the |Create| factory function. The caller is expected to move 57 // the returned values out of this struct. 58 struct BASE_EXPORT SharedMemory { 59 UnsafeSharedMemoryRegion region; 60 std::unique_ptr<PersistentMemoryAllocator> allocator; 61 62 SharedMemory(UnsafeSharedMemoryRegion, 63 std::unique_ptr<PersistentMemoryAllocator>); 64 ~SharedMemory(); 65 66 // Movable 67 SharedMemory(SharedMemory&&); 68 SharedMemory& operator=(SharedMemory&&); 69 70 // Not copyable 71 SharedMemory(SharedMemory&) = delete; 72 SharedMemory& operator=(SharedMemory&) = delete; 73 }; 74 75 // Factory to initialize a shared |memory_region| and |allocator| for 76 // |process_id| based on |config|. On success, returns true and updates 77 // the values of |memory_region| and |allocator|. On failure, returns false 78 // and |memory_region| and |allocator| are unchanged. 79 static std::optional<SharedMemory> Create(int process_id, 80 const Config& config); 81 82 #if BUILDFLAG(IS_APPLE) 83 // Exposed for testing. 84 static const MachPortsForRendezvous::key_type kRendezvousKey; 85 #endif 86 87 // Returns true if passing the shared memory handle via command-line arguments 88 // is enabled. 89 static bool PassOnCommandLineIsEnabled(std::string_view process_type); 90 91 // Updates the launch parameters to share |unsafe_memory_region| to a 92 // child process that is about to be launched. This should be called in the 93 // parent process as a part of setting up the launch conditions of the child. 94 // This call will update the |command_line| and |launch_options|. On posix, 95 // where we prefer to use a zygote instead of using the launch_options to 96 // launch a new process, the platform |descriptor_to_share| is returned. The 97 // caller is expected to transmit the descriptor to the launch flow for the 98 // zygote. 99 static void AddToLaunchParameters( 100 UnsafeSharedMemoryRegion unsafe_memory_region, 101 #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) 102 GlobalDescriptors::Key descriptor_key, 103 ScopedFD& descriptor_to_share, 104 #endif 105 CommandLine* command_line, 106 LaunchOptions* launch_options); 107 108 // Initialize the (global) histogram shared memory from the launch parameters. 109 // This should be called in the child process before any histogram samples are 110 // recorded. 111 static void InitFromLaunchParameters(const CommandLine& command_line); 112 }; 113 114 } // namespace base 115 116 #endif // BASE_METRICS_HISTOGRAM_SHARED_MEMORY_H_ 117