| Index: ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h
|
| ===================================================================
|
| --- ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h (revision 114253)
|
| +++ ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h (working copy)
|
| @@ -12,169 +12,304 @@
|
| #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_sync_raii.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_rng.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_resources.h"
|
|
|
| +#include "ppapi/c/pp_file_info.h"
|
| #include "ppapi/cpp/completion_callback.h"
|
| +#include "ppapi/cpp/file_io.h"
|
| +#include "ppapi/cpp/file_ref.h"
|
| +#include "ppapi/cpp/file_system.h"
|
|
|
| struct NaClMutex;
|
| +struct PPB_FileIOTrusted;
|
|
|
| namespace plugin {
|
|
|
| class Plugin;
|
| class PnaclCoordinator;
|
|
|
| -struct PnaclTranslationUnit {
|
| - PnaclTranslationUnit(PnaclCoordinator* coord)
|
| - : coordinator(coord),
|
| - obj_len(-1),
|
| - is_shared_library(false),
|
| - soname(""),
|
| - lib_dependencies("") {
|
| - }
|
| - // Punch hole in abstraction.
|
| - PnaclCoordinator* coordinator;
|
| +// Translation creates two temporary files. The first temporary file holds
|
| +// the object file created by llc. The second holds the nexe produced by
|
| +// the linker. Both of these temporary files are used to both write and
|
| +// read according to the following matrix:
|
| +//
|
| +// PnaclCoordinator::obj_file_:
|
| +// written by: llc (passed in explicitly through SRPC)
|
| +// read by: ld (returned via lookup service from SRPC)
|
| +// PnaclCoordinator::nexe_file_:
|
| +// written by: lc (passed in explicitly through SRPC)
|
| +// read by: sel_ldr (passed in explicitly to command channel)
|
| +//
|
|
|
| - // Borrowed reference which must outlive the thread.
|
| - nacl::scoped_ptr<nacl::DescWrapper> pexe_wrapper;
|
| +// PnaclFileDescPair represents a file used as a temporary between stages in
|
| +// translation. It is created in the local temporary file system of the page
|
| +// being processed. The name of the temporary file is a random 32-character
|
| +// hex string. Because both reading and writing are necessary, two I/O objects
|
| +// for the file are opened.
|
| +class PnaclFileDescPair {
|
| + public:
|
| + PnaclFileDescPair(Plugin* plugin,
|
| + pp::FileSystem* file_system,
|
| + PnaclCoordinator* coordinator);
|
| + ~PnaclFileDescPair();
|
| + // Opens a pair of file IO objects referring to a randomly named file in
|
| + // file_system_. One IO is for writing the file and another for reading it.
|
| + void Open(const pp::CompletionCallback& cb);
|
| + // Accessors.
|
| + // The nacl::DescWrapper* for the writeable version of the file.
|
| + nacl::DescWrapper* write_wrapper() { return write_wrapper_.get(); }
|
| + // The nacl::DescWrapper* for the read-only version of the file.
|
| + nacl::DescWrapper* read_wrapper() { return read_wrapper_.get(); }
|
|
|
| - // Object file produced by translator and consumed by the linker.
|
| - nacl::scoped_ptr<nacl::DescWrapper> obj_wrapper;
|
| - int32_t obj_len;
|
| + private:
|
| + NACL_DISALLOW_COPY_AND_ASSIGN(PnaclFileDescPair);
|
|
|
| - // Information extracted from the pexe that is needed by the linker.
|
| - bool is_shared_library;
|
| - nacl::string soname;
|
| - nacl::string lib_dependencies;
|
| + // Gets the POSIX file descriptor for a resource.
|
| + int32_t GetFD(int32_t pp_error,
|
| + const pp::Resource& resource,
|
| + bool is_writable);
|
| + // Called when the writable file IO was opened.
|
| + void WriteFileDidOpen(int32_t pp_error);
|
| + // Called when the readable file IO was opened.
|
| + void ReadFileDidOpen(int32_t pp_error);
|
|
|
| - // The translated user nexe file.
|
| - nacl::scoped_ptr<nacl::DescWrapper> nexe_wrapper;
|
| + Plugin* plugin_;
|
| + pp::FileSystem* file_system_;
|
| + PnaclCoordinator* coordinator_;
|
| + const PPB_FileIOTrusted* file_io_trusted_;
|
| + pp::CompletionCallbackFactory<PnaclFileDescPair> callback_factory_;
|
| + nacl::string filename_;
|
| + // The PPAPI and wrapper state for the writeable file.
|
| + nacl::scoped_ptr<pp::FileRef> write_ref_;
|
| + nacl::scoped_ptr<pp::FileIO> write_io_;
|
| + nacl::scoped_ptr<nacl::DescWrapper> write_wrapper_;
|
| + // The PPAPI and wrapper state for the read-only file.
|
| + nacl::scoped_ptr<pp::FileRef> read_ref_;
|
| + nacl::scoped_ptr<pp::FileIO> read_io_;
|
| + nacl::scoped_ptr<nacl::DescWrapper> read_wrapper_;
|
| + // The callback invoked when both file I/O objects are created.
|
| + pp::CompletionCallback done_callback_;
|
| + // Random number generator used to create filenames.
|
| + struct NaClDescRng rng_desc_;
|
| +};
|
|
|
| - // Callbacks to run when tasks or completed or an error has occurred.
|
| - pp::CompletionCallback translate_done_cb;
|
| - pp::CompletionCallback link_done_cb;
|
| +// A thread safe reference counting class Needed for CompletionCallbackFactory
|
| +// in PnaclCoordinator.
|
| +class PnaclRefCount {
|
| + public:
|
| + PnaclRefCount() : ref_(0) { NaClXMutexCtor(&mu_); }
|
| + ~PnaclRefCount() { NaClMutexDtor(&mu_); }
|
| + int32_t AddRef() {
|
| + nacl::MutexLocker ml(&mu_);
|
| + return ++ref_;
|
| + }
|
| + int32_t Release() {
|
| + nacl::MutexLocker ml(&mu_);
|
| + return --ref_;
|
| + }
|
|
|
| - ErrorInfo error_info;
|
| + private:
|
| + int32_t ref_;
|
| + struct NaClMutex mu_;
|
| };
|
|
|
| -
|
| -typedef std::pair<nacl::string, pp::CompletionCallback> url_callback_pair;
|
| -
|
| -// A class that handles PNaCl client-side translation.
|
| +// A class invoked by Plugin to handle PNaCl client-side translation.
|
| // Usage:
|
| -// (1) Initialize();
|
| -// (2) BitcodeToNative(bitcode, ..., finish_callback);
|
| -// (3) After finish_callback runs, do:
|
| -// fd = ReleaseTranslatedFD();
|
| -// (4) go ahead and load the nexe from "fd"
|
| -// (5) delete
|
| +// (1) Invoke the factory method, e.g.,
|
| +// PnaclCoordinator* coord = BitcodeToNative(plugin,
|
| +// "http://foo.com/my.pexe",
|
| +// TranslateNotifyCallback);
|
| +// (2) TranslateNotifyCallback gets invoked when translation is complete.
|
| +// If the translation was successful, the pp_error argument is PP_OK.
|
| +// Other values indicate errors.
|
| +// (3) After finish_callback runs, get the file descriptor of the translated
|
| +// nexe, e.g.,
|
| +// fd = coord->ReleaseTranslatedFD();
|
| +// (4) Load the nexe from "fd".
|
| +// (5) delete coord.
|
| +//
|
| +// Translation proceeds in two steps:
|
| +// (1) llc translates the bitcode in pexe_url_ to an object in obj_file_.
|
| +// (2) ld links the object code in obj_file_ and produces a nexe in nexe_file_.
|
| +//
|
| +// The coordinator proceeds through several states. They are
|
| +// LOAD_TRANSLATOR_BINARIES
|
| +// Complete when ResourcesDidLoad is invoked.
|
| +// OPEN_LOCAL_FILE_SYSTEM
|
| +// Complete when FileSystemDidOpen is invoked.
|
| +// OPEN_TMP_FOP_LLC_TO_LD_COMMUNICATION
|
| +// Complete when ObjectPairDidOpen is invoked.
|
| +// OPEN_TMP_FOR_LD_TO_SEL_LDR_COMMUNICATION
|
| +// Complete when NexePairDidOpen is invoked.
|
| +// PREPARE_PEXE_FOR_STREAMING
|
| +// Complete when RunTranslate is invoked.
|
| +// START_LD_AND_LLC_SUBPROCESS_AND_INITIATE_TRANSLATION
|
| +// Complete when RunTranslate returns.
|
| +// TRANSLATION_COMPLETE
|
| +// Complete when TranslateFinished is invoked.
|
| +//
|
| +// It should be noted that at the moment we are not properly freeing the
|
| +// PPAPI resources used for the temporary files used in translation. Until
|
| +// that is fixed, (4) and (5) should be done in that order.
|
| +// TODO(sehr): Fix freeing of temporary files.
|
| class PnaclCoordinator {
|
| public:
|
| - PnaclCoordinator()
|
| - : plugin_(NULL),
|
| - translate_notify_callback_(pp::BlockUntilComplete()),
|
| - llc_subprocess_(NULL),
|
| - ld_subprocess_(NULL),
|
| - subprocesses_should_die_(false) {
|
| - NaClXMutexCtor(&subprocess_mu_);
|
| - }
|
| -
|
| virtual ~PnaclCoordinator();
|
|
|
| - // Initialize() can only be called once during the lifetime of this instance.
|
| - void Initialize(Plugin* instance);
|
| + // The factory method for translations.
|
| + static PnaclCoordinator* BitcodeToNative(
|
| + Plugin* plugin,
|
| + const nacl::string& pexe_url,
|
| + const pp::CompletionCallback& translate_notify_callback);
|
|
|
| - void BitcodeToNative(const nacl::string& pexe_url,
|
| - const pp::CompletionCallback& finish_callback);
|
| -
|
| // Call this to take ownership of the FD of the translated nexe after
|
| // BitcodeToNative has completed (and the finish_callback called).
|
| - nacl::DescWrapper* ReleaseTranslatedFD() {
|
| - return translated_fd_.release();
|
| - }
|
| + nacl::DescWrapper* ReleaseTranslatedFD() { return translated_fd_.release(); }
|
|
|
| + // Looks up a file descriptor for an url that was already downloaded.
|
| + // This is used for getting the descriptor for llc and ld nexes as well
|
| + // as the libraries and object files used by the linker.
|
| int32_t GetLoadedFileDesc(int32_t pp_error,
|
| const nacl::string& url,
|
| const nacl::string& component);
|
|
|
| - // Run when faced with a PPAPI error condition. It brings control back to the
|
| - // plugin by invoking the |translate_notify_callback_|.
|
| - void PnaclPpapiError(int32_t pp_error);
|
| // Run |translate_notify_callback_| with an error condition that is not
|
| // PPAPI specific.
|
| - void PnaclNonPpapiError();
|
| - // Wrapper for Plugin ReportLoadAbort.
|
| - void ReportLoadAbort();
|
| - // Wrapper for Plugin ReportLoadError.
|
| - void ReportLoadError(const ErrorInfo& error);
|
| + void ReportNonPpapiError(const nacl::string& message);
|
| + // Run when faced with a PPAPI error condition. Bring control back to the
|
| + // plugin by invoking the |translate_notify_callback_|.
|
| + void ReportPpapiError(int32_t pp_error, const nacl::string& message);
|
| + void ReportPpapiError(int32_t pp_error);
|
|
|
| - // Accessors for use by helper threads.
|
| - nacl::string resource_base_url() const { return resource_base_url_; }
|
| - Plugin* plugin() const { return plugin_; }
|
| - nacl::string llc_url() const { return llc_url_; }
|
| - NaClSubprocess* llc_subprocess() const { return llc_subprocess_; }
|
| - bool StartLlcSubProcess();
|
| - nacl::string ld_url() const { return ld_url_; }
|
| - NaClSubprocess* ld_subprocess() const { return ld_subprocess_; }
|
| - bool StartLdSubProcess();
|
| - bool SubprocessesShouldDie();
|
| - void SetSubprocessesShouldDie(bool subprocesses_should_die);
|
| - PnaclResources* resources() const { return resources_.get(); }
|
| + private:
|
| + NACL_DISALLOW_COPY_AND_ASSIGN(PnaclCoordinator);
|
|
|
| - protected:
|
| + // BitcodeToNative is the factory method for PnaclCoordinators.
|
| + // Therefore the constructor is private.
|
| + PnaclCoordinator(Plugin* plugin,
|
| + const nacl::string& pexe_url,
|
| + const pp::CompletionCallback& translate_notify_callback,
|
| + const nacl::string& resource_base_url);
|
|
|
| - // Callbacks for when various files, etc. have been downloaded.
|
| - void ResourcesDidLoad(int32_t pp_error,
|
| - const nacl::string& url,
|
| - PnaclTranslationUnit* translation_unit);
|
| + // Callback for when llc and ld have been downloaded.
|
| + // This is the first callback invoked in response to BitcodeToNative.
|
| + void ResourcesDidLoad(int32_t pp_error);
|
|
|
| - // Callbacks for compute-based translation steps.
|
| - void RunTranslate(int32_t pp_error,
|
| - const nacl::string& url,
|
| - PnaclTranslationUnit* translation_unit);
|
| - void RunLink(int32_t pp_error, PnaclTranslationUnit* translation_unit);
|
| + // Callbacks for temporary file related stages.
|
| + // They are invoked from ResourcesDidLoad and proceed in declaration order.
|
| + // Invoked when the temporary file system is successfully opened in PPAPI.
|
| + void FileSystemDidOpen(int32_t pp_error);
|
| + // Invoked when the obj_file_ temporary file I/O pair is created.
|
| + void ObjectPairDidOpen(int32_t pp_error);
|
| + // Invoked when the nexe_file_ temporary file I/O pair is created.
|
| + void NexePairDidOpen(int32_t pp_error);
|
|
|
| - // Pnacl translation completed normally.
|
| - void PnaclDidFinish(int32_t pp_error, PnaclTranslationUnit* translation_unit);
|
| + // Once llc and ld nexes have been loaded and the two temporary files have
|
| + // been created, this starts the translation. Translation starts two
|
| + // subprocesses, one for llc and one for ld.
|
| + void RunTranslate(int32_t pp_error);
|
| + // Starts an individual llc or ld subprocess used for translation.
|
| + NaClSubprocess* StartSubprocess(const nacl::string& url);
|
| + // PnaclCoordinator creates a helper thread to allow translations to be
|
| + // invoked via SRPC. This is the helper thread function for translation.
|
| + static void WINAPI DoTranslateThread(void* arg);
|
| + // Returns true if a the translate thread and subprocesses should stop.
|
| + bool SubprocessesShouldDie();
|
| + // Signal the translate thread and subprocesses that they should stop.
|
| + void SetSubprocessesShouldDie(bool subprocesses_should_die);
|
| + // Signal that Pnacl translation completed normally.
|
| + void TranslateFinished(int32_t pp_error);
|
| + // Signal that Pnacl translation failed, from the translation thread only.
|
| + void TranslateFailed(const nacl::string& error_string);
|
|
|
| - private:
|
| - NACL_DISALLOW_COPY_AND_ASSIGN(PnaclCoordinator);
|
| + // Support for file lookups needed for ld.
|
| + // TODO(sehr): remove this when file lookup is through ReverseService.
|
| + // Invoked on the main thread on behalf of the lookup service to start
|
| + // loading a particular URL.
|
| + void LoadOneFile(int32_t pp_error,
|
| + const nacl::string& url,
|
| + nacl::DescWrapper** wrapper,
|
| + pp::CompletionCallback& done_cb);
|
| + // Invoked by the renderer when the file was loaded.
|
| + void DidLoadFile(int32_t pp_error,
|
| + const nacl::string& full_url,
|
| + nacl::DescWrapper** wrapper,
|
| + pp::CompletionCallback& done_cb);
|
| + // Signals the waiting lookup service to resume.
|
| + void ResumeLookup(int32_t pp_error);
|
|
|
| + // The plugin owning the nexe for which we are doing translation.
|
| Plugin* plugin_;
|
| +
|
| pp::CompletionCallback translate_notify_callback_;
|
| - pp::CompletionCallbackFactory<PnaclCoordinator> callback_factory_;
|
| + // PnaclRefCount is only needed to support file lookups.
|
| + // TODO(sehr): remove this when file lookup is through ReverseService.
|
| + pp::CompletionCallbackFactory<PnaclCoordinator,
|
| + PnaclRefCount> callback_factory_;
|
|
|
| // URLs used to lookup downloaded resources.
|
| nacl::string resource_base_url_;
|
| - nacl::string llc_url_;
|
| - nacl::string ld_url_;
|
|
|
| // Helper subprocesses loaded by the plugin (deleted by the plugin).
|
| - // We may want to do cleanup ourselves when we are in the
|
| - // business of compiling multiple bitcode objects / libraries, and
|
| - // if we truly cannot reuse existing loaded subprocesses.
|
| + // A nacl sandbox running the llc nexe.
|
| NaClSubprocess* llc_subprocess_;
|
| + // A nacl sandbox running the ld nexe.
|
| NaClSubprocess* ld_subprocess_;
|
| + // True if the translation thread and subprocesses should exit.
|
| bool subprocesses_should_die_;
|
| + // Used to guard and publish subprocesses_should_die_.
|
| struct NaClMutex subprocess_mu_;
|
|
|
| // Nexe from the final native Link.
|
| nacl::scoped_ptr<nacl::DescWrapper> translated_fd_;
|
|
|
| - // 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<PnaclTranslationUnit> translation_unit_;
|
| + // The helper thread used to do translations via SRPC.
|
| nacl::scoped_ptr<NaClThread> translate_thread_;
|
| - nacl::scoped_ptr<NaClThread> link_thread_;
|
| + // Translation creates local temporary files.
|
| + nacl::scoped_ptr<pp::FileSystem> file_system_;
|
| + // An auxiliary class that manages downloaded resources (llc and ld nexes).
|
| + nacl::scoped_ptr<PnaclResources> resources_;
|
|
|
| - // An auxiliary class that manages downloaded resources.
|
| - nacl::scoped_ptr<PnaclResources> resources_;
|
| + // The URL for the pexe file.
|
| + nacl::string pexe_url_;
|
| + // Borrowed reference which must outlive the thread.
|
| + nacl::scoped_ptr<nacl::DescWrapper> pexe_wrapper_;
|
| + // Object file, produced by the translator and consumed by the linker.
|
| + nacl::scoped_ptr<PnaclFileDescPair> obj_file_;
|
| + // Translated nexe file, produced by the linker and consumed by sel_ldr.
|
| + nacl::scoped_ptr<PnaclFileDescPair> nexe_file_;
|
| + // Callbacks to run when tasks or completed or an error has occurred.
|
| + pp::CompletionCallback translate_done_cb_;
|
| +
|
| + // Used to report information when errors (PPAPI or otherwise) are reported.
|
| + ErrorInfo error_info_;
|
| +
|
| + // Support for file lookups (obsolescent).
|
| + // The SRPC file lookup service for ld.
|
| + static void LookupInputFile(NaClSrpcRpc* rpc,
|
| + NaClSrpcArg** inputs,
|
| + NaClSrpcArg** outputs,
|
| + NaClSrpcClosure* done);
|
| + static NaClSrpcHandlerDesc lookup_methods[];
|
| +
|
| + // Used by the SRPC file lookup service for ld.
|
| + // Looks up url and returns the read-only file descriptor for it.
|
| + // If url is the specially designated filename for the translated object
|
| + // file, it returns obj_file_.read_wrapper(). Otherwise the lookup causes
|
| + // the download of the requested resource via Plugin::StreamAsFile.
|
| + struct NaClDesc* LookupDesc(const nacl::string& url);
|
| +
|
| + struct NaClMutex lookup_service_mu_;
|
| + struct NaClCondVar lookup_service_cv_;
|
| + bool lookup_is_complete_;
|
| };
|
|
|
| //----------------------------------------------------------------------
|
|
|