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 "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 | 116 // Invoke llc followed by ld off the main thread. This allows use of |
|
Derek Schuff
2015/05/08 22:45:59
move or remove this comment.
jvoung (off chromium)
2015/05/08 23:59:32
Done.
| |
| 119 // blocking RPCs that would otherwise block the JavaScript main thread. | 117 // blocking RPCs that would otherwise block the JavaScript main thread. |
| 120 report_translate_finished_ = finish_callback; | 118 report_translate_finished_ = finish_callback; |
| 119 } | |
| 120 | |
| 121 void PnaclTranslateThread::RunCompile( | |
| 122 const pp::CompletionCallback& compile_finished_callback) { | |
| 123 PLUGIN_PRINTF(("PnaclTranslateThread::RunCompile)\n")); | |
| 124 DCHECK(started()); | |
| 125 DCHECK(compiler_subprocess_->service_runtime()); | |
| 126 compiler_subprocess_active_ = true; | |
| 127 | |
| 128 compile_finished_callback_ = compile_finished_callback; | |
| 121 translate_thread_.reset(new NaClThread); | 129 translate_thread_.reset(new NaClThread); |
| 122 if (translate_thread_ == NULL) { | 130 if (translate_thread_ == NULL) { |
| 123 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, | 131 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, |
| 132 "could not allocate thread struct."); | |
| 133 return; | |
| 134 } | |
| 135 const int32_t kArbitraryStackSize = 128 * 1024; | |
| 136 if (!NaClThreadCreateJoinable(translate_thread_.get(), DoCompileThread, this, | |
| 137 kArbitraryStackSize)) { | |
| 138 TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, | |
| 139 "could not create thread."); | |
| 140 translate_thread_.reset(NULL); | |
| 141 } | |
| 142 } | |
| 143 | |
| 144 void PnaclTranslateThread::RunLink() { | |
| 145 PLUGIN_PRINTF(("PnaclTranslateThread::RunLink)\n")); | |
| 146 DCHECK(started()); | |
| 147 DCHECK(ld_subprocess_->service_runtime()); | |
| 148 ld_subprocess_active_ = true; | |
| 149 | |
| 150 // Tear down the previous thread. | |
|
Derek Schuff
2015/05/08 22:45:59
why tear down and fork again instead of reusing th
jvoung (off chromium)
2015/05/08 23:59:32
Ideally we would have a "PostTask" e.g., if we use
Derek Schuff
2015/05/09 00:18:32
This does seem simpler, and probably not too bad f
| |
| 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, just leave now. |
| 194 NaClXMutexLock(&subprocess_mu_); | |
| 195 if (!compiler_subprocess_active_) | |
|
Derek Schuff
2015/05/08 22:45:59
is it intentional to return with the mutex still l
jvoung (off chromium)
2015/05/08 23:59:32
Nope =)
Done.
| |
| 196 return; | |
| 197 NaClXMutexUnlock(&subprocess_mu_); | |
| 198 | |
| 199 // Wait till we are in the helper thread to do the blocking | |
|
Derek Schuff
2015/05/08 22:45:59
maybe say "now that we are in the helper thread, w
jvoung (off chromium)
2015/05/08 23:59:32
Done.
| |
| 200 // StartSrpcServices operation. | |
| 201 if (!compiler_subprocess_->StartSrpcServices()) { | |
| 202 TranslateFailed( | |
| 203 PP_NACL_ERROR_SRPC_CONNECTION_FAIL, | |
| 204 "SRPC connection failure for " + compiler_subprocess_->description()); | |
| 205 return; | |
| 206 } | |
| 207 | |
| 165 SrpcParams params; | 208 SrpcParams params; |
| 166 std::vector<nacl::DescWrapper*> compile_out_files; | 209 std::vector<nacl::DescWrapper*> compile_out_files; |
| 167 size_t i; | 210 size_t i; |
| 168 for (i = 0; i < obj_files_->size(); i++) | 211 for (i = 0; i < obj_files_->size(); i++) |
| 169 compile_out_files.push_back((*obj_files_)[i]->write_wrapper()); | 212 compile_out_files.push_back((*obj_files_)[i]->write_wrapper()); |
| 170 for (; i < PnaclCoordinator::kMaxTranslatorObjectFiles; i++) | 213 for (; i < PnaclCoordinator::kMaxTranslatorObjectFiles; i++) |
| 171 compile_out_files.push_back(invalid_desc_wrapper_); | 214 compile_out_files.push_back(invalid_desc_wrapper_); |
| 172 | 215 |
| 173 PLUGIN_PRINTF( | 216 PLUGIN_PRINTF(("DoCompile using subzero: %d\n", pnacl_options_->use_subzero)); |
| 174 ("DoTranslate using subzero: %d\n", pnacl_options_->use_subzero)); | |
| 175 | 217 |
| 176 pp::Core* core = pp::Module::Get()->core(); | 218 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 // On success, ownership of file_info is transferred. | |
| 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 if (file_info.handle != PP_kInvalidFileHandle) | |
| 188 CloseFileHandle(file_info.handle); | |
| 189 TranslateFailed(PP_NACL_ERROR_PNACL_LLC_SETUP, | |
| 190 "Compile process could not be created: " + | |
| 191 error_info.message()); | |
| 192 return; | |
| 193 } | |
| 194 int64_t compiler_load_time_total = | |
| 195 NaClGetTimeOfDayMicroseconds() - compiler_load_start_time; | |
| 196 GetNaClInterface()->LogTranslateTime("NaCl.Perf.PNaClLoadTime.LoadCompiler", | |
| 197 compiler_load_time_total); | |
| 198 GetNaClInterface()->LogTranslateTime( | |
| 199 pnacl_options_->use_subzero | |
| 200 ? "NaCl.Perf.PNaClLoadTime.LoadCompiler.Subzero" | |
| 201 : "NaCl.Perf.PNaClLoadTime.LoadCompiler.LLC", | |
| 202 compiler_load_time_total); | |
| 203 | |
| 204 { | |
| 205 nacl::MutexLocker ml(&subprocess_mu_); | |
| 206 // If we received a call to AbortSubprocesses() before we had a chance to | |
| 207 // set compiler_subprocess_, shut down and clean up the subprocess started | |
| 208 // here. | |
| 209 if (subprocesses_aborted_) { | |
| 210 compiler_subprocess->service_runtime()->Shutdown(); | |
| 211 delete compiler_subprocess; | |
| 212 return; | |
| 213 } | |
| 214 compiler_subprocess_.reset(compiler_subprocess); | |
| 215 compiler_subprocess = NULL; | |
| 216 compiler_subprocess_active_ = true; | |
| 217 } | |
| 218 | |
| 219 int64_t do_compile_start_time = NaClGetTimeOfDayMicroseconds(); | 219 int64_t do_compile_start_time = NaClGetTimeOfDayMicroseconds(); |
| 220 bool init_success; | 220 bool init_success; |
| 221 | 221 |
| 222 std::vector<char> split_args; | 222 std::vector<char> split_args; |
| 223 if (pnacl_options_->use_subzero) { | 223 if (pnacl_options_->use_subzero) { |
| 224 GetSubzeroCommandLine(&split_args, pnacl_options_->opt_level, | 224 GetSubzeroCommandLine(&split_args, pnacl_options_->opt_level, |
| 225 pnacl_options_->is_debug, architecture_attributes_); | 225 pnacl_options_->is_debug, architecture_attributes_); |
| 226 } else { | 226 } else { |
| 227 GetLlcCommandLine(&split_args, obj_files_->size(), | 227 GetLlcCommandLine(&split_args, obj_files_->size(), |
| 228 pnacl_options_->opt_level, pnacl_options_->is_debug, | 228 pnacl_options_->opt_level, pnacl_options_->is_debug, |
| 229 architecture_attributes_); | 229 architecture_attributes_); |
| 230 } | 230 } |
| 231 | |
| 231 init_success = compiler_subprocess_->InvokeSrpcMethod( | 232 init_success = compiler_subprocess_->InvokeSrpcMethod( |
| 232 "StreamInitWithSplit", "ihhhhhhhhhhhhhhhhC", ¶ms, num_threads_, | 233 "StreamInitWithSplit", "ihhhhhhhhhhhhhhhhC", ¶ms, num_threads_, |
| 233 compile_out_files[0]->desc(), compile_out_files[1]->desc(), | 234 compile_out_files[0]->desc(), compile_out_files[1]->desc(), |
| 234 compile_out_files[2]->desc(), compile_out_files[3]->desc(), | 235 compile_out_files[2]->desc(), compile_out_files[3]->desc(), |
| 235 compile_out_files[4]->desc(), compile_out_files[5]->desc(), | 236 compile_out_files[4]->desc(), compile_out_files[5]->desc(), |
| 236 compile_out_files[6]->desc(), compile_out_files[7]->desc(), | 237 compile_out_files[6]->desc(), compile_out_files[7]->desc(), |
| 237 compile_out_files[8]->desc(), compile_out_files[9]->desc(), | 238 compile_out_files[8]->desc(), compile_out_files[9]->desc(), |
| 238 compile_out_files[10]->desc(), compile_out_files[11]->desc(), | 239 compile_out_files[10]->desc(), compile_out_files[11]->desc(), |
| 239 compile_out_files[12]->desc(), compile_out_files[13]->desc(), | 240 compile_out_files[12]->desc(), compile_out_files[13]->desc(), |
| 240 compile_out_files[14]->desc(), compile_out_files[15]->desc(), | 241 compile_out_files[14]->desc(), compile_out_files[15]->desc(), |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 312 } | 313 } |
| 313 compile_time_ = NaClGetTimeOfDayMicroseconds() - do_compile_start_time; | 314 compile_time_ = NaClGetTimeOfDayMicroseconds() - do_compile_start_time; |
| 314 GetNaClInterface()->LogTranslateTime("NaCl.Perf.PNaClLoadTime.CompileTime", | 315 GetNaClInterface()->LogTranslateTime("NaCl.Perf.PNaClLoadTime.CompileTime", |
| 315 compile_time_); | 316 compile_time_); |
| 316 GetNaClInterface()->LogTranslateTime( | 317 GetNaClInterface()->LogTranslateTime( |
| 317 pnacl_options_->use_subzero | 318 pnacl_options_->use_subzero |
| 318 ? "NaCl.Perf.PNaClLoadTime.CompileTime.Subzero" | 319 ? "NaCl.Perf.PNaClLoadTime.CompileTime.Subzero" |
| 319 : "NaCl.Perf.PNaClLoadTime.CompileTime.LLC", | 320 : "NaCl.Perf.PNaClLoadTime.CompileTime.LLC", |
| 320 compile_time_); | 321 compile_time_); |
| 321 | 322 |
| 322 // Shut down the llc subprocess. | 323 // Shut down the compiler subprocess. |
| 323 NaClXMutexLock(&subprocess_mu_); | 324 NaClXMutexLock(&subprocess_mu_); |
| 324 compiler_subprocess_active_ = false; | 325 compiler_subprocess_active_ = false; |
| 325 compiler_subprocess_.reset(NULL); | 326 compiler_subprocess_->Shutdown(); |
| 326 NaClXMutexUnlock(&subprocess_mu_); | 327 NaClXMutexUnlock(&subprocess_mu_); |
| 327 | 328 |
| 328 if(!RunLdSubprocess()) { | 329 core->CallOnMainThread(0, compile_finished_callback_, PP_OK); |
| 330 } | |
| 331 | |
| 332 void WINAPI PnaclTranslateThread::DoLinkThread(void* arg) { | |
| 333 PnaclTranslateThread* translator = | |
| 334 reinterpret_cast<PnaclTranslateThread*>(arg); | |
| 335 translator->DoLink(); | |
| 336 } | |
| 337 | |
| 338 void PnaclTranslateThread::DoLink() { | |
| 339 // If the main thread asked us to exit in between starting the thread | |
| 340 // and now, just leave now. | |
| 341 NaClXMutexLock(&subprocess_mu_); | |
| 342 if (!ld_subprocess_active_) | |
| 343 return; | |
| 344 NaClXMutexUnlock(&subprocess_mu_); | |
| 345 | |
| 346 // Wait till we are in the helper thread to do the blocking | |
|
Derek Schuff
2015/05/08 22:45:59
here too as above
jvoung (off chromium)
2015/05/08 23:59:32
Done.
| |
| 347 // StartSrpcServices operation. | |
| 348 if (!ld_subprocess_->StartSrpcServices()) { | |
| 349 TranslateFailed( | |
| 350 PP_NACL_ERROR_SRPC_CONNECTION_FAIL, | |
| 351 "SRPC connection failure for " + ld_subprocess_->description()); | |
| 329 return; | 352 return; |
| 330 } | 353 } |
| 331 core->CallOnMainThread(0, report_translate_finished_, PP_OK); | |
| 332 } | |
| 333 | 354 |
| 334 bool PnaclTranslateThread::RunLdSubprocess() { | |
| 335 ErrorInfo error_info; | |
| 336 SrpcParams params; | 355 SrpcParams params; |
| 337 | |
| 338 std::vector<nacl::DescWrapper*> ld_in_files; | 356 std::vector<nacl::DescWrapper*> ld_in_files; |
| 339 size_t i; | 357 size_t i; |
| 340 for (i = 0; i < obj_files_->size(); i++) { | 358 for (i = 0; i < obj_files_->size(); i++) { |
| 341 // Reset object file for reading first. | 359 // Reset object file for reading first. |
| 342 if (!(*obj_files_)[i]->Reset()) { | 360 if (!(*obj_files_)[i]->Reset()) { |
| 343 TranslateFailed(PP_NACL_ERROR_PNACL_LD_SETUP, | 361 TranslateFailed(PP_NACL_ERROR_PNACL_LD_SETUP, |
| 344 "Link process could not reset object file"); | 362 "Link process could not reset object file"); |
| 345 return false; | |
| 346 } | 363 } |
| 347 ld_in_files.push_back((*obj_files_)[i]->read_wrapper()); | 364 ld_in_files.push_back((*obj_files_)[i]->read_wrapper()); |
| 348 } | 365 } |
| 349 for (; i < PnaclCoordinator::kMaxTranslatorObjectFiles; i++) | 366 for (; i < PnaclCoordinator::kMaxTranslatorObjectFiles; i++) |
| 350 ld_in_files.push_back(invalid_desc_wrapper_); | 367 ld_in_files.push_back(invalid_desc_wrapper_); |
| 351 | 368 |
| 352 nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper(); | 369 nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper(); |
| 353 int64_t ld_start_time = NaClGetTimeOfDayMicroseconds(); | |
| 354 PP_NaClFileInfo ld_file_info = resources_->TakeFileInfo(PnaclResources::LD); | |
| 355 // On success, ownership of ld_file_info is transferred. | |
| 356 nacl::scoped_ptr<NaClSubprocess> ld_subprocess(plugin_->LoadHelperNaClModule( | |
| 357 resources_->GetUrl(PnaclResources::LD), ld_file_info, &error_info)); | |
| 358 if (ld_subprocess.get() == NULL) { | |
| 359 if (ld_file_info.handle != PP_kInvalidFileHandle) | |
| 360 CloseFileHandle(ld_file_info.handle); | |
| 361 TranslateFailed(PP_NACL_ERROR_PNACL_LD_SETUP, | |
| 362 "Link process could not be created: " + | |
| 363 error_info.message()); | |
| 364 return false; | |
| 365 } | |
| 366 GetNaClInterface()->LogTranslateTime( | |
| 367 "NaCl.Perf.PNaClLoadTime.LoadLinker", | |
| 368 NaClGetTimeOfDayMicroseconds() - ld_start_time); | |
| 369 { | |
| 370 nacl::MutexLocker ml(&subprocess_mu_); | |
| 371 // If we received a call to AbortSubprocesses() before we had a chance to | |
| 372 // set ld_subprocess_, shut down and clean up the subprocess started here. | |
| 373 if (subprocesses_aborted_) { | |
| 374 ld_subprocess->service_runtime()->Shutdown(); | |
| 375 return false; | |
| 376 } | |
| 377 DCHECK(ld_subprocess_.get() == NULL); | |
| 378 ld_subprocess_.swap(ld_subprocess); | |
| 379 ld_subprocess_active_ = true; | |
| 380 } | |
| 381 | |
| 382 int64_t link_start_time = NaClGetTimeOfDayMicroseconds(); | 370 int64_t link_start_time = NaClGetTimeOfDayMicroseconds(); |
| 383 // Run LD. | 371 // Run LD. |
| 384 bool success = ld_subprocess_->InvokeSrpcMethod( | 372 bool success = ld_subprocess_->InvokeSrpcMethod( |
| 385 "RunWithSplit", | 373 "RunWithSplit", |
| 386 "ihhhhhhhhhhhhhhhhh", | 374 "ihhhhhhhhhhhhhhhhh", |
| 387 ¶ms, | 375 ¶ms, |
| 388 static_cast<int>(obj_files_->size()), | 376 static_cast<int>(obj_files_->size()), |
| 389 ld_in_files[0]->desc(), | 377 ld_in_files[0]->desc(), |
| 390 ld_in_files[1]->desc(), | 378 ld_in_files[1]->desc(), |
| 391 ld_in_files[2]->desc(), | 379 ld_in_files[2]->desc(), |
| 392 ld_in_files[3]->desc(), | 380 ld_in_files[3]->desc(), |
| 393 ld_in_files[4]->desc(), | 381 ld_in_files[4]->desc(), |
| 394 ld_in_files[5]->desc(), | 382 ld_in_files[5]->desc(), |
| 395 ld_in_files[6]->desc(), | 383 ld_in_files[6]->desc(), |
| 396 ld_in_files[7]->desc(), | 384 ld_in_files[7]->desc(), |
| 397 ld_in_files[8]->desc(), | 385 ld_in_files[8]->desc(), |
| 398 ld_in_files[9]->desc(), | 386 ld_in_files[9]->desc(), |
| 399 ld_in_files[10]->desc(), | 387 ld_in_files[10]->desc(), |
| 400 ld_in_files[11]->desc(), | 388 ld_in_files[11]->desc(), |
| 401 ld_in_files[12]->desc(), | 389 ld_in_files[12]->desc(), |
| 402 ld_in_files[13]->desc(), | 390 ld_in_files[13]->desc(), |
| 403 ld_in_files[14]->desc(), | 391 ld_in_files[14]->desc(), |
| 404 ld_in_files[15]->desc(), | 392 ld_in_files[15]->desc(), |
| 405 ld_out_file->desc()); | 393 ld_out_file->desc()); |
| 406 if (!success) { | 394 if (!success) { |
| 407 TranslateFailed(PP_NACL_ERROR_PNACL_LD_INTERNAL, | 395 TranslateFailed(PP_NACL_ERROR_PNACL_LD_INTERNAL, |
| 408 "link failed."); | 396 "link failed."); |
| 409 return false; | 397 return; |
| 410 } | 398 } |
| 411 GetNaClInterface()->LogTranslateTime( | 399 GetNaClInterface()->LogTranslateTime( |
| 412 "NaCl.Perf.PNaClLoadTime.LinkTime", | 400 "NaCl.Perf.PNaClLoadTime.LinkTime", |
| 413 NaClGetTimeOfDayMicroseconds() - link_start_time); | 401 NaClGetTimeOfDayMicroseconds() - link_start_time); |
| 414 PLUGIN_PRINTF(("PnaclCoordinator: link (translator=%p) succeeded\n", | 402 PLUGIN_PRINTF(("PnaclCoordinator: link (translator=%p) succeeded\n", |
| 415 this)); | 403 this)); |
| 404 | |
| 416 // Shut down the ld subprocess. | 405 // Shut down the ld subprocess. |
| 417 NaClXMutexLock(&subprocess_mu_); | 406 NaClXMutexLock(&subprocess_mu_); |
| 418 ld_subprocess_active_ = false; | 407 ld_subprocess_active_ = false; |
| 419 ld_subprocess_.reset(NULL); | 408 ld_subprocess_->Shutdown(); |
| 420 NaClXMutexUnlock(&subprocess_mu_); | 409 NaClXMutexUnlock(&subprocess_mu_); |
| 421 return true; | 410 |
| 411 pp::Core* core = pp::Module::Get()->core(); | |
| 412 core->CallOnMainThread(0, report_translate_finished_, PP_OK); | |
| 422 } | 413 } |
| 423 | 414 |
| 424 void PnaclTranslateThread::TranslateFailed( | 415 void PnaclTranslateThread::TranslateFailed( |
| 425 PP_NaClError err_code, | 416 PP_NaClError err_code, |
| 426 const std::string& error_string) { | 417 const std::string& error_string) { |
| 427 PLUGIN_PRINTF(("PnaclTranslateThread::TranslateFailed (error_string='%s')\n", | 418 PLUGIN_PRINTF(("PnaclTranslateThread::TranslateFailed (error_string='%s')\n", |
| 428 error_string.c_str())); | 419 error_string.c_str())); |
| 429 pp::Core* core = pp::Module::Get()->core(); | 420 pp::Core* core = pp::Module::Get()->core(); |
| 430 if (coordinator_error_info_->message().empty()) { | 421 if (coordinator_error_info_->message().empty()) { |
| 431 // Only use our message if one hasn't already been set by the coordinator | 422 // Only use our message if one hasn't already been set by the coordinator |
| 432 // (e.g. pexe load failed). | 423 // (e.g. pexe load failed). |
| 433 coordinator_error_info_->SetReport(err_code, | 424 coordinator_error_info_->SetReport(err_code, |
| 434 std::string("PnaclCoordinator: ") + | 425 std::string("PnaclCoordinator: ") + |
| 435 error_string); | 426 error_string); |
| 436 } | 427 } |
| 437 core->CallOnMainThread(0, report_translate_finished_, PP_ERROR_FAILED); | 428 core->CallOnMainThread(0, report_translate_finished_, PP_ERROR_FAILED); |
| 438 } | 429 } |
| 439 | 430 |
| 440 void PnaclTranslateThread::AbortSubprocesses() { | 431 void PnaclTranslateThread::AbortSubprocesses() { |
| 441 PLUGIN_PRINTF(("PnaclTranslateThread::AbortSubprocesses\n")); | 432 PLUGIN_PRINTF(("PnaclTranslateThread::AbortSubprocesses\n")); |
| 442 NaClXMutexLock(&subprocess_mu_); | 433 NaClXMutexLock(&subprocess_mu_); |
| 443 if (compiler_subprocess_ != NULL && compiler_subprocess_active_) { | 434 if (compiler_subprocess_ != NULL && compiler_subprocess_active_) { |
| 435 // We only run the service_runtime's Shutdown and do not run the | |
| 436 // NaClSubprocess Shutdown, which would otherwise nullify some | |
| 437 // pointers that could still be in use (srpc_client, etc.). | |
| 444 compiler_subprocess_->service_runtime()->Shutdown(); | 438 compiler_subprocess_->service_runtime()->Shutdown(); |
| 445 compiler_subprocess_active_ = false; | 439 compiler_subprocess_active_ = false; |
| 446 } | 440 } |
| 447 if (ld_subprocess_ != NULL && ld_subprocess_active_) { | 441 if (ld_subprocess_ != NULL && ld_subprocess_active_) { |
| 448 ld_subprocess_->service_runtime()->Shutdown(); | 442 ld_subprocess_->service_runtime()->Shutdown(); |
| 449 ld_subprocess_active_ = false; | 443 ld_subprocess_active_ = false; |
| 450 } | 444 } |
| 451 subprocesses_aborted_ = true; | |
| 452 NaClXMutexUnlock(&subprocess_mu_); | 445 NaClXMutexUnlock(&subprocess_mu_); |
| 453 nacl::MutexLocker ml(&cond_mu_); | 446 nacl::MutexLocker ml(&cond_mu_); |
| 454 done_ = true; | 447 done_ = true; |
| 455 // Free all buffered bitcode chunks | 448 // Free all buffered bitcode chunks |
| 456 data_buffers_.clear(); | 449 data_buffers_.clear(); |
| 457 NaClXCondVarSignal(&buffer_cond_); | 450 NaClXCondVarSignal(&buffer_cond_); |
| 458 } | 451 } |
| 459 | 452 |
| 460 PnaclTranslateThread::~PnaclTranslateThread() { | 453 PnaclTranslateThread::~PnaclTranslateThread() { |
| 461 PLUGIN_PRINTF(("~PnaclTranslateThread (translate_thread=%p)\n", this)); | 454 PLUGIN_PRINTF(("~PnaclTranslateThread (translate_thread=%p)\n", this)); |
| 462 AbortSubprocesses(); | 455 AbortSubprocesses(); |
| 463 if (translate_thread_ != NULL) | 456 if (translate_thread_ != NULL) |
| 464 NaClThreadJoin(translate_thread_.get()); | 457 NaClThreadJoin(translate_thread_.get()); |
| 465 PLUGIN_PRINTF(("~PnaclTranslateThread joined\n")); | 458 PLUGIN_PRINTF(("~PnaclTranslateThread joined\n")); |
| 466 NaClCondVarDtor(&buffer_cond_); | 459 NaClCondVarDtor(&buffer_cond_); |
| 467 NaClMutexDtor(&cond_mu_); | 460 NaClMutexDtor(&cond_mu_); |
| 468 NaClMutexDtor(&subprocess_mu_); | 461 NaClMutexDtor(&subprocess_mu_); |
| 469 } | 462 } |
| 470 | 463 |
| 471 } // namespace plugin | 464 } // namespace plugin |
| OLD | NEW |