OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "native_client/src/trusted/plugin/pnacl_translate_thread.h" |
| 6 |
| 7 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h" |
| 8 #include "native_client/src/trusted/plugin/plugin.h" |
| 9 #include "native_client/src/trusted/plugin/pnacl_resources.h" |
| 10 #include "native_client/src/trusted/plugin/srpc_params.h" |
| 11 #include "native_client/src/trusted/plugin/utility.h" |
| 12 |
| 13 namespace plugin { |
| 14 |
| 15 PnaclTranslateThread::PnaclTranslateThread() : subprocesses_should_die_(false), |
| 16 manifest_(NULL), |
| 17 obj_file_(NULL), |
| 18 nexe_file_(NULL), |
| 19 pexe_wrapper_(NULL), |
| 20 error_info_(NULL), |
| 21 resources_(NULL), |
| 22 plugin_(NULL) { |
| 23 NaClXMutexCtor(&subprocess_mu_); |
| 24 } |
| 25 |
| 26 void PnaclTranslateThread::RunTranslate(pp::CompletionCallback finish_callback, |
| 27 const Manifest* manifest, |
| 28 const Manifest* ld_manifest, |
| 29 LocalTempFile* obj_file, |
| 30 LocalTempFile* nexe_file, |
| 31 nacl::DescWrapper* pexe_wrapper, |
| 32 ErrorInfo* error_info, |
| 33 PnaclResources* resources, |
| 34 Plugin* plugin) { |
| 35 PLUGIN_PRINTF(("PnaclTranslateThread::RunTranslate)\n")); |
| 36 manifest_ = manifest; |
| 37 ld_manifest_ = ld_manifest; |
| 38 obj_file_ = obj_file; |
| 39 nexe_file_ = nexe_file; |
| 40 pexe_wrapper_ = pexe_wrapper; |
| 41 error_info_ = error_info; |
| 42 resources_ = resources; |
| 43 plugin_ = plugin; |
| 44 |
| 45 // Invoke llc followed by ld off the main thread. This allows use of |
| 46 // blocking RPCs that would otherwise block the JavaScript main thread. |
| 47 report_translate_finished_ = finish_callback; |
| 48 translate_thread_.reset(new NaClThread); |
| 49 if (translate_thread_ == NULL) { |
| 50 TranslateFailed("could not allocate thread struct."); |
| 51 return; |
| 52 } |
| 53 const int32_t kArbitraryStackSize = 128 * 1024; |
| 54 if (!NaClThreadCreateJoinable(translate_thread_.get(), |
| 55 DoTranslateThread, |
| 56 this, |
| 57 kArbitraryStackSize)) { |
| 58 TranslateFailed("could not create thread."); |
| 59 } |
| 60 } |
| 61 |
| 62 NaClSubprocess* PnaclTranslateThread::StartSubprocess( |
| 63 const nacl::string& url_for_nexe, |
| 64 const Manifest* manifest) { |
| 65 PLUGIN_PRINTF(("PnaclTranslateThread::StartSubprocess (url_for_nexe=%s)\n", |
| 66 url_for_nexe.c_str())); |
| 67 nacl::DescWrapper* wrapper = resources_->WrapperForUrl(url_for_nexe); |
| 68 nacl::scoped_ptr<NaClSubprocess> subprocess( |
| 69 plugin_->LoadHelperNaClModule(wrapper, manifest, error_info_)); |
| 70 if (subprocess.get() == NULL) { |
| 71 PLUGIN_PRINTF(( |
| 72 "PnaclTranslateThread::StartSubprocess: subprocess creation failed\n")); |
| 73 return NULL; |
| 74 } |
| 75 return subprocess.release(); |
| 76 } |
| 77 |
| 78 void WINAPI PnaclTranslateThread::DoTranslateThread(void* arg) { |
| 79 PnaclTranslateThread* translator = |
| 80 reinterpret_cast<PnaclTranslateThread*>(arg); |
| 81 nacl::scoped_ptr<NaClSubprocess> llc_subprocess( |
| 82 translator->StartSubprocess(PnaclUrls::GetLlcUrl(), |
| 83 translator->manifest_)); |
| 84 if (llc_subprocess == NULL) { |
| 85 translator->TranslateFailed("Compile process could not be created."); |
| 86 return; |
| 87 } |
| 88 // Run LLC. |
| 89 SrpcParams params; |
| 90 nacl::DescWrapper* llc_out_file = translator->obj_file_->write_wrapper(); |
| 91 PluginReverseInterface* llc_reverse = |
| 92 llc_subprocess->service_runtime()->rev_interface(); |
| 93 llc_reverse->AddQuotaManagedFile(translator->obj_file_->identifier(), |
| 94 translator->obj_file_->write_file_io()); |
| 95 if (!llc_subprocess->InvokeSrpcMethod("RunWithDefaultCommandLine", |
| 96 "hh", |
| 97 ¶ms, |
| 98 translator->pexe_wrapper_->desc(), |
| 99 llc_out_file->desc())) { |
| 100 translator->TranslateFailed("compile failed."); |
| 101 return; |
| 102 } |
| 103 // LLC returns values that are used to determine how linking is done. |
| 104 int is_shared_library = (params.outs()[0]->u.ival != 0); |
| 105 nacl::string soname = params.outs()[1]->arrays.str; |
| 106 nacl::string lib_dependencies = params.outs()[2]->arrays.str; |
| 107 PLUGIN_PRINTF(("PnaclCoordinator: compile (translator=%p) succeeded" |
| 108 " is_shared_library=%d, soname='%s', lib_dependencies='%s')\n", |
| 109 arg, is_shared_library, soname.c_str(), |
| 110 lib_dependencies.c_str())); |
| 111 // Shut down the llc subprocess. |
| 112 llc_subprocess.reset(NULL); |
| 113 if (translator->SubprocessesShouldDie()) { |
| 114 translator->TranslateFailed("stopped by coordinator."); |
| 115 return; |
| 116 } |
| 117 nacl::scoped_ptr<NaClSubprocess> ld_subprocess( |
| 118 translator->StartSubprocess(PnaclUrls::GetLdUrl(), |
| 119 translator->ld_manifest_)); |
| 120 if (ld_subprocess == NULL) { |
| 121 translator->TranslateFailed("Link process could not be created."); |
| 122 return; |
| 123 } |
| 124 // Run LD. |
| 125 nacl::DescWrapper* ld_in_file = translator->obj_file_->read_wrapper(); |
| 126 nacl::DescWrapper* ld_out_file = translator->nexe_file_->write_wrapper(); |
| 127 PluginReverseInterface* ld_reverse = |
| 128 ld_subprocess->service_runtime()->rev_interface(); |
| 129 ld_reverse->AddQuotaManagedFile(translator->nexe_file_->identifier(), |
| 130 translator->nexe_file_->write_file_io()); |
| 131 if (!ld_subprocess->InvokeSrpcMethod("RunWithDefaultCommandLine", |
| 132 "hhiCC", |
| 133 ¶ms, |
| 134 ld_in_file->desc(), |
| 135 ld_out_file->desc(), |
| 136 is_shared_library, |
| 137 soname.c_str(), |
| 138 lib_dependencies.c_str())) { |
| 139 translator->TranslateFailed("link failed."); |
| 140 return; |
| 141 } |
| 142 PLUGIN_PRINTF(("PnaclCoordinator: link (translator=%p) succeeded\n", arg)); |
| 143 // Shut down the ld subprocess. |
| 144 ld_subprocess.reset(NULL); |
| 145 if (translator->SubprocessesShouldDie()) { |
| 146 translator->TranslateFailed("stopped by coordinator."); |
| 147 return; |
| 148 } |
| 149 pp::Core* core = pp::Module::Get()->core(); |
| 150 core->CallOnMainThread(0, translator->report_translate_finished_, PP_OK); |
| 151 } |
| 152 |
| 153 void PnaclTranslateThread::TranslateFailed(const nacl::string& error_string) { |
| 154 PLUGIN_PRINTF(("PnaclTranslateThread::TranslateFailed (error_string='%s')\n", |
| 155 error_string.c_str())); |
| 156 pp::Core* core = pp::Module::Get()->core(); |
| 157 error_info_->SetReport(ERROR_UNKNOWN, |
| 158 nacl::string("PnaclCoordinator: ") + error_string); |
| 159 core->CallOnMainThread(0, report_translate_finished_, PP_ERROR_FAILED); |
| 160 } |
| 161 |
| 162 bool PnaclTranslateThread::SubprocessesShouldDie() { |
| 163 nacl::MutexLocker ml(&subprocess_mu_); |
| 164 return subprocesses_should_die_; |
| 165 } |
| 166 |
| 167 void PnaclTranslateThread::SetSubprocessesShouldDie( |
| 168 bool subprocesses_should_die) { |
| 169 nacl::MutexLocker ml(&subprocess_mu_); |
| 170 subprocesses_should_die_ = subprocesses_should_die; |
| 171 } |
| 172 |
| 173 PnaclTranslateThread::~PnaclTranslateThread() { |
| 174 NaClMutexDtor(&subprocess_mu_); |
| 175 } |
| 176 |
| 177 } // namespace plugin |
OLD | NEW |