summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsehr@google.com <sehr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-10 01:31:37 +0000
committersehr@google.com <sehr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-10 01:31:37 +0000
commit063b841e1b7462f9af20d8a5e1613c0effe97a72 (patch)
treeba6da251d9264d3bfec6e125c909ca11bec0f7fe
parent4585ed7d8bf3417c6470a44b03d8a007dbc24974 (diff)
downloadchromium_src-063b841e1b7462f9af20d8a5e1613c0effe97a72.zip
chromium_src-063b841e1b7462f9af20d8a5e1613c0effe97a72.tar.gz
chromium_src-063b841e1b7462f9af20d8a5e1613c0effe97a72.tar.bz2
Refactor the pnacl coordinator to load resources all at once, then load
the pexe. This will allow separating these tasks more cleanly, and also makes the translation of individual pexes/psos more cleanly separated from the common portions. BUG= http://code.google.com/p/nativeclient/issues/detail?id=2409 TEST= run_pnacl_example_browser_test Review URL: http://codereview.chromium.org/8490018 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@109359 0039d316-1c4b-4281-b951-d872f2087c98
-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_