1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_PNACL_COORDINATOR_H_
6 #define NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_PNACL_COORDINATOR_H_
12 #include "native_client/src/include/nacl_macros.h"
13 #include "native_client/src/include/nacl_string.h"
14 #include "native_client/src/shared/platform/nacl_sync_raii.h"
15 #include "native_client/src/shared/srpc/nacl_srpc.h"
16 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
18 #include "ppapi/cpp/completion_callback.h"
20 #include "ppapi/native_client/src/trusted/plugin/callback_source.h"
21 #include "ppapi/native_client/src/trusted/plugin/file_downloader.h"
22 #include "ppapi/native_client/src/trusted/plugin/nacl_subprocess.h"
23 #include "ppapi/native_client/src/trusted/plugin/plugin_error.h"
24 #include "ppapi/native_client/src/trusted/plugin/pnacl_resources.h"
26 struct PP_PNaClOptions;
31 class PnaclCoordinator;
32 class PnaclTranslateThread;
35 // A class invoked by Plugin to handle PNaCl client-side translation.
37 // (1) Invoke the factory method, e.g.,
38 // PnaclCoordinator* coord = BitcodeToNative(plugin,
39 // "http://foo.com/my.pexe",
41 // TranslateNotifyCallback);
42 // (2) TranslateNotifyCallback gets invoked when translation is complete.
43 // If the translation was successful, the pp_error argument is PP_OK.
44 // Other values indicate errors.
45 // (3) After finish_callback runs, get the file descriptor of the translated
47 // fd = coord->ReleaseTranslatedFD();
48 // (4) Load the nexe from "fd".
51 // Translation proceeds in two steps:
52 // (1) llc translates the bitcode in pexe_url_ to an object in obj_file_.
53 // (2) ld links the object code in obj_file_ and produces a nexe in nexe_file_.
55 // The coordinator proceeds through several states. They are
56 // OPEN_BITCODE_STREAM
57 // Complete when BitcodeStreamDidOpen is invoked
58 // LOAD_TRANSLATOR_BINARIES
59 // Complete when ResourcesDidLoad is invoked.
61 // Get an FD which contains the cached nexe, or is writeable for
62 // translation output. Complete when NexeFdDidOpen is called.
64 // If there was a cache hit, go to OPEN_NEXE_FOR_SEL_LDR, otherwise,
65 // continue streaming the bitcode, and:
66 // OPEN_TMP_FOR_LLC_TO_LD_COMMUNICATION
67 // Complete when ObjectFileDidOpen is invoked.
68 // OPEN_NEXE_FD_FOR_WRITING
69 // Complete when RunTranslate is invoked.
70 // START_LD_AND_LLC_SUBPROCESS_AND_INITIATE_TRANSLATION
71 // Complete when RunTranslate returns.
72 // TRANSLATION_COMPLETE
73 // Complete when TranslateFinished is invoked.
75 // OPEN_NEXE_FOR_SEL_LDR
76 // Complete when NexeReadDidOpen is invoked.
77 class PnaclCoordinator: public CallbackSource<FileStreamData> {
79 // Maximum number of object files passable to the translator. Cannot be
80 // changed without changing the RPC signatures.
81 const static size_t kMaxTranslatorObjectFiles = 16;
82 virtual ~PnaclCoordinator();
84 // The factory method for translations.
85 static PnaclCoordinator* BitcodeToNative(
87 const nacl::string& pexe_url,
88 const PP_PNaClOptions& pnacl_options,
89 const pp::CompletionCallback& translate_notify_callback);
91 // Call this to take ownership of the FD of the translated nexe after
92 // BitcodeToNative has completed (and the finish_callback called).
93 nacl::DescWrapper* ReleaseTranslatedFD();
95 // Run |translate_notify_callback_| with an error condition that is not
96 // PPAPI specific. Also set ErrorInfo report.
97 void ReportNonPpapiError(PP_NaClError err, const nacl::string& message);
98 // Run when faced with a PPAPI error condition. Bring control back to the
99 // plugin by invoking the |translate_notify_callback_|.
100 // Also set ErrorInfo report.
101 void ReportPpapiError(PP_NaClError err,
102 int32_t pp_error, const nacl::string& message);
103 // Bring control back to the plugin by invoking the
104 // |translate_notify_callback_|. This does not set the ErrorInfo report,
105 // it is assumed that it was already set.
106 void ExitWithError();
108 // Implement FileDownloader's template of the CallbackSource interface.
109 // This method returns a callback which will be called by the FileDownloader
110 // to stream the bitcode data as it arrives. The callback
111 // (BitcodeStreamGotData) passes it to llc over SRPC.
112 StreamCallback GetCallback();
114 // Return a callback that should be notified when |bytes_compiled| bytes
115 // have been compiled.
116 pp::CompletionCallback GetCompileProgressCallback(int64_t bytes_compiled);
118 // Return a callback that should be notified when an interesting UMA timing
119 // is ready to be reported.
120 pp::CompletionCallback GetUMATimeCallback(const nacl::string& event_name,
123 // Get the last known load progress.
124 void GetCurrentProgress(int64_t* bytes_loaded, int64_t* bytes_total);
126 // Return true if the total progress to report (w/ progress events) is known.
127 bool ExpectedProgressKnown() { return expected_pexe_size_ != -1; }
129 // Return true if we should delay the progress event reporting.
130 // This delay approximates:
131 // - the size of the buffer of bytes sent but not-yet-compiled by LLC.
132 // - the linking time.
133 bool ShouldDelayProgressEvent() {
134 const uint32_t kProgressEventSlopPct = 5;
135 return ((expected_pexe_size_ - pexe_bytes_compiled_) * 100 /
136 expected_pexe_size_) < kProgressEventSlopPct;
140 NACL_DISALLOW_COPY_AND_ASSIGN(PnaclCoordinator);
142 // BitcodeToNative is the factory method for PnaclCoordinators.
143 // Therefore the constructor is private.
144 PnaclCoordinator(Plugin* plugin,
145 const nacl::string& pexe_url,
146 const PP_PNaClOptions& pnacl_options,
147 const pp::CompletionCallback& translate_notify_callback);
149 // Invoke to issue a GET request for bitcode.
150 void OpenBitcodeStream();
151 // Invoked when we've started an URL fetch for the pexe to check for
153 void BitcodeStreamDidOpen(int32_t pp_error);
155 // Callback for when the resource info JSON file has been read.
156 void ResourceInfoWasRead(int32_t pp_error);
158 // Callback for when llc and ld have been downloaded.
159 void ResourcesDidLoad(int32_t pp_error);
160 // Invoked when we've gotten a temp FD for the nexe, either with the nexe
161 // data, or a writeable fd to save to.
162 void NexeFdDidOpen(int32_t pp_error);
163 // Invoked when a pexe data chunk arrives (when using streaming translation)
164 void BitcodeStreamGotData(int32_t pp_error, FileStreamData data);
165 // Invoked when a pexe data chunk is compiled.
166 void BitcodeGotCompiled(int32_t pp_error, int64_t bytes_compiled);
167 // Invoked when the pexe download finishes (using streaming translation)
168 void BitcodeStreamDidFinish(int32_t pp_error);
169 // Invoked when the write descriptor for obj_file_ is created.
170 void ObjectFileDidOpen(int32_t pp_error);
171 // Once llc and ld nexes have been loaded and the two temporary files have
172 // been created, this starts the translation. Translation starts two
173 // subprocesses, one for llc and one for ld.
174 void RunTranslate(int32_t pp_error);
176 // Invoked when translation is finished.
177 void TranslateFinished(int32_t pp_error);
179 // Invoked when the read descriptor for nexe_file_ is created.
180 void NexeReadDidOpen(int32_t pp_error);
182 // Invoked when a UMA timing measurement from the translate thread is ready.
183 void DoUMATimeMeasure(
184 int32_t pp_error, const nacl::string& event_name, int64_t microsecs);
186 // Keeps track of the pp_error upon entry to TranslateFinished,
187 // for inspection after cleanup.
188 int32_t translate_finish_error_;
190 // The plugin owning the nexe for which we are doing translation.
193 pp::CompletionCallback translate_notify_callback_;
194 // Set to true when the translation (if applicable) is finished and the nexe
195 // file is loaded, (or when there was an error), and the browser has been
196 // notified via ReportTranslationFinished. If it is not set before
197 // plugin/coordinator destruction, the destructor will call
198 // ReportTranslationFinished.
199 bool translation_finished_reported_;
200 // Threadsafety is required to support file lookups.
201 pp::CompletionCallbackFactory<PnaclCoordinator,
202 pp::ThreadSafeThreadTraits> callback_factory_;
204 // The manifest used by resource loading and ld + llc's reverse service
205 // to look up objects and libraries.
206 int32_t manifest_id_;
207 // An auxiliary class that manages downloaded resources (llc and ld nexes).
208 nacl::scoped_ptr<PnaclResources> resources_;
210 // The URL for the pexe file.
211 nacl::string pexe_url_;
212 // Options for translation.
213 PP_PNaClOptions pnacl_options_;
214 // Architecture-specific attributes used for translation. These are
215 // supplied by Chrome, not the developer, and are therefore different
216 // from PNaCl options.
217 nacl::string architecture_attributes_;
219 // Object file, produced by the translator and consumed by the linker.
220 std::vector<TempFile*> obj_files_;
221 nacl::scoped_ptr<nacl::DescWrapper> invalid_desc_wrapper_;
222 // Number of split modules (threads) for llc
223 int split_module_count_;
224 int num_object_files_opened_;
226 // Translated nexe file, produced by the linker.
227 nacl::scoped_ptr<TempFile> temp_nexe_file_;
228 // Passed to the browser, which sets it to true if there is a translation
230 PP_Bool is_cache_hit_;
232 // Downloader for streaming translation
233 nacl::scoped_ptr<FileDownloader> streaming_downloader_;
235 // Used to report information when errors (PPAPI or otherwise) are reported.
236 ErrorInfo error_info_;
238 // True if an error was already reported, and translate_notify_callback_
239 // was already run/consumed.
240 bool error_already_reported_;
242 // State for timing and size information for UMA stats.
243 int64_t pnacl_init_time_;
244 int64_t pexe_size_; // Count as we stream -- will converge to pexe size.
245 int64_t pexe_bytes_compiled_; // Count as we compile.
246 int64_t expected_pexe_size_; // Expected download total (-1 if unknown).
248 // The helper thread used to do translations via SRPC.
249 // It accesses fields of PnaclCoordinator so it must have a
251 nacl::scoped_ptr<PnaclTranslateThread> translate_thread_;
254 //----------------------------------------------------------------------
256 } // namespace plugin;
257 #endif // NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_PNACL_COORDINATOR_H_