Index: src/trusted/plugin/pnacl_coordinator.cc |
diff --git a/src/trusted/plugin/pnacl_coordinator.cc b/src/trusted/plugin/pnacl_coordinator.cc |
deleted file mode 100644 |
index eb48d6d093a651cddabff4f3c16996973f474035..0000000000000000000000000000000000000000 |
--- a/src/trusted/plugin/pnacl_coordinator.cc |
+++ /dev/null |
@@ -1,734 +0,0 @@ |
-// Copyright (c) 2011 The Native Client Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "native_client/src/trusted/plugin/pnacl_coordinator.h" |
- |
-#include <utility> |
-#include <vector> |
- |
-#include "native_client/src/include/portability_io.h" |
-#include "native_client/src/shared/platform/nacl_check.h" |
-#include "native_client/src/trusted/desc/nacl_desc_wrapper.h" |
-#include "native_client/src/trusted/plugin/browser_interface.h" |
-#include "native_client/src/trusted/plugin/nacl_subprocess.h" |
-#include "native_client/src/trusted/plugin/nexe_arch.h" |
-#include "native_client/src/trusted/plugin/plugin.h" |
-#include "native_client/src/trusted/plugin/plugin_error.h" |
-#include "native_client/src/trusted/plugin/pnacl_srpc_lib.h" |
-#include "native_client/src/trusted/plugin/scriptable_handle.h" |
-#include "native_client/src/trusted/plugin/utility.h" |
- |
-#include "ppapi/c/pp_errors.h" |
- |
-namespace { |
- |
-typedef std::vector<nacl::string> string_vector; |
-int32_t kArbitraryStackSize = 128 << 10; |
- |
-} // namespace |
- |
-namespace plugin { |
- |
-class Plugin; |
- |
-void PnaclCoordinator::Initialize(Plugin* instance) { |
- PLUGIN_PRINTF(("PnaclCoordinator::Initialize (this=%p)\n", |
- static_cast<void*>(this))); |
- CHECK(instance != NULL); |
- CHECK(instance_ == NULL); // Can only initialize once. |
- instance_ = instance; |
- callback_factory_.Initialize(this); |
-} |
- |
-PnaclCoordinator::~PnaclCoordinator() { |
- PLUGIN_PRINTF(("PnaclCoordinator::~PnaclCoordinator (this=%p)\n", |
- static_cast<void*>(this))); |
- |
- // Delete helper thread args. Join helper thread first (since it may be |
- // using the args), which will block the page from Refreshing while a |
- // translation is happening. |
- if (translate_args_ != NULL) { |
- translate_args_->should_die = true; |
- // Assume that when X_args_ != NULL, then X_thread_ != NULL too. |
- NaClThreadJoin(translate_thread_.get()); |
- } |
- if (link_args_ != NULL) { |
- link_args_->should_die = true; |
- NaClThreadJoin(link_thread_.get()); |
- } |
- |
- // Delete all delayed_callbacks. |
- delayed_callbacks.erase(delayed_callbacks.begin(), delayed_callbacks.end()); |
- |
- for (std::map<nacl::string, nacl::DescWrapper*>::iterator |
- i = linker_resource_fds_.begin(), e = linker_resource_fds_.end(); |
- i != e; |
- ++i) { |
- delete i->second; |
- } |
- linker_resource_fds_.clear(); |
-} |
- |
-void PnaclCoordinator::ReportLoadAbort() { |
- instance_->ReportLoadAbort(); |
-} |
- |
-void PnaclCoordinator::ReportLoadError(const ErrorInfo& error) { |
- instance_->ReportLoadError(error); |
-} |
- |
-void PnaclCoordinator::PnaclPpapiError(int32_t pp_error) { |
- // Attempt to free all the intermediate callbacks we ever created. |
- callback_factory_.CancelAll(); |
- translate_notify_callback_.Run(pp_error); |
-} |
- |
-void PnaclCoordinator::PnaclNonPpapiError() { |
- PnaclPpapiError(PP_ERROR_FAILED); |
-} |
- |
-void PnaclCoordinator::PnaclDidFinish(int32_t pp_error) { |
- PLUGIN_PRINTF(("PnaclCoordinator::PnaclDidFinish (pp_error=%" |
- NACL_PRId32")\n", pp_error)); |
- translate_notify_callback_.Run(pp_error); |
-} |
- |
-////////////////////////////////////////////////////////////////////// |
- |
-DelayedCallback* |
-PnaclCoordinator::MakeDelayedCallback(pp::CompletionCallback cb, |
- uint32_t num_deps) { |
- DelayedCallback* delayed_callback = new DelayedCallback(cb, num_deps); |
- delayed_callbacks.insert(delayed_callback); |
- return delayed_callback; |
-} |
- |
-void PnaclCoordinator::SetObjectFile(NaClSrpcImcDescType fd, int32_t len) { |
- obj_fd_.reset(instance_->wrapper_factory()->MakeGeneric(fd)); |
- obj_len_ = len; |
-} |
- |
-void PnaclCoordinator::SetTranslatedFile(NaClSrpcImcDescType fd) { |
- translated_fd_.reset(instance_->wrapper_factory()->MakeGeneric(fd)); |
-} |
- |
-int32_t PnaclCoordinator::GetLoadedFileDesc(int32_t pp_error, |
- const nacl::string& url, |
- const nacl::string& component) { |
- ErrorInfo error_info; |
- int32_t file_desc = instance_->GetPOSIXFileDesc(url); |
- if (pp_error != PP_OK || file_desc == NACL_NO_FILE_DESC) { |
- if (pp_error == PP_ERROR_ABORTED) { |
- ReportLoadAbort(); |
- } else { |
- // TODO(jvoung): Make a generic load error, or just use ERROR_UNKNOWN? |
- error_info.SetReport(ERROR_UNKNOWN, |
- "PNaCl " + component + " load failed."); |
- ReportLoadError(error_info); |
- } |
- return -1; |
- } |
- int32_t file_desc_ok_to_close = DUP(file_desc); |
- if (file_desc_ok_to_close == NACL_NO_FILE_DESC) { |
- // TODO(jvoung): Make a generic load error, or just use ERROR_UNKNOWN? |
- error_info.SetReport(ERROR_UNKNOWN, |
- "PNaCl " + component + " load failed: " |
- "could not dup fd."); |
- ReportLoadError(error_info); |
- return -1; |
- } |
- return file_desc_ok_to_close; |
-} |
- |
-NaClSubprocessId PnaclCoordinator::HelperNexeDidLoad(int32_t fd, |
- ErrorInfo* error_info) { |
- // Inform JavaScript that we successfully loaded a helper nexe. |
- instance_->EnqueueProgressEvent("progress", |
- Plugin::LENGTH_IS_NOT_COMPUTABLE, |
- Plugin::kUnknownBytes, |
- Plugin::kUnknownBytes); |
- nacl::scoped_ptr<nacl::DescWrapper> |
- wrapper(instance_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY)); |
- |
- return instance_->LoadHelperNaClModule(wrapper.get(), error_info); |
-} |
- |
-////////////////////////////////////////////////////////////////////// |
-// First few callbacks. |
- |
-void PnaclCoordinator::LLCReady(int32_t pp_error, |
- const nacl::string& llc_url, |
- DelayedCallback* delayed_callback) { |
- // pp_error is checked by GetLoadedFileDesc. |
- int32_t file_desc_ok_to_close = GetLoadedFileDesc(pp_error, llc_url, "llc"); |
- ErrorInfo error_info; |
- if (file_desc_ok_to_close < 0) { |
- PnaclPpapiError(pp_error); |
- return; |
- } |
- NaClSubprocessId llc_id = |
- HelperNexeDidLoad(file_desc_ok_to_close, &error_info); |
- PLUGIN_PRINTF(("PnaclCoordinator::LLCReady (pp_error=%" |
- NACL_PRId32" nexe_id=%" |
- NACL_PRId32")\n", |
- pp_error, |
- llc_id)); |
- if (kInvalidNaClSubprocessId == llc_id) { |
- error_info.SetReport(ERROR_UNKNOWN, |
- "Could not load pnacl compiler nexe"); |
- ReportLoadError(error_info); |
- PnaclNonPpapiError(); |
- return; |
- } |
- llc_subprocess_ = instance_ ->nacl_subprocess(llc_id); |
- delayed_callback->RunIfTime(); |
-} |
- |
-void PnaclCoordinator::LDReady(int32_t pp_error, |
- const nacl::string& ld_url, |
- DelayedCallback* delayed_callback) { |
- // pp_error is checked by GetLoadedFileDesc. |
- int32_t file_desc_ok_to_close = GetLoadedFileDesc(pp_error, ld_url, "ld"); |
- ErrorInfo error_info; |
- if (file_desc_ok_to_close < 0) { |
- PnaclPpapiError(pp_error); |
- return; |
- } |
- NaClSubprocessId ld_id = |
- HelperNexeDidLoad(file_desc_ok_to_close, &error_info); |
- PLUGIN_PRINTF(("PnaclCoordinator::LDReady (pp_error=%" |
- NACL_PRId32" nexe_id=%" |
- NACL_PRId32")\n", |
- pp_error, |
- ld_id)); |
- if (kInvalidNaClSubprocessId == ld_id) { |
- error_info.SetReport(ERROR_UNKNOWN, |
- "Could not load pnacl linker nexe"); |
- ReportLoadError(error_info); |
- PnaclNonPpapiError(); |
- return; |
- } |
- ld_subprocess_ = instance_ ->nacl_subprocess(ld_id); |
- delayed_callback->RunIfTime(); |
-} |
- |
-void PnaclCoordinator::PexeReady(int32_t pp_error, |
- const nacl::string& pexe_url, |
- DelayedCallback* delayed_callback) { |
- PLUGIN_PRINTF(("PnaclCoordinator::PexeReady (pp_error=%" |
- NACL_PRId32")\n", pp_error)); |
- // pp_error is checked by GetLoadedFileDesc. |
- int32_t fd = GetLoadedFileDesc(pp_error, pexe_url, "pexe"); |
- if (fd < 0) { |
- PnaclPpapiError(pp_error); |
- } else { |
- pexe_fd_.reset(instance_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY)); |
- delayed_callback->RunIfTime(); |
- } |
-} |
- |
-void PnaclCoordinator::LinkResourceReady(int32_t pp_error, |
- const nacl::string& url, |
- DelayedCallback* delayed_callback) { |
- PLUGIN_PRINTF(("PnaclCoordinator::LinkResourceReady (pp_error=%" |
- NACL_PRId32", url=%s)\n", pp_error, url.c_str())); |
- // pp_error is checked by GetLoadedFileDesc. |
- int32_t fd = GetLoadedFileDesc(pp_error, url, "linker resource " + url); |
- if (fd < 0) { |
- PnaclPpapiError(pp_error); |
- } else { |
- linker_resource_fds_[url] = |
- instance_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY); |
- delayed_callback->RunIfTime(); |
- } |
-} |
- |
-////////////////////////////////////////////////////////////////////// |
- |
-namespace { |
-void AbortTranslateThread(DoTranslateArgs* args, |
- const nacl::string& error_string) { |
- pp::Core* core = pp::Module::Get()->core(); |
- args->error_info.SetReport(ERROR_UNKNOWN, error_string); |
- core->CallOnMainThread(0, args->finish_cb, PP_ERROR_FAILED); |
- NaClThreadExit(1); |
-} |
-} // namespace |
- |
-void WINAPI DoTranslateThread(void* arg) { |
- DoTranslateArgs* p = reinterpret_cast<DoTranslateArgs*>(arg); |
- NaClSubprocess* llc_subprocess = p->subprocess; |
- |
- // Set up LLC flags first. |
- // TODO(jvoung): Bake these into the llc nexe? |
- // May also want to improve scriptability, but the only thing we need |
- // probably is PIC vs non-PIC and micro-arch specification. |
- const char* llc_args_x8632[] = { "-march=x86", |
- "-mcpu=pentium4", |
- "-mtriple=i686-none-linux-gnu", |
- "-asm-verbose=false", |
- "-filetype=obj" }; |
- const char* llc_args_x8664[] = { "-march=x86-64", |
- "-mcpu=core2", |
- "-mtriple=x86_64-none-linux-gnu", |
- "-asm-verbose=false", |
- "-filetype=obj" }; |
- const char* llc_args_arm[] = { "-march=arm", |
- "-mcpu=cortex-a8", |
- "-mtriple=armv7a-none-linux-gnueabi", |
- "-asm-verbose=false", |
- "-filetype=obj", |
- "-arm-reserve-r9", |
- "-sfi-disable-cp", |
- "-arm_static_tls", |
- "-sfi-store -sfi-stack -sfi-branch -sfi-data", |
- "-no-inline-jumptables" }; |
- |
- nacl::string sandbox_isa = GetSandboxISA(); |
- const char** llc_args; |
- size_t num_args; |
- |
- if (sandbox_isa.compare("x86-32") == 0) { |
- llc_args = llc_args_x8632; |
- num_args = NACL_ARRAY_SIZE(llc_args_x8632); |
- } else if (sandbox_isa.compare("x86-64") == 0) { |
- llc_args = llc_args_x8664; |
- num_args = NACL_ARRAY_SIZE(llc_args_x8664); |
- } else if (sandbox_isa.compare("arm") == 0) { |
- llc_args = llc_args_arm; |
- num_args = NACL_ARRAY_SIZE(llc_args_arm); |
- } else { |
- AbortTranslateThread(p, |
- "PnaclCoordinator compiler unhandled ISA " + |
- sandbox_isa + "."); |
- return; |
- } |
- |
- for (uint32_t i = 0; i < num_args; i++) { |
- if (p->should_die) { |
- NaClThreadExit(1); |
- } |
- SrpcParams dummy_params; |
- if (!PnaclSrpcLib::InvokeSrpcMethod(p->browser, |
- llc_subprocess, |
- "AddArg", |
- "C", |
- &dummy_params, |
- llc_args[i])) { |
- AbortTranslateThread(p, |
- "PnaclCoordinator compiler AddArg(" + |
- nacl::string(llc_args[i]) + ") failed."); |
- } |
- } |
- |
- if (p->should_die) { |
- NaClThreadExit(1); |
- } |
- SrpcParams params; |
- if (!PnaclSrpcLib::InvokeSrpcMethod(p->browser, |
- llc_subprocess, |
- "Translate", |
- "h", |
- ¶ms, |
- p->pexe_fd->desc())) { |
- AbortTranslateThread(p, |
- "PnaclCoordinator compile failed."); |
- } else { |
- // Grab the outparams. |
- p->obj_fd = params.outs()[0]->u.hval; |
- p->obj_len = params.outs()[1]->u.ival; |
- PLUGIN_PRINTF(("PnaclCoordinator::InvokeTranslate succeeded (bytes=%" |
- NACL_PRId32")\n", p->obj_len)); |
- } |
- if (p->should_die) { |
- NaClThreadExit(1); |
- } |
- pp::Core* core = pp::Module::Get()->core(); |
- core->CallOnMainThread(0, p->finish_cb, PP_OK); |
- NaClThreadExit(0); |
-} |
- |
-void |
-PnaclCoordinator::RunTranslateDidFinish(int32_t pp_error, |
- DelayedCallback* delayed_callback) { |
- PLUGIN_PRINTF(("PnaclCoordinator::RunTranslateDidFinish (pp_error=%" |
- NACL_PRId32")\n", pp_error)); |
- if (pp_error != PP_OK) { |
- ReportLoadError(translate_args_->error_info); |
- PnaclPpapiError(pp_error); |
- return; |
- } |
- SetObjectFile(translate_args_->obj_fd, translate_args_->obj_len); |
- instance_->EnqueueProgressEvent("progress", |
- Plugin::LENGTH_IS_NOT_COMPUTABLE, |
- Plugin::kUnknownBytes, |
- Plugin::kUnknownBytes); |
- delayed_callback->RunIfTime(); |
-} |
- |
-void PnaclCoordinator::RunTranslate(int32_t pp_error, |
- DelayedCallback* delayed_callback) { |
- PLUGIN_PRINTF(("PnaclCoordinator::RunTranslate (pp_error=%" |
- NACL_PRId32")\n", pp_error)); |
- assert(PP_OK == pp_error); |
- |
- // Invoke llvm asynchronously. |
- pp::CompletionCallback finish_cb = |
- callback_factory_.NewCallback(&PnaclCoordinator::RunTranslateDidFinish, |
- delayed_callback); |
- translate_args_.reset(new DoTranslateArgs(llc_subprocess_, |
- instance_->browser_interface(), |
- finish_cb, |
- pexe_fd_.get())); |
- translate_thread_.reset(new NaClThread); |
- if (translate_thread_ != NULL && translate_args_ != NULL) { |
- if (!NaClThreadCreateJoinable(translate_thread_.get(), |
- DoTranslateThread, |
- translate_args_.get(), |
- kArbitraryStackSize)) { |
- ErrorInfo error_info; |
- error_info.SetReport(ERROR_UNKNOWN, |
- "Could not create a translator thread.\n"); |
- ReportLoadError(error_info); |
- PnaclNonPpapiError(); |
- } |
- } else { |
- ErrorInfo error_info; |
- error_info.SetReport(ERROR_UNKNOWN, |
- "Could not allocate DoTranslateThread()\n"); |
- ReportLoadError(error_info); |
- PnaclNonPpapiError(); |
- } |
-} |
- |
-////////////////////////////////////////////////////////////////////// |
-// Helper functions for loading native libs. |
-// Done here to avoid hacking on the manifest parser further... |
- |
-namespace { |
- |
-// Fake filename for the object file generated by llvm. |
-const nacl::string kGeneratedObjectFileName = |
- nacl::string("___PNACL_GENERATED"); |
- |
-string_vector LinkResources(const nacl::string& sandbox_isa, |
- bool withGenerated) { |
- string_vector results; |
- nacl::string base_dir = "pnacl_support/" + sandbox_isa; |
- |
- // NOTE: order of items == link order. |
- if (withGenerated) { |
- results.push_back(kGeneratedObjectFileName); |
- } |
- results.push_back(base_dir + "/libcrt_platform.a"); |
- results.push_back(base_dir + "/libgcc.a"); |
- results.push_back(base_dir + "/libgcc_eh.a"); |
- return results; |
-} |
- |
-} // namespace |
- |
-////////////////////////////////////////////////////////////////////// |
-// Final link callbacks. |
- |
-namespace { |
- |
-void AbortLinkThread(DoLinkArgs* args, const nacl::string& error_string) { |
- ErrorInfo error_info; |
- pp::Core* core = pp::Module::Get()->core(); |
- args->error_info.SetReport(ERROR_UNKNOWN, error_string); |
- core->CallOnMainThread(0, args->finish_cb, PP_ERROR_FAILED); |
- NaClThreadExit(1); |
-} |
- |
-} // namespace |
- |
-void WINAPI DoLinkThread(void* arg) { |
- DoLinkArgs* p = reinterpret_cast<DoLinkArgs*>(arg); |
- NaClSubprocess* ld_subprocess = p->subprocess; |
- |
- // Set up command line arguments (flags then files). |
- |
- //// Flags. |
- // TODO(jvoung): Be able to handle the dynamic linking flags too, |
- // and don't hardcode so much here. |
- string_vector flags; |
- nacl::string sandbox_isa = GetSandboxISA(); |
- flags.push_back("-nostdlib"); |
- flags.push_back("-m"); |
- if (sandbox_isa.compare("x86-32") == 0) { |
- flags.push_back("elf_nacl"); |
- } else if (sandbox_isa.compare("x86-64") == 0) { |
- flags.push_back("elf64_nacl"); |
- } else if (sandbox_isa.compare("arm") == 0) { |
- flags.push_back("armelf_nacl"); |
- } else { |
- AbortLinkThread(p, |
- "PnaclCoordinator linker unhandled ISA " + |
- sandbox_isa + "."); |
- } |
- |
- for (string_vector::iterator i = flags.begin(), e = flags.end(); |
- i != e; ++i) { |
- const nacl::string& flag = *i; |
- if (p->should_die) { |
- NaClThreadExit(1); |
- } |
- SrpcParams dummy_params; |
- if (!PnaclSrpcLib::InvokeSrpcMethod(p->browser, |
- ld_subprocess, |
- "AddArg", |
- "C", |
- &dummy_params, |
- flag.c_str())) { |
- AbortLinkThread(p, |
- "PnaclCoordinator linker AddArg(" + flag + |
- ") failed."); |
- } |
- } |
- |
- //// Files. |
- PnaclCoordinator* pnacl = p->coordinator; |
- string_vector files = LinkResources(sandbox_isa, true); |
- for (string_vector::iterator i = files.begin(), e = files.end(); |
- i != e; ++i) { |
- const nacl::string& link_file = *i; |
- if (p->should_die) { |
- NaClThreadExit(1); |
- } |
- // Add as argument. |
- SrpcParams dummy_params; |
- if (!PnaclSrpcLib::InvokeSrpcMethod(p->browser, |
- ld_subprocess, |
- "AddArg", |
- "C", |
- &dummy_params, |
- link_file.c_str())) { |
- AbortLinkThread(p, |
- "PnaclCoordinator linker AddArg(" + |
- link_file + ") failed."); |
- } |
- // Also map the file name to descriptor. |
- if (i->compare(kGeneratedObjectFileName) == 0) { |
- SrpcParams dummy_params2; |
- if (!PnaclSrpcLib::InvokeSrpcMethod(p->browser, |
- ld_subprocess, |
- "AddFileWithSize", |
- "Chi", |
- &dummy_params2, |
- link_file.c_str(), |
- p->obj_fd->desc(), |
- p->obj_len)) { |
- AbortLinkThread(p, |
- "PnaclCoordinator linker AddFileWithSize" |
- "(" + link_file + ") failed."); |
- } |
- } else { |
- SrpcParams dummy_params2; |
- if (!PnaclSrpcLib::InvokeSrpcMethod(p->browser, |
- ld_subprocess, |
- "AddFile", |
- "Ch", |
- &dummy_params2, |
- link_file.c_str(), |
- pnacl->GetLinkerResourceFD( |
- link_file))) { |
- AbortLinkThread(p, |
- "PnaclCoordinator linker AddFile(" + link_file + |
- ") failed."); |
- } |
- } |
- } |
- |
- if (p->should_die) { |
- NaClThreadExit(1); |
- } |
- |
- // Finally, do the Link! |
- SrpcParams params; |
- if (!PnaclSrpcLib::InvokeSrpcMethod(p->browser, |
- ld_subprocess, |
- "Link", |
- "", |
- ¶ms)) { |
- AbortLinkThread(p, "PnaclCoordinator link failed."); |
- } else { |
- // Grab the outparams. |
- p->nexe_fd = params.outs()[0]->u.hval; |
- int32_t nexe_size = params.outs()[1]->u.ival; // only for debug. |
- PLUGIN_PRINTF(("PnaclCoordinator::InvokeLink succeeded (bytes=%" |
- NACL_PRId32")\n", nexe_size)); |
- } |
- if (p->should_die) { |
- NaClThreadExit(1); |
- } |
- pp::Core* core = pp::Module::Get()->core(); |
- core->CallOnMainThread(0, p->finish_cb, PP_OK); |
- NaClThreadExit(0); |
-} |
- |
-void PnaclCoordinator::RunLinkDidFinish(int32_t pp_error) { |
- PLUGIN_PRINTF(("PnaclCoordinator::RunLinkDidFinish (pp_error=%" |
- NACL_PRId32")\n", pp_error)); |
- if (pp_error != PP_OK) { |
- ReportLoadError(link_args_->error_info); |
- PnaclPpapiError(pp_error); |
- return; |
- } |
- SetTranslatedFile(link_args_->nexe_fd); |
- instance_->EnqueueProgressEvent("progress", |
- Plugin::LENGTH_IS_NOT_COMPUTABLE, |
- Plugin::kUnknownBytes, |
- Plugin::kUnknownBytes); |
- PnaclDidFinish(PP_OK); |
-} |
- |
-void PnaclCoordinator::RunLink(int32_t pp_error) { |
- PLUGIN_PRINTF(("PnaclCoordinator::RunLink (pp_error=%" |
- NACL_PRId32")\n", pp_error)); |
- assert(PP_OK == pp_error); |
- |
- // Invoke llvm asynchronously. |
- pp::CompletionCallback finish_cb = |
- callback_factory_.NewCallback(&PnaclCoordinator::RunLinkDidFinish); |
- link_args_.reset(new DoLinkArgs(ld_subprocess_, |
- instance_->browser_interface(), |
- finish_cb, |
- this, |
- obj_fd_.get(), |
- obj_len_)); |
- link_thread_.reset(new NaClThread); |
- if (link_args_ != NULL && link_thread_ != NULL) { |
- if (!NaClThreadCreateJoinable(link_thread_.get(), |
- DoLinkThread, |
- link_args_.get(), |
- kArbitraryStackSize)) { |
- ErrorInfo error_info; |
- error_info.SetReport(ERROR_UNKNOWN, |
- "Could not create a linker thread.\n"); |
- ReportLoadError(error_info); |
- PnaclNonPpapiError(); |
- } |
- } else { |
- ErrorInfo error_info; |
- error_info.SetReport(ERROR_UNKNOWN, |
- "Could not allocate DoLinkThread()\n"); |
- ReportLoadError(error_info); |
- PnaclNonPpapiError(); |
- } |
-} |
- |
-////////////////////////////////////////////////////////////////////// |
- |
-bool PnaclCoordinator::ScheduleDownload(const nacl::string& url, |
- const pp::CompletionCallback& cb) { |
- if (!instance_->StreamAsFile(url, |
- cb.pp_completion_callback())) { |
- ErrorInfo error_info; |
- error_info.SetReport(ERROR_UNKNOWN, |
- "PnaclCoordinator: Failed to download file: " + |
- url + "\n"); |
- ReportLoadError(error_info); |
- PnaclNonPpapiError(); |
- return false; |
- } |
- return true; |
-} |
- |
-void PnaclCoordinator::AddDownloadToDelayedCallback( |
- void (PnaclCoordinator::*handler)(int32_t, |
- const nacl::string&, |
- DelayedCallback*), |
- DelayedCallback* delayed_callback, |
- const nacl::string& url, |
- std::vector<url_callback_pair>& queue) { |
- // Queue up the URL download w/ a callback that invokes the delayed_callback. |
- queue.push_back(std::make_pair( |
- url, |
- callback_factory_.NewCallback(handler, |
- url, |
- delayed_callback))); |
- delayed_callback->IncrRequirements(1); |
-} |
- |
-void PnaclCoordinator::BitcodeToNative( |
- const nacl::string& pexe_url, |
- const nacl::string& llc_url, |
- const nacl::string& ld_url, |
- const pp::CompletionCallback& finish_callback) { |
- PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (pexe=%s, llc=%s, ld=%s)\n", |
- pexe_url.c_str(), |
- llc_url.c_str(), |
- ld_url.c_str())); |
- translate_notify_callback_ = finish_callback; |
- |
- string_vector link_resources = LinkResources(GetSandboxISA(), false); |
- |
- // Steps: |
- // (1) Schedule downloads for llc, ld nexes, and native libraries. |
- // (2) When llc download and pexe has completed, run the translation. |
- // (3) When llc translation has finished, and ld, native libs are available, |
- // do the link. |
- // (4) When the link is done, we are done, call the finish_callback. |
- // Hand off the SHM file descriptor returned by link. |
- |
- // Set up async callbacks for these steps in reverse order. |
- |
- // (3) Run link. |
- |
- pp::CompletionCallback run_link_callback = |
- callback_factory_.NewCallback(&PnaclCoordinator::RunLink); |
- DelayedCallback* delayed_link_callback = |
- MakeDelayedCallback(run_link_callback, 0); |
- |
- // (2) Run translation. |
- pp::CompletionCallback run_translate_callback = |
- callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate, |
- delayed_link_callback); |
- // Linking depends on the compile finishing, so incr requirements by one. |
- delayed_link_callback->IncrRequirements(1); |
- |
- DelayedCallback* delayed_translate_callback = MakeDelayedCallback( |
- run_translate_callback, 0); |
- |
- // (1) Load nexes and assets using StreamAsFile(). This will kick off |
- // the whole process. |
- |
- // First, just collect the list of stuff to download. |
- std::vector<url_callback_pair> downloads; |
- |
- AddDownloadToDelayedCallback(&PnaclCoordinator::PexeReady, |
- delayed_translate_callback, |
- pexe_url, |
- downloads); |
- AddDownloadToDelayedCallback(&PnaclCoordinator::LLCReady, |
- delayed_translate_callback, |
- llc_url, |
- downloads); |
- AddDownloadToDelayedCallback(&PnaclCoordinator::LDReady, |
- delayed_link_callback, |
- ld_url, |
- downloads); |
- for (string_vector::iterator |
- i = link_resources.begin(), e = link_resources.end(); |
- i != e; |
- ++i) { |
- AddDownloadToDelayedCallback(&PnaclCoordinator::LinkResourceReady, |
- delayed_link_callback, |
- *i, |
- downloads); |
- } |
- |
- // Finally, actually schedule the downloads. |
- for (size_t i = 0; i < downloads.size(); ++i) { |
- if (!ScheduleDownload(downloads[i].first, downloads[i].second)) { |
- break; // error should have been reported by ScheduleDownload. |
- } |
- } |
- downloads.clear(); |
- |
- return; |
-} |
- |
-} // namespace plugin |