summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ppapi/native_client/src/trusted/plugin/build.scons1
-rw-r--r--ppapi/native_client/src/trusted/plugin/plugin.gypi1
-rw-r--r--ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc393
-rw-r--r--ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h155
-rw-r--r--ppapi/native_client/src/trusted/plugin/pnacl_resources.cc119
-rw-r--r--ppapi/native_client/src/trusted/plugin/pnacl_resources.h78
6 files changed, 362 insertions, 385 deletions
diff --git a/ppapi/native_client/src/trusted/plugin/build.scons b/ppapi/native_client/src/trusted/plugin/build.scons
index 40828d8..15c6f71 100644
--- a/ppapi/native_client/src/trusted/plugin/build.scons
+++ b/ppapi/native_client/src/trusted/plugin/build.scons
@@ -67,6 +67,7 @@ common_inputs = [
'nexe_arch.cc',
'plugin.cc',
'pnacl_coordinator.cc',
+ 'pnacl_resources.cc',
'pnacl_srpc_lib.cc',
'scriptable_handle.cc',
'service_runtime.cc',
diff --git a/ppapi/native_client/src/trusted/plugin/plugin.gypi b/ppapi/native_client/src/trusted/plugin/plugin.gypi
index 4aa6900..94cc158 100644
--- a/ppapi/native_client/src/trusted/plugin/plugin.gypi
+++ b/ppapi/native_client/src/trusted/plugin/plugin.gypi
@@ -16,6 +16,7 @@
'nexe_arch.cc',
'plugin.cc',
'pnacl_coordinator.cc',
+ 'pnacl_resources.cc',
'pnacl_srpc_lib.cc',
'scriptable_handle.cc',
'service_runtime.cc',
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
index a402aed..9a947fa 100644
--- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
+++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
@@ -9,6 +9,7 @@
#include "native_client/src/include/portability_io.h"
#include "native_client/src/shared/platform/nacl_check.h"
+#include "native_client/src/shared/platform/nacl_sync_raii.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"
@@ -32,11 +33,6 @@ namespace plugin {
class Plugin;
-void PnaclResources::AddFDForUrl(const nacl::string& url, int32_t fd) {
- resource_wrappers_[url] =
- plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY);
-}
-
void PnaclCoordinator::Initialize(Plugin* plugin) {
PLUGIN_PRINTF(("PnaclCoordinator::Initialize (this=%p)\n",
static_cast<void*>(this)));
@@ -44,7 +40,8 @@ void PnaclCoordinator::Initialize(Plugin* plugin) {
CHECK(plugin_ == NULL); // Can only initialize once.
plugin_ = plugin;
callback_factory_.Initialize(this);
- resources_.reset(new PnaclResources(plugin));
+ resources_.reset(new PnaclResources(plugin, this));
+ resources_->Initialize();
}
PnaclCoordinator::~PnaclCoordinator() {
@@ -62,9 +59,6 @@ PnaclCoordinator::~PnaclCoordinator() {
if (link_thread_.get() != NULL) {
NaClThreadJoin(link_thread_.get());
}
-
- // Delete all delayed_callbacks.
- delayed_callbacks.erase(delayed_callbacks.begin(), delayed_callbacks.end());
}
void PnaclCoordinator::ReportLoadAbort() {
@@ -87,22 +81,21 @@ void PnaclCoordinator::PnaclNonPpapiError() {
void PnaclCoordinator::PnaclDidFinish(int32_t pp_error,
PnaclTranslationUnit* translation_unit) {
- UNREFERENCED_PARAMETER(translation_unit);
PLUGIN_PRINTF(("PnaclCoordinator::PnaclDidFinish (pp_error=%"
NACL_PRId32")\n", pp_error));
+ if (pp_error != PP_OK) {
+ ReportLoadError(translation_unit->error_info);
+ PnaclPpapiError(pp_error);
+ return;
+ }
+ // Transfer ownership of the nexe wrapper to the coordinator.
+ translated_fd_.reset(translation_unit->nexe_wrapper.release());
+ plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress);
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;
-}
-
int32_t PnaclCoordinator::GetLoadedFileDesc(int32_t pp_error,
const nacl::string& url,
const nacl::string& component) {
@@ -131,108 +124,52 @@ int32_t PnaclCoordinator::GetLoadedFileDesc(int32_t pp_error,
return file_desc_ok_to_close;
}
-NaClSubprocessId PnaclCoordinator::HelperNexeDidLoad(int32_t fd,
- ErrorInfo* error_info) {
- // Inform JavaScript that we successfully loaded a helper nexe.
- plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress);
- nacl::scoped_ptr<nacl::DescWrapper>
- wrapper(plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY));
-
- return plugin_->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");
+bool PnaclCoordinator::StartLlcSubProcess() {
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));
+ nacl::DescWrapper* wrapper = resources_->WrapperForUrl(llc_url_);
+ NaClSubprocessId llc_id = plugin_->LoadHelperNaClModule(wrapper, &error_info);
+ PLUGIN_PRINTF(("PnaclCoordinator::StartLlcSubProcess (nexe_id=%"
+ NACL_PRId32")\n", llc_id));
if (kInvalidNaClSubprocessId == llc_id) {
- error_info.SetReport(ERROR_UNKNOWN,
- "Could not load pnacl compiler nexe");
+ error_info.SetReport(ERROR_UNKNOWN, "Could not load pnacl compiler nexe");
ReportLoadError(error_info);
PnaclNonPpapiError();
- return;
+ return NULL;
}
- llc_subprocess_ = plugin_ ->nacl_subprocess(llc_id);
- delayed_callback->RunIfTime();
+ llc_subprocess_ = plugin_->nacl_subprocess(llc_id);
+ return (llc_subprocess_ != NULL);
}
-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");
+bool PnaclCoordinator::StartLdSubProcess() {
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));
+ nacl::DescWrapper* wrapper = resources_->WrapperForUrl(ld_url_);
+ NaClSubprocessId ld_id = plugin_->LoadHelperNaClModule(wrapper, &error_info);
+ PLUGIN_PRINTF(("PnaclCoordinator::StartLdSubProcess (nexe_id=%"
+ NACL_PRId32")\n", ld_id));
if (kInvalidNaClSubprocessId == ld_id) {
- error_info.SetReport(ERROR_UNKNOWN,
- "Could not load pnacl linker nexe");
+ error_info.SetReport(ERROR_UNKNOWN, "Could not load pnacl linker nexe");
ReportLoadError(error_info);
PnaclNonPpapiError();
- return;
+ return NULL;
}
- ld_subprocess_ = plugin_ ->nacl_subprocess(ld_id);
- delayed_callback->RunIfTime();
+ ld_subprocess_ = plugin_->nacl_subprocess(ld_id);
+ return (ld_subprocess_ != NULL);
}
-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 {
- resources_->AddFDForUrl(url, fd);
- delayed_callback->RunIfTime();
- }
+bool PnaclCoordinator::SubprocessesShouldDie() {
+ nacl::MutexLocker ml(&subprocess_mu_);
+ return subprocesses_should_die_;
}
-void PnaclCoordinator::PexeReady(int32_t pp_error,
- const nacl::string& pexe_url,
- PnaclTranslationUnit* translation_unit,
- 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 {
- translation_unit->pexe_wrapper.reset(
- plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY));
- delayed_callback->RunIfTime();
- }
+void PnaclCoordinator::SetSubprocessesShouldDie(bool subprocesses_should_die) {
+ nacl::MutexLocker ml(&subprocess_mu_);
+ subprocesses_should_die_ = subprocesses_should_die;
}
//////////////////////////////////////////////////////////////////////
+// First few callbacks.
+
+//////////////////////////////////////////////////////////////////////
namespace {
void AbortTranslateThread(PnaclTranslationUnit* translation_unit,
@@ -353,52 +290,50 @@ void WINAPI DoTranslateThread(void* arg) {
} // namespace
-void
-PnaclCoordinator::RunTranslateDidFinish(int32_t pp_error,
- PnaclTranslationUnit* translation_unit,
- DelayedCallback* link_callback) {
- PLUGIN_PRINTF(("PnaclCoordinator::RunTranslateDidFinish (pp_error=%"
+void PnaclCoordinator::RunTranslate(int32_t pp_error,
+ const nacl::string& pexe_url,
+ PnaclTranslationUnit* translation_unit) {
+ PLUGIN_PRINTF(("PnaclCoordinator::RunTranslate (pp_error=%"
NACL_PRId32")\n", pp_error));
- if (pp_error != PP_OK) {
- ReportLoadError(translation_unit->error_info);
+ // pp_error is checked by GetLoadedFileDesc.
+ int32_t fd = GetLoadedFileDesc(pp_error, pexe_url, "pexe");
+ if (fd < 0) {
PnaclPpapiError(pp_error);
return;
}
- plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress);
- link_callback->RunIfTime();
-}
-
-void PnaclCoordinator::RunTranslate(int32_t pp_error,
- PnaclTranslationUnit* translation_unit,
- DelayedCallback* delayed_link_callback) {
- PLUGIN_PRINTF(("PnaclCoordinator::RunTranslate (pp_error=%"
- NACL_PRId32")\n", pp_error));
- assert(PP_OK == pp_error);
-
+ translation_unit->pexe_wrapper.reset(
+ plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY));
+ if (!StartLlcSubProcess()) {
+ ErrorInfo error_info;
+ error_info.SetReport(ERROR_UNKNOWN,
+ "Could not start compiler subprocess\n");
+ ReportLoadError(error_info);
+ PnaclNonPpapiError();
+ return;
+ }
// Invoke llvm asynchronously.
- // RunTranslateDidFinish runs on the main thread when llvm is done.
+ // RunLink runs on the main thread when llvm is done.
translation_unit->translate_done_cb =
- callback_factory_.NewCallback(&PnaclCoordinator::RunTranslateDidFinish,
- translation_unit,
- delayed_link_callback);
+ callback_factory_.NewCallback(&PnaclCoordinator::RunLink,
+ translation_unit);
translate_thread_.reset(new NaClThread);
- if (translate_thread_ != NULL) {
- if (!NaClThreadCreateJoinable(translate_thread_.get(),
- DoTranslateThread,
- translation_unit,
- kArbitraryStackSize)) {
- ErrorInfo error_info;
- error_info.SetReport(ERROR_UNKNOWN,
- "Could not create a translator thread.\n");
- ReportLoadError(error_info);
- PnaclNonPpapiError();
- }
- } else {
+ if (translate_thread_ == NULL) {
ErrorInfo error_info;
error_info.SetReport(ERROR_UNKNOWN,
"Could not allocate DoTranslateThread()\n");
ReportLoadError(error_info);
PnaclNonPpapiError();
+ return;
+ }
+ if (!NaClThreadCreateJoinable(translate_thread_.get(),
+ DoTranslateThread,
+ translation_unit,
+ kArbitraryStackSize)) {
+ ErrorInfo error_info;
+ error_info.SetReport(ERROR_UNKNOWN,
+ "Could not create a translator thread.\n");
+ ReportLoadError(error_info);
+ PnaclNonPpapiError();
}
}
@@ -531,13 +466,14 @@ void WINAPI DoLinkThread(void* arg) {
}
} else {
SrpcParams dummy_params2;
+ NaClDesc* link_file_desc = resources->WrapperForUrl(link_file)->desc();
if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
ld_subprocess,
"AddFile",
"Ch",
&dummy_params2,
link_file.c_str(),
- resources->DescForUrl(link_file))) {
+ link_file_desc)) {
AbortLinkThread(p,
"PnaclCoordinator linker AddFile(" + link_file +
") failed.");
@@ -575,101 +511,76 @@ void WINAPI DoLinkThread(void* arg) {
} // namespace
-void PnaclCoordinator::RunLinkDidFinish(
- int32_t pp_error,
- PnaclTranslationUnit* translation_unit) {
- PLUGIN_PRINTF(("PnaclCoordinator::RunLinkDidFinish (pp_error=%"
+void PnaclCoordinator::RunLink(int32_t pp_error,
+ PnaclTranslationUnit* translation_unit) {
+ PLUGIN_PRINTF(("PnaclCoordinator::RunLink (pp_error=%"
NACL_PRId32")\n", pp_error));
if (pp_error != PP_OK) {
ReportLoadError(translation_unit->error_info);
PnaclPpapiError(pp_error);
return;
}
- // Transfer ownership of the nexe wrapper to the coordinator.
- translated_fd_.reset(translation_unit->nexe_wrapper.release());
plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress);
- PnaclDidFinish(PP_OK, translation_unit);
-}
-
-void PnaclCoordinator::RunLink(int32_t pp_error,
- PnaclTranslationUnit* translation_unit) {
- PLUGIN_PRINTF(("PnaclCoordinator::RunLink (pp_error=%"
- NACL_PRId32")\n", pp_error));
- assert(PP_OK == pp_error);
+ if (!StartLdSubProcess()) {
+ ErrorInfo error_info;
+ error_info.SetReport(ERROR_UNKNOWN,
+ "Could not start linker subprocess\n");
+ ReportLoadError(error_info);
+ PnaclNonPpapiError();
+ return;
+ }
// Invoke ld asynchronously.
- // When ld has completed, RunLinkDidFinish is run on the main thread.
+ // When ld has completed, PnaclDidFinish is run on the main thread.
translation_unit->link_done_cb =
- callback_factory_.NewCallback(&PnaclCoordinator::RunLinkDidFinish,
+ callback_factory_.NewCallback(&PnaclCoordinator::PnaclDidFinish,
translation_unit);
link_thread_.reset(new NaClThread);
- if (link_thread_ != NULL) {
- if (!NaClThreadCreateJoinable(link_thread_.get(),
- DoLinkThread,
- translation_unit,
- kArbitraryStackSize)) {
- ErrorInfo error_info;
- error_info.SetReport(ERROR_UNKNOWN,
- "Could not create a linker thread.\n");
- ReportLoadError(error_info);
- PnaclNonPpapiError();
- }
- } else {
+ if (link_thread_ == NULL) {
ErrorInfo error_info;
error_info.SetReport(ERROR_UNKNOWN,
"Could not allocate DoLinkThread()\n");
ReportLoadError(error_info);
PnaclNonPpapiError();
+ return;
+ }
+ if (!NaClThreadCreateJoinable(link_thread_.get(),
+ DoLinkThread,
+ translation_unit,
+ kArbitraryStackSize)) {
+ ErrorInfo error_info;
+ error_info.SetReport(ERROR_UNKNOWN,
+ "Could not create a linker thread.\n");
+ ReportLoadError(error_info);
+ PnaclNonPpapiError();
}
}
//////////////////////////////////////////////////////////////////////
-bool PnaclCoordinator::ScheduleDownload(const nacl::string& url,
- const pp::CompletionCallback& cb) {
- if (!plugin_->StreamAsFile(url, cb.pp_completion_callback())) {
+void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error,
+ const nacl::string& pexe_url,
+ PnaclTranslationUnit* translation) {
+ PLUGIN_PRINTF(("PnaclCoordinator::ResourcesDidLoad (pp_error=%"
+ NACL_PRId32")\n", pp_error));
+ if (pp_error != PP_OK) {
+ ReportLoadError(translation->error_info);
+ PnaclPpapiError(pp_error);
+ return;
+ }
+ pp::CompletionCallback cb =
+ callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate,
+ pexe_url,
+ translation);
+
+ if (!plugin_->StreamAsFile(pexe_url, cb.pp_completion_callback())) {
ErrorInfo error_info;
error_info.SetReport(ERROR_UNKNOWN,
"PnaclCoordinator: Failed to download file: " +
- url + "\n");
+ pexe_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::AddDownloadToDelayedCallback(
- void (PnaclCoordinator::*handler)(int32_t,
- const nacl::string&,
- PnaclTranslationUnit*,
- DelayedCallback*),
- DelayedCallback* delayed_callback,
- const nacl::string& url,
- PnaclTranslationUnit* translation_unit,
- 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,
- translation_unit,
- delayed_callback)));
- delayed_callback->IncrRequirements(1);
}
void PnaclCoordinator::BitcodeToNative(
@@ -681,80 +592,38 @@ void PnaclCoordinator::BitcodeToNative(
pexe_url.c_str(),
llc_url.c_str(),
ld_url.c_str()));
+ llc_url_ = llc_url;
+ ld_url_ = ld_url;
translate_notify_callback_ = finish_callback;
- string_vector link_resources = LinkResources(GetSandboxISA(), false);
-
- // TODO(sehr): revise to download llc, ld, and native libraries in one step.
- // TODO(sehr): save these resources for possible multiple uses (e.g., psos).
-
// 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.
+ // (1) Schedule downloads for llc, ld nexes, and native libraries (resources).
+ // (2) When resources have been downloaded, download pexe.
+ // (3) When pexe download has completed, start translation.
+ // (4) When llc translation has finished do the link.
+ // (5) 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.
-
translation_unit_.reset(new PnaclTranslationUnit(this));
- pp::CompletionCallback run_link_callback =
- callback_factory_.NewCallback(&PnaclCoordinator::RunLink,
+ // When resources loading completes, this causes the pexe download.
+ pp::CompletionCallback resources_cb =
+ callback_factory_.NewCallback(&PnaclCoordinator::ResourcesDidLoad,
+ pexe_url,
translation_unit_.get());
- DelayedCallback* delayed_link_callback =
- MakeDelayedCallback(run_link_callback, 0);
-
- // (2) Run translation.
- pp::CompletionCallback run_translate_callback =
- callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate,
- translation_unit_.get(),
- 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,
- translation_unit_.get(),
- downloads);
- AddDownloadToDelayedCallback(&PnaclCoordinator::LLCReady,
- delayed_translate_callback,
- llc_url,
- downloads);
- AddDownloadToDelayedCallback(&PnaclCoordinator::LDReady,
- delayed_link_callback,
- ld_url,
- downloads);
+ resources_->AddResourceUrl(llc_url);
+ resources_->AddResourceUrl(ld_url);
+ string_vector link_resources = LinkResources(GetSandboxISA(), false);
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.
- }
+ resources_->AddResourceUrl(*i);
}
- downloads.clear();
+ resources_->RunWhenAllLoaded(resources_cb);
+ resources_->StartDownloads();
}
} // namespace plugin
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h
index 8579b41..c8fecee 100644
--- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h
+++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h
@@ -18,6 +18,7 @@
#include "native_client/src/trusted/plugin/delayed_callback.h"
#include "native_client/src/trusted/plugin/nacl_subprocess.h"
#include "native_client/src/trusted/plugin/plugin_error.h"
+#include "native_client/src/trusted/plugin/pnacl_resources.h"
#include "ppapi/cpp/completion_callback.h"
@@ -27,43 +28,6 @@ namespace plugin {
class Plugin;
class PnaclCoordinator;
-class PnaclResources;
-
-class PnaclResources {
- public:
- PnaclResources(Plugin* plugin)
- : plugin_(plugin),
- llc_desc_(kNaClSrpcInvalidImcDesc),
- ld_desc_(kNaClSrpcInvalidImcDesc) { }
-
- ~PnaclResources() {
- for (std::map<nacl::string, nacl::DescWrapper*>::iterator
- i = resource_wrappers_.begin(), e = resource_wrappers_.end();
- i != e;
- ++i) {
- delete i->second;
- }
- resource_wrappers_.clear();
- }
-
- // The file descriptor for the llc nexe.
- NaClSrpcImcDescType llc_desc() const { return llc_desc_; }
- void set_llc_desc(NaClSrpcImcDescType llc_desc) { llc_desc_ = llc_desc; }
- // The file descriptor for the ld nexe.
- NaClSrpcImcDescType ld_desc() const { return ld_desc_; }
- void set_ld_desc(NaClSrpcImcDescType ld_desc) { ld_desc_ = ld_desc; }
-
- NaClSrpcImcDescType DescForUrl(const nacl::string& url) {
- return resource_wrappers_[url]->desc();
- }
- void AddFDForUrl(const nacl::string& url, int32_t fd);
-
- private:
- Plugin* plugin_;
- NaClSrpcImcDescType llc_desc_;
- NaClSrpcImcDescType ld_desc_;
- std::map<nacl::string, nacl::DescWrapper*> resource_wrappers_;
-};
struct PnaclTranslationUnit {
PnaclTranslationUnit(PnaclCoordinator* coord)
@@ -136,103 +100,51 @@ class PnaclCoordinator {
return translated_fd_.release();
}
+ int32_t GetLoadedFileDesc(int32_t pp_error,
+ const nacl::string& url,
+ const nacl::string& component);
+
+ // Run when faced with a PPAPI error condition. It brings control back to the
+ // plugin by invoking the |translate_notify_callback_|.
+ void PnaclPpapiError(int32_t pp_error);
+ // Run |translate_notify_callback_| with an error condition that is not
+ // PPAPI specific.
+ void PnaclNonPpapiError();
+ // Wrapper for Plugin ReportLoadAbort.
+ void ReportLoadAbort();
+ // Wrapper for Plugin ReportLoadError.
+ void ReportLoadError(const ErrorInfo& error);
+
+
+
// Accessors for use by helper threads.
Plugin* plugin() const { return plugin_; }
+ nacl::string llc_url() const { return llc_url_; }
NaClSubprocess* llc_subprocess() const { return llc_subprocess_; }
+ bool StartLlcSubProcess();
+ nacl::string ld_url() const { return ld_url_; }
NaClSubprocess* ld_subprocess() const { return ld_subprocess_; }
- bool SubprocessesShouldDie() {
- NaClXMutexLock(&subprocess_mu_);
- bool retval = subprocesses_should_die_;
- NaClXMutexUnlock(&subprocess_mu_);
- return retval;
- }
- void SetSubprocessesShouldDie(bool subprocesses_should_die) {
- NaClXMutexLock(&subprocess_mu_);
- subprocesses_should_die_ = subprocesses_should_die;
- NaClXMutexUnlock(&subprocess_mu_);
- }
+ bool StartLdSubProcess();
+ bool SubprocessesShouldDie();
+ void SetSubprocessesShouldDie(bool subprocesses_should_die);
PnaclResources* resources() const { return resources_.get(); }
protected:
- // Delay a callback until |num_dependencies| are met.
- DelayedCallback* MakeDelayedCallback(pp::CompletionCallback cb,
- uint32_t num_dependencies);
-
- // Helper functions for generating callbacks that will be run when a
- // download of |url| has completed. The generated callback will
- // run |handler|. The |handler| itself is given a pp_error code,
- // the url of the download, and another callback in the
- // form of the supplied |delayed_callback|.
- void AddDownloadToDelayedCallback(
- void (PnaclCoordinator::*handler)(int32_t,
- const nacl::string&,
- DelayedCallback*),
- DelayedCallback* delayed_callback,
- const nacl::string& url,
- std::vector<url_callback_pair>& queue);
- void AddDownloadToDelayedCallback(
- void (PnaclCoordinator::*handler)(int32_t,
- const nacl::string&,
- PnaclTranslationUnit*,
- DelayedCallback*),
- DelayedCallback* delayed_callback,
- const nacl::string& url,
- PnaclTranslationUnit* translation_unit,
- std::vector<url_callback_pair>& queue);
-
- bool ScheduleDownload(const nacl::string& url,
- const pp::CompletionCallback& cb);
-
// Callbacks for when various files, etc. have been downloaded.
- void PexeReady(int32_t pp_error,
- const nacl::string& url,
- PnaclTranslationUnit* translation_unit,
- DelayedCallback* delayed_callback);
- void LLCReady(int32_t pp_error,
- const nacl::string& url,
- DelayedCallback* delayed_callback);
- void LDReady(int32_t pp_error,
- const nacl::string& url,
- DelayedCallback* delayed_callback);
- void LinkResourceReady(int32_t pp_error,
- const nacl::string& url,
- DelayedCallback* delayed_callback);
-
- int32_t GetLoadedFileDesc(int32_t pp_error,
- const nacl::string& url,
- const nacl::string& component);
-
- // Helper for starting helper nexes after they are downloaded.
- NaClSubprocessId HelperNexeDidLoad(int32_t fd, ErrorInfo* error_info);
+ void ResourcesDidLoad(int32_t pp_error,
+ const nacl::string& url,
+ PnaclTranslationUnit* translation_unit);
// Callbacks for compute-based translation steps.
void RunTranslate(int32_t pp_error,
- PnaclTranslationUnit* translation_unit,
- DelayedCallback* delayed_callback);
- void RunTranslateDidFinish(int32_t pp_error,
- PnaclTranslationUnit* translation_unit,
- DelayedCallback* delayed_callback);
+ const nacl::string& url,
+ PnaclTranslationUnit* translation_unit);
void RunLink(int32_t pp_error, PnaclTranslationUnit* translation_unit);
- void RunLinkDidFinish(int32_t pp_error,
- PnaclTranslationUnit* translation_unit);
// Pnacl translation completed normally.
void PnaclDidFinish(int32_t pp_error, PnaclTranslationUnit* translation_unit);
- // Run when faced with a PPAPI error condition. It brings control back to the
- // plugin by invoking the |translate_notify_callback_|.
- void PnaclPpapiError(int32_t pp_error);
-
- // Run |translate_notify_callback_| with an error condition that is not
- // PPAPI specific.
- void PnaclNonPpapiError();
-
- // Wrapper for Plugin ReportLoadAbort.
- void ReportLoadAbort();
- // Wrapper for Plugin ReportLoadError.
- void ReportLoadError(const ErrorInfo& error);
-
private:
NACL_DISALLOW_COPY_AND_ASSIGN(PnaclCoordinator);
@@ -240,12 +152,9 @@ class PnaclCoordinator {
pp::CompletionCallback translate_notify_callback_;
pp::CompletionCallbackFactory<PnaclCoordinator> callback_factory_;
- // State for a single translation.
- // TODO(jvoung): see if we can manage this state better, especially when we
- // start having to translate multiple bitcode files for the same application
- // (for DSOs).
-
- std::set<DelayedCallback*> delayed_callbacks;
+ // URLs used to lookup downloaded resources.
+ nacl::string llc_url_;
+ nacl::string ld_url_;
// Helper subprocesses loaded by the plugin (deleted by the plugin).
// We may want to do cleanup ourselves when we are in the
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_resources.cc b/ppapi/native_client/src/trusted/plugin/pnacl_resources.cc
new file mode 100644
index 0000000..afc3431
--- /dev/null
+++ b/ppapi/native_client/src/trusted/plugin/pnacl_resources.cc
@@ -0,0 +1,119 @@
+// Copyright (c) 2011 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_resources.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/plugin.h"
+#include "native_client/src/trusted/plugin/plugin_error.h"
+#include "native_client/src/trusted/plugin/pnacl_coordinator.h"
+#include "native_client/src/trusted/plugin/utility.h"
+
+#include "ppapi/c/pp_errors.h"
+
+namespace plugin {
+
+class Plugin;
+
+PnaclResources::~PnaclResources() {
+ for (std::map<nacl::string, nacl::DescWrapper*>::iterator
+ i = resource_wrappers_.begin(), e = resource_wrappers_.end();
+ i != e;
+ ++i) {
+ delete i->second;
+ }
+ resource_wrappers_.clear();
+}
+
+void PnaclResources::Initialize() {
+ callback_factory_.Initialize(this);
+}
+
+void PnaclResources::AddResourceUrl(const nacl::string& url) {
+ // Use previously loaded resources if available.
+ if (resource_wrappers_.find(url) != resource_wrappers_.end()) {
+ return;
+ }
+ all_loaded_ = false;
+ resource_urls_.push_back(url);
+}
+
+void PnaclResources::StartDownloads() {
+ // If there are no resources to be loaded, report all loaded to invoke
+ // client callbacks as needed.
+ if (all_loaded_) {
+ AllLoaded(PP_OK);
+ return;
+ }
+ pp::CompletionCallback all_loaded_callback =
+ callback_factory_.NewCallback(&PnaclResources::AllLoaded);
+ // Create a counter (barrier) callback to track when all of the resources
+ // are loaded.
+ uint32_t resource_count = static_cast<uint32_t>(resource_urls_.size());
+ delayed_callback_.reset(
+ new DelayedCallback(all_loaded_callback, resource_count));
+
+ // Schedule the downloads.
+ CHECK(resource_urls_.size() > 0);
+ for (size_t i = 0; i < resource_urls_.size(); ++i) {
+ const nacl::string& url = resource_urls_[i];
+ pp::CompletionCallback ready_callback =
+ callback_factory_.NewCallback(&PnaclResources::ResourceReady, url);
+ if (!plugin_->StreamAsFile(url, ready_callback.pp_completion_callback())) {
+ ErrorInfo error_info;
+ error_info.SetReport(ERROR_UNKNOWN,
+ "PnaclCoordinator: Failed to download file: " +
+ url + "\n");
+ coordinator_->ReportLoadError(error_info);
+ coordinator_->PnaclNonPpapiError();
+ break;
+ }
+ }
+ resource_urls_.clear();
+}
+
+void PnaclResources::ResourceReady(int32_t pp_error,
+ const nacl::string& url) {
+ PLUGIN_PRINTF(("PnaclResources::ResourceReady (pp_error=%"
+ NACL_PRId32", url=%s)\n", pp_error, url.c_str()));
+ // pp_error is checked by GetLoadedFileDesc.
+ int32_t fd = coordinator_->GetLoadedFileDesc(pp_error,
+ url,
+ "resource " + url);
+ if (fd < 0) {
+ coordinator_->PnaclPpapiError(pp_error);
+ } else {
+ resource_wrappers_[url] =
+ plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY);
+ delayed_callback_->RunIfTime();
+ }
+}
+
+void PnaclResources::AllLoaded(int32_t pp_error) {
+ PLUGIN_PRINTF(("PnaclResources::AllLoaded (pp_error=%"NACL_PRId32")\n",
+ pp_error));
+ all_loaded_ = true;
+ // Run the client-specified callback if one was set.
+ if (client_callback_is_valid_) {
+ pp::Core* core = pp::Module::Get()->core();
+ core->CallOnMainThread(0, client_callback_, PP_OK);
+ }
+}
+
+void PnaclResources::RunWhenAllLoaded(pp::CompletionCallback& client_callback) {
+ if (all_loaded_) {
+ pp::Core* core = pp::Module::Get()->core();
+ core->CallOnMainThread(0, client_callback, PP_OK);
+ }
+ client_callback_ = client_callback;
+ client_callback_is_valid_ = true;
+}
+
+} // namespace plugin
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_resources.h b/ppapi/native_client/src/trusted/plugin/pnacl_resources.h
new file mode 100644
index 0000000..fa7edb0
--- /dev/null
+++ b/ppapi/native_client/src/trusted/plugin/pnacl_resources.h
@@ -0,0 +1,78 @@
+// Copyright (c) 2011 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.
+
+#ifndef NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_PNACL_RESOURCES_H_
+#define NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_PNACL_RESOURCES_H_
+
+#include <map>
+#include <vector>
+
+#include "native_client/src/include/nacl_macros.h"
+#include "native_client/src/include/nacl_string.h"
+#include "native_client/src/shared/srpc/nacl_srpc.h"
+#include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
+#include "native_client/src/trusted/plugin/delayed_callback.h"
+#include "native_client/src/trusted/plugin/plugin_error.h"
+
+#include "ppapi/cpp/completion_callback.h"
+
+namespace plugin {
+
+class Plugin;
+class PnaclCoordinator;
+
+class PnaclResources {
+ public:
+ PnaclResources(Plugin* plugin, PnaclCoordinator* coordinator)
+ : plugin_(plugin),
+ coordinator_(coordinator),
+ all_loaded_(true),
+ client_callback_is_valid_(false)
+ { }
+
+ virtual ~PnaclResources();
+
+ void Initialize();
+
+ nacl::DescWrapper* WrapperForUrl(const nacl::string& url) {
+ return resource_wrappers_[url];
+ }
+
+ // Add an URL for download.
+ void AddResourceUrl(const nacl::string& url);
+ // Start fetching the URLs.
+ void StartDownloads();
+ // Set the callback for what to do when all the resources are available.
+ void RunWhenAllLoaded(pp::CompletionCallback& client_callback);
+
+ private:
+ NACL_DISALLOW_COPY_AND_ASSIGN(PnaclResources);
+
+ // Callback invoked each time one resource has been loaded.
+ void ResourceReady(int32_t pp_error, const nacl::string& url);
+ // Callback invoked when all resources have been loaded.
+ void AllLoaded(int32_t pp_error);
+
+ Plugin* plugin_;
+ PnaclCoordinator* coordinator_;
+ std::vector<nacl::string> resource_urls_;
+ std::map<nacl::string, nacl::DescWrapper*> resource_wrappers_;
+ nacl::scoped_ptr<DelayedCallback> delayed_callback_;
+ // Set once all resources have been loaded to indicate that future calls to
+ // RunWhenAllLoaded should immediately invoke the client callback. This
+ // simplifies the client while allowing resources to be used for subsequent
+ // translations.
+ bool all_loaded_;
+ // Callback to be invoked when all resources can be guaranteed available.
+ pp::CompletionCallback client_callback_;
+ // If RunWhenAllLoaded was called before all resources have been loaded,
+ // this indicates that the registered client callback should be used when
+ // the last resource arrives.
+ bool client_callback_is_valid_;
+ // Factory for ready callbacks, etc.
+ pp::CompletionCallbackFactory<PnaclResources> callback_factory_;
+};
+
+} // namespace plugin;
+#endif // NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_PNACL_RESOURCES_H_