summaryrefslogtreecommitdiffstats
path: root/ppapi/native_client
diff options
context:
space:
mode:
authorsehr@google.com <sehr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-04 21:04:38 +0000
committersehr@google.com <sehr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-04 21:04:38 +0000
commitdc912ae1f6424b7312439d11174c07d54a784f61 (patch)
tree5fcd268217ae49beb4ed249d76c562a1f8ec5aef /ppapi/native_client
parent902a288e65950b9ec2029ab6bd50c013df1b1a59 (diff)
downloadchromium_src-dc912ae1f6424b7312439d11174c07d54a784f61.zip
chromium_src-dc912ae1f6424b7312439d11174c07d54a784f61.tar.gz
chromium_src-dc912ae1f6424b7312439d11174c07d54a784f61.tar.bz2
Refactor pnacl coordinator to make it easier to pass metadata values from the
translator to the linker. BUG= http://code.google.com/p/nativeclient/issues/detail?id=2409 TEST= ./scons run_pnacl_example_browser_test Review URL: http://codereview.chromium.org/8463007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@108710 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/native_client')
-rw-r--r--ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc290
-rw-r--r--ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h152
-rw-r--r--ppapi/native_client/src/trusted/plugin/pnacl_thread_args.h97
3 files changed, 280 insertions, 259 deletions
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
index 7e35399..19b0cdc 100644
--- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
+++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
@@ -32,50 +32,47 @@ namespace plugin {
class Plugin;
-void PnaclCoordinator::Initialize(Plugin* instance) {
+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)));
- CHECK(instance != NULL);
- CHECK(instance_ == NULL); // Can only initialize once.
- instance_ = instance;
+ CHECK(plugin != NULL);
+ CHECK(plugin_ == NULL); // Can only initialize once.
+ plugin_ = plugin;
callback_factory_.Initialize(this);
+ resources_.reset(new PnaclResources(plugin));
}
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
+ // Join helper threads 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.
+ if (translate_thread_.get() != NULL || link_thread_.get() != NULL) {
+ SetSubprocessesShouldDie(true);
+ }
+ if (translate_thread_.get() != NULL) {
NaClThreadJoin(translate_thread_.get());
}
- if (link_args_ != NULL) {
- link_args_->should_die = true;
+ if (link_thread_.get() != NULL) {
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();
+ plugin_->ReportLoadAbort();
}
void PnaclCoordinator::ReportLoadError(const ErrorInfo& error) {
- instance_->ReportLoadError(error);
+ plugin_->ReportLoadError(error);
}
void PnaclCoordinator::PnaclPpapiError(int32_t pp_error) {
@@ -88,7 +85,9 @@ void PnaclCoordinator::PnaclNonPpapiError() {
PnaclPpapiError(PP_ERROR_FAILED);
}
-void PnaclCoordinator::PnaclDidFinish(int32_t pp_error) {
+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));
translate_notify_callback_.Run(pp_error);
@@ -104,20 +103,11 @@ PnaclCoordinator::MakeDelayedCallback(pp::CompletionCallback cb,
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);
+ int32_t file_desc = plugin_->GetPOSIXFileDesc(url);
if (pp_error != PP_OK || file_desc == NACL_NO_FILE_DESC) {
if (pp_error == PP_ERROR_ABORTED) {
ReportLoadAbort();
@@ -144,11 +134,11 @@ int32_t PnaclCoordinator::GetLoadedFileDesc(int32_t pp_error,
NaClSubprocessId PnaclCoordinator::HelperNexeDidLoad(int32_t fd,
ErrorInfo* error_info) {
// Inform JavaScript that we successfully loaded a helper nexe.
- instance_->EnqueueProgressEvent(Plugin::kProgressEventProgress);
+ plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress);
nacl::scoped_ptr<nacl::DescWrapper>
- wrapper(instance_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY));
+ wrapper(plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY));
- return instance_->LoadHelperNaClModule(wrapper.get(), error_info);
+ return plugin_->LoadHelperNaClModule(wrapper.get(), error_info);
}
//////////////////////////////////////////////////////////////////////
@@ -178,7 +168,7 @@ void PnaclCoordinator::LLCReady(int32_t pp_error,
PnaclNonPpapiError();
return;
}
- llc_subprocess_ = instance_ ->nacl_subprocess(llc_id);
+ llc_subprocess_ = plugin_ ->nacl_subprocess(llc_id);
delayed_callback->RunIfTime();
}
@@ -206,37 +196,38 @@ void PnaclCoordinator::LDReady(int32_t pp_error,
PnaclNonPpapiError();
return;
}
- ld_subprocess_ = instance_ ->nacl_subprocess(ld_id);
+ ld_subprocess_ = plugin_ ->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));
+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, pexe_url, "pexe");
+ int32_t fd = GetLoadedFileDesc(pp_error, url, "linker resource " + url);
if (fd < 0) {
PnaclPpapiError(pp_error);
} else {
- pexe_fd_.reset(instance_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY));
+ resources_->AddFDForUrl(url, fd);
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()));
+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, url, "linker resource " + url);
+ int32_t fd = GetLoadedFileDesc(pp_error, pexe_url, "pexe");
if (fd < 0) {
PnaclPpapiError(pp_error);
} else {
- linker_resource_fds_[url] =
- instance_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY);
+ translation_unit->pexe_wrapper.reset(
+ plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY));
delayed_callback->RunIfTime();
}
}
@@ -244,18 +235,21 @@ void PnaclCoordinator::LinkResourceReady(int32_t pp_error,
//////////////////////////////////////////////////////////////////////
namespace {
-void AbortTranslateThread(DoTranslateArgs* args,
+void AbortTranslateThread(PnaclTranslationUnit* translation_unit,
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);
+ translation_unit->error_info.SetReport(ERROR_UNKNOWN, error_string);
+ core->CallOnMainThread(0, translation_unit->translate_done_cb,
+ PP_ERROR_FAILED);
NaClThreadExit(1);
}
-} // namespace
void WINAPI DoTranslateThread(void* arg) {
- DoTranslateArgs* p = reinterpret_cast<DoTranslateArgs*>(arg);
- NaClSubprocess* llc_subprocess = p->subprocess;
+ PnaclTranslationUnit* p = reinterpret_cast<PnaclTranslationUnit*>(arg);
+ PnaclCoordinator* coordinator = p->coordinator;
+ NaClSubprocess* llc_subprocess = coordinator->llc_subprocess();
+ Plugin* plugin = coordinator->plugin();
+ BrowserInterface* browser = plugin->browser_interface();
// Set up LLC flags first.
// TODO(jvoung): Bake these into the llc nexe?
@@ -279,7 +273,11 @@ void WINAPI DoTranslateThread(void* arg) {
"-arm-reserve-r9",
"-sfi-disable-cp",
"-arm_static_tls",
- "-sfi-store -sfi-stack -sfi-branch -sfi-data",
+ "-sfi-store",
+ "-sfi-load",
+ "-sfi-stack",
+ "-sfi-branch",
+ "-sfi-data",
"-no-inline-jumptables" };
nacl::string sandbox_isa = GetSandboxISA();
@@ -303,11 +301,11 @@ void WINAPI DoTranslateThread(void* arg) {
}
for (uint32_t i = 0; i < num_args; i++) {
- if (p->should_die) {
+ if (coordinator->SubprocessesShouldDie()) {
NaClThreadExit(1);
}
SrpcParams dummy_params;
- if (!PnaclSrpcLib::InvokeSrpcMethod(p->browser,
+ if (!PnaclSrpcLib::InvokeSrpcMethod(browser,
llc_subprocess,
"AddArg",
"C",
@@ -319,67 +317,75 @@ void WINAPI DoTranslateThread(void* arg) {
}
}
- if (p->should_die) {
+ if (coordinator->SubprocessesShouldDie()) {
NaClThreadExit(1);
}
SrpcParams params;
- if (!PnaclSrpcLib::InvokeSrpcMethod(p->browser,
+ if (!PnaclSrpcLib::InvokeSrpcMethod(browser,
llc_subprocess,
"Translate",
"h",
&params,
- p->pexe_fd->desc())) {
+ p->pexe_wrapper->desc())) {
AbortTranslateThread(p,
"PnaclCoordinator compile failed.");
} else {
// Grab the outparams.
- p->obj_fd = params.outs()[0]->u.hval;
+ p->obj_wrapper.reset(
+ plugin->wrapper_factory()->MakeGeneric(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));
+ p->is_shared_library = params.outs()[2]->u.ival;
+ p->soname = params.outs()[3]->arrays.str;
+ p->lib_dependencies = params.outs()[4]->arrays.str;
+ PLUGIN_PRINTF(("PnaclCoordinator::Translate SRPC succeeded (bytes=%"
+ NACL_PRId32", is_shared_library=%d, soname='%s', "
+ "lib_dependencies='%s')\n", p->obj_len,
+ p->is_shared_library, p->soname.c_str(),
+ p->lib_dependencies.c_str()));
}
- if (p->should_die) {
+ if (coordinator->SubprocessesShouldDie()) {
NaClThreadExit(1);
}
pp::Core* core = pp::Module::Get()->core();
- core->CallOnMainThread(0, p->finish_cb, PP_OK);
+ core->CallOnMainThread(0, p->translate_done_cb, PP_OK);
NaClThreadExit(0);
}
+} // namespace
+
void
PnaclCoordinator::RunTranslateDidFinish(int32_t pp_error,
- DelayedCallback* delayed_callback) {
+ PnaclTranslationUnit* translation_unit,
+ DelayedCallback* link_callback) {
PLUGIN_PRINTF(("PnaclCoordinator::RunTranslateDidFinish (pp_error=%"
NACL_PRId32")\n", pp_error));
if (pp_error != PP_OK) {
- ReportLoadError(translate_args_->error_info);
+ ReportLoadError(translation_unit->error_info);
PnaclPpapiError(pp_error);
return;
}
- SetObjectFile(translate_args_->obj_fd, translate_args_->obj_len);
- instance_->EnqueueProgressEvent(Plugin::kProgressEventProgress);
- delayed_callback->RunIfTime();
+ plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress);
+ link_callback->RunIfTime();
}
void PnaclCoordinator::RunTranslate(int32_t pp_error,
- DelayedCallback* delayed_callback) {
+ PnaclTranslationUnit* translation_unit,
+ DelayedCallback* delayed_link_callback) {
PLUGIN_PRINTF(("PnaclCoordinator::RunTranslate (pp_error=%"
NACL_PRId32")\n", pp_error));
assert(PP_OK == pp_error);
// Invoke llvm asynchronously.
- pp::CompletionCallback finish_cb =
+ // RunTranslateDidFinish runs on the main thread when llvm is done.
+ translation_unit->translate_done_cb =
callback_factory_.NewCallback(&PnaclCoordinator::RunTranslateDidFinish,
- delayed_callback);
- translate_args_.reset(new DoTranslateArgs(llc_subprocess_,
- instance_->browser_interface(),
- finish_cb,
- pexe_fd_.get()));
+ translation_unit,
+ delayed_link_callback);
translate_thread_.reset(new NaClThread);
- if (translate_thread_ != NULL && translate_args_ != NULL) {
+ if (translate_thread_ != NULL) {
if (!NaClThreadCreateJoinable(translate_thread_.get(),
DoTranslateThread,
- translate_args_.get(),
+ translation_unit,
kArbitraryStackSize)) {
ErrorInfo error_info;
error_info.SetReport(ERROR_UNKNOWN,
@@ -428,19 +434,21 @@ string_vector LinkResources(const nacl::string& sandbox_isa,
namespace {
-void AbortLinkThread(DoLinkArgs* args, const nacl::string& error_string) {
+void AbortLinkThread(PnaclTranslationUnit* translation_unit,
+ 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);
+ translation_unit->error_info.SetReport(ERROR_UNKNOWN, error_string);
+ core->CallOnMainThread(0, translation_unit->link_done_cb, PP_ERROR_FAILED);
NaClThreadExit(1);
}
-} // namespace
-
void WINAPI DoLinkThread(void* arg) {
- DoLinkArgs* p = reinterpret_cast<DoLinkArgs*>(arg);
- NaClSubprocess* ld_subprocess = p->subprocess;
+ PnaclTranslationUnit* p = reinterpret_cast<PnaclTranslationUnit*>(arg);
+ PnaclCoordinator* coordinator = p->coordinator;
+ NaClSubprocess* ld_subprocess = coordinator->ld_subprocess();
+ Plugin* plugin = coordinator->plugin();
+ BrowserInterface* browser_interface = plugin->browser_interface();
// Set up command line arguments (flags then files).
@@ -466,11 +474,11 @@ void WINAPI DoLinkThread(void* arg) {
for (string_vector::iterator i = flags.begin(), e = flags.end();
i != e; ++i) {
const nacl::string& flag = *i;
- if (p->should_die) {
+ if (coordinator->SubprocessesShouldDie()) {
NaClThreadExit(1);
}
SrpcParams dummy_params;
- if (!PnaclSrpcLib::InvokeSrpcMethod(p->browser,
+ if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
ld_subprocess,
"AddArg",
"C",
@@ -483,17 +491,17 @@ void WINAPI DoLinkThread(void* arg) {
}
//// Files.
- PnaclCoordinator* pnacl = p->coordinator;
string_vector files = LinkResources(sandbox_isa, true);
+ PnaclResources* resources = coordinator->resources();
for (string_vector::iterator i = files.begin(), e = files.end();
i != e; ++i) {
const nacl::string& link_file = *i;
- if (p->should_die) {
+ if (coordinator->SubprocessesShouldDie()) {
NaClThreadExit(1);
}
// Add as argument.
SrpcParams dummy_params;
- if (!PnaclSrpcLib::InvokeSrpcMethod(p->browser,
+ if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
ld_subprocess,
"AddArg",
"C",
@@ -506,13 +514,13 @@ void WINAPI DoLinkThread(void* arg) {
// Also map the file name to descriptor.
if (i->compare(kGeneratedObjectFileName) == 0) {
SrpcParams dummy_params2;
- if (!PnaclSrpcLib::InvokeSrpcMethod(p->browser,
+ if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
ld_subprocess,
"AddFileWithSize",
"Chi",
&dummy_params2,
link_file.c_str(),
- p->obj_fd->desc(),
+ p->obj_wrapper->desc(),
p->obj_len)) {
AbortLinkThread(p,
"PnaclCoordinator linker AddFileWithSize"
@@ -520,14 +528,13 @@ void WINAPI DoLinkThread(void* arg) {
}
} else {
SrpcParams dummy_params2;
- if (!PnaclSrpcLib::InvokeSrpcMethod(p->browser,
+ if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
ld_subprocess,
"AddFile",
"Ch",
&dummy_params2,
link_file.c_str(),
- pnacl->GetLinkerResourceFD(
- link_file))) {
+ resources->DescForUrl(link_file))) {
AbortLinkThread(p,
"PnaclCoordinator linker AddFile(" + link_file +
") failed.");
@@ -535,13 +542,13 @@ void WINAPI DoLinkThread(void* arg) {
}
}
- if (p->should_die) {
+ if (coordinator->SubprocessesShouldDie()) {
NaClThreadExit(1);
}
// Finally, do the Link!
SrpcParams params;
- if (!PnaclSrpcLib::InvokeSrpcMethod(p->browser,
+ if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
ld_subprocess,
"Link",
"",
@@ -549,51 +556,54 @@ void WINAPI DoLinkThread(void* arg) {
AbortLinkThread(p, "PnaclCoordinator link failed.");
} else {
// Grab the outparams.
- p->nexe_fd = params.outs()[0]->u.hval;
+ p->nexe_wrapper.reset(
+ plugin->wrapper_factory()->MakeGeneric(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) {
+ if (coordinator->SubprocessesShouldDie()) {
NaClThreadExit(1);
}
pp::Core* core = pp::Module::Get()->core();
- core->CallOnMainThread(0, p->finish_cb, PP_OK);
+ core->CallOnMainThread(0, p->link_done_cb, PP_OK);
NaClThreadExit(0);
}
-void PnaclCoordinator::RunLinkDidFinish(int32_t pp_error) {
+} // namespace
+
+void PnaclCoordinator::RunLinkDidFinish(
+ int32_t pp_error,
+ PnaclTranslationUnit* translation_unit) {
PLUGIN_PRINTF(("PnaclCoordinator::RunLinkDidFinish (pp_error=%"
NACL_PRId32")\n", pp_error));
if (pp_error != PP_OK) {
- ReportLoadError(link_args_->error_info);
+ ReportLoadError(translation_unit->error_info);
PnaclPpapiError(pp_error);
return;
}
- SetTranslatedFile(link_args_->nexe_fd);
- instance_->EnqueueProgressEvent(Plugin::kProgressEventProgress);
- PnaclDidFinish(PP_OK);
+ // 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) {
+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);
- // 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_));
+ // Invoke ld asynchronously.
+ // When ld has completed, RunLinkDidFinish is run on the main thread.
+ translation_unit->link_done_cb =
+ callback_factory_.NewCallback(&PnaclCoordinator::RunLinkDidFinish,
+ translation_unit);
link_thread_.reset(new NaClThread);
- if (link_args_ != NULL && link_thread_ != NULL) {
+ if (link_thread_ != NULL) {
if (!NaClThreadCreateJoinable(link_thread_.get(),
DoLinkThread,
- link_args_.get(),
+ translation_unit,
kArbitraryStackSize)) {
ErrorInfo error_info;
error_info.SetReport(ERROR_UNKNOWN,
@@ -614,8 +624,7 @@ void PnaclCoordinator::RunLink(int32_t pp_error) {
bool PnaclCoordinator::ScheduleDownload(const nacl::string& url,
const pp::CompletionCallback& cb) {
- if (!instance_->StreamAsFile(url,
- cb.pp_completion_callback())) {
+ if (!plugin_->StreamAsFile(url, cb.pp_completion_callback())) {
ErrorInfo error_info;
error_info.SetReport(ERROR_UNKNOWN,
"PnaclCoordinator: Failed to download file: " +
@@ -637,8 +646,25 @@ void PnaclCoordinator::AddDownloadToDelayedCallback(
// 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);
}
@@ -656,6 +682,9 @@ void PnaclCoordinator::BitcodeToNative(
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.
@@ -668,20 +697,24 @@ void PnaclCoordinator::BitcodeToNative(
// (3) Run link.
+ translation_unit_.reset(new PnaclTranslationUnit(this));
+
pp::CompletionCallback run_link_callback =
- callback_factory_.NewCallback(&PnaclCoordinator::RunLink);
+ callback_factory_.NewCallback(&PnaclCoordinator::RunLink,
+ 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);
+ DelayedCallback* delayed_translate_callback =
+ MakeDelayedCallback(run_translate_callback, 0);
// (1) Load nexes and assets using StreamAsFile(). This will kick off
// the whole process.
@@ -692,6 +725,7 @@ void PnaclCoordinator::BitcodeToNative(
AddDownloadToDelayedCallback(&PnaclCoordinator::PexeReady,
delayed_translate_callback,
pexe_url,
+ translation_unit_.get(),
downloads);
AddDownloadToDelayedCallback(&PnaclCoordinator::LLCReady,
delayed_translate_callback,
@@ -718,8 +752,6 @@ void PnaclCoordinator::BitcodeToNative(
}
}
downloads.clear();
-
- return;
}
} // 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 13369d2..8579b41 100644
--- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h
+++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h
@@ -11,21 +11,93 @@
#include "native_client/src/include/nacl_macros.h"
#include "native_client/src/include/nacl_string.h"
+#include "native_client/src/shared/platform/nacl_sync_checked.h"
#include "native_client/src/shared/platform/nacl_threads.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/nacl_subprocess.h"
#include "native_client/src/trusted/plugin/plugin_error.h"
-#include "native_client/src/trusted/plugin/pnacl_thread_args.h"
#include "ppapi/cpp/completion_callback.h"
+struct NaClMutex;
+
namespace plugin {
class Plugin;
-struct DoTranslateArgs;
-struct DoLinkArgs;
+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)
+ : coordinator(coord),
+ obj_len(-1),
+ is_shared_library(false),
+ soname(""),
+ lib_dependencies("") {
+ }
+ // Punch hole in abstraction.
+ PnaclCoordinator* coordinator;
+
+ // Borrowed reference which must outlive the thread.
+ nacl::scoped_ptr<nacl::DescWrapper> pexe_wrapper;
+
+ // Object file produced by translator and consumed by the linker.
+ nacl::scoped_ptr<nacl::DescWrapper> obj_wrapper;
+ int32_t obj_len;
+
+ // Information extracted from the pexe that is needed by the linker.
+ bool is_shared_library;
+ nacl::string soname;
+ nacl::string lib_dependencies;
+
+ // The translated user nexe file.
+ nacl::scoped_ptr<nacl::DescWrapper> nexe_wrapper;
+
+ // Callbacks to run when tasks or completed or an error has occurred.
+ pp::CompletionCallback translate_done_cb;
+ pp::CompletionCallback link_done_cb;
+
+ ErrorInfo error_info;
+};
+
typedef std::pair<nacl::string, pp::CompletionCallback> url_callback_pair;
@@ -40,13 +112,12 @@ typedef std::pair<nacl::string, pp::CompletionCallback> url_callback_pair;
class PnaclCoordinator {
public:
PnaclCoordinator()
- : instance_(NULL),
+ : plugin_(NULL),
translate_notify_callback_(pp::BlockUntilComplete()),
llc_subprocess_(NULL),
ld_subprocess_(NULL),
- obj_len_(-1),
- translate_args_(NULL),
- link_args_(NULL) {
+ subprocesses_should_die_(false) {
+ NaClXMutexCtor(&subprocess_mu_);
}
virtual ~PnaclCoordinator();
@@ -65,22 +136,30 @@ class PnaclCoordinator {
return translated_fd_.release();
}
- // This method should really be private, but it is used to
- // communicate with the linker thread.
- NaClSrpcImcDescType GetLinkerResourceFD(const nacl::string& url) {
- return linker_resource_fds_[url]->desc();
+ // Accessors for use by helper threads.
+ Plugin* plugin() const { return plugin_; }
+ NaClSubprocess* llc_subprocess() const { return llc_subprocess_; }
+ 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_);
+ }
+ PnaclResources* resources() const { return resources_.get(); }
protected:
- void SetObjectFile(NaClSrpcImcDescType fd, int32_t len);
- void SetTranslatedFile(NaClSrpcImcDescType fd);
-
// Delay a callback until |num_dependencies| are met.
DelayedCallback* MakeDelayedCallback(pp::CompletionCallback cb,
uint32_t num_dependencies);
- // Helper function for generating callbacks that will be run when a
+ // 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
@@ -92,6 +171,15 @@ class PnaclCoordinator {
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);
@@ -99,6 +187,7 @@ class PnaclCoordinator {
// 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,
@@ -118,14 +207,18 @@ class PnaclCoordinator {
NaClSubprocessId HelperNexeDidLoad(int32_t fd, ErrorInfo* error_info);
// Callbacks for compute-based translation steps.
- void RunTranslate(int32_t pp_error, DelayedCallback* delayed_callback);
+ void RunTranslate(int32_t pp_error,
+ PnaclTranslationUnit* translation_unit,
+ DelayedCallback* delayed_callback);
void RunTranslateDidFinish(int32_t pp_error,
+ PnaclTranslationUnit* translation_unit,
DelayedCallback* delayed_callback);
- void RunLink(int32_t pp_error);
- void RunLinkDidFinish(int32_t pp_error);
+ 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);
+ 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_|.
@@ -143,7 +236,7 @@ class PnaclCoordinator {
private:
NACL_DISALLOW_COPY_AND_ASSIGN(PnaclCoordinator);
- Plugin* instance_;
+ Plugin* plugin_;
pp::CompletionCallback translate_notify_callback_;
pp::CompletionCallbackFactory<PnaclCoordinator> callback_factory_;
@@ -154,20 +247,14 @@ class PnaclCoordinator {
std::set<DelayedCallback*> delayed_callbacks;
- // Helper subprocess loaded by the plugin (deleted by the plugin).
+ // Helper subprocesses loaded by the plugin (deleted by the plugin).
// We may want to do cleanup ourselves when we are in the
// business of compiling multiple bitcode objects / libraries, and
// if we truly cannot reuse existing loaded subprocesses.
NaClSubprocess* llc_subprocess_;
NaClSubprocess* ld_subprocess_;
-
- // Bitcode file pulled from the Net.
- nacl::scoped_ptr<nacl::DescWrapper> pexe_fd_;
-
- // Object "file" obtained after compiling with LLVM, along with the length
- // of the "file".
- nacl::scoped_ptr<nacl::DescWrapper> obj_fd_;
- int32_t obj_len_;
+ bool subprocesses_should_die_;
+ struct NaClMutex subprocess_mu_;
// Nexe from the final native Link.
nacl::scoped_ptr<nacl::DescWrapper> translated_fd_;
@@ -175,13 +262,12 @@ class PnaclCoordinator {
// Perhaps make this a single thread that invokes (S)RPCs followed by
// callbacks based on a Queue of requests. A generic mechanism would make
// it easier to add steps later (the mechanism could look like PostMessage?).
- nacl::scoped_ptr<DoTranslateArgs> translate_args_;
+ nacl::scoped_ptr<PnaclTranslationUnit> translation_unit_;
nacl::scoped_ptr<NaClThread> translate_thread_;
-
- nacl::scoped_ptr<DoLinkArgs> link_args_;
nacl::scoped_ptr<NaClThread> link_thread_;
- std::map<nacl::string, nacl::DescWrapper*> linker_resource_fds_;
+ // An auxiliary class that manages downloaded resources.
+ nacl::scoped_ptr<PnaclResources> resources_;
};
//----------------------------------------------------------------------
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_thread_args.h b/ppapi/native_client/src/trusted/plugin/pnacl_thread_args.h
deleted file mode 100644
index 9fb4a43..0000000
--- a/ppapi/native_client/src/trusted/plugin/pnacl_thread_args.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// 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_THREAD_ARGS_H_
-#define NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_PNACL_THREAD_ARGS_H_
-
-#include "native_client/src/trusted/plugin/plugin_error.h"
-
-#include "ppapi/cpp/completion_callback.h"
-
-namespace plugin {
-
-class BrowserInterface;
-class NaClSubprocess;
-class PnaclCoordinator;
-
-// Base structure for storing pnacl helper thread arguments.
-struct PnaclThreadArgs {
- PnaclThreadArgs(NaClSubprocess* subprocess_,
- BrowserInterface* browser_,
- pp::CompletionCallback finish_cb_)
- : should_die(false),
- subprocess(subprocess_),
- browser(browser_),
- finish_cb(finish_cb_) {
- }
-
- // Bool to signal to the thread that it should end whenever possible.
- bool should_die;
-
- // SRPC Nexe subprocess that does the work.
- NaClSubprocess* subprocess;
- // Browser Interface for SRPC setup.
- BrowserInterface* browser;
-
- // Callback to run when task is completed or an error has occurred.
- pp::CompletionCallback finish_cb;
-
- ErrorInfo error_info;
-};
-
-//----------------------------------------------------------------------
-// Helper thread arguments.
-
-// TODO(jvoung): Move these to the compile / link files when we separate
-// those bits from pnacl_coordinator.
-
-// Arguments needed to run LLVM in a separate thread, to go from
-// bitcode -> object file. This prevents LLVM from blocking the main thread.
-struct DoTranslateArgs : PnaclThreadArgs {
- DoTranslateArgs(NaClSubprocess* subprocess_,
- BrowserInterface* browser_,
- pp::CompletionCallback finish_cb_,
- nacl::DescWrapper* pexe_fd_)
- : PnaclThreadArgs(subprocess_, browser_, finish_cb_),
- pexe_fd(pexe_fd_),
- obj_fd(kNaClSrpcInvalidImcDesc),
- obj_len(-1) {
- }
-
- // Borrowed references which must outlive the thread.
- nacl::DescWrapper* pexe_fd;
-
- // Output.
- NaClSrpcImcDescType obj_fd;
- int32_t obj_len;
-};
-
-// Arguments needed to run LD in a separate thread, to go from
-// object file -> nexe.
-struct DoLinkArgs : PnaclThreadArgs {
- DoLinkArgs(NaClSubprocess* subprocess_,
- BrowserInterface* browser_,
- pp::CompletionCallback finish_cb_,
- PnaclCoordinator* coordinator_,
- nacl::DescWrapper* obj_fd_,
- int32_t obj_len_)
- : PnaclThreadArgs(subprocess_, browser_, finish_cb_),
- coordinator(coordinator_),
- obj_fd(obj_fd_),
- obj_len(obj_len_),
- nexe_fd(kNaClSrpcInvalidImcDesc) {
- }
- PnaclCoordinator* coordinator; // Punch hole in abstraction.
-
- // Borrowed references which must outlive the thread.
- nacl::DescWrapper* obj_fd;
- int32_t obj_len;
-
- // Output.
- NaClSrpcImcDescType nexe_fd;
-};
-
-
-} // namespace plugin;
-#endif // NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_PNACL_THREAD_ARGS_H_