1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
|
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_ASH_COMPONENTS_MEMORY_USERSPACE_SWAP_USERSPACE_SWAP_H_
#define CHROMEOS_ASH_COMPONENTS_MEMORY_USERSPACE_SWAP_USERSPACE_SWAP_H_
#include <sys/mman.h>
#include <cstdint>
#include <vector>
#include "base/component_export.h"
#include "base/process/process_handle.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "chromeos/ash/components/memory/userspace_swap/region.h"
#include "chromeos/ash/components/memory/userspace_swap/userspace_swap.mojom.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
#ifndef MREMAP_DONTUNMAP
#define MREMAP_DONTUNMAP 4
#endif
namespace userspace_swap {
namespace mojom {
class UserspaceSwap;
} // namespace mojom
} // namespace userspace_swap
// This file is for containing the browser and renderer common userspace swap
// components such as helper functions and structures.
namespace ash {
namespace memory {
namespace userspace_swap {
class UserfaultFD;
class SwapFile;
// UserspaceSwapConfig is a structure which contains all configuration values
// for userspace swap.
struct COMPONENT_EXPORT(USERSPACE_SWAP) UserspaceSwapConfig {
UserspaceSwapConfig();
UserspaceSwapConfig(const UserspaceSwapConfig& other);
// Returns the Current UserspaceSwapConfig.
static const UserspaceSwapConfig& Get();
friend std::ostream& operator<<(std::ostream& out,
const UserspaceSwapConfig& c);
// enabled is true if the userspace swap feature is enabled.
bool enabled;
// Number of pages per region represents the number of pages we will use for
// each chunk we attempt to swap at a time.
uint16_t number_of_pages_per_region;
// If true the swap file will be compressed on disk.
bool use_compressed_swap_file;
// Minimum disk space swap available is the lower limit of free disk space on
// the swap device. If the available space on the device backing storage
// is lower than this value no further swapping is allowed, this prevents
// userspace swap from exhausting disk space.
uint64_t minimum_swap_disk_space_available;
// Maximum swap disk space represents the maxmium disk space userspace swap is
// allowed to use across all renderers.
uint64_t maximum_swap_disk_space_bytes;
// Renderer maximum disk file size represents the maximum size a swap file may
// for an individual renderer.
uint64_t renderer_maximum_disk_swap_file_size_bytes;
// Renderer region limit per swap limits the number of regions that that an
// individual renderer can swap on each swap, note that each region is
// configured by the number of pages per region so these two together limit
// the total number of pages per swap round of a process.
uint32_t renderer_region_limit_per_swap;
// The blocked refault time is the minimum time a region must be swapped out
// without being blocked. This prevents disk thrashing where if a region
// is immediately refaulted we don't want to swap it again as it'll likely be
// needed in the future, for example, if a region has a blocked refault time
// of 30s if it is refaulted in less than 30s it will never be swapped again.
base::TimeDelta blocked_refault_time;
// Graph walk frequency represents the (shortest) duration in which you can
// walk the graph, that is, a graph walk frequency of 60s means that you will
// not walk the graph more than once every 60s.
base::TimeDelta graph_walk_frequency;
// The process Swap frequency limits the frequency on which a process may be
// swapped, for example 60s means that a process will not be swapped more than
// once every 60s.
base::TimeDelta process_swap_frequency;
// Invisible Time Before Swap is the amount of time a renderer must be
// invisible before it can be considered for swap.
base::TimeDelta invisible_time_before_swap;
// Swap on freeze, if true will swap a process when all frames are frozen.
bool swap_on_freeze;
// Swap on moderate pressure will walk the graph (based on the frequency of
// graph walk frequency) looking for renderers to swap based on visibility
// state.
bool swap_on_moderate_pressure;
// Shuffle maps order will randomly shuffle the processes maps ordering before
// swapping, it does this so that subsequent swaps can start from different
// memory regions.
bool shuffle_maps_on_swap;
};
// Returns true if the kernel supports all the features necessary for userspace
// swap. These features are userfaultfd(2) and mremap(2) with MREMAP_DONTUNMAP
// support this method is the source of truth for the browser UserspaceSwap and
// the rendererer UserspaceSwapImpl.
COMPONENT_EXPORT(USERSPACE_SWAP) bool KernelSupportsUserspaceSwap();
// Returns true if there is kernel support for userspace swap and the feature is
// enabled.
COMPONENT_EXPORT(USERSPACE_SWAP) bool UserspaceSwapSupportedAndEnabled();
// GetGlobalSwapDiskspaceUsed returns the number of bytes currently on disk for
// ALL renderers.
COMPONENT_EXPORT(USERSPACE_SWAP) uint64_t GetGlobalSwapDiskspaceUsed();
// GetGlobalMemoryReclaimed returns the number of bytes (physical memory) which
// has been reclaimed by userspace swap. This number may not match what is on
// disk due to encryption and compression.
COMPONENT_EXPORT(USERSPACE_SWAP) uint64_t GetGlobalMemoryReclaimed();
// DisableSwapGlobally is the global swap kill switch, it prevents any further
// swapping.
COMPONENT_EXPORT(USERSPACE_SWAP) void DisableSwapGlobally();
// Returns true if swap is allowed (globally).
COMPONENT_EXPORT(USERSPACE_SWAP) bool IsSwapAllowedGlobally();
// RendererSwapData is attached to a ProcessNode and owned by the ProcessNode on
// the PerformanceManager graph.
class COMPONENT_EXPORT(USERSPACE_SWAP) RendererSwapData {
public:
virtual ~RendererSwapData();
static std::unique_ptr<RendererSwapData> Create(
int render_process_host_id,
base::ProcessId pid,
std::unique_ptr<UserfaultFD> uffd,
std::unique_ptr<SwapFile> swap_file,
const Region& swap_remap_area,
mojo::PendingRemote<::userspace_swap::mojom::UserspaceSwap> remote);
// Returns the Render Process Host ID associated with this RendererSwapData.
virtual int render_process_host_id() const = 0;
// If true this renderer has not been disallowed swap.
virtual bool SwapAllowed() const = 0;
// DisallowSwap prevents further swapping of this renderer. This cannot be
// unset.
virtual void DisallowSwap() = 0;
// There is a subtle difference between SwapdiskspaceWrittenBytes and
// SwapDiskspaceUsedBytes. Because punching a hole in a file may not reclaim a
// block on disk only after the entire block has been punched will the space
// actually be reclaimed on disk. However, SwapDiskspaceWrittenBytes will
// contain the total number of bytes that we think are on disk, these numbers
// will be equal when there is no waste of block space on disk.
virtual uint64_t SwapDiskspaceWrittenBytes() const = 0;
virtual uint64_t SwapDiskspaceUsedBytes() const = 0;
virtual uint64_t ReclaimedBytes() const = 0;
protected:
RendererSwapData();
};
// SwapRenderer will initiate a swap on the renderer belonging to the
// RendererSwapData |data|. |size_limit_bytes| is a limit imposed by the system
// based on settings.
COMPONENT_EXPORT(USERSPACE_SWAP)
bool SwapRenderer(RendererSwapData* data, size_t size_limit_bytes);
// GetPartitionAllocSuperPagesInUse will return |max_superpages| worth of
// regions that are currently allocated by PartitionAlloc.
COMPONENT_EXPORT(USERSPACE_SWAP)
bool GetPartitionAllocSuperPagesInUse(
int32_t max_superpages,
std::vector<::userspace_swap::mojom::MemoryRegionPtr>& regions);
} // namespace userspace_swap
} // namespace memory
} // namespace ash
#endif // CHROMEOS_ASH_COMPONENTS_MEMORY_USERSPACE_SWAP_USERSPACE_SWAP_H_
|