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
base / trace_event / malloc_dump_provider.h [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_
#define BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_
#include "base/allocator/buildflags.h"
#include "base/base_export.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/singleton.h"
#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "base/trace_event/memory_dump_provider.h"
#include "build/build_config.h"
#include "partition_alloc/buildflags.h"
#if PA_BUILDFLAG(USE_PARTITION_ALLOC)
#include "partition_alloc/partition_stats.h" // nogncheck
#endif
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \
BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
#define MALLOC_MEMORY_TRACING_SUPPORTED
#endif
namespace base {
namespace trace_event {
class MemoryAllocatorDump;
// Dump provider which collects process-wide memory stats.
class BASE_EXPORT MallocDumpProvider : public MemoryDumpProvider {
public:
// Name of the allocated_objects dump. Use this to declare suballocator dumps
// from other dump providers.
static const char kAllocatedObjects[];
static MallocDumpProvider* GetInstance();
// The Extreme LUD is implemented in //components/gwp_asan, which //base
// cannot depend on. The following API allows an injection of stats-report
// function of the Extreme LUD.
struct ExtremeLUDStats {
#if PA_BUILDFLAG(USE_PARTITION_ALLOC)
// This default-constructs to be zero'ed.
partition_alloc::LightweightQuarantineStats lq_stats{0};
#endif
size_t capacity_in_bytes = 0;
};
struct ExtremeLUDStatsSet {
ExtremeLUDStats for_small_objects{};
ExtremeLUDStats for_large_objects{};
};
#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
using ExtremeLUDGetStatsCallback = RepeatingCallback<ExtremeLUDStatsSet()>;
static void SetExtremeLUDGetStatsCallback(
ExtremeLUDGetStatsCallback callback);
#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
MallocDumpProvider(const MallocDumpProvider&) = delete;
MallocDumpProvider& operator=(const MallocDumpProvider&) = delete;
// MemoryDumpProvider implementation.
bool OnMemoryDump(const MemoryDumpArgs& args,
ProcessMemoryDump* pmd) override;
private:
struct CumulativeEludStats {
size_t quarantined_bytes = 0;
size_t quarantined_count = 0;
size_t miss_count = 0;
};
friend struct DefaultSingletonTraits<MallocDumpProvider>;
MallocDumpProvider();
~MallocDumpProvider() override;
void ReportPerMinuteStats(uint64_t syscall_count,
size_t cumulative_brp_quarantined_bytes,
size_t cumulative_brp_quarantined_count,
const ExtremeLUDStats& elud_stats_for_small_objects,
const ExtremeLUDStats& elud_stats_for_large_objects,
MemoryAllocatorDump* malloc_dump,
MemoryAllocatorDump* partition_alloc_dump,
MemoryAllocatorDump* elud_dump_for_small_objects,
MemoryAllocatorDump* elud_dump_for_large_objects);
bool emit_metrics_on_memory_dump_
GUARDED_BY(emit_metrics_on_memory_dump_lock_) = true;
base::Lock emit_metrics_on_memory_dump_lock_;
#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
// Returns a reference to the injected stats-report function of the Extreme
// LUD. The returned callback is_null() if the Extreme LUD is not enabled.
static ExtremeLUDGetStatsCallback& GetExtremeLUDGetStatsCallback();
// To be accurate, this requires the dump provider to be created very early,
// which is the case. The alternative would be to drop the first data point,
// which is not desirable as early process activity is highly relevant.
base::TimeTicks last_memory_dump_time_ = base::TimeTicks::Now();
uint64_t last_syscall_count_ = 0;
size_t last_cumulative_brp_quarantined_bytes_ = 0;
size_t last_cumulative_brp_quarantined_count_ = 0;
CumulativeEludStats last_cumulative_elud_stats_for_small_objects_{0};
CumulativeEludStats last_cumulative_elud_stats_for_large_objects_{0};
#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
};
#if PA_BUILDFLAG(USE_PARTITION_ALLOC)
// This class is used to invert the dependency of PartitionAlloc on the
// PartitionAllocMemoryDumpProvider. This implements an interface that will
// be called with memory statistics for each bucket in the allocator.
class BASE_EXPORT MemoryDumpPartitionStatsDumper final
: public partition_alloc::PartitionStatsDumper {
public:
MemoryDumpPartitionStatsDumper(const char* root_name,
ProcessMemoryDump* memory_dump,
MemoryDumpLevelOfDetail level_of_detail);
static constexpr char kPartitionsDumpName[] = "partitions";
// PartitionStatsDumper implementation.
void PartitionDumpTotals(
const char* partition_name,
const partition_alloc::PartitionMemoryStats*) override;
void PartitionsDumpBucketStats(
const char* partition_name,
const partition_alloc::PartitionBucketMemoryStats*) override;
size_t total_mmapped_bytes() const { return total_mmapped_bytes_; }
size_t total_resident_bytes() const { return total_resident_bytes_; }
size_t total_active_bytes() const { return total_active_bytes_; }
size_t total_active_count() const { return total_active_count_; }
uint64_t syscall_count() const { return syscall_count_; }
size_t cumulative_brp_quarantined_bytes() const {
return cumulative_brp_quarantined_bytes_;
}
size_t cumulative_brp_quarantined_count() const {
return cumulative_brp_quarantined_count_;
}
private:
const char* root_name_;
raw_ptr<base::trace_event::ProcessMemoryDump> memory_dump_;
uint64_t uid_ = 0;
size_t total_mmapped_bytes_ = 0;
size_t total_resident_bytes_ = 0;
size_t total_active_bytes_ = 0;
size_t total_active_count_ = 0;
uint64_t syscall_count_ = 0;
size_t cumulative_brp_quarantined_bytes_ = 0;
size_t cumulative_brp_quarantined_count_ = 0;
bool detailed_;
};
#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC)
} // namespace trace_event
} // namespace base
#endif // BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_