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

Side by Side Diff: trunk/src/tools/gn/toolchain_manager.cc

Issue 46313006: Revert 232657 "GN: toolchain threading cleanup" (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 7 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « trunk/src/tools/gn/toolchain.cc ('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) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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 "tools/gn/toolchain_manager.h" 5 #include "tools/gn/toolchain_manager.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "build/build_config.h" 10 #include "build/build_config.h"
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 return SourceFile(dir.value() + "BUILD.gn"); 71 return SourceFile(dir.value() + "BUILD.gn");
72 } 72 }
73 73
74 } // namespace 74 } // namespace
75 75
76 struct ToolchainManager::Info { 76 struct ToolchainManager::Info {
77 Info(const BuildSettings* build_settings, 77 Info(const BuildSettings* build_settings,
78 const Label& toolchain_name, 78 const Label& toolchain_name,
79 const std::string& output_subdir_name) 79 const std::string& output_subdir_name)
80 : state(TOOLCHAIN_NOT_LOADED), 80 : state(TOOLCHAIN_NOT_LOADED),
81 settings(build_settings, output_subdir_name), 81 toolchain(toolchain_name),
82 toolchain(new Toolchain(&settings, toolchain_name)),
83 toolchain_set(false), 82 toolchain_set(false),
83 settings(build_settings, &toolchain, output_subdir_name),
84 toolchain_file_loaded(false), 84 toolchain_file_loaded(false),
85 item_node(NULL) { 85 item_node(NULL) {
86 settings.set_toolchain_label(toolchain_name);
87 }
88
89 ~Info() {
90 if (!item_node) // See toolchain definition for more.
91 delete toolchain;
92 } 86 }
93 87
94 // Makes sure that an ItemNode is created for the toolchain, which lets 88 // Makes sure that an ItemNode is created for the toolchain, which lets
95 // targets depend on the (potentially future) loading of the toolchain. 89 // targets depend on the (potentially future) loading of the toolchain.
96 // 90 //
97 // We can't always do this at the beginning since when doing the default 91 // We can't always do this at the beginning since when doing the default
98 // build config, we don't know the toolchain name yet. We also need to go 92 // build config, we don't know the toolchain name yet. We also need to go
99 // through some effort to avoid doing this inside the toolchain manager's 93 // through some effort to avoid doing this inside the toolchain manager's
100 // lock (to avoid holding two locks at once). 94 // lock (to avoid holding two locks at once).
101 void EnsureItemNode() { 95 void EnsureItemNode() {
102 if (!item_node) { 96 if (!item_node) {
103 ItemTree& tree = settings.build_settings()->item_tree(); 97 ItemTree& tree = settings.build_settings()->item_tree();
104 item_node = new ItemNode(toolchain); 98 item_node = new ItemNode(&toolchain);
105 tree.AddNodeLocked(item_node); 99 tree.AddNodeLocked(item_node);
106 } 100 }
107 } 101 }
108 102
109 ToolchainState state; 103 ToolchainState state;
110 104
105 Toolchain toolchain;
106 bool toolchain_set;
107 LocationRange toolchain_definition_location;
108
111 // The first place in the build that we saw a reference for this toolchain. 109 // The first place in the build that we saw a reference for this toolchain.
112 // This allows us to report errors if it can't be loaded and blame some 110 // This allows us to report errors if it can't be loaded and blame some
113 // reasonable place of the code. This will be empty for the default toolchain. 111 // reasonable place of the code. This will be empty for the default toolchain.
114 LocationRange specified_from; 112 LocationRange specified_from;
115 113
116 // When the state is TOOLCHAIN_SETTINGS_LOADED, the settings should be 114 // When the state is TOOLCHAIN_SETTINGS_LOADED, the settings should be
117 // considered read-only and can be read without locking. Otherwise, they 115 // considered read-only and can be read without locking. Otherwise, they
118 // should not be accessed at all except to load them (which can therefore 116 // should not be accessed at all except to load them (which can therefore
119 // also be done outside of the lock). This works as long as the state flag 117 // also be done outside of the lock). This works as long as the state flag
120 // is only ever read or written inside the lock. 118 // is only ever read or written inside the lock.
121 Settings settings; 119 Settings settings;
122 120
123 // When we create an item node, this pointer will be owned by that node
124 // so it's lifetime is managed by the dependency graph. Before we've created
125 // the ItemNode, this class has to takre responsibility for this pointer.
126 Toolchain* toolchain;
127 bool toolchain_set;
128 LocationRange toolchain_definition_location;
129
130 // Set when the file corresponding to the toolchain definition is loaded. 121 // Set when the file corresponding to the toolchain definition is loaded.
131 // This will normally be set right after "toolchain_set". However, if the 122 // This will normally be set right after "toolchain_set". However, if the
132 // toolchain definition is missing, the file might be marked loaded but the 123 // toolchain definition is missing, the file might be marked loaded but the
133 // toolchain definition could still be unset. 124 // toolchain definition could still be unset.
134 bool toolchain_file_loaded; 125 bool toolchain_file_loaded;
135 126
136 // While state == TOOLCHAIN_SETTINGS_LOADING || TOOLCHAIN_DEFINITION_LOADING, 127 // While state == TOOLCHAIN_SETTINGS_LOADING || TOOLCHAIN_DEFINITION_LOADING,
137 // this will collect all scheduled invocations using this toolchain. They'll 128 // this will collect all scheduled invocations using this toolchain. They'll
138 // be issued once the settings file has been interpreted. 129 // be issued once the settings file has been interpreted.
139 // 130 //
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 const Toolchain* ToolchainManager::GetToolchainDefinitionUnlocked( 195 const Toolchain* ToolchainManager::GetToolchainDefinitionUnlocked(
205 const Label& toolchain_name) { 196 const Label& toolchain_name) {
206 base::AutoLock lock(GetLock()); 197 base::AutoLock lock(GetLock());
207 ToolchainMap::iterator found = toolchains_.find(toolchain_name); 198 ToolchainMap::iterator found = toolchains_.find(toolchain_name);
208 if (found == toolchains_.end() || !found->second->toolchain_set) 199 if (found == toolchains_.end() || !found->second->toolchain_set)
209 return NULL; 200 return NULL;
210 201
211 // Since we don't allow defining a toolchain more than once, we know that 202 // Since we don't allow defining a toolchain more than once, we know that
212 // once it's set it won't be mutated, so we can safely return this pointer 203 // once it's set it won't be mutated, so we can safely return this pointer
213 // for reading outside the lock. 204 // for reading outside the lock.
214 return found->second->toolchain; 205 return &found->second->toolchain;
215 } 206 }
216 207
217 bool ToolchainManager::SetDefaultToolchainUnlocked( 208 bool ToolchainManager::SetDefaultToolchainUnlocked(
218 const Label& default_toolchain, 209 const Label& default_toolchain,
219 const LocationRange& defined_here, 210 const LocationRange& defined_here,
220 Err* err) { 211 Err* err) {
221 base::AutoLock lock(GetLock()); 212 base::AutoLock lock(GetLock());
222 if (!default_toolchain_.is_null()) { 213 if (!default_toolchain_.is_null()) {
223 *err = Err(defined_here, "Default toolchain already set."); 214 *err = Err(defined_here, "Default toolchain already set.");
224 err->AppendSubErr(Err(default_toolchain_defined_here_, 215 err->AppendSubErr(Err(default_toolchain_defined_here_,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 info = LoadNewToolchainLocked(defined_from, tc.label(), err); 254 info = LoadNewToolchainLocked(defined_from, tc.label(), err);
264 if (!info) 255 if (!info)
265 return false; 256 return false;
266 } else { 257 } else {
267 // It's important to preserve the exact Toolchain object in our tree since 258 // It's important to preserve the exact Toolchain object in our tree since
268 // it will be in the ItemTree and targets may have dependencies on it. 259 // it will be in the ItemTree and targets may have dependencies on it.
269 info = found->second; 260 info = found->second;
270 } 261 }
271 262
272 // The labels should match or else we're setting the wrong one! 263 // The labels should match or else we're setting the wrong one!
273 CHECK(info->toolchain->label() == tc.label()); 264 CHECK(info->toolchain.label() == tc.label());
274 265
275 // Save the toolchain. We can just overwrite our definition. 266 // Save the toolchain. We can just overwrite our definition, but we need to
276 *info->toolchain = tc; 267 // be careful to preserve the is_default flag.
268 bool is_default = info->toolchain.is_default();
269 info->toolchain = tc;
270 info->toolchain.set_is_default(is_default);
277 271
278 if (info->toolchain_set) { 272 if (info->toolchain_set) {
279 *err = Err(defined_from, "Duplicate toolchain definition."); 273 *err = Err(defined_from, "Duplicate toolchain definition.");
280 err->AppendSubErr(Err( 274 err->AppendSubErr(Err(
281 info->toolchain_definition_location, 275 info->toolchain_definition_location,
282 "Previously defined here.", 276 "Previously defined here.",
283 "A toolchain can only be defined once. One tricky way that this could\n" 277 "A toolchain can only be defined once. One tricky way that this could\n"
284 "happen is if your definition is itself in a file that's interpreted\n" 278 "happen is if your definition is itself in a file that's interpreted\n"
285 "under different toolchains, which would result in multiple\n" 279 "under different toolchains, which would result in multiple\n"
286 "definitions as the file is loaded multiple times. So be sure your\n" 280 "definitions as the file is loaded multiple times. So be sure your\n"
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 toolchains_[default_toolchain_] = info; 416 toolchains_[default_toolchain_] = info;
423 toolchains_.erase(old_default); 417 toolchains_.erase(old_default);
424 418
425 // Toolchain should not have been loaded in the build config file. 419 // Toolchain should not have been loaded in the build config file.
426 CHECK(!info->toolchain_set); 420 CHECK(!info->toolchain_set);
427 421
428 // We need to set the toolchain label now that we know it. There's no way 422 // We need to set the toolchain label now that we know it. There's no way
429 // to set the label, but we can assign the toolchain to a new one. Loading 423 // to set the label, but we can assign the toolchain to a new one. Loading
430 // the build config can not change the toolchain, so we won't be overwriting 424 // the build config can not change the toolchain, so we won't be overwriting
431 // anything useful. 425 // anything useful.
432 *info->toolchain = Toolchain(&info->settings, default_toolchain_); 426 info->toolchain = Toolchain(default_toolchain_);
433 info->settings.set_is_default(true); 427 info->toolchain.set_is_default(true);
434 info->settings.set_toolchain_label(default_toolchain_);
435 info->EnsureItemNode(); 428 info->EnsureItemNode();
436 429
437 // The default toolchain is loaded in greedy mode so all targets we 430 // The default toolchain is loaded in greedy mode so all targets we
438 // encounter are generated. Non-default toolchain settings stay in non-greedy 431 // encounter are generated. Non-default toolchain settings stay in non-greedy
439 // so we only generate the minimally required set. 432 // so we only generate the minimally required set.
440 info->settings.set_greedy_target_generation(true); 433 info->settings.set_greedy_target_generation(true);
441 434
442 // Schedule a load of the toolchain build file. 435 // Schedule a load of the toolchain build file.
443 Err err; 436 Err err;
444 ScheduleInvocationLocked(LocationRange(), default_toolchain_, 437 ScheduleInvocationLocked(LocationRange(), default_toolchain_,
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 void ToolchainManager::BackgroundLoadBuildConfig(Info* info, 479 void ToolchainManager::BackgroundLoadBuildConfig(Info* info,
487 bool is_default, 480 bool is_default,
488 const ParseNode* root) { 481 const ParseNode* root) {
489 // Danger: No early returns without decrementing the work count. 482 // Danger: No early returns without decrementing the work count.
490 if (root && !g_scheduler->is_failed()) { 483 if (root && !g_scheduler->is_failed()) {
491 // Nobody should be accessing settings at this point other than us since we 484 // Nobody should be accessing settings at this point other than us since we
492 // haven't marked it loaded, so we can do it outside the lock. 485 // haven't marked it loaded, so we can do it outside the lock.
493 Scope* base_config = info->settings.base_config(); 486 Scope* base_config = info->settings.base_config();
494 base_config->set_source_dir(SourceDir("//")); 487 base_config->set_source_dir(SourceDir("//"));
495 488
496 info->settings.build_settings()->build_args().SetupRootScope( 489 info->settings.build_settings()->build_args().SetupRootScope(base_config,
497 base_config, info->toolchain->args()); 490 info->settings.toolchain()->args());
498 491
499 base_config->SetProcessingBuildConfig(); 492 base_config->SetProcessingBuildConfig();
500 if (is_default) 493 if (is_default)
501 base_config->SetProcessingDefaultBuildConfig(); 494 base_config->SetProcessingDefaultBuildConfig();
502 495
503 ScopedTrace trace(TraceItem::TRACE_FILE_EXECUTE, 496 ScopedTrace trace(TraceItem::TRACE_FILE_EXECUTE,
504 info->settings.build_settings()->build_config_file().value()); 497 info->settings.build_settings()->build_config_file().value());
505 trace.SetToolchain(info->settings.toolchain_label()); 498 trace.SetToolchain(info->settings.toolchain()->label());
506 499
507 const BlockNode* root_block = root->AsBlock(); 500 const BlockNode* root_block = root->AsBlock();
508 Err err; 501 Err err;
509 root_block->ExecuteBlockInScope(base_config, &err); 502 root_block->ExecuteBlockInScope(base_config, &err);
510 503
511 trace.Done(); 504 trace.Done();
512 505
513 base_config->ClearProcessingBuildConfig(); 506 base_config->ClearProcessingBuildConfig();
514 if (is_default) 507 if (is_default)
515 base_config->ClearProcessingDefaultBuildConfig(); 508 base_config->ClearProcessingDefaultBuildConfig();
(...skipping 24 matching lines...) Expand all
540 } 533 }
541 g_scheduler->DecrementWorkCount(); 534 g_scheduler->DecrementWorkCount();
542 } 535 }
543 536
544 void ToolchainManager::BackgroundInvoke(const Info* info, 537 void ToolchainManager::BackgroundInvoke(const Info* info,
545 const SourceFile& file_name, 538 const SourceFile& file_name,
546 const ParseNode* root) { 539 const ParseNode* root) {
547 if (root && !g_scheduler->is_failed()) { 540 if (root && !g_scheduler->is_failed()) {
548 if (g_scheduler->verbose_logging()) { 541 if (g_scheduler->verbose_logging()) {
549 g_scheduler->Log("Running", file_name.value() + " with toolchain " + 542 g_scheduler->Log("Running", file_name.value() + " with toolchain " +
550 info->toolchain->label().GetUserVisibleName(false)); 543 info->toolchain.label().GetUserVisibleName(false));
551 } 544 }
552 545
553 Scope our_scope(info->settings.base_config()); 546 Scope our_scope(info->settings.base_config());
554 ScopePerFileProvider per_file_provider(&our_scope); 547 ScopePerFileProvider per_file_provider(&our_scope);
555 our_scope.set_source_dir(file_name.GetDir()); 548 our_scope.set_source_dir(file_name.GetDir());
556 549
557 ScopedTrace trace(TraceItem::TRACE_FILE_EXECUTE, file_name.value()); 550 ScopedTrace trace(TraceItem::TRACE_FILE_EXECUTE, file_name.value());
558 trace.SetToolchain(info->settings.toolchain_label()); 551 trace.SetToolchain(info->settings.toolchain()->label());
559 552
560 Err err; 553 Err err;
561 root->Execute(&our_scope, &err); 554 root->Execute(&our_scope, &err);
562 if (err.has_error()) 555 if (err.has_error())
563 g_scheduler->FailWithError(err); 556 g_scheduler->FailWithError(err);
564 557
565 trace.Done(); 558 trace.Done();
566 559
567 { 560 {
568 // Check to see if any build config invocations depend on this file and 561 // Check to see if any build config invocations depend on this file and
(...skipping 15 matching lines...) Expand all
584 } 577 }
585 } 578 }
586 } 579 }
587 580
588 g_scheduler->DecrementWorkCount(); 581 g_scheduler->DecrementWorkCount();
589 } 582 }
590 583
591 base::Lock& ToolchainManager::GetLock() const { 584 base::Lock& ToolchainManager::GetLock() const {
592 return build_settings_->item_tree().lock(); 585 return build_settings_->item_tree().lock();
593 } 586 }
OLDNEW
« no previous file with comments | « trunk/src/tools/gn/toolchain.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698