Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(234)

Side by Side Diff: base/metrics/field_trial.cc

Issue 2565683003: Share field trial allocator on Mac (Closed)
Patch Set: Use intentionally dummy value and fix comment Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/metrics/field_trial.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/pickle.h" 15 #include "base/pickle.h"
16 #include "base/process/memory.h" 16 #include "base/process/memory.h"
17 #include "base/rand_util.h" 17 #include "base/rand_util.h"
18 #include "base/strings/string_number_conversions.h" 18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h" 19 #include "base/strings/string_util.h"
20 #include "base/strings/stringprintf.h" 20 #include "base/strings/stringprintf.h"
21 #include "base/strings/utf_string_conversions.h" 21 #include "base/strings/utf_string_conversions.h"
22 22
23 // On systems that use the zygote process to spawn child processes, we must 23 // On systems that use the zygote process to spawn child processes, we must
24 // retrieve the correct fd using the mapping in GlobalDescriptors. 24 // retrieve the correct fd using the mapping in GlobalDescriptors.
25 #if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_MACOSX) && \ 25 #if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_MACOSX) && \
26 !defined(OS_ANDROID) 26 !defined(OS_ANDROID)
27 #define POSIX_WITH_ZYGOTE 1 27 #define POSIX_WITH_ZYGOTE 1
28 #endif 28 #endif
29 29
30 #if defined(POSIX_WITH_ZYGOTE) 30 #if defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX)
31 #include "base/posix/global_descriptors.h" 31 #include "base/posix/global_descriptors.h"
32 #endif 32 #endif
33 33
34 namespace base { 34 namespace base {
35 35
36 namespace { 36 namespace {
37 37
38 // Define a separator character to use when creating a persistent form of an 38 // Define a separator character to use when creating a persistent form of an
39 // instance. This is intended for use as a command line argument, passed to a 39 // instance. This is intended for use as a command line argument, passed to a
40 // second process to mimic our state (i.e., provide the same group name). 40 // second process to mimic our state (i.e., provide the same group name).
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 HANDLE src = allocator->shared_memory()->handle().GetHandle(); 277 HANDLE src = allocator->shared_memory()->handle().GetHandle();
278 ProcessHandle process = GetCurrentProcess(); 278 ProcessHandle process = GetCurrentProcess();
279 DWORD access = SECTION_MAP_READ | SECTION_QUERY; 279 DWORD access = SECTION_MAP_READ | SECTION_QUERY;
280 HANDLE dst; 280 HANDLE dst;
281 if (!::DuplicateHandle(process, src, process, &dst, access, true, 0)) 281 if (!::DuplicateHandle(process, src, process, &dst, access, true, 0))
282 return kInvalidPlatformFile; 282 return kInvalidPlatformFile;
283 return dst; 283 return dst;
284 } 284 }
285 #endif 285 #endif
286 286
287 #if defined(POSIX_WITH_ZYGOTE) 287 #if defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX)
288 int CreateReadOnlyHandle(FieldTrialList::FieldTrialAllocator* allocator) { 288 int CreateReadOnlyHandle(FieldTrialList::FieldTrialAllocator* allocator) {
289 SharedMemoryHandle new_handle; 289 SharedMemoryHandle new_handle;
290 allocator->shared_memory()->ShareReadOnlyToProcess(GetCurrentProcessHandle(), 290 allocator->shared_memory()->ShareReadOnlyToProcess(GetCurrentProcessHandle(),
291 &new_handle); 291 &new_handle);
292 return SharedMemory::GetFdFromSharedMemoryHandle(new_handle); 292 return SharedMemory::GetFdFromSharedMemoryHandle(new_handle);
293 } 293 }
294 #endif 294 #endif
295 295
296 } // namespace 296 } // namespace
297 297
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after
798 798
799 #if defined(OS_WIN) 799 #if defined(OS_WIN)
800 if (cmd_line.HasSwitch(field_trial_handle_switch)) { 800 if (cmd_line.HasSwitch(field_trial_handle_switch)) {
801 std::string handle_switch = 801 std::string handle_switch =
802 cmd_line.GetSwitchValueASCII(field_trial_handle_switch); 802 cmd_line.GetSwitchValueASCII(field_trial_handle_switch);
803 bool result = CreateTrialsFromHandleSwitch(handle_switch); 803 bool result = CreateTrialsFromHandleSwitch(handle_switch);
804 DCHECK(result); 804 DCHECK(result);
805 } 805 }
806 #endif 806 #endif
807 807
808 #if defined(POSIX_WITH_ZYGOTE) 808 #if defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX)
809 // If we failed to create trials from the descriptor, fallback to the command 809 // On POSIX, we check if the handle is valid by seeing if the browser process
810 // line. Otherwise we're good -- return. 810 // sent over the switch (we don't care about the value). Invalid handles
811 if (CreateTrialsFromDescriptor(fd_key)) 811 // occur in some browser tests which don't initialize the allocator.
812 return; 812 if (cmd_line.HasSwitch(field_trial_handle_switch)) {
813 bool result = CreateTrialsFromDescriptor(fd_key);
814 DCHECK(result);
815 }
813 #endif 816 #endif
814 817
815 if (cmd_line.HasSwitch(switches::kForceFieldTrials)) { 818 if (cmd_line.HasSwitch(switches::kForceFieldTrials)) {
816 bool result = FieldTrialList::CreateTrialsFromString( 819 bool result = FieldTrialList::CreateTrialsFromString(
817 cmd_line.GetSwitchValueASCII(switches::kForceFieldTrials), 820 cmd_line.GetSwitchValueASCII(switches::kForceFieldTrials),
818 std::set<std::string>()); 821 std::set<std::string>());
819 DCHECK(result); 822 DCHECK(result);
820 } 823 }
821 } 824 }
822 825
823 // static 826 // static
824 void FieldTrialList::CreateFeaturesFromCommandLine( 827 void FieldTrialList::CreateFeaturesFromCommandLine(
825 const base::CommandLine& command_line, 828 const base::CommandLine& command_line,
826 const char* enable_features_switch, 829 const char* enable_features_switch,
827 const char* disable_features_switch, 830 const char* disable_features_switch,
828 FeatureList* feature_list) { 831 FeatureList* feature_list) {
829 // Fallback to command line if not using shared memory. 832 // Fallback to command line if not using shared memory.
830 if (!kUseSharedMemoryForFieldTrials || 833 if (!kUseSharedMemoryForFieldTrials ||
831 !global_->field_trial_allocator_.get()) { 834 !global_->field_trial_allocator_.get()) {
832 return feature_list->InitializeFromCommandLine( 835 return feature_list->InitializeFromCommandLine(
833 command_line.GetSwitchValueASCII(enable_features_switch), 836 command_line.GetSwitchValueASCII(enable_features_switch),
834 command_line.GetSwitchValueASCII(disable_features_switch)); 837 command_line.GetSwitchValueASCII(disable_features_switch));
835 } 838 }
836 839
837 feature_list->InitializeFromSharedMemory( 840 feature_list->InitializeFromSharedMemory(
838 global_->field_trial_allocator_.get()); 841 global_->field_trial_allocator_.get());
839 } 842 }
840 843
841 #if defined(POSIX_WITH_ZYGOTE) 844 #if defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX)
842 // static 845 // static
843 bool FieldTrialList::CreateTrialsFromDescriptor(int fd_key) { 846 bool FieldTrialList::CreateTrialsFromDescriptor(int fd_key) {
844 if (!kUseSharedMemoryForFieldTrials) 847 if (!kUseSharedMemoryForFieldTrials)
845 return false; 848 return false;
846 849
847 if (fd_key == -1) 850 if (fd_key == -1)
848 return false; 851 return false;
849 852
850 int fd = GlobalDescriptors::GetInstance()->MaybeGet(fd_key); 853 int fd = GlobalDescriptors::GetInstance()->MaybeGet(fd_key);
851 if (fd == -1) 854 if (fd == -1)
852 return false; 855 return false;
853 856
857 #if defined(POSIX_WITH_ZYGOTE)
854 SharedMemoryHandle shm_handle(fd, true); 858 SharedMemoryHandle shm_handle(fd, true);
859 #elif defined(OS_MACOSX)
860 SharedMemoryHandle shm_handle(FileDescriptor(fd, true));
861 #endif
862
855 bool result = FieldTrialList::CreateTrialsFromSharedMemoryHandle(shm_handle); 863 bool result = FieldTrialList::CreateTrialsFromSharedMemoryHandle(shm_handle);
856 DCHECK(result); 864 DCHECK(result);
857 return true; 865 return true;
858 } 866 }
859 #endif 867 #endif
860 868
861 #if defined(OS_WIN) 869 #if defined(OS_WIN)
862 // static 870 // static
863 void FieldTrialList::AppendFieldTrialHandleIfNeeded( 871 void FieldTrialList::AppendFieldTrialHandleIfNeeded(
864 HandlesToInheritVector* handles) { 872 HandlesToInheritVector* handles) {
(...skipping 29 matching lines...) Expand all
894 // content browser tests currently don't create a FieldTrialList because they 902 // content browser tests currently don't create a FieldTrialList because they
895 // don't run ChromeBrowserMainParts code where it's done for Chrome. 903 // don't run ChromeBrowserMainParts code where it's done for Chrome.
896 // Some tests depend on the enable and disable features flag switch, though, 904 // Some tests depend on the enable and disable features flag switch, though,
897 // so we can still add those even though AllStatesToString() will be a no-op. 905 // so we can still add those even though AllStatesToString() will be a no-op.
898 if (!global_) { 906 if (!global_) {
899 AddFeatureAndFieldTrialFlags(enable_features_switch, 907 AddFeatureAndFieldTrialFlags(enable_features_switch,
900 disable_features_switch, cmd_line); 908 disable_features_switch, cmd_line);
901 return; 909 return;
902 } 910 }
903 911
904 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE) 912 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX)
905 // Use shared memory to pass the state if the feature is enabled, otherwise 913 // Use shared memory to pass the state if the feature is enabled, otherwise
906 // fallback to passing it via the command line as a string. 914 // fallback to passing it via the command line as a string.
907 if (kUseSharedMemoryForFieldTrials) { 915 if (kUseSharedMemoryForFieldTrials) {
908 InstantiateFieldTrialAllocatorIfNeeded(); 916 InstantiateFieldTrialAllocatorIfNeeded();
909 // If the readonly handle didn't get duplicated properly, then fallback to 917 // If the readonly handle didn't get duplicated properly, then fallback to
910 // original behavior. 918 // original behavior.
911 if (global_->readonly_allocator_handle_ == kInvalidPlatformFile) { 919 if (global_->readonly_allocator_handle_ == kInvalidPlatformFile) {
912 AddFeatureAndFieldTrialFlags(enable_features_switch, 920 AddFeatureAndFieldTrialFlags(enable_features_switch,
913 disable_features_switch, cmd_line); 921 disable_features_switch, cmd_line);
914 return; 922 return;
915 } 923 }
916 924
917 global_->field_trial_allocator_->UpdateTrackingHistograms(); 925 global_->field_trial_allocator_->UpdateTrackingHistograms();
918 926
919 #if defined(OS_WIN) 927 #if defined(OS_WIN)
920 // We need to pass a named anonymous handle to shared memory over the 928 // We need to pass a named anonymous handle to shared memory over the
921 // command line on Windows, since the child doesn't know which of the 929 // command line on Windows, since the child doesn't know which of the
922 // handles it inherited it should open. On POSIX, we don't need to do this 930 // handles it inherited it should open.
923 // -- we dup the fd into a fixed fd kFieldTrialDescriptor, so we can just
924 // look it up there.
925 // PlatformFile is typedef'd to HANDLE which is typedef'd to void *. We 931 // PlatformFile is typedef'd to HANDLE which is typedef'd to void *. We
926 // basically cast the handle into an int (uintptr_t, to be exact), stringify 932 // basically cast the handle into an int (uintptr_t, to be exact), stringify
927 // the int, and pass it as a command-line flag. The child process will do 933 // the int, and pass it as a command-line flag. The child process will do
928 // the reverse conversions to retrieve the handle. See 934 // the reverse conversions to retrieve the handle. See
929 // http://stackoverflow.com/a/153077 935 // http://stackoverflow.com/a/153077
930 auto uintptr_handle = 936 auto uintptr_handle =
931 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_); 937 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_);
932 std::string field_trial_handle = std::to_string(uintptr_handle); 938 std::string field_trial_handle = std::to_string(uintptr_handle);
933 cmd_line->AppendSwitchASCII(field_trial_handle_switch, field_trial_handle); 939 cmd_line->AppendSwitchASCII(field_trial_handle_switch, field_trial_handle);
940 #elif defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX)
941 // On POSIX, we dup the fd into a fixed fd kFieldTrialDescriptor, so we
942 // don't have to pass over the handle (it's not even the right handle
943 // anyways). But some browser tests don't create the allocator, so we need
944 // to be able to distinguish valid and invalid handles. We do that by just
945 // checking that the flag is set with a dummy value.
946 cmd_line->AppendSwitchASCII(field_trial_handle_switch, "1");
934 #endif 947 #endif
935 return; 948 return;
936 } 949 }
937 #endif 950 #endif
938 951
939 AddFeatureAndFieldTrialFlags(enable_features_switch, disable_features_switch, 952 AddFeatureAndFieldTrialFlags(enable_features_switch, disable_features_switch,
940 cmd_line); 953 cmd_line);
941 } 954 }
942 955
943 // static 956 // static
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
1189 if (!global_) 1202 if (!global_)
1190 return; 1203 return;
1191 AutoLock auto_lock(global_->lock_); 1204 AutoLock auto_lock(global_->lock_);
1192 // Create the allocator if not already created and add all existing trials. 1205 // Create the allocator if not already created and add all existing trials.
1193 if (global_->field_trial_allocator_ != nullptr) 1206 if (global_->field_trial_allocator_ != nullptr)
1194 return; 1207 return;
1195 1208
1196 SharedMemoryCreateOptions options; 1209 SharedMemoryCreateOptions options;
1197 options.size = kFieldTrialAllocationSize; 1210 options.size = kFieldTrialAllocationSize;
1198 options.share_read_only = true; 1211 options.share_read_only = true;
1212 #if defined(OS_MACOSX) && !defined(OS_IOS)
1213 options.type = SharedMemoryHandle::POSIX;
1214 #endif
1199 1215
1200 std::unique_ptr<SharedMemory> shm(new SharedMemory()); 1216 std::unique_ptr<SharedMemory> shm(new SharedMemory());
1201 if (!shm->Create(options)) 1217 if (!shm->Create(options))
1202 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize); 1218 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize);
1203 1219
1204 if (!shm->Map(kFieldTrialAllocationSize)) 1220 if (!shm->Map(kFieldTrialAllocationSize))
1205 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize); 1221 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize);
1206 1222
1207 global_->field_trial_allocator_.reset( 1223 global_->field_trial_allocator_.reset(
1208 new FieldTrialAllocator(std::move(shm), 0, kAllocatorName, false)); 1224 new FieldTrialAllocator(std::move(shm), 0, kAllocatorName, false));
1209 global_->field_trial_allocator_->CreateTrackingHistograms(kAllocatorName); 1225 global_->field_trial_allocator_->CreateTrackingHistograms(kAllocatorName);
1210 1226
1211 // Add all existing field trials. 1227 // Add all existing field trials.
1212 for (const auto& registered : global_->registered_) { 1228 for (const auto& registered : global_->registered_) {
1213 AddToAllocatorWhileLocked(registered.second); 1229 AddToAllocatorWhileLocked(registered.second);
1214 } 1230 }
1215 1231
1216 // Add all existing features. 1232 // Add all existing features.
1217 FeatureList::GetInstance()->AddFeaturesToAllocator( 1233 FeatureList::GetInstance()->AddFeaturesToAllocator(
1218 global_->field_trial_allocator_.get()); 1234 global_->field_trial_allocator_.get());
1219 1235
1220 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE) 1236 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE) || defined(OS_MACOSX)
1221 // Set |readonly_allocator_handle_| so we can pass it to be inherited and 1237 // Set |readonly_allocator_handle_| so we can pass it to be inherited and
1222 // via the command line. 1238 // via the command line.
1223 global_->readonly_allocator_handle_ = 1239 global_->readonly_allocator_handle_ =
1224 CreateReadOnlyHandle(global_->field_trial_allocator_.get()); 1240 CreateReadOnlyHandle(global_->field_trial_allocator_.get());
1225 #endif 1241 #endif
1226 } 1242 }
1227 #endif 1243 #endif
1228 1244
1229 // static 1245 // static
1230 void FieldTrialList::AddToAllocatorWhileLocked(FieldTrial* field_trial) { 1246 void FieldTrialList::AddToAllocatorWhileLocked(FieldTrial* field_trial) {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1325 return; 1341 return;
1326 } 1342 }
1327 AutoLock auto_lock(global_->lock_); 1343 AutoLock auto_lock(global_->lock_);
1328 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); 1344 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name();
1329 trial->AddRef(); 1345 trial->AddRef();
1330 trial->SetTrialRegistered(); 1346 trial->SetTrialRegistered();
1331 global_->registered_[trial->trial_name()] = trial; 1347 global_->registered_[trial->trial_name()] = trial;
1332 } 1348 }
1333 1349
1334 } // namespace base 1350 } // namespace base
OLDNEW
« no previous file with comments | « base/metrics/field_trial.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698