diff options
author | sehr@google.com <sehr@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-04 21:04:38 +0000 |
---|---|---|
committer | sehr@google.com <sehr@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-04 21:04:38 +0000 |
commit | dc912ae1f6424b7312439d11174c07d54a784f61 (patch) | |
tree | 5fcd268217ae49beb4ed249d76c562a1f8ec5aef /ppapi/native_client | |
parent | 902a288e65950b9ec2029ab6bd50c013df1b1a59 (diff) | |
download | chromium_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')
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", ¶ms, - 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_ |