| Index: ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc
|
| diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..84960b713d89982bd2e017d12251443ada2243c0
|
| --- /dev/null
|
| +++ b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc
|
| @@ -0,0 +1,177 @@
|
| +// Copyright (c) 2012 The Chromium 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_translate_thread.h"
|
| +
|
| +#include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
|
| +#include "native_client/src/trusted/plugin/plugin.h"
|
| +#include "native_client/src/trusted/plugin/pnacl_resources.h"
|
| +#include "native_client/src/trusted/plugin/srpc_params.h"
|
| +#include "native_client/src/trusted/plugin/utility.h"
|
| +
|
| +namespace plugin {
|
| +
|
| +PnaclTranslateThread::PnaclTranslateThread() : subprocesses_should_die_(false),
|
| + manifest_(NULL),
|
| + obj_file_(NULL),
|
| + nexe_file_(NULL),
|
| + pexe_wrapper_(NULL),
|
| + error_info_(NULL),
|
| + resources_(NULL),
|
| + plugin_(NULL) {
|
| + NaClXMutexCtor(&subprocess_mu_);
|
| +}
|
| +
|
| +void PnaclTranslateThread::RunTranslate(pp::CompletionCallback finish_callback,
|
| + const Manifest* manifest,
|
| + const Manifest* ld_manifest,
|
| + LocalTempFile* obj_file,
|
| + LocalTempFile* nexe_file,
|
| + nacl::DescWrapper* pexe_wrapper,
|
| + ErrorInfo* error_info,
|
| + PnaclResources* resources,
|
| + Plugin* plugin) {
|
| + PLUGIN_PRINTF(("PnaclTranslateThread::RunTranslate)\n"));
|
| + manifest_ = manifest;
|
| + ld_manifest_ = ld_manifest;
|
| + obj_file_ = obj_file;
|
| + nexe_file_ = nexe_file;
|
| + pexe_wrapper_ = pexe_wrapper;
|
| + error_info_ = error_info;
|
| + resources_ = resources;
|
| + plugin_ = plugin;
|
| +
|
| + // Invoke llc followed by ld off the main thread. This allows use of
|
| + // blocking RPCs that would otherwise block the JavaScript main thread.
|
| + report_translate_finished_ = finish_callback;
|
| + translate_thread_.reset(new NaClThread);
|
| + if (translate_thread_ == NULL) {
|
| + TranslateFailed("could not allocate thread struct.");
|
| + return;
|
| + }
|
| + const int32_t kArbitraryStackSize = 128 * 1024;
|
| + if (!NaClThreadCreateJoinable(translate_thread_.get(),
|
| + DoTranslateThread,
|
| + this,
|
| + kArbitraryStackSize)) {
|
| + TranslateFailed("could not create thread.");
|
| + }
|
| +}
|
| +
|
| +NaClSubprocess* PnaclTranslateThread::StartSubprocess(
|
| + const nacl::string& url_for_nexe,
|
| + const Manifest* manifest) {
|
| + PLUGIN_PRINTF(("PnaclTranslateThread::StartSubprocess (url_for_nexe=%s)\n",
|
| + url_for_nexe.c_str()));
|
| + nacl::DescWrapper* wrapper = resources_->WrapperForUrl(url_for_nexe);
|
| + nacl::scoped_ptr<NaClSubprocess> subprocess(
|
| + plugin_->LoadHelperNaClModule(wrapper, manifest, error_info_));
|
| + if (subprocess.get() == NULL) {
|
| + PLUGIN_PRINTF((
|
| + "PnaclTranslateThread::StartSubprocess: subprocess creation failed\n"));
|
| + return NULL;
|
| + }
|
| + return subprocess.release();
|
| +}
|
| +
|
| +void WINAPI PnaclTranslateThread::DoTranslateThread(void* arg) {
|
| + PnaclTranslateThread* translator =
|
| + reinterpret_cast<PnaclTranslateThread*>(arg);
|
| + nacl::scoped_ptr<NaClSubprocess> llc_subprocess(
|
| + translator->StartSubprocess(PnaclUrls::GetLlcUrl(),
|
| + translator->manifest_));
|
| + if (llc_subprocess == NULL) {
|
| + translator->TranslateFailed("Compile process could not be created.");
|
| + return;
|
| + }
|
| + // Run LLC.
|
| + SrpcParams params;
|
| + nacl::DescWrapper* llc_out_file = translator->obj_file_->write_wrapper();
|
| + PluginReverseInterface* llc_reverse =
|
| + llc_subprocess->service_runtime()->rev_interface();
|
| + llc_reverse->AddQuotaManagedFile(translator->obj_file_->identifier(),
|
| + translator->obj_file_->write_file_io());
|
| + if (!llc_subprocess->InvokeSrpcMethod("RunWithDefaultCommandLine",
|
| + "hh",
|
| + ¶ms,
|
| + translator->pexe_wrapper_->desc(),
|
| + llc_out_file->desc())) {
|
| + translator->TranslateFailed("compile failed.");
|
| + return;
|
| + }
|
| + // LLC returns values that are used to determine how linking is done.
|
| + int is_shared_library = (params.outs()[0]->u.ival != 0);
|
| + nacl::string soname = params.outs()[1]->arrays.str;
|
| + nacl::string lib_dependencies = params.outs()[2]->arrays.str;
|
| + PLUGIN_PRINTF(("PnaclCoordinator: compile (translator=%p) succeeded"
|
| + " is_shared_library=%d, soname='%s', lib_dependencies='%s')\n",
|
| + arg, is_shared_library, soname.c_str(),
|
| + lib_dependencies.c_str()));
|
| + // Shut down the llc subprocess.
|
| + llc_subprocess.reset(NULL);
|
| + if (translator->SubprocessesShouldDie()) {
|
| + translator->TranslateFailed("stopped by coordinator.");
|
| + return;
|
| + }
|
| + nacl::scoped_ptr<NaClSubprocess> ld_subprocess(
|
| + translator->StartSubprocess(PnaclUrls::GetLdUrl(),
|
| + translator->ld_manifest_));
|
| + if (ld_subprocess == NULL) {
|
| + translator->TranslateFailed("Link process could not be created.");
|
| + return;
|
| + }
|
| + // Run LD.
|
| + nacl::DescWrapper* ld_in_file = translator->obj_file_->read_wrapper();
|
| + nacl::DescWrapper* ld_out_file = translator->nexe_file_->write_wrapper();
|
| + PluginReverseInterface* ld_reverse =
|
| + ld_subprocess->service_runtime()->rev_interface();
|
| + ld_reverse->AddQuotaManagedFile(translator->nexe_file_->identifier(),
|
| + translator->nexe_file_->write_file_io());
|
| + if (!ld_subprocess->InvokeSrpcMethod("RunWithDefaultCommandLine",
|
| + "hhiCC",
|
| + ¶ms,
|
| + ld_in_file->desc(),
|
| + ld_out_file->desc(),
|
| + is_shared_library,
|
| + soname.c_str(),
|
| + lib_dependencies.c_str())) {
|
| + translator->TranslateFailed("link failed.");
|
| + return;
|
| + }
|
| + PLUGIN_PRINTF(("PnaclCoordinator: link (translator=%p) succeeded\n", arg));
|
| + // Shut down the ld subprocess.
|
| + ld_subprocess.reset(NULL);
|
| + if (translator->SubprocessesShouldDie()) {
|
| + translator->TranslateFailed("stopped by coordinator.");
|
| + return;
|
| + }
|
| + pp::Core* core = pp::Module::Get()->core();
|
| + core->CallOnMainThread(0, translator->report_translate_finished_, PP_OK);
|
| +}
|
| +
|
| +void PnaclTranslateThread::TranslateFailed(const nacl::string& error_string) {
|
| + PLUGIN_PRINTF(("PnaclTranslateThread::TranslateFailed (error_string='%s')\n",
|
| + error_string.c_str()));
|
| + pp::Core* core = pp::Module::Get()->core();
|
| + error_info_->SetReport(ERROR_UNKNOWN,
|
| + nacl::string("PnaclCoordinator: ") + error_string);
|
| + core->CallOnMainThread(0, report_translate_finished_, PP_ERROR_FAILED);
|
| +}
|
| +
|
| +bool PnaclTranslateThread::SubprocessesShouldDie() {
|
| + nacl::MutexLocker ml(&subprocess_mu_);
|
| + return subprocesses_should_die_;
|
| +}
|
| +
|
| +void PnaclTranslateThread::SetSubprocessesShouldDie(
|
| + bool subprocesses_should_die) {
|
| + nacl::MutexLocker ml(&subprocess_mu_);
|
| + subprocesses_should_die_ = subprocesses_should_die;
|
| +}
|
| +
|
| +PnaclTranslateThread::~PnaclTranslateThread() {
|
| + NaClMutexDtor(&subprocess_mu_);
|
| +}
|
| +
|
| +} // namespace plugin
|
|
|