| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <iterator> | 9 #include <iterator> |
| 10 #include <sstream> | 10 #include <sstream> |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 const pp::CompletionCallback& finish_callback, | 80 const pp::CompletionCallback& finish_callback, |
| 81 NaClSubprocess* compiler_subprocess, | 81 NaClSubprocess* compiler_subprocess, |
| 82 NaClSubprocess* ld_subprocess, | 82 NaClSubprocess* ld_subprocess, |
| 83 std::vector<base::File>* obj_files, | 83 std::vector<base::File>* obj_files, |
| 84 int num_threads, | 84 int num_threads, |
| 85 base::File* nexe_file, | 85 base::File* nexe_file, |
| 86 ErrorInfo* error_info, | 86 ErrorInfo* error_info, |
| 87 PP_PNaClOptions* pnacl_options, | 87 PP_PNaClOptions* pnacl_options, |
| 88 const std::string& architecture_attributes, | 88 const std::string& architecture_attributes, |
| 89 PnaclCoordinator* coordinator) { | 89 PnaclCoordinator* coordinator) { |
| 90 PLUGIN_PRINTF(("PnaclTranslateThread::SetupState)\n")); | |
| 91 compiler_subprocess_ = compiler_subprocess; | 90 compiler_subprocess_ = compiler_subprocess; |
| 92 ld_subprocess_ = ld_subprocess; | 91 ld_subprocess_ = ld_subprocess; |
| 93 obj_files_ = obj_files; | 92 obj_files_ = obj_files; |
| 94 num_threads_ = num_threads; | 93 num_threads_ = num_threads; |
| 95 nexe_file_ = nexe_file; | 94 nexe_file_ = nexe_file; |
| 96 coordinator_error_info_ = error_info; | 95 coordinator_error_info_ = error_info; |
| 97 pnacl_options_ = pnacl_options; | 96 pnacl_options_ = pnacl_options; |
| 98 architecture_attributes_ = architecture_attributes; | 97 architecture_attributes_ = architecture_attributes; |
| 99 coordinator_ = coordinator; | 98 coordinator_ = coordinator; |
| 100 | 99 |
| 101 report_translate_finished_ = finish_callback; | 100 report_translate_finished_ = finish_callback; |
| 102 } | 101 } |
| 103 | 102 |
| 104 void PnaclTranslateThread::RunCompile( | 103 void PnaclTranslateThread::RunCompile( |
| 105 const pp::CompletionCallback& compile_finished_callback) { | 104 const pp::CompletionCallback& compile_finished_callback) { |
| 106 PLUGIN_PRINTF(("PnaclTranslateThread::RunCompile)\n")); | |
| 107 DCHECK(started()); | 105 DCHECK(started()); |
| 108 DCHECK(compiler_subprocess_->service_runtime()); | 106 DCHECK(compiler_subprocess_->service_runtime()); |
| 109 compiler_subprocess_active_ = true; | 107 compiler_subprocess_active_ = true; |
| 110 | 108 |
| 111 // Take ownership of this IPC channel to make sure that it does not get | 109 // Take ownership of this IPC channel to make sure that it does not get |
| 112 // freed on the child thread when the child thread calls Shutdown(). | 110 // freed on the child thread when the child thread calls Shutdown(). |
| 113 compiler_channel_ = | 111 compiler_channel_ = |
| 114 compiler_subprocess_->service_runtime()->TakeTranslatorChannel(); | 112 compiler_subprocess_->service_runtime()->TakeTranslatorChannel(); |
| 115 // compiler_channel_ is a IPC::SyncChannel, which is not thread-safe and | 113 // compiler_channel_ is a IPC::SyncChannel, which is not thread-safe and |
| 116 // cannot be used directly by the child thread, so create a | 114 // cannot be used directly by the child thread, so create a |
| 117 // SyncMessageFilter which can be used by the child thread. | 115 // SyncMessageFilter which can be used by the child thread. |
| 118 compiler_channel_filter_ = compiler_channel_->CreateSyncMessageFilter(); | 116 compiler_channel_filter_ = compiler_channel_->CreateSyncMessageFilter(); |
| 119 // Make a copy of the process ID, again to avoid any thread-safety issues | 117 // Make a copy of the process ID, again to avoid any thread-safety issues |
| 120 // involved in accessing compiler_subprocess_ on the child thread. | 118 // involved in accessing compiler_subprocess_ on the child thread. |
| 121 compiler_channel_peer_pid_ = | 119 compiler_channel_peer_pid_ = |
| 122 compiler_subprocess_->service_runtime()->get_process_id(); | 120 compiler_subprocess_->service_runtime()->get_process_id(); |
| 123 | 121 |
| 124 compile_finished_callback_ = compile_finished_callback; | 122 compile_finished_callback_ = compile_finished_callback; |
| 125 translate_thread_.reset(new CompileThread(this)); | 123 translate_thread_.reset(new CompileThread(this)); |
| 126 translate_thread_->Start(); | 124 translate_thread_->Start(); |
| 127 } | 125 } |
| 128 | 126 |
| 129 void PnaclTranslateThread::RunLink() { | 127 void PnaclTranslateThread::RunLink() { |
| 130 PLUGIN_PRINTF(("PnaclTranslateThread::RunLink)\n")); | |
| 131 DCHECK(started()); | 128 DCHECK(started()); |
| 132 DCHECK(ld_subprocess_->service_runtime()); | 129 DCHECK(ld_subprocess_->service_runtime()); |
| 133 ld_subprocess_active_ = true; | 130 ld_subprocess_active_ = true; |
| 134 | 131 |
| 135 // Take ownership of this IPC channel to make sure that it does not get | 132 // Take ownership of this IPC channel to make sure that it does not get |
| 136 // freed on the child thread when the child thread calls Shutdown(). | 133 // freed on the child thread when the child thread calls Shutdown(). |
| 137 ld_channel_ = ld_subprocess_->service_runtime()->TakeTranslatorChannel(); | 134 ld_channel_ = ld_subprocess_->service_runtime()->TakeTranslatorChannel(); |
| 138 // ld_channel_ is a IPC::SyncChannel, which is not thread-safe and cannot be | 135 // ld_channel_ is a IPC::SyncChannel, which is not thread-safe and cannot be |
| 139 // used directly by the child thread, so create a SyncMessageFilter which | 136 // used directly by the child thread, so create a SyncMessageFilter which |
| 140 // can be used by the child thread. | 137 // can be used by the child thread. |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 return; | 202 return; |
| 206 } | 203 } |
| 207 | 204 |
| 208 std::vector<ppapi::proxy::SerializedHandle> compiler_output_files; | 205 std::vector<ppapi::proxy::SerializedHandle> compiler_output_files; |
| 209 for (base::File& obj_file : *obj_files_) { | 206 for (base::File& obj_file : *obj_files_) { |
| 210 compiler_output_files.push_back( | 207 compiler_output_files.push_back( |
| 211 GetHandleForSubprocess(&obj_file, PP_FILEOPENFLAG_WRITE, | 208 GetHandleForSubprocess(&obj_file, PP_FILEOPENFLAG_WRITE, |
| 212 compiler_channel_peer_pid_)); | 209 compiler_channel_peer_pid_)); |
| 213 } | 210 } |
| 214 | 211 |
| 215 PLUGIN_PRINTF(("DoCompile using subzero: %d\n", pnacl_options_->use_subzero)); | |
| 216 | |
| 217 pp::Core* core = pp::Module::Get()->core(); | 212 pp::Core* core = pp::Module::Get()->core(); |
| 218 base::TimeTicks do_compile_start_time = base::TimeTicks::Now(); | 213 base::TimeTicks do_compile_start_time = base::TimeTicks::Now(); |
| 219 | 214 |
| 220 std::vector<std::string> args; | 215 std::vector<std::string> args; |
| 221 if (pnacl_options_->use_subzero) { | 216 if (pnacl_options_->use_subzero) { |
| 222 GetSubzeroCommandLine(&args, pnacl_options_->opt_level, | 217 GetSubzeroCommandLine(&args, pnacl_options_->opt_level, |
| 223 PP_ToBool(pnacl_options_->is_debug), | 218 PP_ToBool(pnacl_options_->is_debug), |
| 224 architecture_attributes_); | 219 architecture_attributes_); |
| 225 } else { | 220 } else { |
| 226 GetLlcCommandLine(&args, obj_files_->size(), | 221 GetLlcCommandLine(&args, obj_files_->size(), |
| (...skipping 11 matching lines...) Expand all Loading... |
| 238 "Compile stream init failed: " | 233 "Compile stream init failed: " |
| 239 "reply not received from PNaCl translator " | 234 "reply not received from PNaCl translator " |
| 240 "(it probably crashed)"); | 235 "(it probably crashed)"); |
| 241 return; | 236 return; |
| 242 } | 237 } |
| 243 if (!success) { | 238 if (!success) { |
| 244 TranslateFailed(PP_NACL_ERROR_PNACL_LLC_INTERNAL, | 239 TranslateFailed(PP_NACL_ERROR_PNACL_LLC_INTERNAL, |
| 245 std::string("Stream init failed: ") + error_str); | 240 std::string("Stream init failed: ") + error_str); |
| 246 return; | 241 return; |
| 247 } | 242 } |
| 248 PLUGIN_PRINTF(("PnaclCoordinator: StreamInit successful\n")); | |
| 249 | 243 |
| 250 // llc process is started. | 244 // llc process is started. |
| 251 while(!done_ || data_buffers_.size() > 0) { | 245 while(!done_ || data_buffers_.size() > 0) { |
| 252 cond_mu_.Acquire(); | 246 cond_mu_.Acquire(); |
| 253 while(!done_ && data_buffers_.size() == 0) { | 247 while(!done_ && data_buffers_.size() == 0) { |
| 254 buffer_cond_.Wait(); | 248 buffer_cond_.Wait(); |
| 255 } | 249 } |
| 256 PLUGIN_PRINTF(("PnaclTranslateThread awake (done=%d, size=%" NACL_PRIuS | |
| 257 ")\n", | |
| 258 done_, data_buffers_.size())); | |
| 259 if (data_buffers_.size() > 0) { | 250 if (data_buffers_.size() > 0) { |
| 260 std::string data; | 251 std::string data; |
| 261 data.swap(data_buffers_.front()); | 252 data.swap(data_buffers_.front()); |
| 262 data_buffers_.pop_front(); | 253 data_buffers_.pop_front(); |
| 263 cond_mu_.Release(); | 254 cond_mu_.Release(); |
| 264 PLUGIN_PRINTF(("StreamChunk\n")); | |
| 265 | 255 |
| 266 if (!compiler_channel_filter_->Send( | 256 if (!compiler_channel_filter_->Send( |
| 267 new PpapiMsg_PnaclTranslatorCompileChunk(data, &success))) { | 257 new PpapiMsg_PnaclTranslatorCompileChunk(data, &success))) { |
| 268 TranslateFailed(PP_NACL_ERROR_PNACL_LLC_INTERNAL, | 258 TranslateFailed(PP_NACL_ERROR_PNACL_LLC_INTERNAL, |
| 269 "Compile stream chunk failed: " | 259 "Compile stream chunk failed: " |
| 270 "reply not received from PNaCl translator " | 260 "reply not received from PNaCl translator " |
| 271 "(it probably crashed)"); | 261 "(it probably crashed)"); |
| 272 return; | 262 return; |
| 273 } | 263 } |
| 274 if (!success) { | 264 if (!success) { |
| 275 // If the error was reported by the translator, then we fall through | 265 // If the error was reported by the translator, then we fall through |
| 276 // and call PpapiMsg_PnaclTranslatorCompileEnd, which returns a string | 266 // and call PpapiMsg_PnaclTranslatorCompileEnd, which returns a string |
| 277 // describing the error, which we can then send to the Javascript | 267 // describing the error, which we can then send to the Javascript |
| 278 // console. | 268 // console. |
| 279 break; | 269 break; |
| 280 } | 270 } |
| 281 PLUGIN_PRINTF(("StreamChunk Successful\n")); | |
| 282 core->CallOnMainThread( | 271 core->CallOnMainThread( |
| 283 0, | 272 0, |
| 284 coordinator_->GetCompileProgressCallback(data.size()), | 273 coordinator_->GetCompileProgressCallback(data.size()), |
| 285 PP_OK); | 274 PP_OK); |
| 286 } else { | 275 } else { |
| 287 cond_mu_.Release(); | 276 cond_mu_.Release(); |
| 288 } | 277 } |
| 289 } | 278 } |
| 290 PLUGIN_PRINTF(("PnaclTranslateThread done with chunks\n")); | |
| 291 // Finish llc. | 279 // Finish llc. |
| 292 if (!compiler_channel_filter_->Send( | 280 if (!compiler_channel_filter_->Send( |
| 293 new PpapiMsg_PnaclTranslatorCompileEnd(&success, &error_str))) { | 281 new PpapiMsg_PnaclTranslatorCompileEnd(&success, &error_str))) { |
| 294 TranslateFailed(PP_NACL_ERROR_PNACL_LLC_INTERNAL, | 282 TranslateFailed(PP_NACL_ERROR_PNACL_LLC_INTERNAL, |
| 295 "Compile stream end failed: " | 283 "Compile stream end failed: " |
| 296 "reply not received from PNaCl translator " | 284 "reply not received from PNaCl translator " |
| 297 "(it probably crashed)"); | 285 "(it probably crashed)"); |
| 298 return; | 286 return; |
| 299 } | 287 } |
| 300 if (!success) { | 288 if (!success) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 } | 354 } |
| 367 if (!success) { | 355 if (!success) { |
| 368 TranslateFailed(PP_NACL_ERROR_PNACL_LD_INTERNAL, | 356 TranslateFailed(PP_NACL_ERROR_PNACL_LD_INTERNAL, |
| 369 "link failed: linker returned failure status."); | 357 "link failed: linker returned failure status."); |
| 370 return; | 358 return; |
| 371 } | 359 } |
| 372 | 360 |
| 373 GetNaClInterface()->LogTranslateTime( | 361 GetNaClInterface()->LogTranslateTime( |
| 374 "NaCl.Perf.PNaClLoadTime.LinkTime", | 362 "NaCl.Perf.PNaClLoadTime.LinkTime", |
| 375 (base::TimeTicks::Now() - link_start_time).InMicroseconds()); | 363 (base::TimeTicks::Now() - link_start_time).InMicroseconds()); |
| 376 PLUGIN_PRINTF(("PnaclCoordinator: link (translator=%p) succeeded\n", | |
| 377 this)); | |
| 378 | 364 |
| 379 // Shut down the ld subprocess. | 365 // Shut down the ld subprocess. |
| 380 { | 366 { |
| 381 base::AutoLock lock(subprocess_mu_); | 367 base::AutoLock lock(subprocess_mu_); |
| 382 ld_subprocess_active_ = false; | 368 ld_subprocess_active_ = false; |
| 383 ld_subprocess_->Shutdown(); | 369 ld_subprocess_->Shutdown(); |
| 384 } | 370 } |
| 385 | 371 |
| 386 pp::Core* core = pp::Module::Get()->core(); | 372 pp::Core* core = pp::Module::Get()->core(); |
| 387 core->CallOnMainThread(0, report_translate_finished_, PP_OK); | 373 core->CallOnMainThread(0, report_translate_finished_, PP_OK); |
| 388 } | 374 } |
| 389 | 375 |
| 390 void PnaclTranslateThread::TranslateFailed( | 376 void PnaclTranslateThread::TranslateFailed( |
| 391 PP_NaClError err_code, | 377 PP_NaClError err_code, |
| 392 const std::string& error_string) { | 378 const std::string& error_string) { |
| 393 PLUGIN_PRINTF(("PnaclTranslateThread::TranslateFailed (error_string='%s')\n", | |
| 394 error_string.c_str())); | |
| 395 pp::Core* core = pp::Module::Get()->core(); | 379 pp::Core* core = pp::Module::Get()->core(); |
| 396 if (coordinator_error_info_->message().empty()) { | 380 if (coordinator_error_info_->message().empty()) { |
| 397 // Only use our message if one hasn't already been set by the coordinator | 381 // Only use our message if one hasn't already been set by the coordinator |
| 398 // (e.g. pexe load failed). | 382 // (e.g. pexe load failed). |
| 399 coordinator_error_info_->SetReport(err_code, | 383 coordinator_error_info_->SetReport(err_code, |
| 400 std::string("PnaclCoordinator: ") + | 384 std::string("PnaclCoordinator: ") + |
| 401 error_string); | 385 error_string); |
| 402 } | 386 } |
| 403 core->CallOnMainThread(0, report_translate_finished_, PP_ERROR_FAILED); | 387 core->CallOnMainThread(0, report_translate_finished_, PP_ERROR_FAILED); |
| 404 } | 388 } |
| 405 | 389 |
| 406 void PnaclTranslateThread::AbortSubprocesses() { | 390 void PnaclTranslateThread::AbortSubprocesses() { |
| 407 PLUGIN_PRINTF(("PnaclTranslateThread::AbortSubprocesses\n")); | |
| 408 { | 391 { |
| 409 base::AutoLock lock(subprocess_mu_); | 392 base::AutoLock lock(subprocess_mu_); |
| 410 if (compiler_subprocess_ != NULL && compiler_subprocess_active_) { | 393 if (compiler_subprocess_ != NULL && compiler_subprocess_active_) { |
| 411 // We only run the service_runtime's Shutdown and do not run the | 394 // We only run the service_runtime's Shutdown and do not run the |
| 412 // NaClSubprocess Shutdown, which would otherwise nullify some | 395 // NaClSubprocess Shutdown, which would otherwise nullify some |
| 413 // pointers that could still be in use (srpc_client, etc.). | 396 // pointers that could still be in use (srpc_client, etc.). |
| 414 compiler_subprocess_->service_runtime()->Shutdown(); | 397 compiler_subprocess_->service_runtime()->Shutdown(); |
| 415 compiler_subprocess_active_ = false; | 398 compiler_subprocess_active_ = false; |
| 416 } | 399 } |
| 417 if (ld_subprocess_ != NULL && ld_subprocess_active_) { | 400 if (ld_subprocess_ != NULL && ld_subprocess_active_) { |
| 418 ld_subprocess_->service_runtime()->Shutdown(); | 401 ld_subprocess_->service_runtime()->Shutdown(); |
| 419 ld_subprocess_active_ = false; | 402 ld_subprocess_active_ = false; |
| 420 } | 403 } |
| 421 } | 404 } |
| 422 base::AutoLock lock(cond_mu_); | 405 base::AutoLock lock(cond_mu_); |
| 423 done_ = true; | 406 done_ = true; |
| 424 // Free all buffered bitcode chunks | 407 // Free all buffered bitcode chunks |
| 425 data_buffers_.clear(); | 408 data_buffers_.clear(); |
| 426 buffer_cond_.Signal(); | 409 buffer_cond_.Signal(); |
| 427 } | 410 } |
| 428 | 411 |
| 429 PnaclTranslateThread::~PnaclTranslateThread() { | 412 PnaclTranslateThread::~PnaclTranslateThread() { |
| 430 PLUGIN_PRINTF(("~PnaclTranslateThread (translate_thread=%p)\n", this)); | |
| 431 AbortSubprocesses(); | 413 AbortSubprocesses(); |
| 432 if (translate_thread_) | 414 if (translate_thread_) |
| 433 translate_thread_->Join(); | 415 translate_thread_->Join(); |
| 434 PLUGIN_PRINTF(("~PnaclTranslateThread joined\n")); | |
| 435 } | 416 } |
| 436 | 417 |
| 437 } // namespace plugin | 418 } // namespace plugin |
| OLD | NEW |