1 // Copyright 2014 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 #include "base/memory/discardable_memory.h"
6
7 #include "base/feature_list.h"
8 #include "base/memory/discardable_memory_internal.h"
9 #include "base/memory/madv_free_discardable_memory_posix.h"
10 #include "base/metrics/field_trial_params.h"
11 #include "base/notreached.h"
12 #include "build/build_config.h"
13
14 #if BUILDFLAG(IS_ANDROID)
15 #include "third_party/ashmem/ashmem.h"
16 #endif // BUILDFLAG(IS_ANDROID)
17
18 namespace base {
19
20 namespace features {
21 #if BUILDFLAG(IS_POSIX)
22 // Feature flag allowing the use of MADV_FREE discardable memory when there are
23 // multiple supported discardable memory backings.
24 BASE_FEATURE(kMadvFreeDiscardableMemory,
25 "MadvFreeDiscardableMemory",
26 base::FEATURE_DISABLED_BY_DEFAULT);
27 #endif // BUILDFLAG(IS_POSIX)
28
29 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
30 BASE_FEATURE(kDiscardableMemoryBackingTrial,
31 "DiscardableMemoryBackingTrial",
32 base::FEATURE_DISABLED_BY_DEFAULT);
33
34 // Association of trial group names to trial group enum. Array order must match
35 // order of DiscardableMemoryTrialGroup enum.
36 const base::FeatureParam<DiscardableMemoryTrialGroup>::Option
37 kDiscardableMemoryBackingParamOptions[] = {
38 {DiscardableMemoryTrialGroup::kEmulatedSharedMemory, "shmem"},
39 {DiscardableMemoryTrialGroup::kMadvFree, "madvfree"},
40 {DiscardableMemoryTrialGroup::kAshmem, "ashmem"}};
41
42 const base::FeatureParam<DiscardableMemoryTrialGroup>
43 kDiscardableMemoryBackingParam{
44 &kDiscardableMemoryBackingTrial, "DiscardableMemoryBacking",
45 DiscardableMemoryTrialGroup::kEmulatedSharedMemory,
46 &kDiscardableMemoryBackingParamOptions};
47
48 #endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) ||
49 // BUILDFLAG(IS_CHROMEOS)
50
51 } // namespace features
52
53 namespace {
54
55 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
56
GetBackingForFieldTrial()57 DiscardableMemoryBacking GetBackingForFieldTrial() {
58 DiscardableMemoryTrialGroup trial_group =
59 GetDiscardableMemoryBackingFieldTrialGroup();
60 switch (trial_group) {
61 case DiscardableMemoryTrialGroup::kEmulatedSharedMemory:
62 case DiscardableMemoryTrialGroup::kAshmem:
63 return DiscardableMemoryBacking::kSharedMemory;
64 case DiscardableMemoryTrialGroup::kMadvFree:
65 return DiscardableMemoryBacking::kMadvFree;
66 }
67 NOTREACHED();
68 }
69 #endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) ||
70 // BUILDFLAG(IS_CHROMEOS)
71
72 } // namespace
73
74 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
75
76 // Probe capabilities of this device to determine whether we should participate
77 // in the discardable memory backing trial.
DiscardableMemoryBackingFieldTrialIsEnabled()78 bool DiscardableMemoryBackingFieldTrialIsEnabled() {
79 #if BUILDFLAG(IS_ANDROID)
80 if (!ashmem_device_is_supported())
81 return false;
82 #endif // BUILDFLAG(IS_ANDROID)
83 if (base::GetMadvFreeSupport() != base::MadvFreeSupport::kSupported)
84 return false;
85
86 // IMPORTANT: Only query the feature after we determine the device has the
87 // capabilities required, which will have the side-effect of assigning a
88 // trial-group.
89 return base::FeatureList::IsEnabled(features::kDiscardableMemoryBackingTrial);
90 }
91
GetDiscardableMemoryBackingFieldTrialGroup()92 DiscardableMemoryTrialGroup GetDiscardableMemoryBackingFieldTrialGroup() {
93 DCHECK(DiscardableMemoryBackingFieldTrialIsEnabled());
94 return features::kDiscardableMemoryBackingParam.Get();
95 }
96 #endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) ||
97 // BUILDFLAG(IS_CHROMEOS)
98
99 DiscardableMemory::DiscardableMemory() = default;
100
101 DiscardableMemory::~DiscardableMemory() = default;
102
GetDiscardableMemoryBacking()103 DiscardableMemoryBacking GetDiscardableMemoryBacking() {
104 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
105 if (DiscardableMemoryBackingFieldTrialIsEnabled()) {
106 return GetBackingForFieldTrial();
107 }
108 #endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) ||
109 // BUILDFLAG(IS_CHROMEOS)
110
111 #if BUILDFLAG(IS_ANDROID)
112 if (ashmem_device_is_supported())
113 return DiscardableMemoryBacking::kSharedMemory;
114 #endif // BUILDFLAG(IS_ANDROID)
115
116 #if BUILDFLAG(IS_POSIX)
117 if (base::FeatureList::IsEnabled(
118 base::features::kMadvFreeDiscardableMemory) &&
119 base::GetMadvFreeSupport() == base::MadvFreeSupport::kSupported) {
120 return DiscardableMemoryBacking::kMadvFree;
121 }
122 #endif // BUILDFLAG(IS_POSIX)
123
124 return DiscardableMemoryBacking::kSharedMemory;
125 }
126
127 } // namespace base
128