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 |