File: partition_alloc_support.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (187 lines) | stat: -rw-r--r-- 7,406 bytes parent folder | download | duplicates (3)
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
// Copyright 2021 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_ALLOCATOR_PARTITION_ALLOC_SUPPORT_H_
#define BASE_ALLOCATOR_PARTITION_ALLOC_SUPPORT_H_

#include <map>
#include <string>

#include "base/allocator/partition_alloc_features.h"
#include "base/base_export.h"
#include "base/feature_list.h"
#include "base/memory/scoped_refptr.h"
#include "base/synchronization/lock.h"
#include "base/task/sequenced_task_runner.h"
#include "base/thread_annotations.h"
#include "partition_alloc/buildflags.h"
#include "partition_alloc/partition_alloc_config.h"
#include "partition_alloc/scheduler_loop_quarantine_support.h"
#include "partition_alloc/thread_cache.h"

namespace base::allocator {

// Starts a periodic timer on the current thread to purge all thread caches.
BASE_EXPORT void StartThreadCachePeriodicPurge();

BASE_EXPORT void StartMemoryReclaimer(
    scoped_refptr<SequencedTaskRunner> task_runner);

BASE_EXPORT std::map<std::string, std::string> ProposeSyntheticFinchTrials();

// Install handlers for when dangling raw_ptr(s) have been detected. This prints
// two StackTraces. One where the memory is freed, one where the last dangling
// raw_ptr stopped referencing it.
//
// This is currently effective, only when compiled with
// `enable_dangling_raw_ptr_checks` build flag.
BASE_EXPORT void InstallDanglingRawPtrChecks();
BASE_EXPORT void InstallUnretainedDanglingRawPtrChecks();

// Once called, makes `free()` do nothing. This is done to reduce
// shutdown hangs on CrOS.
// Does nothing if Dangling Pointer Detector (`docs/dangling_ptr.md`)
// is not active.
// Does nothing if allocator shim support is not built.
BASE_EXPORT void MakeFreeNoOp();

// Allows to re-configure PartitionAlloc at run-time.
class BASE_EXPORT PartitionAllocSupport {
 public:
  struct BrpConfiguration {
    bool enable_brp = false;

    // TODO(https://crbug.com/371135823): Remove after the investigation.
    size_t extra_extras_size = 0;
    bool suppress_double_free_detected_crash = false;
    bool suppress_corruption_detected_crash = false;
  };

  // Reconfigure* functions re-configure PartitionAlloc. It is impossible to
  // configure PartitionAlloc before/at its initialization using information not
  // known at compile-time (e.g. process type, Finch), because by the time this
  // information is available memory allocations would have surely happened,
  // that requiring a functioning allocator.
  //
  // *Earlyish() is called as early as it is reasonably possible.
  // *AfterZygoteFork() is its complement to finish configuring process-specific
  // stuff that had to be postponed due to *Earlyish() being called with
  // |process_type==kZygoteProcess|.
  // *AfterFeatureListInit() is called in addition to the above, once
  // FeatureList has been initialized and ready to use. It is guaranteed to be
  // called on non-zygote processes or after the zygote has been forked.
  // *AfterTaskRunnerInit() is called once it is possible to post tasks, and
  // after the previous steps.
  //
  // *Earlyish() must be called exactly once. *AfterZygoteFork() must be called
  // once iff *Earlyish() was called before with |process_type==kZygoteProcess|.
  //
  // *AfterFeatureListInit() may be called more than once, but will perform its
  // re-configuration steps exactly once.
  //
  // *AfterTaskRunnerInit() may be called more than once.
  void ReconfigureForTests();
  void ReconfigureEarlyish(const std::string& process_type);
  void ReconfigureAfterZygoteFork(const std::string& process_type);
  void ReconfigureAfterFeatureListInit(
      const std::string& process_type,
      bool configure_dangling_pointer_detector = true);
  void ReconfigureAfterTaskRunnerInit(const std::string& process_type);

  // |has_main_frame| tells us if the renderer contains a main frame.
  // The default value is intended for other process types, where the parameter
  // does not make sense.
  void OnForegrounded(bool has_main_frame = false);
  void OnBackgrounded();

#if PA_BUILDFLAG(ENABLE_DANGLING_RAW_PTR_CHECKS)
  static std::string ExtractDanglingPtrSignatureForTests(
      std::string stacktrace);
#endif

  static PartitionAllocSupport* Get();

  static BrpConfiguration GetBrpConfiguration(const std::string& process_type);

  // Returns true if memory tagging should be enabled if available for the given
  // process type. May be called multiple times per process.
  static bool ShouldEnableMemoryTagging(const std::string& process_type);

  // For calling from within third_party/blink/.
  static bool ShouldEnableMemoryTaggingInRendererProcess();

  // Returns true if PA advanced checks should be enabled if available for the
  // given process type. May be called multiple times per process.
  static bool ShouldEnablePartitionAllocWithAdvancedChecks(
      const std::string& process_type);

  // Returns quarantine configuration for `process_name` and `branch_type`.
  static ::partition_alloc::internal::SchedulerLoopQuarantineConfig
  GetSchedulerLoopQuarantineConfiguration(
      const std::string& process_type,
      features::internal::SchedulerLoopQuarantineBranchType branch_type);

 private:
  PartitionAllocSupport();

  base::Lock lock_;
  bool called_for_tests_ GUARDED_BY(lock_) = false;
  bool called_earlyish_ GUARDED_BY(lock_) = false;
  bool called_after_zygote_fork_ GUARDED_BY(lock_) = false;
  bool called_after_feature_list_init_ GUARDED_BY(lock_) = false;
  bool called_after_thread_pool_init_ GUARDED_BY(lock_) = false;
  std::string established_process_type_ GUARDED_BY(lock_) = "INVALID";

#if PA_CONFIG(THREAD_CACHE_SUPPORTED) && \
    PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
  size_t largest_cached_size_ =
      ::partition_alloc::kThreadCacheDefaultSizeThreshold;
#endif
};

BASE_EXPORT BASE_DECLARE_FEATURE(kDisableMemoryReclaimerInBackground);

// Visible in header for testing.
class BASE_EXPORT MemoryReclaimerSupport {
 public:
  static MemoryReclaimerSupport& Instance();
  MemoryReclaimerSupport();
  ~MemoryReclaimerSupport();
  void Start(scoped_refptr<TaskRunner> task_runner);
  void SetForegrounded(bool in_foreground);

  void ResetForTesting();
  bool has_pending_task_for_testing() const { return has_pending_task_; }
  static TimeDelta GetInterval();

  // Visible for testing
  static constexpr base::TimeDelta kFirstPAPurgeOrReclaimDelay =
      base::Minutes(1);

 private:
  void Run();
  void MaybeScheduleTask(TimeDelta delay = TimeDelta());

  scoped_refptr<TaskRunner> task_runner_;
  bool in_foreground_ = true;
  bool has_pending_task_ = false;
};

// Utility function to detect Double-Free or Out-of-Bounds writes.
// This function can be called to memory assumed to be valid.
// If not, this may crash (not guaranteed).
// This is useful if you want to investigate crashes at `free()`,
// to know which point at execution it goes wrong.
BASE_EXPORT void CheckHeapIntegrity(const void* ptr);

// The function here is called right before crashing with
// `DoubleFreeOrCorruptionDetected()`. We provide an address for the slot start
// to the function, and it may use that for debugging purpose.
BASE_EXPORT void SetDoubleFreeOrCorruptionDetectedFn(void (*fn)(uintptr_t));

using partition_alloc::ScopedSchedulerLoopQuarantineExclusion;

}  // namespace base::allocator

#endif  // BASE_ALLOCATOR_PARTITION_ALLOC_SUPPORT_H_