Chromium Code Reviews| Index: ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc |
| =================================================================== |
| --- ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc (revision 114029) |
| +++ ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc (working copy) |
| @@ -17,622 +17,554 @@ |
| #include "native_client/src/trusted/plugin/plugin.h" |
| #include "native_client/src/trusted/plugin/plugin_error.h" |
| #include "native_client/src/trusted/plugin/pnacl_srpc_lib.h" |
| -#include "native_client/src/trusted/plugin/scriptable_handle.h" |
| #include "native_client/src/trusted/plugin/utility.h" |
| #include "ppapi/c/pp_errors.h" |
| +#include "ppapi/c/ppb_file_io.h" |
| +#include "ppapi/cpp/file_io.h" |
| -namespace { |
| +namespace plugin { |
| -typedef std::vector<nacl::string> string_vector; |
| -int32_t kArbitraryStackSize = 128 << 10; |
| +class Plugin; |
| -} // namespace |
| +namespace { |
| -namespace plugin { |
| +const char kLlcUrl[] = "llc"; |
| +const char kLdUrl[] = "ld"; |
| -class Plugin; |
| +// Fake filename for the object file generated by llvm. |
|
robertm
2011/12/13 17:06:39
llvm -> llc
sehr (please use chromium)
2011/12/13 20:05:04
Done.
jvoung - send to chromium...
2011/12/13 21:35:49
Actually, this comments sounds like it is for "__P
|
| +nacl::string ResourceBaseUrl() { |
| + return nacl::string("pnacl_support/") + GetSandboxISA() + "/"; |
| +} |
| -void PnaclCoordinator::Initialize(Plugin* plugin) { |
| - PLUGIN_PRINTF(("PnaclCoordinator::Initialize (this=%p)\n", |
| - static_cast<void*>(this))); |
| - CHECK(plugin != NULL); |
| - CHECK(plugin_ == NULL); // Can only initialize once. |
| - plugin_ = plugin; |
| - callback_factory_.Initialize(this); |
| - resources_.reset(new PnaclResources(plugin, this)); |
| - resources_->Initialize(); |
| +// Lookup service called by translator nexes. |
| +// TODO(sehr): replace this lookup by ReverseService. |
| +void LookupInputFile(NaClSrpcRpc* rpc, |
| + NaClSrpcArg** inputs, |
| + NaClSrpcArg** outputs, |
| + NaClSrpcClosure* done) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::LookupInputFile (url=%s)\n", |
| + inputs[0]->arrays.str)); |
| + NaClSrpcClosureRunner runner(done); |
| + rpc->result = NACL_SRPC_RESULT_APP_ERROR; |
| + const char* file_name = inputs[0]->arrays.str; |
| + PnaclCoordinator* coordinator = reinterpret_cast<PnaclCoordinator*>( |
| + rpc->channel->server_instance_data); |
| + outputs[0]->u.hval = coordinator->LookupDesc(file_name); |
| + rpc->result = NACL_SRPC_RESULT_OK; |
| } |
| -PnaclCoordinator::~PnaclCoordinator() { |
| - PLUGIN_PRINTF(("PnaclCoordinator::~PnaclCoordinator (this=%p)\n", |
| - static_cast<void*>(this))); |
| +NaClSrpcHandlerDesc lookup_methods[] = { |
| + { "LookupInputFile:s:h", LookupInputFile }, |
| + { NULL, NULL } |
| +}; |
| - // Join helper threads which will block the page from refreshing while a |
| - // translation is happening. |
| - if (translate_thread_.get() != NULL || link_thread_.get() != NULL) { |
| - SetSubprocessesShouldDie(true); |
| +} // namespace |
| + |
| +////////////////////////////////////////////////////////////////////// |
| +PnaclFileDescPair::PnaclFileDescPair(Plugin* plugin, |
| + pp::FileSystem* file_system, |
| + PnaclCoordinator* coordinator) |
| + : plugin_(plugin), |
| + file_system_(file_system), |
| + coordinator_(coordinator) { |
| + PLUGIN_PRINTF(("PnaclFileDescPair::PnaclFileDescPair (plugin=%p, " |
| + "file_system=%p, coordinator=%p)\n", |
| + static_cast<void*>(plugin), static_cast<void*>(file_system), |
| + static_cast<void*>(coordinator))); |
| + callback_factory_.Initialize(this); |
| + CHECK(NaClDescRngCtor(&rng_desc_)); |
| + file_io_trusted_= static_cast<const PPB_FileIOTrusted*>( |
| + pp::Module::Get()->GetBrowserInterface(PPB_FILEIOTRUSTED_INTERFACE)); |
| + // Get a random temp file name. |
| + struct NaClDesc* desc = reinterpret_cast<struct NaClDesc*>(&rng_desc_); |
| + const struct NaClDescVtbl* vtbl = |
| + reinterpret_cast<const struct NaClDescVtbl*>(desc->base.vtbl); |
| + // Filename consists of a slash then 32 random characters. |
| + filename_ = "/"; |
| + const int32_t kTempFileNameWords = 4; |
| + for (int32_t i = 0; i < kTempFileNameWords; ++i) { |
|
robertm
2011/12/13 17:06:39
this looks like a good candidate for factoring out
sehr (please use chromium)
2011/12/13 20:05:04
Done.
|
| + int32_t num; |
| + CHECK(sizeof num == vtbl->Read(desc, |
| + reinterpret_cast<char*>(&num), |
| + sizeof num)); |
| + char frag[16]; |
| + SNPRINTF(frag, sizeof frag, "%08x", num); |
| + filename_ += nacl::string(frag); |
| } |
| - if (translate_thread_.get() != NULL) { |
| - NaClThreadJoin(translate_thread_.get()); |
| - } |
| - if (link_thread_.get() != NULL) { |
| - NaClThreadJoin(link_thread_.get()); |
| - } |
| } |
| -void PnaclCoordinator::ReportLoadAbort() { |
| - plugin_->ReportLoadAbort(); |
| +PnaclFileDescPair::~PnaclFileDescPair() { |
| + PLUGIN_PRINTF(("PnaclFileDescPair::~PnaclFileDescPair\n")); |
| + NaClDescUnref(reinterpret_cast<NaClDesc*>(&rng_desc_)); |
| } |
| -void PnaclCoordinator::ReportLoadError(const ErrorInfo& error) { |
| - plugin_->ReportLoadError(error); |
| +void PnaclFileDescPair::Open(const pp::CompletionCallback& cb) { |
| + PLUGIN_PRINTF(("PnaclFileDescPair::Open\n")); |
| + done_callback_ = cb; |
| + |
| + write_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str())); |
| + write_io_.reset(new pp::FileIO(plugin_)); |
| + read_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str())); |
| + read_io_.reset(new pp::FileIO(plugin_)); |
| + |
| + pp::CompletionCallback open_write_cb = |
| + callback_factory_.NewCallback(&PnaclFileDescPair::WriteFileDidOpen); |
| + // Open the writeable file. |
| + write_io_->Open(*write_ref_, |
| + PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE, |
| + open_write_cb); |
| } |
| -void PnaclCoordinator::PnaclPpapiError(int32_t pp_error) { |
| - // Attempt to free all the intermediate callbacks we ever created. |
| - callback_factory_.CancelAll(); |
| - translate_notify_callback_.Run(pp_error); |
| +int32_t PnaclFileDescPair::GetFD(int32_t pp_error, |
| + const pp::Resource& resource, |
| + const nacl::string& component) { |
| + PLUGIN_PRINTF(("PnaclFileDescPair::GetFD (pp_error=%" |
| + NACL_PRId32", component=%s)\n", pp_error, component.c_str())); |
| + if (pp_error != PP_OK) { |
| + coordinator_->ReportPpapiError(pp_error, |
| + nacl::string("PnaclFileDescPair::GetFD ") + |
| + component + " failed\n"); |
| + return -1; |
| + } |
| + int32_t file_desc = file_io_trusted_->GetOSFileDescriptor( |
| + resource.pp_resource()); |
| +#if NACL_WINDOWS |
| + // Convert the Windows HANDLE from Pepper to a POSIX file descriptor. |
| + int32_t posix_desc = _open_osfhandle(file_desc, _O_RDWR | _O_BINARY); |
|
jvoung - send to chromium...
2011/12/13 03:14:33
nit: Should this know if it was GetFD for a readon
sehr (please use chromium)
2011/12/13 20:05:04
Great catch, though. Done here.
|
| + if (posix_desc == -1) { |
| + // Close the Windows HANDLE if it can't be converted. |
| + CloseHandle(reinterpret_cast<HANDLE>(file_desc)); |
|
jvoung - send to chromium...
2011/12/13 03:14:33
ReportPpapiError here as well, like the other erro
sehr (please use chromium)
2011/12/13 20:05:04
I deferred error reporting to the clients as you s
|
| + return NACL_NO_FILE_DESC; |
| + } |
| + file_desc = posix_desc; |
| +#endif |
| + int32_t file_desc_ok_to_close = DUP(file_desc); |
| + if (file_desc_ok_to_close == NACL_NO_FILE_DESC) { |
| + coordinator_->ReportPpapiError( |
| + pp_error, |
| + nacl::string("PnaclFileDescPair::GetFD dup ") + |
| + component + " failed\n"); |
| + return -1; |
| + } |
| + return file_desc_ok_to_close; |
| } |
| -void PnaclCoordinator::PnaclNonPpapiError() { |
| - PnaclPpapiError(PP_ERROR_FAILED); |
| +void PnaclFileDescPair::WriteFileDidOpen(int32_t pp_error) { |
| + PLUGIN_PRINTF(("PnaclFileDescPair::WriteFileDidOpen (pp_error=%" |
| + NACL_PRId32")\n", pp_error)); |
| + // Remember the object temporary file descriptor. |
| + int32_t fd = GetFD(pp_error, *write_io_, "write"); |
| + if (fd < 0) { |
| + return; |
| + } |
| + write_wrapper_.reset(plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDWR)); |
| + pp::CompletionCallback open_read_cb = |
| + callback_factory_.NewCallback(&PnaclFileDescPair::ReadFileDidOpen); |
| + // Open the read only file. |
| + read_io_->Open(*read_ref_, PP_FILEOPENFLAG_READ, open_read_cb); |
| } |
| -void PnaclCoordinator::PnaclDidFinish(int32_t pp_error, |
| - PnaclTranslationUnit* translation_unit) { |
| - PLUGIN_PRINTF(("PnaclCoordinator::PnaclDidFinish (pp_error=%" |
| +void PnaclFileDescPair::ReadFileDidOpen(int32_t pp_error) { |
| + PLUGIN_PRINTF(("PnaclFileDescPair::ReadFileDidOpen (pp_error=%" |
| NACL_PRId32")\n", pp_error)); |
| - if (pp_error != PP_OK) { |
| - ReportLoadError(translation_unit->error_info); |
| - PnaclPpapiError(pp_error); |
| + // Remember the object temporary file descriptor. |
| + int32_t fd = GetFD(pp_error, *read_io_, "read"); |
| + if (fd < 0) { |
| return; |
|
jvoung - send to chromium...
2011/12/13 03:14:33
I guess these "return;"s are counting on GetFD to
sehr (please use chromium)
2011/12/13 20:05:04
I moved the error handling to here.
|
| } |
| - // 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); |
| + read_wrapper_.reset(plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY)); |
| + // Run the client's completion callback. |
| + pp::Core* core = pp::Module::Get()->core(); |
| + core->CallOnMainThread(0, done_callback_, PP_OK); |
| } |
| ////////////////////////////////////////////////////////////////////// |
| +PnaclCoordinator* PnaclCoordinator::BitcodeToNative( |
| + Plugin* plugin, |
| + const nacl::string& pexe_url, |
| + const pp::CompletionCallback& translate_notify_callback) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (plugin=%p, pexe=%s)\n", |
| + static_cast<void*>(plugin), pexe_url.c_str())); |
| + PnaclCoordinator* coordinator = new PnaclCoordinator(plugin); |
|
robertm
2011/12/13 17:06:39
it might be simpler to pass the args into the cons
sehr (please use chromium)
2011/12/13 20:05:04
Done.
|
| + coordinator->pexe_url_ = pexe_url; |
| + coordinator->translate_notify_callback_ = translate_notify_callback; |
| + // Load llc and ld. |
| + coordinator->resource_base_url_ = ResourceBaseUrl(); |
| + coordinator->resources_.reset( |
| + new PnaclResources(plugin, coordinator, coordinator->resource_base_url_)); |
| + CHECK(coordinator->resources_ != NULL); |
| + pp::CompletionCallback resources_cb = |
| + coordinator->callback_factory_.NewCallback( |
| + &PnaclCoordinator::ResourcesDidLoad); |
| + coordinator->resources_->AddResourceUrl(kLlcUrl); |
| + coordinator->resources_->AddResourceUrl(kLdUrl); |
| + coordinator->resources_->RunWhenAllLoaded(resources_cb); |
|
robertm
2011/12/13 17:06:39
could this also go into the contructor of PnaclRes
sehr (please use chromium)
2011/12/13 20:05:04
Done.
|
| + coordinator->resources_->StartDownloads(); |
| + // ResourcesDidLoad will be invoked when all resources have been received. |
| + return coordinator; |
| +} |
| int32_t PnaclCoordinator::GetLoadedFileDesc(int32_t pp_error, |
| const nacl::string& url, |
| const nacl::string& component) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::GetLoadedFileDesc (pp_error=%" |
| + NACL_PRId32", url=%s, component=%s)\n", pp_error, |
| + url.c_str(), component.c_str())); |
| + PLUGIN_PRINTF(("PnaclCoordinator::GetLoadedFileDesc (pp_error=%d\n")); |
| ErrorInfo error_info; |
| 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(); |
| + plugin_->ReportLoadAbort(); |
| } else { |
| - // TODO(jvoung): Make a generic load error, or just use ERROR_UNKNOWN? |
| - error_info.SetReport(ERROR_UNKNOWN, |
| - "PNaCl " + component + " load failed."); |
| - ReportLoadError(error_info); |
| + ReportPpapiError(pp_error, component + " load failed.\n"); |
| } |
| return -1; |
| } |
| int32_t file_desc_ok_to_close = DUP(file_desc); |
| if (file_desc_ok_to_close == NACL_NO_FILE_DESC) { |
| - // TODO(jvoung): Make a generic load error, or just use ERROR_UNKNOWN? |
| - error_info.SetReport(ERROR_UNKNOWN, |
| - "PNaCl " + component + " load failed: " |
| - "could not dup fd."); |
| - ReportLoadError(error_info); |
| + ReportPpapiError(PP_ERROR_FAILED, component + " could not dup fd.\n"); |
| return -1; |
| } |
| return file_desc_ok_to_close; |
| } |
| -bool PnaclCoordinator::StartLlcSubProcess() { |
| - ErrorInfo error_info; |
| - 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"); |
| - ReportLoadError(error_info); |
| - PnaclNonPpapiError(); |
| - return NULL; |
| +PnaclCoordinator::PnaclCoordinator(Plugin* plugin) |
| + : plugin_(plugin), |
| + translate_notify_callback_(pp::BlockUntilComplete()), |
| + llc_subprocess_(NULL), |
| + ld_subprocess_(NULL), |
| + subprocesses_should_die_(false) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::PnaclCoordinator (this=%p, plugin=%p)\n", |
| + static_cast<void*>(this), static_cast<void*>(plugin))); |
| + callback_factory_.Initialize(this); |
| + NaClXMutexCtor(&subprocess_mu_); |
| + // Initialize the file lookup related members. |
| + NaClXMutexCtor(&mu_); |
| + NaClXCondVarCtor(&cv_); |
| + // Open the temporary file system. |
| + file_system_.reset( |
| + new pp::FileSystem(plugin, PP_FILESYSTEMTYPE_LOCALTEMPORARY)); |
| + CHECK(file_system_ != NULL); |
| +} |
| + |
| +PnaclCoordinator::~PnaclCoordinator() { |
| + PLUGIN_PRINTF(("PnaclCoordinator::~PnaclCoordinator (this=%p)\n", |
| + static_cast<void*>(this))); |
| + // Join helper thread which will block the page from refreshing while a |
| + // translation is happening. |
| + if (translate_thread_.get() != NULL) { |
| + SetSubprocessesShouldDie(true); |
| + NaClThreadJoin(translate_thread_.get()); |
| } |
| - llc_subprocess_ = plugin_->nacl_subprocess(llc_id); |
| - return (llc_subprocess_ != NULL); |
| + NaClCondVarDtor(&cv_); |
| + NaClMutexDtor(&mu_); |
| + NaClMutexDtor(&subprocess_mu_); |
| } |
| -bool PnaclCoordinator::StartLdSubProcess() { |
| +void PnaclCoordinator::ReportNonPpapiError(const nacl::string& message) { |
| ErrorInfo error_info; |
| - 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"); |
| - ReportLoadError(error_info); |
| - PnaclNonPpapiError(); |
| - return NULL; |
| - } |
| - ld_subprocess_ = plugin_->nacl_subprocess(ld_id); |
| - return (ld_subprocess_ != NULL); |
| + error_info.SetReport(ERROR_UNKNOWN, |
| + nacl::string("PnaclCoordinator: ") + message); |
| + ReportPpapiError(PP_ERROR_FAILED, error_info); |
| } |
| -bool PnaclCoordinator::SubprocessesShouldDie() { |
| - nacl::MutexLocker ml(&subprocess_mu_); |
| - return subprocesses_should_die_; |
| +void PnaclCoordinator::ReportPpapiError(int32_t pp_error, |
| + const nacl::string& message) { |
| + ErrorInfo error_info; |
| + error_info.SetReport(ERROR_UNKNOWN, |
| + nacl::string("PnaclCoordinator: ") + message); |
| + ReportPpapiError(pp_error, error_info); |
| } |
| -void PnaclCoordinator::SetSubprocessesShouldDie(bool subprocesses_should_die) { |
| - nacl::MutexLocker ml(&subprocess_mu_); |
| - subprocesses_should_die_ = subprocesses_should_die; |
| +void PnaclCoordinator::ReportPpapiError(int32_t pp_error, |
| + const ErrorInfo& error_info) { |
| + plugin_->ReportLoadError(error_info); |
| + // Free all the intermediate callbacks we ever created. |
| + callback_factory_.CancelAll(); |
| + translate_notify_callback_.Run(pp_error); |
| } |
| -////////////////////////////////////////////////////////////////////// |
| -// First few callbacks. |
| +void PnaclCoordinator::PnaclDidFinish(int32_t pp_error) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::PnaclDidFinish (pp_error=%" |
| + NACL_PRId32")\n", pp_error)); |
| + if (pp_error != PP_OK) { |
| + ReportPpapiError(pp_error, error_info_); |
| + return; |
| + } |
| + // Transfer ownership of the nexe wrapper to the coordinator. |
| + // TODO(sehr): need to release the translation unit here while transferring. |
| + translated_fd_.reset(nexe_file_->read_wrapper()); |
| + plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress); |
| + translate_notify_callback_.Run(pp_error); |
| +} |
| -////////////////////////////////////////////////////////////////////// |
| - |
| -namespace { |
| -void AbortTranslateThread(PnaclTranslationUnit* translation_unit, |
| - const nacl::string& error_string) { |
| +void PnaclCoordinator::PnaclFailed(const nacl::string& error_string) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::PnaclFailed (error_string=%" |
| + NACL_PRId32")\n", error_string.c_str())); |
| pp::Core* core = pp::Module::Get()->core(); |
| - translation_unit->error_info.SetReport(ERROR_UNKNOWN, error_string); |
| - core->CallOnMainThread(0, translation_unit->translate_done_cb, |
| - PP_ERROR_FAILED); |
| + error_info_.SetReport(ERROR_UNKNOWN, |
| + nacl::string("PnaclCoordinator: ") + error_string); |
| + core->CallOnMainThread(0, translate_done_cb_, PP_ERROR_FAILED); |
| NaClThreadExit(1); |
| } |
| -void WINAPI DoTranslateThread(void* arg) { |
| - 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(); |
| +void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::ResourcesDidLoad (pp_error=%" |
| + NACL_PRId32")\n", pp_error)); |
| + if (pp_error != PP_OK) { |
| + ReportPpapiError(pp_error, "resources failed to load\n"); |
| + return; |
| + } |
| + // Open the local temporary file system to create the temporary files |
| + // for the object and nexe. |
| + pp::CompletionCallback cb = |
| + callback_factory_.NewCallback(&PnaclCoordinator::FileSystemDidOpen); |
| + if (!file_system_->Open(0, cb)) { |
| + ReportNonPpapiError("failed to open file system.\n"); |
| + } |
| +} |
| - // Set up LLC flags first. |
| - // TODO(jvoung): Bake these into the llc nexe? |
| - // May also want to improve scriptability, but the only thing we need |
| - // probably is PIC vs non-PIC and micro-arch specification. |
| - const char* llc_args_x8632[] = { "-march=x86", |
| - "-mcpu=pentium4", |
| - "-mtriple=i686-none-nacl-gnu", |
| - "-asm-verbose=false", |
| - "-filetype=obj" }; |
| - const char* llc_args_x8664[] = { "-march=x86-64", |
| - "-mcpu=core2", |
| - "-mtriple=x86_64-none-nacl-gnu", |
| - "-asm-verbose=false", |
| - "-filetype=obj" }; |
| - const char* llc_args_arm[] = { "-march=arm", |
| - "-mcpu=cortex-a8", |
| - "-mtriple=armv7a-none-nacl-gnueabi", |
| - "-asm-verbose=false", |
| - "-filetype=obj", |
| - "-arm-reserve-r9", |
| - "-sfi-disable-cp", |
| - "-arm_static_tls", |
| - "-sfi-store", |
| - "-sfi-load", |
| - "-sfi-stack", |
| - "-sfi-branch", |
| - "-sfi-data", |
| - "-no-inline-jumptables" }; |
| +void PnaclCoordinator::FileSystemDidOpen(int32_t pp_error) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::FileSystemDidOpen (pp_error=%" |
| + NACL_PRId32")\n", pp_error)); |
| + if (pp_error != PP_OK) { |
| + ReportPpapiError(pp_error, "file system didn't open.\n"); |
| + return; |
| + } |
| + // Create the object file pair for connecting llc and ld. |
| + obj_file_.reset(new PnaclFileDescPair(plugin_, file_system_.get(), this)); |
| + pp::CompletionCallback cb = |
| + callback_factory_.NewCallback(&PnaclCoordinator::ObjectPairDidOpen); |
| + obj_file_->Open(cb); |
| +} |
| - nacl::string sandbox_isa = GetSandboxISA(); |
| - const char** llc_args; |
| - size_t num_args; |
| - |
| - if (sandbox_isa.compare("x86-32") == 0) { |
| - llc_args = llc_args_x8632; |
| - num_args = NACL_ARRAY_SIZE(llc_args_x8632); |
| - } else if (sandbox_isa.compare("x86-64") == 0) { |
| - llc_args = llc_args_x8664; |
| - num_args = NACL_ARRAY_SIZE(llc_args_x8664); |
| - } else if (sandbox_isa.compare("arm") == 0) { |
| - llc_args = llc_args_arm; |
| - num_args = NACL_ARRAY_SIZE(llc_args_arm); |
| - } else { |
| - AbortTranslateThread(p, |
| - "PnaclCoordinator compiler unhandled ISA " + |
| - sandbox_isa + "."); |
| +void PnaclCoordinator::ObjectPairDidOpen(int32_t pp_error) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::ObjectPairDidOpen (pp_error=%" |
| + NACL_PRId32")\n", pp_error)); |
| + if (pp_error != PP_OK) { |
| + ReportPpapiError(pp_error, error_info_); |
| return; |
| } |
| + // Create the nexe file pair for connecting ld and sel_ldr. |
| + nexe_file_.reset(new PnaclFileDescPair(plugin_, file_system_.get(), this)); |
| + pp::CompletionCallback cb = |
| + callback_factory_.NewCallback(&PnaclCoordinator::NexePairDidOpen); |
| + nexe_file_->Open(cb); |
| +} |
| - for (uint32_t i = 0; i < num_args; i++) { |
| - if (coordinator->SubprocessesShouldDie()) { |
| - NaClThreadExit(1); |
| - } |
| - SrpcParams dummy_params; |
| - if (!PnaclSrpcLib::InvokeSrpcMethod(browser, |
| - llc_subprocess, |
| - "AddArg", |
| - "C", |
| - &dummy_params, |
| - llc_args[i])) { |
| - AbortTranslateThread(p, |
| - "PnaclCoordinator compiler AddArg(" + |
| - nacl::string(llc_args[i]) + ") failed."); |
| - } |
| +void PnaclCoordinator::NexePairDidOpen(int32_t pp_error) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::NexePairDidOpen (pp_error=%" |
| + NACL_PRId32")\n", pp_error)); |
| + if (pp_error != PP_OK) { |
| + ReportPpapiError(pp_error, error_info_); |
| + return; |
| } |
| + // Load the pexe file and get the translation started. |
| + pp::CompletionCallback cb = |
| + callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate); |
| - if (coordinator->SubprocessesShouldDie()) { |
| - NaClThreadExit(1); |
| + if (!plugin_->StreamAsFile(pexe_url_, cb.pp_completion_callback())) { |
| + ReportNonPpapiError(nacl::string("failed to download ") + pexe_url_ + "\n"); |
| } |
| - SrpcParams params; |
| - if (!PnaclSrpcLib::InvokeSrpcMethod(browser, |
| - llc_subprocess, |
| - "Translate", |
| - "h", |
| - ¶ms, |
| - p->pexe_wrapper->desc())) { |
| - AbortTranslateThread(p, |
| - "PnaclCoordinator compile failed."); |
| - } else { |
| - // Grab the outparams. |
| - p->obj_wrapper.reset( |
| - plugin->wrapper_factory()->MakeGeneric(params.outs()[0]->u.hval)); |
| - p->obj_len = params.outs()[1]->u.ival; |
| - p->is_shared_library = params.outs()[2]->u.ival != 0; |
| - 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 (coordinator->SubprocessesShouldDie()) { |
| - NaClThreadExit(1); |
| - } |
| - pp::Core* core = pp::Module::Get()->core(); |
| - core->CallOnMainThread(0, p->translate_done_cb, PP_OK); |
| - NaClThreadExit(0); |
| } |
| -} // namespace |
| - |
| -void PnaclCoordinator::RunTranslate(int32_t pp_error, |
| - const nacl::string& pexe_url, |
| - PnaclTranslationUnit* translation_unit) { |
| +void PnaclCoordinator::RunTranslate(int32_t pp_error) { |
| PLUGIN_PRINTF(("PnaclCoordinator::RunTranslate (pp_error=%" |
| NACL_PRId32")\n", pp_error)); |
| - // pp_error is checked by GetLoadedFileDesc. |
| - int32_t fd = GetLoadedFileDesc(pp_error, pexe_url, "pexe"); |
| + int32_t fd = GetLoadedFileDesc(pp_error, pexe_url_, "pexe"); |
| if (fd < 0) { |
| - PnaclPpapiError(pp_error); |
| return; |
| } |
| - 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(); |
| + pexe_wrapper_.reset(plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY)); |
| + llc_subprocess_ = StartSubprocess(kLlcUrl); |
| + if (llc_subprocess_ == NULL) { |
| + ReportNonPpapiError("could not start compiler subprocess\n"); |
| return; |
| } |
| - // Invoke llvm asynchronously. |
| - // RunLink runs on the main thread when llvm is done. |
| - translation_unit->translate_done_cb = |
| - callback_factory_.NewCallback(&PnaclCoordinator::RunLink, |
| - translation_unit); |
| + ld_subprocess_ = StartSubprocess(kLdUrl); |
| + if (ld_subprocess_ == NULL) { |
| + ReportNonPpapiError("could not start linker subprocess\n"); |
| + return; |
| + } |
| + // Invoke llc followed by ld off the main thread. This allows use of |
| + // blocking RPCs that would otherwise block the JavaScript main thread. |
| + translate_done_cb_ = |
| + callback_factory_.NewCallback(&PnaclCoordinator::PnaclDidFinish); |
| translate_thread_.reset(new NaClThread); |
| if (translate_thread_ == NULL) { |
| - ErrorInfo error_info; |
| - error_info.SetReport(ERROR_UNKNOWN, |
| - "Could not allocate DoTranslateThread()\n"); |
| - ReportLoadError(error_info); |
| - PnaclNonPpapiError(); |
| + ReportNonPpapiError("could not allocate thread struct\n"); |
| return; |
| } |
| + const int32_t kArbitraryStackSize = 128 << 10; |
| if (!NaClThreadCreateJoinable(translate_thread_.get(), |
| DoTranslateThread, |
| - translation_unit, |
| + this, |
| kArbitraryStackSize)) { |
| - ErrorInfo error_info; |
| - error_info.SetReport(ERROR_UNKNOWN, |
| - "Could not create a translator thread.\n"); |
| - ReportLoadError(error_info); |
| - PnaclNonPpapiError(); |
| + ReportNonPpapiError("could not create thread\n"); |
| } |
| } |
| -////////////////////////////////////////////////////////////////////// |
| -// Helper functions for loading native libs. |
| -// Done here to avoid hacking on the manifest parser further... |
| - |
| -namespace { |
| - |
| -// Fake filename for the object file generated by llvm. |
| -nacl::string GeneratedObjectFileName() { |
| - return nacl::string("___PNACL_GENERATED"); |
| -} |
| - |
| -nacl::string ResourceBaseUrl() { |
| - nacl::string sandbox_isa = GetSandboxISA(); |
| - nacl::string base_url = "pnacl_support/" + sandbox_isa + "/"; |
| - return base_url; |
| -} |
| - |
| -string_vector LinkResources(const nacl::string& sandbox_isa, |
| - bool withGenerated) { |
| - string_vector results; |
| - // NOTE: order of items == link order. |
| - if (sandbox_isa.compare("x86-64") == 0) { |
| - results.push_back("libpnacl_irt_shim.a"); |
| +NaClSubprocess* PnaclCoordinator::StartSubprocess(const nacl::string& url) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::StartSubprocess (url=%s)\n", url.c_str())); |
| + ErrorInfo error_info; |
| + nacl::DescWrapper* wrapper = resources_->WrapperForUrl(url); |
| + NaClSubprocessId id = plugin_->LoadHelperNaClModule(wrapper, &error_info); |
|
jvoung - send to chromium...
2011/12/13 03:14:33
The error_info here is set but dropped. Would it
sehr (please use chromium)
2011/12/13 20:05:04
I goofed bonding the error_info_ member variable t
|
| + if (kInvalidNaClSubprocessId == id) { |
| + return NULL; |
| } |
| - results.push_back("crtbegin.o"); |
| - if (withGenerated) { |
| - results.push_back(GeneratedObjectFileName()); |
| - } |
| - results.push_back("libcrt_platform.a"); |
| - results.push_back("libgcc.a"); |
| - results.push_back("libgcc_eh.a"); |
| - results.push_back("crtend.o"); |
| - return results; |
| + return plugin_->nacl_subprocess(id); |
| } |
| -} // namespace |
| - |
| -////////////////////////////////////////////////////////////////////// |
| -// Final link callbacks. |
| - |
| -namespace { |
| - |
| -void AbortLinkThread(PnaclTranslationUnit* translation_unit, |
| - const nacl::string& error_string) { |
| - ErrorInfo error_info; |
| - pp::Core* core = pp::Module::Get()->core(); |
| - translation_unit->error_info.SetReport(ERROR_UNKNOWN, error_string); |
| - core->CallOnMainThread(0, translation_unit->link_done_cb, PP_ERROR_FAILED); |
| - NaClThreadExit(1); |
| -} |
| - |
| -void WINAPI DoLinkThread(void* arg) { |
| - PnaclTranslationUnit* p = reinterpret_cast<PnaclTranslationUnit*>(arg); |
| - PnaclCoordinator* coordinator = p->coordinator; |
| - NaClSubprocess* ld_subprocess = coordinator->ld_subprocess(); |
| - Plugin* plugin = coordinator->plugin(); |
| +void WINAPI PnaclCoordinator::DoTranslateThread(void* arg) { |
| + PnaclCoordinator* coordinator = reinterpret_cast<PnaclCoordinator*>(arg); |
| + Plugin* plugin = coordinator->plugin_; |
| BrowserInterface* browser_interface = plugin->browser_interface(); |
| - // Set up command line arguments (flags then files). |
| - |
| - //// Flags. |
| - // TODO(jvoung): Be able to handle the dynamic linking flags too, |
| - // and don't hardcode so much here. |
| - string_vector flags; |
| - nacl::string sandbox_isa = GetSandboxISA(); |
| - flags.push_back("-nostdlib"); |
| - flags.push_back("-m"); |
| - if (sandbox_isa.compare("x86-32") == 0) { |
| - flags.push_back("elf_nacl"); |
| - } else if (sandbox_isa.compare("x86-64") == 0) { |
| - flags.push_back("elf64_nacl"); |
| - flags.push_back("-entry=_pnacl_wrapper_start"); |
| - } else if (sandbox_isa.compare("arm") == 0) { |
| - flags.push_back("armelf_nacl"); |
| - } else { |
| - AbortLinkThread(p, |
| - "PnaclCoordinator linker unhandled ISA " + |
| - sandbox_isa + "."); |
| + // Run LLC. |
| + SrpcParams params; |
| + nacl::DescWrapper* llc_out_file = coordinator->obj_file_->write_wrapper(); |
| + if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface, |
| + coordinator->llc_subprocess_, |
| + "RunWithDefaultCommandLine", |
| + "hh", |
| + ¶ms, |
| + coordinator->pexe_wrapper_->desc(), |
| + llc_out_file->desc())) { |
| + coordinator->PnaclFailed("compile failed."); |
| } |
| - |
| - for (string_vector::iterator i = flags.begin(), e = flags.end(); |
| - i != e; ++i) { |
| - const nacl::string& flag = *i; |
| - if (coordinator->SubprocessesShouldDie()) { |
| - NaClThreadExit(1); |
| - } |
| - SrpcParams dummy_params; |
| - if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface, |
| - ld_subprocess, |
| - "AddArg", |
| - "C", |
| - &dummy_params, |
| - flag.c_str())) { |
| - AbortLinkThread(p, |
| - "PnaclCoordinator linker AddArg(" + flag + |
| - ") failed."); |
| - } |
| - } |
| - |
| - //// Files. |
| - 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 (coordinator->SubprocessesShouldDie()) { |
| - NaClThreadExit(1); |
| - } |
| - // Add as argument. |
| - SrpcParams dummy_params; |
| - if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface, |
| - ld_subprocess, |
| - "AddArg", |
| - "C", |
| - &dummy_params, |
| - link_file.c_str())) { |
| - AbortLinkThread(p, |
| - "PnaclCoordinator linker AddArg(" + |
| - link_file + ") failed."); |
| - } |
| - // Also map the file name to descriptor. |
| - if (i->compare(GeneratedObjectFileName()) == 0) { |
| - SrpcParams dummy_params2; |
| - if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface, |
| - ld_subprocess, |
| - "AddFileWithSize", |
| - "Chi", |
| - &dummy_params2, |
| - link_file.c_str(), |
| - p->obj_wrapper->desc(), |
| - p->obj_len)) { |
| - AbortLinkThread(p, |
| - "PnaclCoordinator linker AddFileWithSize" |
| - "(" + link_file + ") failed."); |
| - } |
| - } 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(), |
| - link_file_desc)) { |
| - AbortLinkThread(p, |
| - "PnaclCoordinator linker AddFile(" + link_file + |
| - ") failed."); |
| - } |
| - } |
| - } |
| - |
| + // LLC returns values that are used to determine how linking is cone. |
|
jvoung - send to chromium...
2011/12/13 03:14:33
cone -> done
sehr (please use chromium)
2011/12/13 20:05:04
Done.
|
| + int is_shared_library = (params.outs()[0]->u.ival != 0); |
| + nacl::string soname = params.outs()[1]->arrays.str; |
| + nacl::string lib_dependencies = params.outs()[2]->arrays.str; |
| + PLUGIN_PRINTF(("PnaclCoordinator: compile (coordinator=%p) succeeded" |
| + " is_shared_library=%d, soname='%s', lib_dependencies='%s')\n", |
| + arg, is_shared_library, soname.c_str(), |
| + lib_dependencies.c_str())); |
| if (coordinator->SubprocessesShouldDie()) { |
| NaClThreadExit(1); |
| } |
| - |
| - // Finally, do the Link! |
| - SrpcParams params; |
| + // Set up the lookup service for filename to handle resolution. |
| + NaClSrpcService* service = |
| + reinterpret_cast<NaClSrpcService*>(calloc(1, sizeof(*service))); |
| + if (NULL == service) { |
| + coordinator->PnaclFailed("lookup service alloc failed."); |
| + } |
| + if (!NaClSrpcServiceHandlerCtor(service, lookup_methods)) { |
| + free(service); |
| + coordinator->PnaclFailed("lookup service constructor failed."); |
| + } |
| + char* service_string = const_cast<char*>(service->service_string); |
| + NaClSubprocess* ld_subprocess = coordinator->ld_subprocess_; |
| + ld_subprocess->srpc_client()->AttachService(service, coordinator); |
| + nacl::DescWrapper* ld_out_file = coordinator->nexe_file_->write_wrapper(); |
| if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface, |
| ld_subprocess, |
| - "Link", |
| - "", |
| - ¶ms)) { |
| - AbortLinkThread(p, "PnaclCoordinator link failed."); |
| - } else { |
| - // Grab the outparams. |
| - 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)); |
| + "RunWithDefaultCommandLine", |
| + "ChiCC", |
| + ¶ms, |
| + service_string, |
| + ld_out_file->desc(), |
| + is_shared_library, |
| + soname.c_str(), |
| + lib_dependencies.c_str())) { |
| + coordinator->PnaclFailed("link failed."); |
| } |
| + PLUGIN_PRINTF(("PnaclCoordinator: link (coordinator=%p) succeeded\n", arg)); |
| if (coordinator->SubprocessesShouldDie()) { |
| NaClThreadExit(1); |
| } |
| pp::Core* core = pp::Module::Get()->core(); |
| - core->CallOnMainThread(0, p->link_done_cb, PP_OK); |
| + core->CallOnMainThread(0, coordinator->translate_done_cb_, PP_OK); |
| NaClThreadExit(0); |
| } |
| -} // namespace |
| +bool PnaclCoordinator::SubprocessesShouldDie() { |
| + nacl::MutexLocker ml(&subprocess_mu_); |
| + return subprocesses_should_die_; |
| +} |
| -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; |
| - } |
| - plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress); |
| - if (!StartLdSubProcess()) { |
| - ErrorInfo error_info; |
| - error_info.SetReport(ERROR_UNKNOWN, |
| - "Could not start linker subprocess\n"); |
| - ReportLoadError(error_info); |
| - PnaclNonPpapiError(); |
| - return; |
| - } |
| +void PnaclCoordinator::SetSubprocessesShouldDie(bool subprocesses_should_die) { |
| + nacl::MutexLocker ml(&subprocess_mu_); |
| + subprocesses_should_die_ = subprocesses_should_die; |
| +} |
| - // Invoke ld asynchronously. |
| - // When ld has completed, PnaclDidFinish is run on the main thread. |
| - translation_unit->link_done_cb = |
| - callback_factory_.NewCallback(&PnaclCoordinator::PnaclDidFinish, |
| - translation_unit); |
| - link_thread_.reset(new NaClThread); |
| - if (link_thread_ == NULL) { |
| - ErrorInfo error_info; |
| - error_info.SetReport(ERROR_UNKNOWN, |
| - "Could not allocate DoLinkThread()\n"); |
| - ReportLoadError(error_info); |
| - PnaclNonPpapiError(); |
| - return; |
| +void PnaclCoordinator::LoadOneFile(int32_t pp_error, |
| + const nacl::string& url, |
| + nacl::DescWrapper** wrapper, |
| + pp::CompletionCallback& done_cb) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::LoadOneFile (pp_error=%" |
| + NACL_PRId32", url=%s)\n", pp_error, url.c_str())); |
| + const nacl::string& full_url = resource_base_url_ + url; |
| + pp::CompletionCallback callback = |
| + callback_factory_.NewCallback(&PnaclCoordinator::DidLoadFile, |
| + full_url, |
| + wrapper, |
| + done_cb); |
| + if (!plugin_->StreamAsFile(full_url, callback.pp_completion_callback())) { |
| + ReportNonPpapiError(nacl::string("failed to load ") + url + "\n"); |
| } |
| - 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(); |
| - } |
| } |
| -////////////////////////////////////////////////////////////////////// |
| - |
| -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); |
| +void PnaclCoordinator::DidLoadFile(int32_t pp_error, |
| + const nacl::string& full_url, |
| + nacl::DescWrapper** wrapper, |
| + pp::CompletionCallback& done_cb) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::DidLoadFile (pp_error=%" |
| + NACL_PRId32", url=%s)\n", pp_error, full_url.c_str())); |
| + int32_t fd = GetLoadedFileDesc(pp_error, full_url, "resource"); |
| + if (fd < 0) { |
| return; |
| } |
| - pp::CompletionCallback cb = |
| - callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate, |
| - pexe_url, |
| - translation); |
| + *wrapper = plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY); |
| + done_cb.Run(PP_OK); |
| +} |
| - if (!plugin_->StreamAsFile(pexe_url, cb.pp_completion_callback())) { |
| - ErrorInfo error_info; |
| - error_info.SetReport(ERROR_UNKNOWN, |
| - "PnaclCoordinator: Failed to download file: " + |
| - pexe_url + "\n"); |
| - ReportLoadError(error_info); |
| - PnaclNonPpapiError(); |
| - } |
| +void PnaclCoordinator::ResumeLookup(int32_t pp_error) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::ResumeLookup (pp_error=%" |
| + NACL_PRId32", url=%s)\n", pp_error)); |
| + UNREFERENCED_PARAMETER(pp_error); |
| + nacl::MutexLocker ml(&mu_); |
| + lookup_is_complete_ = true; |
| + NaClXCondVarBroadcast(&cv_); |
| } |
| -void PnaclCoordinator::BitcodeToNative( |
| - const nacl::string& pexe_url, |
| - const pp::CompletionCallback& finish_callback) { |
| - PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (pexe=%s)\n", |
| - pexe_url.c_str())); |
| - // The base URL for finding all the resources will be obtained from the |
| - // PNaCl manifest file. |
| - // Also, the llc and ld pathnames should be read from the manifest. |
| - // TODO(sehr): change to use the manifest file when ready. |
| - resource_base_url_ = ResourceBaseUrl(); |
| - llc_url_ = "llc"; |
| - ld_url_ = "ld"; |
| - translate_notify_callback_ = finish_callback; |
| - |
| - // Steps: |
| - // (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. |
| - |
| - translation_unit_.reset(new PnaclTranslationUnit(this)); |
| - |
| - // When resources loading completes, this causes the pexe download. |
| - pp::CompletionCallback resources_cb = |
| - callback_factory_.NewCallback(&PnaclCoordinator::ResourcesDidLoad, |
| - pexe_url, |
| - translation_unit_.get()); |
| - 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) { |
| - resources_->AddResourceUrl(*i); |
| +struct NaClDesc* PnaclCoordinator::LookupDesc(const nacl::string& url) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::LookupDesc (url=%s)\n", url.c_str())); |
| + // This filename is part of the contract with the linker. |
| + // TODO(sehr): Pass the FD in, and move lookup for this file to the linker. |
| + const nacl::string kGeneratedObjectFileName = "___PNACL_GENERATED"; |
| + if (url == kGeneratedObjectFileName) { |
| + return obj_file_->read_wrapper()->desc(); |
| } |
| - resources_->RunWhenAllLoaded(resources_cb); |
| - resources_->StartDownloads(); |
| + nacl::DescWrapper* wrapper; |
| + // Create the callback used to report when lookup is done. |
| + pp::CompletionCallback resume_cb = |
| + callback_factory_.NewCallback(&PnaclCoordinator::ResumeLookup); |
| + // Run the lookup request on the main thread. |
| + lookup_is_complete_ = false; |
| + pp::CompletionCallback load_cb = |
| + callback_factory_.NewCallback(&PnaclCoordinator::LoadOneFile, |
| + url, &wrapper, resume_cb); |
| + pp::Core* core = pp::Module::Get()->core(); |
| + core->CallOnMainThread(0, load_cb, PP_OK); |
| + // Wait for completion (timeout every 10ms to check for process end). |
| + const int32_t kTenMilliseconds = 10 * 1000 * 1000; |
| + NACL_TIMESPEC_T reltime; |
| + reltime.tv_sec = 0; |
| + reltime.tv_nsec = kTenMilliseconds; |
| + NaClXMutexLock(&mu_); |
| + while (!lookup_is_complete_) { |
| + // Check for termination. |
| + if (SubprocessesShouldDie()) { |
| + NaClXMutexUnlock(&mu_); |
| + NaClThreadExit(0); |
| + } |
| + NaClXCondVarTimedWaitRelative(&cv_, &mu_, &reltime); |
| + } |
| + NaClXMutexUnlock(&mu_); |
| + return wrapper->desc(); |
| } |
| } // namespace plugin |