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 |