| 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 "components/nacl/renderer/plugin/pnacl_translate_thread.h" | 5 #include "components/nacl/renderer/plugin/pnacl_translate_thread.h" |
| 6 | 6 |
| 7 #include <iterator> | 7 #include <iterator> |
| 8 #include <sstream> | 8 #include <sstream> |
| 9 | 9 |
| 10 #include "components/nacl/renderer/plugin/plugin.h" | 10 #include "components/nacl/renderer/plugin/plugin.h" |
| 11 #include "components/nacl/renderer/plugin/plugin_error.h" | 11 #include "components/nacl/renderer/plugin/plugin_error.h" |
| 12 #include "components/nacl/renderer/plugin/pnacl_resources.h" | |
| 13 #include "components/nacl/renderer/plugin/srpc_params.h" | 12 #include "components/nacl/renderer/plugin/srpc_params.h" |
| 14 #include "components/nacl/renderer/plugin/temporary_file.h" | 13 #include "components/nacl/renderer/plugin/temporary_file.h" |
| 15 #include "components/nacl/renderer/plugin/utility.h" | 14 #include "components/nacl/renderer/plugin/utility.h" |
| 16 #include "native_client/src/shared/platform/nacl_check.h" | 15 #include "native_client/src/shared/platform/nacl_check.h" |
| 17 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h" | 16 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h" |
| 18 #include "ppapi/cpp/var.h" | 17 #include "ppapi/cpp/var.h" |
| 19 | 18 |
| 20 namespace plugin { | 19 namespace plugin { |
| 21 namespace { | 20 namespace { |
| 22 | 21 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 | 66 |
| 68 for (const std::string& arg : args) { | 67 for (const std::string& arg : args) { |
| 69 std::copy(arg.begin(), arg.end(), std::back_inserter(*split_args)); | 68 std::copy(arg.begin(), arg.end(), std::back_inserter(*split_args)); |
| 70 split_args->push_back('\x00'); | 69 split_args->push_back('\x00'); |
| 71 } | 70 } |
| 72 } | 71 } |
| 73 | 72 |
| 74 } // namespace | 73 } // namespace |
| 75 | 74 |
| 76 PnaclTranslateThread::PnaclTranslateThread() | 75 PnaclTranslateThread::PnaclTranslateThread() |
| 77 : compiler_subprocess_active_(false), | 76 : compiler_subprocess_(NULL), |
| 77 ld_subprocess_(NULL), |
| 78 compiler_subprocess_active_(false), |
| 78 ld_subprocess_active_(false), | 79 ld_subprocess_active_(false), |
| 79 subprocesses_aborted_(false), | |
| 80 done_(false), | 80 done_(false), |
| 81 compile_time_(0), | 81 compile_time_(0), |
| 82 obj_files_(NULL), | 82 obj_files_(NULL), |
| 83 num_threads_(0), | 83 num_threads_(0), |
| 84 nexe_file_(NULL), | 84 nexe_file_(NULL), |
| 85 coordinator_error_info_(NULL), | 85 coordinator_error_info_(NULL), |
| 86 resources_(NULL), | 86 coordinator_(NULL) { |
| 87 coordinator_(NULL), | |
| 88 plugin_(NULL) { | |
| 89 NaClXMutexCtor(&subprocess_mu_); | 87 NaClXMutexCtor(&subprocess_mu_); |
| 90 NaClXMutexCtor(&cond_mu_); | 88 NaClXMutexCtor(&cond_mu_); |
| 91 NaClXCondVarCtor(&buffer_cond_); | 89 NaClXCondVarCtor(&buffer_cond_); |
| 92 } | 90 } |
| 93 | 91 |
| 94 void PnaclTranslateThread::RunTranslate( | 92 void PnaclTranslateThread::SetupState( |
| 95 const pp::CompletionCallback& finish_callback, | 93 const pp::CompletionCallback& finish_callback, |
| 94 NaClSubprocess* compiler_subprocess, |
| 95 NaClSubprocess* ld_subprocess, |
| 96 const std::vector<TempFile*>* obj_files, | 96 const std::vector<TempFile*>* obj_files, |
| 97 int num_threads, | 97 int num_threads, |
| 98 TempFile* nexe_file, | 98 TempFile* nexe_file, |
| 99 nacl::DescWrapper* invalid_desc_wrapper, | 99 nacl::DescWrapper* invalid_desc_wrapper, |
| 100 ErrorInfo* error_info, | 100 ErrorInfo* error_info, |
| 101 PnaclResources* resources, | |
| 102 PP_PNaClOptions* pnacl_options, | 101 PP_PNaClOptions* pnacl_options, |
| 103 const std::string& architecture_attributes, | 102 const std::string& architecture_attributes, |
| 104 PnaclCoordinator* coordinator, | 103 PnaclCoordinator* coordinator) { |
| 105 Plugin* plugin) { | 104 PLUGIN_PRINTF(("PnaclTranslateThread::SetupState)\n")); |
| 106 PLUGIN_PRINTF(("PnaclStreamingTranslateThread::RunTranslate)\n")); | 105 compiler_subprocess_ = compiler_subprocess; |
| 106 ld_subprocess_ = ld_subprocess; |
| 107 obj_files_ = obj_files; | 107 obj_files_ = obj_files; |
| 108 num_threads_ = num_threads; | 108 num_threads_ = num_threads; |
| 109 nexe_file_ = nexe_file; | 109 nexe_file_ = nexe_file; |
| 110 invalid_desc_wrapper_ = invalid_desc_wrapper; | 110 invalid_desc_wrapper_ = invalid_desc_wrapper; |
| 111 coordinator_error_info_ = error_info; | 111 coordinator_error_info_ = error_info; |
| 112 resources_ = resources; | |
| 113 pnacl_options_ = pnacl_options; | 112 pnacl_options_ = pnacl_options; |
| 114 architecture_attributes_ = architecture_attributes; | 113 architecture_attributes_ = architecture_attributes; |
| 115 coordinator_ = coordinator; | 114 coordinator_ = coordinator; |
| 116 plugin_ = plugin; | |
| 117 | 115 |
| 118 // Invoke llc followed by ld off the main thread. This allows use of | |
| 119 // blocking RPCs that would otherwise block the JavaScript main thread. | |
| 120 report_translate_finished_ = finish_callback; | 116 report_translate_finished_ = finish_callback; |
| 117 } |
| 118 |
| 119 void PnaclTranslateThread::RunCompile( |
| 120 const pp::CompletionCallback& compile_finished_callback) { |
| 121 PLUGIN_PRINTF(("PnaclTranslateThread::RunCompile)\n")); |
| 122 DCHECK(started()); |
| 123 DCHECK(compiler_subprocess_->service_runtime()); |
| 124 compiler_subprocess_active_ = true; |
| 125 |
| 126 compile_finished_callback_ = compile_finished_callback; |
| 121 translate_thread_.reset(new NaClThread); | 127 translate_thread_.reset(new NaClThread); |
| 122 if (translate_thread_ == NULL) { | 128 if (translate_thread_ == NULL) { |
| 123 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, | 129 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, |
| 130 "could not allocate thread struct."); |
| 131 return; |
| 132 } |
| 133 const int32_t kArbitraryStackSize = 128 * 1024; |
| 134 if (!NaClThreadCreateJoinable(translate_thread_.get(), DoCompileThread, this, |
| 135 kArbitraryStackSize)) { |
| 136 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, |
| 137 "could not create thread."); |
| 138 translate_thread_.reset(NULL); |
| 139 } |
| 140 } |
| 141 |
| 142 void PnaclTranslateThread::RunLink() { |
| 143 PLUGIN_PRINTF(("PnaclTranslateThread::RunLink)\n")); |
| 144 DCHECK(started()); |
| 145 DCHECK(ld_subprocess_->service_runtime()); |
| 146 ld_subprocess_active_ = true; |
| 147 |
| 148 // Tear down the previous thread. |
| 149 // TODO(jvoung): Use base/threading or something where we can have a |
| 150 // persistent thread and easily post tasks to that persistent thread. |
| 151 NaClThreadJoin(translate_thread_.get()); |
| 152 translate_thread_.reset(new NaClThread); |
| 153 if (translate_thread_ == NULL) { |
| 154 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, |
| 124 "could not allocate thread struct."); | 155 "could not allocate thread struct."); |
| 125 return; | 156 return; |
| 126 } | 157 } |
| 127 const int32_t kArbitraryStackSize = 128 * 1024; | 158 const int32_t kArbitraryStackSize = 128 * 1024; |
| 128 if (!NaClThreadCreateJoinable(translate_thread_.get(), | 159 if (!NaClThreadCreateJoinable(translate_thread_.get(), DoLinkThread, this, |
| 129 DoTranslateThread, | |
| 130 this, | |
| 131 kArbitraryStackSize)) { | 160 kArbitraryStackSize)) { |
| 132 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, | 161 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, |
| 133 "could not create thread."); | 162 "could not create thread."); |
| 134 translate_thread_.reset(NULL); | 163 translate_thread_.reset(NULL); |
| 135 } | 164 } |
| 136 } | 165 } |
| 137 | 166 |
| 138 // Called from main thread to send bytes to the translator. | 167 // Called from main thread to send bytes to the translator. |
| 139 void PnaclTranslateThread::PutBytes(const void* bytes, int32_t count) { | 168 void PnaclTranslateThread::PutBytes(const void* bytes, int32_t count) { |
| 140 CHECK(bytes != NULL); | 169 CHECK(bytes != NULL); |
| 141 NaClXMutexLock(&cond_mu_); | 170 NaClXMutexLock(&cond_mu_); |
| 142 data_buffers_.push_back(std::vector<char>()); | 171 data_buffers_.push_back(std::vector<char>()); |
| 143 data_buffers_.back().insert(data_buffers_.back().end(), | 172 data_buffers_.back().insert(data_buffers_.back().end(), |
| 144 static_cast<const char*>(bytes), | 173 static_cast<const char*>(bytes), |
| 145 static_cast<const char*>(bytes) + count); | 174 static_cast<const char*>(bytes) + count); |
| 146 NaClXCondVarSignal(&buffer_cond_); | 175 NaClXCondVarSignal(&buffer_cond_); |
| 147 NaClXMutexUnlock(&cond_mu_); | 176 NaClXMutexUnlock(&cond_mu_); |
| 148 } | 177 } |
| 149 | 178 |
| 150 void PnaclTranslateThread::EndStream() { | 179 void PnaclTranslateThread::EndStream() { |
| 151 NaClXMutexLock(&cond_mu_); | 180 NaClXMutexLock(&cond_mu_); |
| 152 done_ = true; | 181 done_ = true; |
| 153 NaClXCondVarSignal(&buffer_cond_); | 182 NaClXCondVarSignal(&buffer_cond_); |
| 154 NaClXMutexUnlock(&cond_mu_); | 183 NaClXMutexUnlock(&cond_mu_); |
| 155 } | 184 } |
| 156 | 185 |
| 157 void WINAPI PnaclTranslateThread::DoTranslateThread(void* arg) { | 186 void WINAPI PnaclTranslateThread::DoCompileThread(void* arg) { |
| 158 PnaclTranslateThread* translator = | 187 PnaclTranslateThread* translator = |
| 159 reinterpret_cast<PnaclTranslateThread*>(arg); | 188 reinterpret_cast<PnaclTranslateThread*>(arg); |
| 160 translator->DoTranslate(); | 189 translator->DoCompile(); |
| 161 } | 190 } |
| 162 | 191 |
| 163 void PnaclTranslateThread::DoTranslate() { | 192 void PnaclTranslateThread::DoCompile() { |
| 164 ErrorInfo error_info; | 193 // If the main thread asked us to exit in between starting the thread |
| 194 // and now, just leave now. |
| 195 { |
| 196 nacl::MutexLocker ml(&subprocess_mu_); |
| 197 if (!compiler_subprocess_active_) |
| 198 return; |
| 199 } |
| 200 |
| 201 // Now that we are in helper thread, we can do the the blocking |
| 202 // StartSrpcServices operation. |
| 203 if (!compiler_subprocess_->StartSrpcServices()) { |
| 204 TranslateFailed( |
| 205 PP_NACL_ERROR_SRPC_CONNECTION_FAIL, |
| 206 "SRPC connection failure for " + compiler_subprocess_->description()); |
| 207 return; |
| 208 } |
| 209 |
| 165 SrpcParams params; | 210 SrpcParams params; |
| 166 std::vector<nacl::DescWrapper*> compile_out_files; | 211 std::vector<nacl::DescWrapper*> compile_out_files; |
| 167 size_t i; | 212 size_t i; |
| 168 for (i = 0; i < obj_files_->size(); i++) | 213 for (i = 0; i < obj_files_->size(); i++) |
| 169 compile_out_files.push_back((*obj_files_)[i]->write_wrapper()); | 214 compile_out_files.push_back((*obj_files_)[i]->write_wrapper()); |
| 170 for (; i < PnaclCoordinator::kMaxTranslatorObjectFiles; i++) | 215 for (; i < PnaclCoordinator::kMaxTranslatorObjectFiles; i++) |
| 171 compile_out_files.push_back(invalid_desc_wrapper_); | 216 compile_out_files.push_back(invalid_desc_wrapper_); |
| 172 | 217 |
| 173 PLUGIN_PRINTF( | 218 PLUGIN_PRINTF(("DoCompile using subzero: %d\n", pnacl_options_->use_subzero)); |
| 174 ("DoTranslate using subzero: %d\n", pnacl_options_->use_subzero)); | |
| 175 | 219 |
| 176 pp::Core* core = pp::Module::Get()->core(); | 220 pp::Core* core = pp::Module::Get()->core(); |
| 177 int64_t compiler_load_start_time = NaClGetTimeOfDayMicroseconds(); | |
| 178 PnaclResources::ResourceType compiler_type = pnacl_options_->use_subzero | |
| 179 ? PnaclResources::SUBZERO | |
| 180 : PnaclResources::LLC; | |
| 181 // Ownership of file_info is transferred here. | |
| 182 PP_NaClFileInfo file_info = resources_->TakeFileInfo(compiler_type); | |
| 183 const std::string& url = resources_->GetUrl(compiler_type); | |
| 184 NaClSubprocess* compiler_subprocess = | |
| 185 plugin_->LoadHelperNaClModule(url, file_info, &error_info); | |
| 186 if (compiler_subprocess == NULL) { | |
| 187 TranslateFailed(PP_NACL_ERROR_PNACL_LLC_SETUP, | |
| 188 "Compile process could not be created: " + | |
| 189 error_info.message()); | |
| 190 return; | |
| 191 } | |
| 192 int64_t compiler_load_time_total = | |
| 193 NaClGetTimeOfDayMicroseconds() - compiler_load_start_time; | |
| 194 GetNaClInterface()->LogTranslateTime("NaCl.Perf.PNaClLoadTime.LoadCompiler", | |
| 195 compiler_load_time_total); | |
| 196 GetNaClInterface()->LogTranslateTime( | |
| 197 pnacl_options_->use_subzero | |
| 198 ? "NaCl.Perf.PNaClLoadTime.LoadCompiler.Subzero" | |
| 199 : "NaCl.Perf.PNaClLoadTime.LoadCompiler.LLC", | |
| 200 compiler_load_time_total); | |
| 201 | |
| 202 { | |
| 203 nacl::MutexLocker ml(&subprocess_mu_); | |
| 204 // If we received a call to AbortSubprocesses() before we had a chance to | |
| 205 // set compiler_subprocess_, shut down and clean up the subprocess started | |
| 206 // here. | |
| 207 if (subprocesses_aborted_) { | |
| 208 compiler_subprocess->service_runtime()->Shutdown(); | |
| 209 delete compiler_subprocess; | |
| 210 return; | |
| 211 } | |
| 212 compiler_subprocess_.reset(compiler_subprocess); | |
| 213 compiler_subprocess = NULL; | |
| 214 compiler_subprocess_active_ = true; | |
| 215 } | |
| 216 | |
| 217 int64_t do_compile_start_time = NaClGetTimeOfDayMicroseconds(); | 221 int64_t do_compile_start_time = NaClGetTimeOfDayMicroseconds(); |
| 218 bool init_success; | 222 bool init_success; |
| 219 | 223 |
| 220 std::vector<char> split_args; | 224 std::vector<char> split_args; |
| 221 if (pnacl_options_->use_subzero) { | 225 if (pnacl_options_->use_subzero) { |
| 222 GetSubzeroCommandLine(&split_args, pnacl_options_->opt_level, | 226 GetSubzeroCommandLine(&split_args, pnacl_options_->opt_level, |
| 223 pnacl_options_->is_debug, architecture_attributes_); | 227 pnacl_options_->is_debug, architecture_attributes_); |
| 224 } else { | 228 } else { |
| 225 GetLlcCommandLine(&split_args, obj_files_->size(), | 229 GetLlcCommandLine(&split_args, obj_files_->size(), |
| 226 pnacl_options_->opt_level, pnacl_options_->is_debug, | 230 pnacl_options_->opt_level, pnacl_options_->is_debug, |
| 227 architecture_attributes_); | 231 architecture_attributes_); |
| 228 } | 232 } |
| 233 |
| 229 init_success = compiler_subprocess_->InvokeSrpcMethod( | 234 init_success = compiler_subprocess_->InvokeSrpcMethod( |
| 230 "StreamInitWithSplit", "ihhhhhhhhhhhhhhhhC", ¶ms, num_threads_, | 235 "StreamInitWithSplit", "ihhhhhhhhhhhhhhhhC", ¶ms, num_threads_, |
| 231 compile_out_files[0]->desc(), compile_out_files[1]->desc(), | 236 compile_out_files[0]->desc(), compile_out_files[1]->desc(), |
| 232 compile_out_files[2]->desc(), compile_out_files[3]->desc(), | 237 compile_out_files[2]->desc(), compile_out_files[3]->desc(), |
| 233 compile_out_files[4]->desc(), compile_out_files[5]->desc(), | 238 compile_out_files[4]->desc(), compile_out_files[5]->desc(), |
| 234 compile_out_files[6]->desc(), compile_out_files[7]->desc(), | 239 compile_out_files[6]->desc(), compile_out_files[7]->desc(), |
| 235 compile_out_files[8]->desc(), compile_out_files[9]->desc(), | 240 compile_out_files[8]->desc(), compile_out_files[9]->desc(), |
| 236 compile_out_files[10]->desc(), compile_out_files[11]->desc(), | 241 compile_out_files[10]->desc(), compile_out_files[11]->desc(), |
| 237 compile_out_files[12]->desc(), compile_out_files[13]->desc(), | 242 compile_out_files[12]->desc(), compile_out_files[13]->desc(), |
| 238 compile_out_files[14]->desc(), compile_out_files[15]->desc(), | 243 compile_out_files[14]->desc(), compile_out_files[15]->desc(), |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 } | 315 } |
| 311 compile_time_ = NaClGetTimeOfDayMicroseconds() - do_compile_start_time; | 316 compile_time_ = NaClGetTimeOfDayMicroseconds() - do_compile_start_time; |
| 312 GetNaClInterface()->LogTranslateTime("NaCl.Perf.PNaClLoadTime.CompileTime", | 317 GetNaClInterface()->LogTranslateTime("NaCl.Perf.PNaClLoadTime.CompileTime", |
| 313 compile_time_); | 318 compile_time_); |
| 314 GetNaClInterface()->LogTranslateTime( | 319 GetNaClInterface()->LogTranslateTime( |
| 315 pnacl_options_->use_subzero | 320 pnacl_options_->use_subzero |
| 316 ? "NaCl.Perf.PNaClLoadTime.CompileTime.Subzero" | 321 ? "NaCl.Perf.PNaClLoadTime.CompileTime.Subzero" |
| 317 : "NaCl.Perf.PNaClLoadTime.CompileTime.LLC", | 322 : "NaCl.Perf.PNaClLoadTime.CompileTime.LLC", |
| 318 compile_time_); | 323 compile_time_); |
| 319 | 324 |
| 320 // Shut down the llc subprocess. | 325 // Shut down the compiler subprocess. |
| 321 NaClXMutexLock(&subprocess_mu_); | 326 NaClXMutexLock(&subprocess_mu_); |
| 322 compiler_subprocess_active_ = false; | 327 compiler_subprocess_active_ = false; |
| 323 compiler_subprocess_.reset(NULL); | 328 compiler_subprocess_->Shutdown(); |
| 324 NaClXMutexUnlock(&subprocess_mu_); | 329 NaClXMutexUnlock(&subprocess_mu_); |
| 325 | 330 |
| 326 if(!RunLdSubprocess()) { | 331 core->CallOnMainThread(0, compile_finished_callback_, PP_OK); |
| 332 } |
| 333 |
| 334 void WINAPI PnaclTranslateThread::DoLinkThread(void* arg) { |
| 335 PnaclTranslateThread* translator = |
| 336 reinterpret_cast<PnaclTranslateThread*>(arg); |
| 337 translator->DoLink(); |
| 338 } |
| 339 |
| 340 void PnaclTranslateThread::DoLink() { |
| 341 // If the main thread asked us to exit in between starting the thread |
| 342 // and now, just leave now. |
| 343 { |
| 344 nacl::MutexLocker ml(&subprocess_mu_); |
| 345 if (!ld_subprocess_active_) |
| 346 return; |
| 347 } |
| 348 |
| 349 // Now that we are in helper thread, we can do the the blocking |
| 350 // StartSrpcServices operation. |
| 351 if (!ld_subprocess_->StartSrpcServices()) { |
| 352 TranslateFailed( |
| 353 PP_NACL_ERROR_SRPC_CONNECTION_FAIL, |
| 354 "SRPC connection failure for " + ld_subprocess_->description()); |
| 327 return; | 355 return; |
| 328 } | 356 } |
| 329 core->CallOnMainThread(0, report_translate_finished_, PP_OK); | |
| 330 } | |
| 331 | 357 |
| 332 bool PnaclTranslateThread::RunLdSubprocess() { | |
| 333 ErrorInfo error_info; | |
| 334 SrpcParams params; | 358 SrpcParams params; |
| 335 | |
| 336 std::vector<nacl::DescWrapper*> ld_in_files; | 359 std::vector<nacl::DescWrapper*> ld_in_files; |
| 337 size_t i; | 360 size_t i; |
| 338 for (i = 0; i < obj_files_->size(); i++) { | 361 for (i = 0; i < obj_files_->size(); i++) { |
| 339 // Reset object file for reading first. | 362 // Reset object file for reading first. |
| 340 if (!(*obj_files_)[i]->Reset()) { | 363 if (!(*obj_files_)[i]->Reset()) { |
| 341 TranslateFailed(PP_NACL_ERROR_PNACL_LD_SETUP, | 364 TranslateFailed(PP_NACL_ERROR_PNACL_LD_SETUP, |
| 342 "Link process could not reset object file"); | 365 "Link process could not reset object file"); |
| 343 return false; | |
| 344 } | 366 } |
| 345 ld_in_files.push_back((*obj_files_)[i]->read_wrapper()); | 367 ld_in_files.push_back((*obj_files_)[i]->read_wrapper()); |
| 346 } | 368 } |
| 347 for (; i < PnaclCoordinator::kMaxTranslatorObjectFiles; i++) | 369 for (; i < PnaclCoordinator::kMaxTranslatorObjectFiles; i++) |
| 348 ld_in_files.push_back(invalid_desc_wrapper_); | 370 ld_in_files.push_back(invalid_desc_wrapper_); |
| 349 | 371 |
| 350 nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper(); | 372 nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper(); |
| 351 int64_t ld_start_time = NaClGetTimeOfDayMicroseconds(); | |
| 352 PP_NaClFileInfo ld_file_info = resources_->TakeFileInfo(PnaclResources::LD); | |
| 353 // Ownership of ld_file_info is transferred here. | |
| 354 nacl::scoped_ptr<NaClSubprocess> ld_subprocess(plugin_->LoadHelperNaClModule( | |
| 355 resources_->GetUrl(PnaclResources::LD), ld_file_info, &error_info)); | |
| 356 if (ld_subprocess.get() == NULL) { | |
| 357 TranslateFailed(PP_NACL_ERROR_PNACL_LD_SETUP, | |
| 358 "Link process could not be created: " + | |
| 359 error_info.message()); | |
| 360 return false; | |
| 361 } | |
| 362 GetNaClInterface()->LogTranslateTime( | |
| 363 "NaCl.Perf.PNaClLoadTime.LoadLinker", | |
| 364 NaClGetTimeOfDayMicroseconds() - ld_start_time); | |
| 365 { | |
| 366 nacl::MutexLocker ml(&subprocess_mu_); | |
| 367 // If we received a call to AbortSubprocesses() before we had a chance to | |
| 368 // set ld_subprocess_, shut down and clean up the subprocess started here. | |
| 369 if (subprocesses_aborted_) { | |
| 370 ld_subprocess->service_runtime()->Shutdown(); | |
| 371 return false; | |
| 372 } | |
| 373 DCHECK(ld_subprocess_.get() == NULL); | |
| 374 ld_subprocess_.swap(ld_subprocess); | |
| 375 ld_subprocess_active_ = true; | |
| 376 } | |
| 377 | |
| 378 int64_t link_start_time = NaClGetTimeOfDayMicroseconds(); | 373 int64_t link_start_time = NaClGetTimeOfDayMicroseconds(); |
| 379 // Run LD. | 374 // Run LD. |
| 380 bool success = ld_subprocess_->InvokeSrpcMethod( | 375 bool success = ld_subprocess_->InvokeSrpcMethod( |
| 381 "RunWithSplit", | 376 "RunWithSplit", |
| 382 "ihhhhhhhhhhhhhhhhh", | 377 "ihhhhhhhhhhhhhhhhh", |
| 383 ¶ms, | 378 ¶ms, |
| 384 static_cast<int>(obj_files_->size()), | 379 static_cast<int>(obj_files_->size()), |
| 385 ld_in_files[0]->desc(), | 380 ld_in_files[0]->desc(), |
| 386 ld_in_files[1]->desc(), | 381 ld_in_files[1]->desc(), |
| 387 ld_in_files[2]->desc(), | 382 ld_in_files[2]->desc(), |
| 388 ld_in_files[3]->desc(), | 383 ld_in_files[3]->desc(), |
| 389 ld_in_files[4]->desc(), | 384 ld_in_files[4]->desc(), |
| 390 ld_in_files[5]->desc(), | 385 ld_in_files[5]->desc(), |
| 391 ld_in_files[6]->desc(), | 386 ld_in_files[6]->desc(), |
| 392 ld_in_files[7]->desc(), | 387 ld_in_files[7]->desc(), |
| 393 ld_in_files[8]->desc(), | 388 ld_in_files[8]->desc(), |
| 394 ld_in_files[9]->desc(), | 389 ld_in_files[9]->desc(), |
| 395 ld_in_files[10]->desc(), | 390 ld_in_files[10]->desc(), |
| 396 ld_in_files[11]->desc(), | 391 ld_in_files[11]->desc(), |
| 397 ld_in_files[12]->desc(), | 392 ld_in_files[12]->desc(), |
| 398 ld_in_files[13]->desc(), | 393 ld_in_files[13]->desc(), |
| 399 ld_in_files[14]->desc(), | 394 ld_in_files[14]->desc(), |
| 400 ld_in_files[15]->desc(), | 395 ld_in_files[15]->desc(), |
| 401 ld_out_file->desc()); | 396 ld_out_file->desc()); |
| 402 if (!success) { | 397 if (!success) { |
| 403 TranslateFailed(PP_NACL_ERROR_PNACL_LD_INTERNAL, | 398 TranslateFailed(PP_NACL_ERROR_PNACL_LD_INTERNAL, |
| 404 "link failed."); | 399 "link failed."); |
| 405 return false; | 400 return; |
| 406 } | 401 } |
| 407 GetNaClInterface()->LogTranslateTime( | 402 GetNaClInterface()->LogTranslateTime( |
| 408 "NaCl.Perf.PNaClLoadTime.LinkTime", | 403 "NaCl.Perf.PNaClLoadTime.LinkTime", |
| 409 NaClGetTimeOfDayMicroseconds() - link_start_time); | 404 NaClGetTimeOfDayMicroseconds() - link_start_time); |
| 410 PLUGIN_PRINTF(("PnaclCoordinator: link (translator=%p) succeeded\n", | 405 PLUGIN_PRINTF(("PnaclCoordinator: link (translator=%p) succeeded\n", |
| 411 this)); | 406 this)); |
| 407 |
| 412 // Shut down the ld subprocess. | 408 // Shut down the ld subprocess. |
| 413 NaClXMutexLock(&subprocess_mu_); | 409 NaClXMutexLock(&subprocess_mu_); |
| 414 ld_subprocess_active_ = false; | 410 ld_subprocess_active_ = false; |
| 415 ld_subprocess_.reset(NULL); | 411 ld_subprocess_->Shutdown(); |
| 416 NaClXMutexUnlock(&subprocess_mu_); | 412 NaClXMutexUnlock(&subprocess_mu_); |
| 417 return true; | 413 |
| 414 pp::Core* core = pp::Module::Get()->core(); |
| 415 core->CallOnMainThread(0, report_translate_finished_, PP_OK); |
| 418 } | 416 } |
| 419 | 417 |
| 420 void PnaclTranslateThread::TranslateFailed( | 418 void PnaclTranslateThread::TranslateFailed( |
| 421 PP_NaClError err_code, | 419 PP_NaClError err_code, |
| 422 const std::string& error_string) { | 420 const std::string& error_string) { |
| 423 PLUGIN_PRINTF(("PnaclTranslateThread::TranslateFailed (error_string='%s')\n", | 421 PLUGIN_PRINTF(("PnaclTranslateThread::TranslateFailed (error_string='%s')\n", |
| 424 error_string.c_str())); | 422 error_string.c_str())); |
| 425 pp::Core* core = pp::Module::Get()->core(); | 423 pp::Core* core = pp::Module::Get()->core(); |
| 426 if (coordinator_error_info_->message().empty()) { | 424 if (coordinator_error_info_->message().empty()) { |
| 427 // Only use our message if one hasn't already been set by the coordinator | 425 // Only use our message if one hasn't already been set by the coordinator |
| 428 // (e.g. pexe load failed). | 426 // (e.g. pexe load failed). |
| 429 coordinator_error_info_->SetReport(err_code, | 427 coordinator_error_info_->SetReport(err_code, |
| 430 std::string("PnaclCoordinator: ") + | 428 std::string("PnaclCoordinator: ") + |
| 431 error_string); | 429 error_string); |
| 432 } | 430 } |
| 433 core->CallOnMainThread(0, report_translate_finished_, PP_ERROR_FAILED); | 431 core->CallOnMainThread(0, report_translate_finished_, PP_ERROR_FAILED); |
| 434 } | 432 } |
| 435 | 433 |
| 436 void PnaclTranslateThread::AbortSubprocesses() { | 434 void PnaclTranslateThread::AbortSubprocesses() { |
| 437 PLUGIN_PRINTF(("PnaclTranslateThread::AbortSubprocesses\n")); | 435 PLUGIN_PRINTF(("PnaclTranslateThread::AbortSubprocesses\n")); |
| 438 NaClXMutexLock(&subprocess_mu_); | 436 NaClXMutexLock(&subprocess_mu_); |
| 439 if (compiler_subprocess_ != NULL && compiler_subprocess_active_) { | 437 if (compiler_subprocess_ != NULL && compiler_subprocess_active_) { |
| 438 // We only run the service_runtime's Shutdown and do not run the |
| 439 // NaClSubprocess Shutdown, which would otherwise nullify some |
| 440 // pointers that could still be in use (srpc_client, etc.). |
| 440 compiler_subprocess_->service_runtime()->Shutdown(); | 441 compiler_subprocess_->service_runtime()->Shutdown(); |
| 441 compiler_subprocess_active_ = false; | 442 compiler_subprocess_active_ = false; |
| 442 } | 443 } |
| 443 if (ld_subprocess_ != NULL && ld_subprocess_active_) { | 444 if (ld_subprocess_ != NULL && ld_subprocess_active_) { |
| 444 ld_subprocess_->service_runtime()->Shutdown(); | 445 ld_subprocess_->service_runtime()->Shutdown(); |
| 445 ld_subprocess_active_ = false; | 446 ld_subprocess_active_ = false; |
| 446 } | 447 } |
| 447 subprocesses_aborted_ = true; | |
| 448 NaClXMutexUnlock(&subprocess_mu_); | 448 NaClXMutexUnlock(&subprocess_mu_); |
| 449 nacl::MutexLocker ml(&cond_mu_); | 449 nacl::MutexLocker ml(&cond_mu_); |
| 450 done_ = true; | 450 done_ = true; |
| 451 // Free all buffered bitcode chunks | 451 // Free all buffered bitcode chunks |
| 452 data_buffers_.clear(); | 452 data_buffers_.clear(); |
| 453 NaClXCondVarSignal(&buffer_cond_); | 453 NaClXCondVarSignal(&buffer_cond_); |
| 454 } | 454 } |
| 455 | 455 |
| 456 PnaclTranslateThread::~PnaclTranslateThread() { | 456 PnaclTranslateThread::~PnaclTranslateThread() { |
| 457 PLUGIN_PRINTF(("~PnaclTranslateThread (translate_thread=%p)\n", this)); | 457 PLUGIN_PRINTF(("~PnaclTranslateThread (translate_thread=%p)\n", this)); |
| 458 AbortSubprocesses(); | 458 AbortSubprocesses(); |
| 459 if (translate_thread_ != NULL) | 459 if (translate_thread_ != NULL) |
| 460 NaClThreadJoin(translate_thread_.get()); | 460 NaClThreadJoin(translate_thread_.get()); |
| 461 PLUGIN_PRINTF(("~PnaclTranslateThread joined\n")); | 461 PLUGIN_PRINTF(("~PnaclTranslateThread joined\n")); |
| 462 NaClCondVarDtor(&buffer_cond_); | 462 NaClCondVarDtor(&buffer_cond_); |
| 463 NaClMutexDtor(&cond_mu_); | 463 NaClMutexDtor(&cond_mu_); |
| 464 NaClMutexDtor(&subprocess_mu_); | 464 NaClMutexDtor(&subprocess_mu_); |
| 465 } | 465 } |
| 466 | 466 |
| 467 } // namespace plugin | 467 } // namespace plugin |
| OLD | NEW |