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 |