Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/metrics/field_trial.h" | 5 #include "base/metrics/field_trial.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/base_switches.h" | 10 #include "base/base_switches.h" |
| 11 #include "base/build_time.h" | 11 #include "base/build_time.h" |
| 12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/metrics/field_trial_param_associator.h" | 14 #include "base/metrics/field_trial_param_associator.h" |
| 15 #include "base/process/memory.h" | 15 #include "base/process/memory.h" |
| 16 #include "base/rand_util.h" | 16 #include "base/rand_util.h" |
| 17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 18 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 19 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
| 20 #include "base/strings/utf_string_conversions.h" | 20 #include "base/strings/utf_string_conversions.h" |
| 21 | 21 |
| 22 // On systems that use the zygote process to spawn child processes, we must | 22 // On POSIX, the fd is shared using the mapping in GlobalDescriptors. |
| 23 // retrieve the correct fd using the mapping in GlobalDescriptors. | 23 #if defined(OS_POSIX) && !defined(OS_NACL) |
| 24 #if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_MACOSX) && \ | |
| 25 !defined(OS_ANDROID) | |
| 26 #define POSIX_WITH_ZYGOTE 1 | |
| 27 #endif | |
| 28 | |
| 29 #if defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX) | |
| 30 #include "base/posix/global_descriptors.h" | 24 #include "base/posix/global_descriptors.h" |
| 31 #endif | 25 #endif |
| 32 | 26 |
| 33 namespace base { | 27 namespace base { |
| 34 | 28 |
| 35 namespace { | 29 namespace { |
| 36 | 30 |
| 37 // Define a separator character to use when creating a persistent form of an | 31 // Define a separator character to use when creating a persistent form of an |
| 38 // instance. This is intended for use as a command line argument, passed to a | 32 // instance. This is intended for use as a command line argument, passed to a |
| 39 // second process to mimic our state (i.e., provide the same group name). | 33 // second process to mimic our state (i.e., provide the same group name). |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 56 // Constants for the field trial allocator. | 50 // Constants for the field trial allocator. |
| 57 const char kAllocatorName[] = "FieldTrialAllocator"; | 51 const char kAllocatorName[] = "FieldTrialAllocator"; |
| 58 | 52 |
| 59 // We allocate 128 KiB to hold all the field trial data. This should be enough, | 53 // We allocate 128 KiB to hold all the field trial data. This should be enough, |
| 60 // as most people use 3 - 25 KiB for field trials (as of 11/25/2016). | 54 // as most people use 3 - 25 KiB for field trials (as of 11/25/2016). |
| 61 // This also doesn't allocate all 128 KiB at once -- the pages only get mapped | 55 // This also doesn't allocate all 128 KiB at once -- the pages only get mapped |
| 62 // to physical memory when they are touched. If the size of the allocated field | 56 // to physical memory when they are touched. If the size of the allocated field |
| 63 // trials does get larger than 128 KiB, then we will drop some field trials in | 57 // trials does get larger than 128 KiB, then we will drop some field trials in |
| 64 // child processes, leading to an inconsistent view between browser and child | 58 // child processes, leading to an inconsistent view between browser and child |
| 65 // processes and possibly causing crashes (see crbug.com/661617). | 59 // processes and possibly causing crashes (see crbug.com/661617). |
| 66 #if !defined(OS_NACL) | |
| 67 const size_t kFieldTrialAllocationSize = 128 << 10; // 128 KiB | 60 const size_t kFieldTrialAllocationSize = 128 << 10; // 128 KiB |
| 68 #endif | |
| 69 | 61 |
| 70 // Writes out string1 and then string2 to pickle. | 62 // Writes out string1 and then string2 to pickle. |
| 71 bool WriteStringPair(Pickle* pickle, | 63 bool WriteStringPair(Pickle* pickle, |
| 72 const StringPiece& string1, | 64 const StringPiece& string1, |
| 73 const StringPiece& string2) { | 65 const StringPiece& string2) { |
| 74 if (!pickle->WriteString(string1)) | 66 if (!pickle->WriteString(string1)) |
| 75 return false; | 67 return false; |
| 76 if (!pickle->WriteString(string2)) | 68 if (!pickle->WriteString(string2)) |
| 77 return false; | 69 return false; |
| 78 return true; | 70 return true; |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 211 HANDLE src = allocator->shared_memory()->handle().GetHandle(); | 203 HANDLE src = allocator->shared_memory()->handle().GetHandle(); |
| 212 ProcessHandle process = GetCurrentProcess(); | 204 ProcessHandle process = GetCurrentProcess(); |
| 213 DWORD access = SECTION_MAP_READ | SECTION_QUERY; | 205 DWORD access = SECTION_MAP_READ | SECTION_QUERY; |
| 214 HANDLE dst; | 206 HANDLE dst; |
| 215 if (!::DuplicateHandle(process, src, process, &dst, access, true, 0)) | 207 if (!::DuplicateHandle(process, src, process, &dst, access, true, 0)) |
| 216 return kInvalidPlatformFile; | 208 return kInvalidPlatformFile; |
| 217 return dst; | 209 return dst; |
| 218 } | 210 } |
| 219 #endif | 211 #endif |
| 220 | 212 |
| 221 #if defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX) | 213 #if defined(OS_POSIX) && !defined(OS_NACL) |
| 222 int CreateReadOnlyHandle(FieldTrialList::FieldTrialAllocator* allocator) { | 214 int CreateReadOnlyHandle(FieldTrialList::FieldTrialAllocator* allocator) { |
| 223 SharedMemoryHandle new_handle; | 215 SharedMemoryHandle new_handle; |
| 224 allocator->shared_memory()->ShareReadOnlyToProcess(GetCurrentProcessHandle(), | 216 allocator->shared_memory()->ShareReadOnlyToProcess(GetCurrentProcessHandle(), |
| 225 &new_handle); | 217 &new_handle); |
| 226 return SharedMemory::GetFdFromSharedMemoryHandle(new_handle); | 218 return SharedMemory::GetFdFromSharedMemoryHandle(new_handle); |
| 227 } | 219 } |
| 228 #endif | 220 #endif |
| 229 | 221 |
| 222 void OnOutOfMemory(size_t size) { | |
| 223 #if defined(OS_NACL) | |
| 224 NOTREACHED(); | |
| 225 #else | |
| 226 TerminateBecauseOutOfMemory(size); | |
| 227 #endif | |
| 228 } | |
| 229 | |
| 230 } // namespace | 230 } // namespace |
| 231 | 231 |
| 232 // statics | 232 // statics |
| 233 const int FieldTrial::kNotFinalized = -1; | 233 const int FieldTrial::kNotFinalized = -1; |
| 234 const int FieldTrial::kDefaultGroupNumber = 0; | 234 const int FieldTrial::kDefaultGroupNumber = 0; |
| 235 bool FieldTrial::enable_benchmarking_ = false; | 235 bool FieldTrial::enable_benchmarking_ = false; |
| 236 | 236 |
| 237 int FieldTrialList::kNoExpirationYear = 0; | 237 int FieldTrialList::kNoExpirationYear = 0; |
| 238 | 238 |
| 239 //------------------------------------------------------------------------------ | 239 //------------------------------------------------------------------------------ |
| (...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 772 | 772 |
| 773 #if defined(OS_WIN) | 773 #if defined(OS_WIN) |
| 774 if (cmd_line.HasSwitch(field_trial_handle_switch)) { | 774 if (cmd_line.HasSwitch(field_trial_handle_switch)) { |
| 775 std::string handle_switch = | 775 std::string handle_switch = |
| 776 cmd_line.GetSwitchValueASCII(field_trial_handle_switch); | 776 cmd_line.GetSwitchValueASCII(field_trial_handle_switch); |
| 777 bool result = CreateTrialsFromHandleSwitch(handle_switch); | 777 bool result = CreateTrialsFromHandleSwitch(handle_switch); |
| 778 DCHECK(result); | 778 DCHECK(result); |
| 779 } | 779 } |
| 780 #endif | 780 #endif |
| 781 | 781 |
| 782 #if defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX) | 782 #if defined(OS_POSIX) && !defined(OS_NACL) |
| 783 // On POSIX, we check if the handle is valid by seeing if the browser process | 783 // On POSIX, we check if the handle is valid by seeing if the browser process |
| 784 // sent over the switch (we don't care about the value). Invalid handles | 784 // sent over the switch (we don't care about the value). Invalid handles |
| 785 // occur in some browser tests which don't initialize the allocator. | 785 // occur in some browser tests which don't initialize the allocator. |
| 786 if (cmd_line.HasSwitch(field_trial_handle_switch)) { | 786 if (cmd_line.HasSwitch(field_trial_handle_switch)) { |
| 787 bool result = CreateTrialsFromDescriptor(fd_key); | 787 bool result = CreateTrialsFromDescriptor(fd_key); |
| 788 DCHECK(result); | 788 DCHECK(result); |
| 789 } | 789 } |
| 790 #endif | 790 #endif |
| 791 | 791 |
| 792 if (cmd_line.HasSwitch(switches::kForceFieldTrials)) { | 792 if (cmd_line.HasSwitch(switches::kForceFieldTrials)) { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 808 !global_->field_trial_allocator_.get()) { | 808 !global_->field_trial_allocator_.get()) { |
| 809 return feature_list->InitializeFromCommandLine( | 809 return feature_list->InitializeFromCommandLine( |
| 810 command_line.GetSwitchValueASCII(enable_features_switch), | 810 command_line.GetSwitchValueASCII(enable_features_switch), |
| 811 command_line.GetSwitchValueASCII(disable_features_switch)); | 811 command_line.GetSwitchValueASCII(disable_features_switch)); |
| 812 } | 812 } |
| 813 | 813 |
| 814 feature_list->InitializeFromSharedMemory( | 814 feature_list->InitializeFromSharedMemory( |
| 815 global_->field_trial_allocator_.get()); | 815 global_->field_trial_allocator_.get()); |
| 816 } | 816 } |
| 817 | 817 |
| 818 #if defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX) | |
| 819 // static | |
| 820 bool FieldTrialList::CreateTrialsFromDescriptor(int fd_key) { | |
| 821 if (!kUseSharedMemoryForFieldTrials) | |
| 822 return false; | |
| 823 | |
| 824 if (fd_key == -1) | |
| 825 return false; | |
| 826 | |
| 827 int fd = GlobalDescriptors::GetInstance()->MaybeGet(fd_key); | |
| 828 if (fd == -1) | |
| 829 return false; | |
| 830 | |
| 831 #if defined(POSIX_WITH_ZYGOTE) | |
| 832 SharedMemoryHandle shm_handle(fd, true); | |
| 833 #elif defined(OS_MACOSX) | |
| 834 SharedMemoryHandle shm_handle(FileDescriptor(fd, true)); | |
| 835 #endif | |
| 836 | |
| 837 bool result = FieldTrialList::CreateTrialsFromSharedMemoryHandle(shm_handle); | |
| 838 DCHECK(result); | |
| 839 return true; | |
| 840 } | |
| 841 #endif | |
| 842 | |
| 843 #if defined(OS_WIN) | 818 #if defined(OS_WIN) |
| 844 // static | 819 // static |
| 845 void FieldTrialList::AppendFieldTrialHandleIfNeeded( | 820 void FieldTrialList::AppendFieldTrialHandleIfNeeded( |
| 846 HandlesToInheritVector* handles) { | 821 HandlesToInheritVector* handles) { |
| 847 if (!global_) | 822 if (!global_) |
| 848 return; | 823 return; |
| 849 if (kUseSharedMemoryForFieldTrials) { | 824 if (kUseSharedMemoryForFieldTrials) { |
| 850 InstantiateFieldTrialAllocatorIfNeeded(); | 825 InstantiateFieldTrialAllocatorIfNeeded(); |
| 851 if (global_->readonly_allocator_handle_) | 826 if (global_->readonly_allocator_handle_) |
| 852 handles->push_back(global_->readonly_allocator_handle_); | 827 handles->push_back(global_->readonly_allocator_handle_); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 876 // content browser tests currently don't create a FieldTrialList because they | 851 // content browser tests currently don't create a FieldTrialList because they |
| 877 // don't run ChromeBrowserMainParts code where it's done for Chrome. | 852 // don't run ChromeBrowserMainParts code where it's done for Chrome. |
| 878 // Some tests depend on the enable and disable features flag switch, though, | 853 // Some tests depend on the enable and disable features flag switch, though, |
| 879 // so we can still add those even though AllStatesToString() will be a no-op. | 854 // so we can still add those even though AllStatesToString() will be a no-op. |
| 880 if (!global_) { | 855 if (!global_) { |
| 881 AddFeatureAndFieldTrialFlags(enable_features_switch, | 856 AddFeatureAndFieldTrialFlags(enable_features_switch, |
| 882 disable_features_switch, cmd_line); | 857 disable_features_switch, cmd_line); |
| 883 return; | 858 return; |
| 884 } | 859 } |
| 885 | 860 |
| 886 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX) | |
| 887 // Use shared memory to pass the state if the feature is enabled, otherwise | 861 // Use shared memory to pass the state if the feature is enabled, otherwise |
| 888 // fallback to passing it via the command line as a string. | 862 // fallback to passing it via the command line as a string. |
| 889 if (kUseSharedMemoryForFieldTrials) { | 863 if (kUseSharedMemoryForFieldTrials) { |
| 890 InstantiateFieldTrialAllocatorIfNeeded(); | 864 InstantiateFieldTrialAllocatorIfNeeded(); |
| 891 // If the readonly handle didn't get duplicated properly, then fallback to | 865 // If the readonly handle didn't get duplicated properly, then fallback to |
| 892 // original behavior. | 866 // original behavior. |
| 893 if (global_->readonly_allocator_handle_ == kInvalidPlatformFile) { | 867 if (global_->readonly_allocator_handle_ == kInvalidPlatformFile) { |
| 894 AddFeatureAndFieldTrialFlags(enable_features_switch, | 868 AddFeatureAndFieldTrialFlags(enable_features_switch, |
| 895 disable_features_switch, cmd_line); | 869 disable_features_switch, cmd_line); |
| 896 return; | 870 return; |
| 897 } | 871 } |
| 898 | 872 |
| 899 global_->field_trial_allocator_->UpdateTrackingHistograms(); | 873 global_->field_trial_allocator_->UpdateTrackingHistograms(); |
| 900 | 874 |
| 901 #if defined(OS_WIN) | 875 #if defined(OS_WIN) |
| 902 // We need to pass a named anonymous handle to shared memory over the | 876 // We need to pass a named anonymous handle to shared memory over the |
| 903 // command line on Windows, since the child doesn't know which of the | 877 // command line on Windows, since the child doesn't know which of the |
| 904 // handles it inherited it should open. | 878 // handles it inherited it should open. |
| 905 // PlatformFile is typedef'd to HANDLE which is typedef'd to void *. We | 879 // PlatformFile is typedef'd to HANDLE which is typedef'd to void *. We |
| 906 // basically cast the handle into an int (uintptr_t, to be exact), stringify | 880 // basically cast the handle into an int (uintptr_t, to be exact), stringify |
| 907 // the int, and pass it as a command-line flag. The child process will do | 881 // the int, and pass it as a command-line flag. The child process will do |
| 908 // the reverse conversions to retrieve the handle. See | 882 // the reverse conversions to retrieve the handle. See |
| 909 // http://stackoverflow.com/a/153077 | 883 // http://stackoverflow.com/a/153077 |
| 910 auto uintptr_handle = | 884 auto uintptr_handle = |
| 911 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_); | 885 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_); |
| 912 std::string field_trial_handle = std::to_string(uintptr_handle); | 886 std::string field_trial_handle = std::to_string(uintptr_handle); |
| 913 cmd_line->AppendSwitchASCII(field_trial_handle_switch, field_trial_handle); | 887 cmd_line->AppendSwitchASCII(field_trial_handle_switch, field_trial_handle); |
| 914 #elif defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX) | 888 #else |
|
bcwhite
2017/01/18 19:24:34
How about:
#elif defined(OS_POSIX)
...
#else
#err
Alexei Svitkine (slow)
2017/01/18 20:05:02
Done.
| |
| 915 // On POSIX, we dup the fd into a fixed fd kFieldTrialDescriptor, so we | 889 // On POSIX, we dup the fd into a fixed fd kFieldTrialDescriptor, so we |
| 916 // don't have to pass over the handle (it's not even the right handle | 890 // don't have to pass over the handle (it's not even the right handle |
| 917 // anyways). But some browser tests don't create the allocator, so we need | 891 // anyways). But some browser tests don't create the allocator, so we need |
| 918 // to be able to distinguish valid and invalid handles. We do that by just | 892 // to be able to distinguish valid and invalid handles. We do that by just |
| 919 // checking that the flag is set with a dummy value. | 893 // checking that the flag is set with a dummy value. |
| 920 cmd_line->AppendSwitchASCII(field_trial_handle_switch, "1"); | 894 cmd_line->AppendSwitchASCII(field_trial_handle_switch, "1"); |
| 921 #endif | 895 #endif |
| 922 return; | 896 return; |
| 923 } | 897 } |
| 924 #endif | |
| 925 | 898 |
| 926 AddFeatureAndFieldTrialFlags(enable_features_switch, disable_features_switch, | 899 AddFeatureAndFieldTrialFlags(enable_features_switch, disable_features_switch, |
| 927 cmd_line); | 900 cmd_line); |
| 928 } | 901 } |
| 929 | 902 |
| 930 // static | 903 // static |
| 931 FieldTrial* FieldTrialList::CreateFieldTrial( | 904 FieldTrial* FieldTrialList::CreateFieldTrial( |
| 932 const std::string& name, | 905 const std::string& name, |
| 933 const std::string& group_name) { | 906 const std::string& group_name) { |
| 934 DCHECK(global_); | 907 DCHECK(global_); |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1142 // static | 1115 // static |
| 1143 bool FieldTrialList::CreateTrialsFromHandleSwitch( | 1116 bool FieldTrialList::CreateTrialsFromHandleSwitch( |
| 1144 const std::string& handle_switch) { | 1117 const std::string& handle_switch) { |
| 1145 int field_trial_handle = std::stoi(handle_switch); | 1118 int field_trial_handle = std::stoi(handle_switch); |
| 1146 HANDLE handle = reinterpret_cast<HANDLE>(field_trial_handle); | 1119 HANDLE handle = reinterpret_cast<HANDLE>(field_trial_handle); |
| 1147 SharedMemoryHandle shm_handle(handle, GetCurrentProcId()); | 1120 SharedMemoryHandle shm_handle(handle, GetCurrentProcId()); |
| 1148 return FieldTrialList::CreateTrialsFromSharedMemoryHandle(shm_handle); | 1121 return FieldTrialList::CreateTrialsFromSharedMemoryHandle(shm_handle); |
| 1149 } | 1122 } |
| 1150 #endif | 1123 #endif |
| 1151 | 1124 |
| 1152 #if !defined(OS_NACL) | 1125 #if defined(OS_POSIX) && !defined(OS_NACL) |
| 1126 // static | |
| 1127 bool FieldTrialList::CreateTrialsFromDescriptor(int fd_key) { | |
| 1128 if (!kUseSharedMemoryForFieldTrials) | |
| 1129 return false; | |
| 1130 | |
| 1131 if (fd_key == -1) | |
| 1132 return false; | |
| 1133 | |
| 1134 int fd = GlobalDescriptors::GetInstance()->MaybeGet(fd_key); | |
| 1135 if (fd == -1) | |
| 1136 return false; | |
| 1137 | |
| 1138 #if defined(OS_MACOSX) && !defined(OS_IOS) | |
| 1139 SharedMemoryHandle shm_handle(FileDescriptor(fd, true)); | |
| 1140 #else | |
| 1141 SharedMemoryHandle shm_handle(fd, true); | |
| 1142 #endif | |
| 1143 | |
| 1144 bool result = FieldTrialList::CreateTrialsFromSharedMemoryHandle(shm_handle); | |
| 1145 DCHECK(result); | |
| 1146 return true; | |
| 1147 } | |
| 1148 #endif | |
| 1149 | |
| 1153 // static | 1150 // static |
| 1154 bool FieldTrialList::CreateTrialsFromSharedMemoryHandle( | 1151 bool FieldTrialList::CreateTrialsFromSharedMemoryHandle( |
| 1155 SharedMemoryHandle shm_handle) { | 1152 SharedMemoryHandle shm_handle) { |
| 1156 // shm gets deleted when it gets out of scope, but that's OK because we need | 1153 // shm gets deleted when it gets out of scope, but that's OK because we need |
| 1157 // it only for the duration of this method. | 1154 // it only for the duration of this method. |
| 1158 std::unique_ptr<SharedMemory> shm(new SharedMemory(shm_handle, true)); | 1155 std::unique_ptr<SharedMemory> shm(new SharedMemory(shm_handle, true)); |
| 1159 if (!shm.get()->Map(kFieldTrialAllocationSize)) | 1156 if (!shm.get()->Map(kFieldTrialAllocationSize)) |
| 1160 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize); | 1157 OnOutOfMemory(kFieldTrialAllocationSize); |
| 1161 | 1158 |
| 1162 return FieldTrialList::CreateTrialsFromSharedMemory(std::move(shm)); | 1159 return FieldTrialList::CreateTrialsFromSharedMemory(std::move(shm)); |
| 1163 } | 1160 } |
| 1164 #endif | |
| 1165 | 1161 |
| 1166 // static | 1162 // static |
| 1167 bool FieldTrialList::CreateTrialsFromSharedMemory( | 1163 bool FieldTrialList::CreateTrialsFromSharedMemory( |
| 1168 std::unique_ptr<SharedMemory> shm) { | 1164 std::unique_ptr<SharedMemory> shm) { |
| 1169 global_->field_trial_allocator_.reset( | 1165 global_->field_trial_allocator_.reset( |
| 1170 new FieldTrialAllocator(std::move(shm), 0, kAllocatorName, true)); | 1166 new FieldTrialAllocator(std::move(shm), 0, kAllocatorName, true)); |
| 1171 FieldTrialAllocator* shalloc = global_->field_trial_allocator_.get(); | 1167 FieldTrialAllocator* shalloc = global_->field_trial_allocator_.get(); |
| 1172 FieldTrialAllocator::Iterator mem_iter(shalloc); | 1168 FieldTrialAllocator::Iterator mem_iter(shalloc); |
| 1173 | 1169 |
| 1174 const FieldTrial::FieldTrialEntry* entry; | 1170 const FieldTrial::FieldTrialEntry* entry; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1188 if (subtle::NoBarrier_Load(&entry->activated)) { | 1184 if (subtle::NoBarrier_Load(&entry->activated)) { |
| 1189 // Call |group()| to mark the trial as "used" and notify observers, if | 1185 // Call |group()| to mark the trial as "used" and notify observers, if |
| 1190 // any. This is useful to ensure that field trials created in child | 1186 // any. This is useful to ensure that field trials created in child |
| 1191 // processes are properly reported in crash reports. | 1187 // processes are properly reported in crash reports. |
| 1192 trial->group(); | 1188 trial->group(); |
| 1193 } | 1189 } |
| 1194 } | 1190 } |
| 1195 return true; | 1191 return true; |
| 1196 } | 1192 } |
| 1197 | 1193 |
| 1198 #if !defined(OS_NACL) | |
| 1199 // static | 1194 // static |
| 1200 void FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded() { | 1195 void FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded() { |
| 1201 if (!global_) | 1196 if (!global_) |
| 1202 return; | 1197 return; |
| 1203 AutoLock auto_lock(global_->lock_); | 1198 AutoLock auto_lock(global_->lock_); |
| 1204 // Create the allocator if not already created and add all existing trials. | 1199 // Create the allocator if not already created and add all existing trials. |
| 1205 if (global_->field_trial_allocator_ != nullptr) | 1200 if (global_->field_trial_allocator_ != nullptr) |
| 1206 return; | 1201 return; |
| 1207 | 1202 |
| 1208 SharedMemoryCreateOptions options; | 1203 SharedMemoryCreateOptions options; |
| 1209 options.size = kFieldTrialAllocationSize; | 1204 options.size = kFieldTrialAllocationSize; |
| 1210 options.share_read_only = true; | 1205 options.share_read_only = true; |
| 1211 #if defined(OS_MACOSX) && !defined(OS_IOS) | 1206 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 1212 options.type = SharedMemoryHandle::POSIX; | 1207 options.type = SharedMemoryHandle::POSIX; |
| 1213 #endif | 1208 #endif |
| 1214 | 1209 |
| 1215 std::unique_ptr<SharedMemory> shm(new SharedMemory()); | 1210 std::unique_ptr<SharedMemory> shm(new SharedMemory()); |
| 1216 if (!shm->Create(options)) | 1211 if (!shm->Create(options)) |
| 1217 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize); | 1212 OnOutOfMemory(kFieldTrialAllocationSize); |
| 1218 | 1213 |
| 1219 if (!shm->Map(kFieldTrialAllocationSize)) | 1214 if (!shm->Map(kFieldTrialAllocationSize)) |
| 1220 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize); | 1215 OnOutOfMemory(kFieldTrialAllocationSize); |
| 1221 | 1216 |
| 1222 global_->field_trial_allocator_.reset( | 1217 global_->field_trial_allocator_.reset( |
| 1223 new FieldTrialAllocator(std::move(shm), 0, kAllocatorName, false)); | 1218 new FieldTrialAllocator(std::move(shm), 0, kAllocatorName, false)); |
| 1224 global_->field_trial_allocator_->CreateTrackingHistograms(kAllocatorName); | 1219 global_->field_trial_allocator_->CreateTrackingHistograms(kAllocatorName); |
| 1225 | 1220 |
| 1226 // Add all existing field trials. | 1221 // Add all existing field trials. |
| 1227 for (const auto& registered : global_->registered_) { | 1222 for (const auto& registered : global_->registered_) { |
| 1228 AddToAllocatorWhileLocked(global_->field_trial_allocator_.get(), | 1223 AddToAllocatorWhileLocked(global_->field_trial_allocator_.get(), |
| 1229 registered.second); | 1224 registered.second); |
| 1230 } | 1225 } |
| 1231 | 1226 |
| 1232 // Add all existing features. | 1227 // Add all existing features. |
| 1233 FeatureList::GetInstance()->AddFeaturesToAllocator( | 1228 FeatureList::GetInstance()->AddFeaturesToAllocator( |
| 1234 global_->field_trial_allocator_.get()); | 1229 global_->field_trial_allocator_.get()); |
| 1235 | 1230 |
| 1236 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX) | 1231 #if !defined(OS_NACL) |
| 1237 // Set |readonly_allocator_handle_| so we can pass it to be inherited and | 1232 // Set |readonly_allocator_handle_| so we can pass it to be inherited and |
| 1238 // via the command line. | 1233 // via the command line. |
| 1239 global_->readonly_allocator_handle_ = | 1234 global_->readonly_allocator_handle_ = |
| 1240 CreateReadOnlyHandle(global_->field_trial_allocator_.get()); | 1235 CreateReadOnlyHandle(global_->field_trial_allocator_.get()); |
| 1241 #endif | 1236 #endif |
| 1242 } | 1237 } |
| 1243 #endif | |
| 1244 | 1238 |
| 1245 // static | 1239 // static |
| 1246 void FieldTrialList::AddToAllocatorWhileLocked( | 1240 void FieldTrialList::AddToAllocatorWhileLocked( |
| 1247 PersistentMemoryAllocator* allocator, | 1241 PersistentMemoryAllocator* allocator, |
| 1248 FieldTrial* field_trial) { | 1242 FieldTrial* field_trial) { |
| 1249 // Don't do anything if the allocator hasn't been instantiated yet. | 1243 // Don't do anything if the allocator hasn't been instantiated yet. |
| 1250 if (allocator == nullptr) | 1244 if (allocator == nullptr) |
| 1251 return; | 1245 return; |
| 1252 | 1246 |
| 1253 // Or if the allocator is read only, which means we are in a child process and | 1247 // Or if the allocator is read only, which means we are in a child process and |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1343 return; | 1337 return; |
| 1344 } | 1338 } |
| 1345 AutoLock auto_lock(global_->lock_); | 1339 AutoLock auto_lock(global_->lock_); |
| 1346 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); | 1340 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); |
| 1347 trial->AddRef(); | 1341 trial->AddRef(); |
| 1348 trial->SetTrialRegistered(); | 1342 trial->SetTrialRegistered(); |
| 1349 global_->registered_[trial->trial_name()] = trial; | 1343 global_->registered_[trial->trial_name()] = trial; |
| 1350 } | 1344 } |
| 1351 | 1345 |
| 1352 } // namespace base | 1346 } // namespace base |
| OLD | NEW |