Index: components/nacl/renderer/plugin/pnacl_translate_thread.cc |
diff --git a/components/nacl/renderer/plugin/pnacl_translate_thread.cc b/components/nacl/renderer/plugin/pnacl_translate_thread.cc |
index 67701215df903aeccba0af8932a2fb64a99c49f5..9ff9ff651086304f2cb1ad2b46f818bf4e300357 100644 |
--- a/components/nacl/renderer/plugin/pnacl_translate_thread.cc |
+++ b/components/nacl/renderer/plugin/pnacl_translate_thread.cc |
@@ -9,7 +9,6 @@ |
#include "components/nacl/renderer/plugin/plugin.h" |
#include "components/nacl/renderer/plugin/plugin_error.h" |
-#include "components/nacl/renderer/plugin/pnacl_resources.h" |
#include "components/nacl/renderer/plugin/srpc_params.h" |
#include "components/nacl/renderer/plugin/temporary_file.h" |
#include "components/nacl/renderer/plugin/utility.h" |
@@ -74,50 +73,82 @@ void GetSubzeroCommandLine(std::vector<char>* split_args, |
} // namespace |
PnaclTranslateThread::PnaclTranslateThread() |
- : compiler_subprocess_active_(false), |
+ : compiler_subprocess_(NULL), |
+ ld_subprocess_(NULL), |
+ compiler_subprocess_active_(false), |
ld_subprocess_active_(false), |
- subprocesses_aborted_(false), |
done_(false), |
compile_time_(0), |
obj_files_(NULL), |
num_threads_(0), |
nexe_file_(NULL), |
coordinator_error_info_(NULL), |
- resources_(NULL), |
- coordinator_(NULL), |
- plugin_(NULL) { |
+ coordinator_(NULL) { |
NaClXMutexCtor(&subprocess_mu_); |
NaClXMutexCtor(&cond_mu_); |
NaClXCondVarCtor(&buffer_cond_); |
} |
-void PnaclTranslateThread::RunTranslate( |
+void PnaclTranslateThread::SetupState( |
const pp::CompletionCallback& finish_callback, |
+ NaClSubprocess* compiler_subprocess, |
+ NaClSubprocess* ld_subprocess, |
const std::vector<TempFile*>* obj_files, |
int num_threads, |
TempFile* nexe_file, |
nacl::DescWrapper* invalid_desc_wrapper, |
ErrorInfo* error_info, |
- PnaclResources* resources, |
PP_PNaClOptions* pnacl_options, |
const std::string& architecture_attributes, |
- PnaclCoordinator* coordinator, |
- Plugin* plugin) { |
- PLUGIN_PRINTF(("PnaclStreamingTranslateThread::RunTranslate)\n")); |
+ PnaclCoordinator* coordinator) { |
+ PLUGIN_PRINTF(("PnaclTranslateThread::SetupState)\n")); |
+ compiler_subprocess_ = compiler_subprocess; |
+ ld_subprocess_ = ld_subprocess; |
obj_files_ = obj_files; |
num_threads_ = num_threads; |
nexe_file_ = nexe_file; |
invalid_desc_wrapper_ = invalid_desc_wrapper; |
coordinator_error_info_ = error_info; |
- resources_ = resources; |
pnacl_options_ = pnacl_options; |
architecture_attributes_ = architecture_attributes; |
coordinator_ = coordinator; |
- plugin_ = plugin; |
- // Invoke llc followed by ld off the main thread. This allows use of |
- // blocking RPCs that would otherwise block the JavaScript main thread. |
report_translate_finished_ = finish_callback; |
+} |
+ |
+void PnaclTranslateThread::RunCompile( |
+ const pp::CompletionCallback& compile_finished_callback) { |
+ PLUGIN_PRINTF(("PnaclTranslateThread::RunCompile)\n")); |
+ DCHECK(started()); |
+ DCHECK(compiler_subprocess_->service_runtime()); |
+ compiler_subprocess_active_ = true; |
+ |
+ compile_finished_callback_ = compile_finished_callback; |
+ translate_thread_.reset(new NaClThread); |
+ if (translate_thread_ == NULL) { |
+ TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, |
+ "could not allocate thread struct."); |
+ return; |
+ } |
+ const int32_t kArbitraryStackSize = 128 * 1024; |
+ if (!NaClThreadCreateJoinable(translate_thread_.get(), DoCompileThread, this, |
+ kArbitraryStackSize)) { |
+ TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, |
+ "could not create thread."); |
+ translate_thread_.reset(NULL); |
+ } |
+} |
+ |
+void PnaclTranslateThread::RunLink() { |
+ PLUGIN_PRINTF(("PnaclTranslateThread::RunLink)\n")); |
+ DCHECK(started()); |
+ DCHECK(ld_subprocess_->service_runtime()); |
+ ld_subprocess_active_ = true; |
+ |
+ // Tear down the previous thread. |
+ // TODO(jvoung): Use base/threading or something where we can have a |
+ // persistent thread and easily post tasks to that persistent thread. |
+ NaClThreadJoin(translate_thread_.get()); |
translate_thread_.reset(new NaClThread); |
if (translate_thread_ == NULL) { |
TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, |
@@ -125,9 +156,7 @@ void PnaclTranslateThread::RunTranslate( |
return; |
} |
const int32_t kArbitraryStackSize = 128 * 1024; |
- if (!NaClThreadCreateJoinable(translate_thread_.get(), |
- DoTranslateThread, |
- this, |
+ if (!NaClThreadCreateJoinable(translate_thread_.get(), DoLinkThread, this, |
kArbitraryStackSize)) { |
TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, |
"could not create thread."); |
@@ -154,14 +183,30 @@ void PnaclTranslateThread::EndStream() { |
NaClXMutexUnlock(&cond_mu_); |
} |
-void WINAPI PnaclTranslateThread::DoTranslateThread(void* arg) { |
+void WINAPI PnaclTranslateThread::DoCompileThread(void* arg) { |
PnaclTranslateThread* translator = |
reinterpret_cast<PnaclTranslateThread*>(arg); |
- translator->DoTranslate(); |
+ translator->DoCompile(); |
} |
-void PnaclTranslateThread::DoTranslate() { |
- ErrorInfo error_info; |
+void PnaclTranslateThread::DoCompile() { |
+ // If the main thread asked us to exit in between starting the thread |
+ // and now, just leave now. |
+ { |
+ nacl::MutexLocker ml(&subprocess_mu_); |
+ if (!compiler_subprocess_active_) |
+ return; |
+ } |
+ |
+ // Now that we are in helper thread, we can do the the blocking |
+ // StartSrpcServices operation. |
+ if (!compiler_subprocess_->StartSrpcServices()) { |
+ TranslateFailed( |
+ PP_NACL_ERROR_SRPC_CONNECTION_FAIL, |
+ "SRPC connection failure for " + compiler_subprocess_->description()); |
+ return; |
+ } |
+ |
SrpcParams params; |
std::vector<nacl::DescWrapper*> compile_out_files; |
size_t i; |
@@ -170,50 +215,9 @@ void PnaclTranslateThread::DoTranslate() { |
for (; i < PnaclCoordinator::kMaxTranslatorObjectFiles; i++) |
compile_out_files.push_back(invalid_desc_wrapper_); |
- PLUGIN_PRINTF( |
- ("DoTranslate using subzero: %d\n", pnacl_options_->use_subzero)); |
+ PLUGIN_PRINTF(("DoCompile using subzero: %d\n", pnacl_options_->use_subzero)); |
pp::Core* core = pp::Module::Get()->core(); |
- int64_t compiler_load_start_time = NaClGetTimeOfDayMicroseconds(); |
- PnaclResources::ResourceType compiler_type = pnacl_options_->use_subzero |
- ? PnaclResources::SUBZERO |
- : PnaclResources::LLC; |
- // Ownership of file_info is transferred here. |
- PP_NaClFileInfo file_info = resources_->TakeFileInfo(compiler_type); |
- const std::string& url = resources_->GetUrl(compiler_type); |
- NaClSubprocess* compiler_subprocess = |
- plugin_->LoadHelperNaClModule(url, file_info, &error_info); |
- if (compiler_subprocess == NULL) { |
- TranslateFailed(PP_NACL_ERROR_PNACL_LLC_SETUP, |
- "Compile process could not be created: " + |
- error_info.message()); |
- return; |
- } |
- int64_t compiler_load_time_total = |
- NaClGetTimeOfDayMicroseconds() - compiler_load_start_time; |
- GetNaClInterface()->LogTranslateTime("NaCl.Perf.PNaClLoadTime.LoadCompiler", |
- compiler_load_time_total); |
- GetNaClInterface()->LogTranslateTime( |
- pnacl_options_->use_subzero |
- ? "NaCl.Perf.PNaClLoadTime.LoadCompiler.Subzero" |
- : "NaCl.Perf.PNaClLoadTime.LoadCompiler.LLC", |
- compiler_load_time_total); |
- |
- { |
- nacl::MutexLocker ml(&subprocess_mu_); |
- // If we received a call to AbortSubprocesses() before we had a chance to |
- // set compiler_subprocess_, shut down and clean up the subprocess started |
- // here. |
- if (subprocesses_aborted_) { |
- compiler_subprocess->service_runtime()->Shutdown(); |
- delete compiler_subprocess; |
- return; |
- } |
- compiler_subprocess_.reset(compiler_subprocess); |
- compiler_subprocess = NULL; |
- compiler_subprocess_active_ = true; |
- } |
- |
int64_t do_compile_start_time = NaClGetTimeOfDayMicroseconds(); |
bool init_success; |
@@ -226,6 +230,7 @@ void PnaclTranslateThread::DoTranslate() { |
pnacl_options_->opt_level, pnacl_options_->is_debug, |
architecture_attributes_); |
} |
+ |
init_success = compiler_subprocess_->InvokeSrpcMethod( |
"StreamInitWithSplit", "ihhhhhhhhhhhhhhhhC", ¶ms, num_threads_, |
compile_out_files[0]->desc(), compile_out_files[1]->desc(), |
@@ -317,22 +322,40 @@ void PnaclTranslateThread::DoTranslate() { |
: "NaCl.Perf.PNaClLoadTime.CompileTime.LLC", |
compile_time_); |
- // Shut down the llc subprocess. |
+ // Shut down the compiler subprocess. |
NaClXMutexLock(&subprocess_mu_); |
compiler_subprocess_active_ = false; |
- compiler_subprocess_.reset(NULL); |
+ compiler_subprocess_->Shutdown(); |
NaClXMutexUnlock(&subprocess_mu_); |
- if(!RunLdSubprocess()) { |
+ core->CallOnMainThread(0, compile_finished_callback_, PP_OK); |
+} |
+ |
+void WINAPI PnaclTranslateThread::DoLinkThread(void* arg) { |
+ PnaclTranslateThread* translator = |
+ reinterpret_cast<PnaclTranslateThread*>(arg); |
+ translator->DoLink(); |
+} |
+ |
+void PnaclTranslateThread::DoLink() { |
+ // If the main thread asked us to exit in between starting the thread |
+ // and now, just leave now. |
+ { |
+ nacl::MutexLocker ml(&subprocess_mu_); |
+ if (!ld_subprocess_active_) |
+ return; |
+ } |
+ |
+ // Now that we are in helper thread, we can do the the blocking |
+ // StartSrpcServices operation. |
+ if (!ld_subprocess_->StartSrpcServices()) { |
+ TranslateFailed( |
+ PP_NACL_ERROR_SRPC_CONNECTION_FAIL, |
+ "SRPC connection failure for " + ld_subprocess_->description()); |
return; |
} |
- core->CallOnMainThread(0, report_translate_finished_, PP_OK); |
-} |
-bool PnaclTranslateThread::RunLdSubprocess() { |
- ErrorInfo error_info; |
SrpcParams params; |
- |
std::vector<nacl::DescWrapper*> ld_in_files; |
size_t i; |
for (i = 0; i < obj_files_->size(); i++) { |
@@ -340,7 +363,6 @@ bool PnaclTranslateThread::RunLdSubprocess() { |
if (!(*obj_files_)[i]->Reset()) { |
TranslateFailed(PP_NACL_ERROR_PNACL_LD_SETUP, |
"Link process could not reset object file"); |
- return false; |
} |
ld_in_files.push_back((*obj_files_)[i]->read_wrapper()); |
} |
@@ -348,33 +370,6 @@ bool PnaclTranslateThread::RunLdSubprocess() { |
ld_in_files.push_back(invalid_desc_wrapper_); |
nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper(); |
- int64_t ld_start_time = NaClGetTimeOfDayMicroseconds(); |
- PP_NaClFileInfo ld_file_info = resources_->TakeFileInfo(PnaclResources::LD); |
- // Ownership of ld_file_info is transferred here. |
- nacl::scoped_ptr<NaClSubprocess> ld_subprocess(plugin_->LoadHelperNaClModule( |
- resources_->GetUrl(PnaclResources::LD), ld_file_info, &error_info)); |
- if (ld_subprocess.get() == NULL) { |
- TranslateFailed(PP_NACL_ERROR_PNACL_LD_SETUP, |
- "Link process could not be created: " + |
- error_info.message()); |
- return false; |
- } |
- GetNaClInterface()->LogTranslateTime( |
- "NaCl.Perf.PNaClLoadTime.LoadLinker", |
- NaClGetTimeOfDayMicroseconds() - ld_start_time); |
- { |
- nacl::MutexLocker ml(&subprocess_mu_); |
- // If we received a call to AbortSubprocesses() before we had a chance to |
- // set ld_subprocess_, shut down and clean up the subprocess started here. |
- if (subprocesses_aborted_) { |
- ld_subprocess->service_runtime()->Shutdown(); |
- return false; |
- } |
- DCHECK(ld_subprocess_.get() == NULL); |
- ld_subprocess_.swap(ld_subprocess); |
- ld_subprocess_active_ = true; |
- } |
- |
int64_t link_start_time = NaClGetTimeOfDayMicroseconds(); |
// Run LD. |
bool success = ld_subprocess_->InvokeSrpcMethod( |
@@ -402,19 +397,22 @@ bool PnaclTranslateThread::RunLdSubprocess() { |
if (!success) { |
TranslateFailed(PP_NACL_ERROR_PNACL_LD_INTERNAL, |
"link failed."); |
- return false; |
+ return; |
} |
GetNaClInterface()->LogTranslateTime( |
"NaCl.Perf.PNaClLoadTime.LinkTime", |
NaClGetTimeOfDayMicroseconds() - link_start_time); |
PLUGIN_PRINTF(("PnaclCoordinator: link (translator=%p) succeeded\n", |
this)); |
+ |
// Shut down the ld subprocess. |
NaClXMutexLock(&subprocess_mu_); |
ld_subprocess_active_ = false; |
- ld_subprocess_.reset(NULL); |
+ ld_subprocess_->Shutdown(); |
NaClXMutexUnlock(&subprocess_mu_); |
- return true; |
+ |
+ pp::Core* core = pp::Module::Get()->core(); |
+ core->CallOnMainThread(0, report_translate_finished_, PP_OK); |
} |
void PnaclTranslateThread::TranslateFailed( |
@@ -437,6 +435,9 @@ void PnaclTranslateThread::AbortSubprocesses() { |
PLUGIN_PRINTF(("PnaclTranslateThread::AbortSubprocesses\n")); |
NaClXMutexLock(&subprocess_mu_); |
if (compiler_subprocess_ != NULL && compiler_subprocess_active_) { |
+ // We only run the service_runtime's Shutdown and do not run the |
+ // NaClSubprocess Shutdown, which would otherwise nullify some |
+ // pointers that could still be in use (srpc_client, etc.). |
compiler_subprocess_->service_runtime()->Shutdown(); |
compiler_subprocess_active_ = false; |
} |
@@ -444,7 +445,6 @@ void PnaclTranslateThread::AbortSubprocesses() { |
ld_subprocess_->service_runtime()->Shutdown(); |
ld_subprocess_active_ = false; |
} |
- subprocesses_aborted_ = true; |
NaClXMutexUnlock(&subprocess_mu_); |
nacl::MutexLocker ml(&cond_mu_); |
done_ = true; |