Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(207)

Side by Side Diff: ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc

Issue 8786005: Move command line processing out of coordinator (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "native_client/src/trusted/plugin/pnacl_coordinator.h" 5 #include "native_client/src/trusted/plugin/pnacl_coordinator.h"
6 6
7 #include <utility> 7 #include <utility>
8 #include <vector> 8 #include <vector>
9 9
10 #include "native_client/src/include/portability_io.h" 10 #include "native_client/src/include/portability_io.h"
11 #include "native_client/src/shared/platform/nacl_check.h" 11 #include "native_client/src/shared/platform/nacl_check.h"
12 #include "native_client/src/shared/platform/nacl_sync_raii.h" 12 #include "native_client/src/shared/platform/nacl_sync_raii.h"
13 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h" 13 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
14 #include "native_client/src/trusted/plugin/browser_interface.h" 14 #include "native_client/src/trusted/plugin/browser_interface.h"
15 #include "native_client/src/trusted/plugin/nacl_subprocess.h" 15 #include "native_client/src/trusted/plugin/nacl_subprocess.h"
16 #include "native_client/src/trusted/plugin/nexe_arch.h" 16 #include "native_client/src/trusted/plugin/nexe_arch.h"
17 #include "native_client/src/trusted/plugin/plugin.h" 17 #include "native_client/src/trusted/plugin/plugin.h"
18 #include "native_client/src/trusted/plugin/plugin_error.h" 18 #include "native_client/src/trusted/plugin/plugin_error.h"
19 #include "native_client/src/trusted/plugin/pnacl_srpc_lib.h" 19 #include "native_client/src/trusted/plugin/pnacl_srpc_lib.h"
20 #include "native_client/src/trusted/plugin/scriptable_handle.h"
21 #include "native_client/src/trusted/plugin/utility.h" 20 #include "native_client/src/trusted/plugin/utility.h"
22 21
23 #include "ppapi/c/pp_errors.h" 22 #include "ppapi/c/pp_errors.h"
23 #include "ppapi/c/ppb_file_io.h"
24 #include "ppapi/cpp/file_io.h"
25
26 namespace plugin {
27
28 class Plugin;
24 29
25 namespace { 30 namespace {
26 31
27 typedef std::vector<nacl::string> string_vector; 32 const char kLlcUrl[] = "llc";
28 int32_t kArbitraryStackSize = 128 << 10; 33 const char kLdUrl[] = "ld";
34
35 // 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
36 nacl::string ResourceBaseUrl() {
37 return nacl::string("pnacl_support/") + GetSandboxISA() + "/";
38 }
39
40 // Lookup service called by translator nexes.
41 // TODO(sehr): replace this lookup by ReverseService.
42 void LookupInputFile(NaClSrpcRpc* rpc,
43 NaClSrpcArg** inputs,
44 NaClSrpcArg** outputs,
45 NaClSrpcClosure* done) {
46 PLUGIN_PRINTF(("PnaclCoordinator::LookupInputFile (url=%s)\n",
47 inputs[0]->arrays.str));
48 NaClSrpcClosureRunner runner(done);
49 rpc->result = NACL_SRPC_RESULT_APP_ERROR;
50 const char* file_name = inputs[0]->arrays.str;
51 PnaclCoordinator* coordinator = reinterpret_cast<PnaclCoordinator*>(
52 rpc->channel->server_instance_data);
53 outputs[0]->u.hval = coordinator->LookupDesc(file_name);
54 rpc->result = NACL_SRPC_RESULT_OK;
55 }
56
57 NaClSrpcHandlerDesc lookup_methods[] = {
58 { "LookupInputFile:s:h", LookupInputFile },
59 { NULL, NULL }
60 };
29 61
30 } // namespace 62 } // namespace
31 63
32 namespace plugin { 64 //////////////////////////////////////////////////////////////////////
33 65 PnaclFileDescPair::PnaclFileDescPair(Plugin* plugin,
34 class Plugin; 66 pp::FileSystem* file_system,
35 67 PnaclCoordinator* coordinator)
36 void PnaclCoordinator::Initialize(Plugin* plugin) { 68 : plugin_(plugin),
37 PLUGIN_PRINTF(("PnaclCoordinator::Initialize (this=%p)\n", 69 file_system_(file_system),
38 static_cast<void*>(this))); 70 coordinator_(coordinator) {
39 CHECK(plugin != NULL); 71 PLUGIN_PRINTF(("PnaclFileDescPair::PnaclFileDescPair (plugin=%p, "
40 CHECK(plugin_ == NULL); // Can only initialize once. 72 "file_system=%p, coordinator=%p)\n",
41 plugin_ = plugin; 73 static_cast<void*>(plugin), static_cast<void*>(file_system),
74 static_cast<void*>(coordinator)));
42 callback_factory_.Initialize(this); 75 callback_factory_.Initialize(this);
43 resources_.reset(new PnaclResources(plugin, this)); 76 CHECK(NaClDescRngCtor(&rng_desc_));
44 resources_->Initialize(); 77 file_io_trusted_= static_cast<const PPB_FileIOTrusted*>(
45 } 78 pp::Module::Get()->GetBrowserInterface(PPB_FILEIOTRUSTED_INTERFACE));
46 79 // Get a random temp file name.
47 PnaclCoordinator::~PnaclCoordinator() { 80 struct NaClDesc* desc = reinterpret_cast<struct NaClDesc*>(&rng_desc_);
48 PLUGIN_PRINTF(("PnaclCoordinator::~PnaclCoordinator (this=%p)\n", 81 const struct NaClDescVtbl* vtbl =
49 static_cast<void*>(this))); 82 reinterpret_cast<const struct NaClDescVtbl*>(desc->base.vtbl);
50 83 // Filename consists of a slash then 32 random characters.
51 // Join helper threads which will block the page from refreshing while a 84 filename_ = "/";
52 // translation is happening. 85 const int32_t kTempFileNameWords = 4;
53 if (translate_thread_.get() != NULL || link_thread_.get() != NULL) { 86 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.
54 SetSubprocessesShouldDie(true); 87 int32_t num;
55 } 88 CHECK(sizeof num == vtbl->Read(desc,
56 if (translate_thread_.get() != NULL) { 89 reinterpret_cast<char*>(&num),
57 NaClThreadJoin(translate_thread_.get()); 90 sizeof num));
58 } 91 char frag[16];
59 if (link_thread_.get() != NULL) { 92 SNPRINTF(frag, sizeof frag, "%08x", num);
60 NaClThreadJoin(link_thread_.get()); 93 filename_ += nacl::string(frag);
61 } 94 }
62 } 95 }
63 96
64 void PnaclCoordinator::ReportLoadAbort() { 97 PnaclFileDescPair::~PnaclFileDescPair() {
65 plugin_->ReportLoadAbort(); 98 PLUGIN_PRINTF(("PnaclFileDescPair::~PnaclFileDescPair\n"));
66 } 99 NaClDescUnref(reinterpret_cast<NaClDesc*>(&rng_desc_));
67 100 }
68 void PnaclCoordinator::ReportLoadError(const ErrorInfo& error) { 101
69 plugin_->ReportLoadError(error); 102 void PnaclFileDescPair::Open(const pp::CompletionCallback& cb) {
70 } 103 PLUGIN_PRINTF(("PnaclFileDescPair::Open\n"));
71 104 done_callback_ = cb;
72 void PnaclCoordinator::PnaclPpapiError(int32_t pp_error) { 105
73 // Attempt to free all the intermediate callbacks we ever created. 106 write_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str()));
74 callback_factory_.CancelAll(); 107 write_io_.reset(new pp::FileIO(plugin_));
75 translate_notify_callback_.Run(pp_error); 108 read_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str()));
76 } 109 read_io_.reset(new pp::FileIO(plugin_));
77 110
78 void PnaclCoordinator::PnaclNonPpapiError() { 111 pp::CompletionCallback open_write_cb =
79 PnaclPpapiError(PP_ERROR_FAILED); 112 callback_factory_.NewCallback(&PnaclFileDescPair::WriteFileDidOpen);
80 } 113 // Open the writeable file.
81 114 write_io_->Open(*write_ref_,
82 void PnaclCoordinator::PnaclDidFinish(int32_t pp_error, 115 PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE,
83 PnaclTranslationUnit* translation_unit) { 116 open_write_cb);
84 PLUGIN_PRINTF(("PnaclCoordinator::PnaclDidFinish (pp_error=%" 117 }
85 NACL_PRId32")\n", pp_error)); 118
119 int32_t PnaclFileDescPair::GetFD(int32_t pp_error,
120 const pp::Resource& resource,
121 const nacl::string& component) {
122 PLUGIN_PRINTF(("PnaclFileDescPair::GetFD (pp_error=%"
123 NACL_PRId32", component=%s)\n", pp_error, component.c_str()));
86 if (pp_error != PP_OK) { 124 if (pp_error != PP_OK) {
87 ReportLoadError(translation_unit->error_info); 125 coordinator_->ReportPpapiError(pp_error,
88 PnaclPpapiError(pp_error); 126 nacl::string("PnaclFileDescPair::GetFD ") +
89 return; 127 component + " failed\n");
90 } 128 return -1;
91 // Transfer ownership of the nexe wrapper to the coordinator. 129 }
92 translated_fd_.reset(translation_unit->nexe_wrapper.release()); 130 int32_t file_desc = file_io_trusted_->GetOSFileDescriptor(
93 plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress); 131 resource.pp_resource());
94 translate_notify_callback_.Run(pp_error); 132 #if NACL_WINDOWS
133 // Convert the Windows HANDLE from Pepper to a POSIX file descriptor.
134 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.
135 if (posix_desc == -1) {
136 // Close the Windows HANDLE if it can't be converted.
137 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
138 return NACL_NO_FILE_DESC;
139 }
140 file_desc = posix_desc;
141 #endif
142 int32_t file_desc_ok_to_close = DUP(file_desc);
143 if (file_desc_ok_to_close == NACL_NO_FILE_DESC) {
144 coordinator_->ReportPpapiError(
145 pp_error,
146 nacl::string("PnaclFileDescPair::GetFD dup ") +
147 component + " failed\n");
148 return -1;
149 }
150 return file_desc_ok_to_close;
151 }
152
153 void PnaclFileDescPair::WriteFileDidOpen(int32_t pp_error) {
154 PLUGIN_PRINTF(("PnaclFileDescPair::WriteFileDidOpen (pp_error=%"
155 NACL_PRId32")\n", pp_error));
156 // Remember the object temporary file descriptor.
157 int32_t fd = GetFD(pp_error, *write_io_, "write");
158 if (fd < 0) {
159 return;
160 }
161 write_wrapper_.reset(plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDWR));
162 pp::CompletionCallback open_read_cb =
163 callback_factory_.NewCallback(&PnaclFileDescPair::ReadFileDidOpen);
164 // Open the read only file.
165 read_io_->Open(*read_ref_, PP_FILEOPENFLAG_READ, open_read_cb);
166 }
167
168 void PnaclFileDescPair::ReadFileDidOpen(int32_t pp_error) {
169 PLUGIN_PRINTF(("PnaclFileDescPair::ReadFileDidOpen (pp_error=%"
170 NACL_PRId32")\n", pp_error));
171 // Remember the object temporary file descriptor.
172 int32_t fd = GetFD(pp_error, *read_io_, "read");
173 if (fd < 0) {
174 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.
175 }
176 read_wrapper_.reset(plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY));
177 // Run the client's completion callback.
178 pp::Core* core = pp::Module::Get()->core();
179 core->CallOnMainThread(0, done_callback_, PP_OK);
95 } 180 }
96 181
97 ////////////////////////////////////////////////////////////////////// 182 //////////////////////////////////////////////////////////////////////
183 PnaclCoordinator* PnaclCoordinator::BitcodeToNative(
184 Plugin* plugin,
185 const nacl::string& pexe_url,
186 const pp::CompletionCallback& translate_notify_callback) {
187 PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (plugin=%p, pexe=%s)\n",
188 static_cast<void*>(plugin), pexe_url.c_str()));
189 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.
190 coordinator->pexe_url_ = pexe_url;
191 coordinator->translate_notify_callback_ = translate_notify_callback;
192 // Load llc and ld.
193 coordinator->resource_base_url_ = ResourceBaseUrl();
194 coordinator->resources_.reset(
195 new PnaclResources(plugin, coordinator, coordinator->resource_base_url_));
196 CHECK(coordinator->resources_ != NULL);
197 pp::CompletionCallback resources_cb =
198 coordinator->callback_factory_.NewCallback(
199 &PnaclCoordinator::ResourcesDidLoad);
200 coordinator->resources_->AddResourceUrl(kLlcUrl);
201 coordinator->resources_->AddResourceUrl(kLdUrl);
202 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.
203 coordinator->resources_->StartDownloads();
204 // ResourcesDidLoad will be invoked when all resources have been received.
205 return coordinator;
206 }
98 207
99 int32_t PnaclCoordinator::GetLoadedFileDesc(int32_t pp_error, 208 int32_t PnaclCoordinator::GetLoadedFileDesc(int32_t pp_error,
100 const nacl::string& url, 209 const nacl::string& url,
101 const nacl::string& component) { 210 const nacl::string& component) {
211 PLUGIN_PRINTF(("PnaclCoordinator::GetLoadedFileDesc (pp_error=%"
212 NACL_PRId32", url=%s, component=%s)\n", pp_error,
213 url.c_str(), component.c_str()));
214 PLUGIN_PRINTF(("PnaclCoordinator::GetLoadedFileDesc (pp_error=%d\n"));
102 ErrorInfo error_info; 215 ErrorInfo error_info;
103 int32_t file_desc = plugin_->GetPOSIXFileDesc(url); 216 int32_t file_desc = plugin_->GetPOSIXFileDesc(url);
104 if (pp_error != PP_OK || file_desc == NACL_NO_FILE_DESC) { 217 if (pp_error != PP_OK || file_desc == NACL_NO_FILE_DESC) {
105 if (pp_error == PP_ERROR_ABORTED) { 218 if (pp_error == PP_ERROR_ABORTED) {
106 ReportLoadAbort(); 219 plugin_->ReportLoadAbort();
107 } else { 220 } else {
108 // TODO(jvoung): Make a generic load error, or just use ERROR_UNKNOWN? 221 ReportPpapiError(pp_error, component + " load failed.\n");
109 error_info.SetReport(ERROR_UNKNOWN,
110 "PNaCl " + component + " load failed.");
111 ReportLoadError(error_info);
112 } 222 }
113 return -1; 223 return -1;
114 } 224 }
115 int32_t file_desc_ok_to_close = DUP(file_desc); 225 int32_t file_desc_ok_to_close = DUP(file_desc);
116 if (file_desc_ok_to_close == NACL_NO_FILE_DESC) { 226 if (file_desc_ok_to_close == NACL_NO_FILE_DESC) {
117 // TODO(jvoung): Make a generic load error, or just use ERROR_UNKNOWN? 227 ReportPpapiError(PP_ERROR_FAILED, component + " could not dup fd.\n");
118 error_info.SetReport(ERROR_UNKNOWN,
119 "PNaCl " + component + " load failed: "
120 "could not dup fd.");
121 ReportLoadError(error_info);
122 return -1; 228 return -1;
123 } 229 }
124 return file_desc_ok_to_close; 230 return file_desc_ok_to_close;
125 } 231 }
126 232
127 bool PnaclCoordinator::StartLlcSubProcess() { 233 PnaclCoordinator::PnaclCoordinator(Plugin* plugin)
234 : plugin_(plugin),
235 translate_notify_callback_(pp::BlockUntilComplete()),
236 llc_subprocess_(NULL),
237 ld_subprocess_(NULL),
238 subprocesses_should_die_(false) {
239 PLUGIN_PRINTF(("PnaclCoordinator::PnaclCoordinator (this=%p, plugin=%p)\n",
240 static_cast<void*>(this), static_cast<void*>(plugin)));
241 callback_factory_.Initialize(this);
242 NaClXMutexCtor(&subprocess_mu_);
243 // Initialize the file lookup related members.
244 NaClXMutexCtor(&mu_);
245 NaClXCondVarCtor(&cv_);
246 // Open the temporary file system.
247 file_system_.reset(
248 new pp::FileSystem(plugin, PP_FILESYSTEMTYPE_LOCALTEMPORARY));
249 CHECK(file_system_ != NULL);
250 }
251
252 PnaclCoordinator::~PnaclCoordinator() {
253 PLUGIN_PRINTF(("PnaclCoordinator::~PnaclCoordinator (this=%p)\n",
254 static_cast<void*>(this)));
255 // Join helper thread which will block the page from refreshing while a
256 // translation is happening.
257 if (translate_thread_.get() != NULL) {
258 SetSubprocessesShouldDie(true);
259 NaClThreadJoin(translate_thread_.get());
260 }
261 NaClCondVarDtor(&cv_);
262 NaClMutexDtor(&mu_);
263 NaClMutexDtor(&subprocess_mu_);
264 }
265
266 void PnaclCoordinator::ReportNonPpapiError(const nacl::string& message) {
128 ErrorInfo error_info; 267 ErrorInfo error_info;
129 nacl::DescWrapper* wrapper = resources_->WrapperForUrl(llc_url_); 268 error_info.SetReport(ERROR_UNKNOWN,
130 NaClSubprocessId llc_id = plugin_->LoadHelperNaClModule(wrapper, &error_info); 269 nacl::string("PnaclCoordinator: ") + message);
131 PLUGIN_PRINTF(("PnaclCoordinator::StartLlcSubProcess (nexe_id=%" 270 ReportPpapiError(PP_ERROR_FAILED, error_info);
132 NACL_PRId32")\n", llc_id)); 271 }
133 if (kInvalidNaClSubprocessId == llc_id) { 272
134 error_info.SetReport(ERROR_UNKNOWN, "Could not load pnacl compiler nexe"); 273 void PnaclCoordinator::ReportPpapiError(int32_t pp_error,
135 ReportLoadError(error_info); 274 const nacl::string& message) {
136 PnaclNonPpapiError(); 275 ErrorInfo error_info;
276 error_info.SetReport(ERROR_UNKNOWN,
277 nacl::string("PnaclCoordinator: ") + message);
278 ReportPpapiError(pp_error, error_info);
279 }
280
281 void PnaclCoordinator::ReportPpapiError(int32_t pp_error,
282 const ErrorInfo& error_info) {
283 plugin_->ReportLoadError(error_info);
284 // Free all the intermediate callbacks we ever created.
285 callback_factory_.CancelAll();
286 translate_notify_callback_.Run(pp_error);
287 }
288
289 void PnaclCoordinator::PnaclDidFinish(int32_t pp_error) {
290 PLUGIN_PRINTF(("PnaclCoordinator::PnaclDidFinish (pp_error=%"
291 NACL_PRId32")\n", pp_error));
292 if (pp_error != PP_OK) {
293 ReportPpapiError(pp_error, error_info_);
294 return;
295 }
296 // Transfer ownership of the nexe wrapper to the coordinator.
297 // TODO(sehr): need to release the translation unit here while transferring.
298 translated_fd_.reset(nexe_file_->read_wrapper());
299 plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress);
300 translate_notify_callback_.Run(pp_error);
301 }
302
303 void PnaclCoordinator::PnaclFailed(const nacl::string& error_string) {
304 PLUGIN_PRINTF(("PnaclCoordinator::PnaclFailed (error_string=%"
305 NACL_PRId32")\n", error_string.c_str()));
306 pp::Core* core = pp::Module::Get()->core();
307 error_info_.SetReport(ERROR_UNKNOWN,
308 nacl::string("PnaclCoordinator: ") + error_string);
309 core->CallOnMainThread(0, translate_done_cb_, PP_ERROR_FAILED);
310 NaClThreadExit(1);
311 }
312
313 void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error) {
314 PLUGIN_PRINTF(("PnaclCoordinator::ResourcesDidLoad (pp_error=%"
315 NACL_PRId32")\n", pp_error));
316 if (pp_error != PP_OK) {
317 ReportPpapiError(pp_error, "resources failed to load\n");
318 return;
319 }
320 // Open the local temporary file system to create the temporary files
321 // for the object and nexe.
322 pp::CompletionCallback cb =
323 callback_factory_.NewCallback(&PnaclCoordinator::FileSystemDidOpen);
324 if (!file_system_->Open(0, cb)) {
325 ReportNonPpapiError("failed to open file system.\n");
326 }
327 }
328
329 void PnaclCoordinator::FileSystemDidOpen(int32_t pp_error) {
330 PLUGIN_PRINTF(("PnaclCoordinator::FileSystemDidOpen (pp_error=%"
331 NACL_PRId32")\n", pp_error));
332 if (pp_error != PP_OK) {
333 ReportPpapiError(pp_error, "file system didn't open.\n");
334 return;
335 }
336 // Create the object file pair for connecting llc and ld.
337 obj_file_.reset(new PnaclFileDescPair(plugin_, file_system_.get(), this));
338 pp::CompletionCallback cb =
339 callback_factory_.NewCallback(&PnaclCoordinator::ObjectPairDidOpen);
340 obj_file_->Open(cb);
341 }
342
343 void PnaclCoordinator::ObjectPairDidOpen(int32_t pp_error) {
344 PLUGIN_PRINTF(("PnaclCoordinator::ObjectPairDidOpen (pp_error=%"
345 NACL_PRId32")\n", pp_error));
346 if (pp_error != PP_OK) {
347 ReportPpapiError(pp_error, error_info_);
348 return;
349 }
350 // Create the nexe file pair for connecting ld and sel_ldr.
351 nexe_file_.reset(new PnaclFileDescPair(plugin_, file_system_.get(), this));
352 pp::CompletionCallback cb =
353 callback_factory_.NewCallback(&PnaclCoordinator::NexePairDidOpen);
354 nexe_file_->Open(cb);
355 }
356
357 void PnaclCoordinator::NexePairDidOpen(int32_t pp_error) {
358 PLUGIN_PRINTF(("PnaclCoordinator::NexePairDidOpen (pp_error=%"
359 NACL_PRId32")\n", pp_error));
360 if (pp_error != PP_OK) {
361 ReportPpapiError(pp_error, error_info_);
362 return;
363 }
364 // Load the pexe file and get the translation started.
365 pp::CompletionCallback cb =
366 callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate);
367
368 if (!plugin_->StreamAsFile(pexe_url_, cb.pp_completion_callback())) {
369 ReportNonPpapiError(nacl::string("failed to download ") + pexe_url_ + "\n");
370 }
371 }
372
373 void PnaclCoordinator::RunTranslate(int32_t pp_error) {
374 PLUGIN_PRINTF(("PnaclCoordinator::RunTranslate (pp_error=%"
375 NACL_PRId32")\n", pp_error));
376 int32_t fd = GetLoadedFileDesc(pp_error, pexe_url_, "pexe");
377 if (fd < 0) {
378 return;
379 }
380 pexe_wrapper_.reset(plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY));
381 llc_subprocess_ = StartSubprocess(kLlcUrl);
382 if (llc_subprocess_ == NULL) {
383 ReportNonPpapiError("could not start compiler subprocess\n");
384 return;
385 }
386 ld_subprocess_ = StartSubprocess(kLdUrl);
387 if (ld_subprocess_ == NULL) {
388 ReportNonPpapiError("could not start linker subprocess\n");
389 return;
390 }
391 // Invoke llc followed by ld off the main thread. This allows use of
392 // blocking RPCs that would otherwise block the JavaScript main thread.
393 translate_done_cb_ =
394 callback_factory_.NewCallback(&PnaclCoordinator::PnaclDidFinish);
395 translate_thread_.reset(new NaClThread);
396 if (translate_thread_ == NULL) {
397 ReportNonPpapiError("could not allocate thread struct\n");
398 return;
399 }
400 const int32_t kArbitraryStackSize = 128 << 10;
401 if (!NaClThreadCreateJoinable(translate_thread_.get(),
402 DoTranslateThread,
403 this,
404 kArbitraryStackSize)) {
405 ReportNonPpapiError("could not create thread\n");
406 }
407 }
408
409 NaClSubprocess* PnaclCoordinator::StartSubprocess(const nacl::string& url) {
410 PLUGIN_PRINTF(("PnaclCoordinator::StartSubprocess (url=%s)\n", url.c_str()));
411 ErrorInfo error_info;
412 nacl::DescWrapper* wrapper = resources_->WrapperForUrl(url);
413 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
414 if (kInvalidNaClSubprocessId == id) {
137 return NULL; 415 return NULL;
138 } 416 }
139 llc_subprocess_ = plugin_->nacl_subprocess(llc_id); 417 return plugin_->nacl_subprocess(id);
140 return (llc_subprocess_ != NULL); 418 }
141 } 419
142 420 void WINAPI PnaclCoordinator::DoTranslateThread(void* arg) {
143 bool PnaclCoordinator::StartLdSubProcess() { 421 PnaclCoordinator* coordinator = reinterpret_cast<PnaclCoordinator*>(arg);
144 ErrorInfo error_info; 422 Plugin* plugin = coordinator->plugin_;
145 nacl::DescWrapper* wrapper = resources_->WrapperForUrl(ld_url_); 423 BrowserInterface* browser_interface = plugin->browser_interface();
146 NaClSubprocessId ld_id = plugin_->LoadHelperNaClModule(wrapper, &error_info); 424
147 PLUGIN_PRINTF(("PnaclCoordinator::StartLdSubProcess (nexe_id=%" 425 // Run LLC.
148 NACL_PRId32")\n", ld_id)); 426 SrpcParams params;
149 if (kInvalidNaClSubprocessId == ld_id) { 427 nacl::DescWrapper* llc_out_file = coordinator->obj_file_->write_wrapper();
150 error_info.SetReport(ERROR_UNKNOWN, "Could not load pnacl linker nexe"); 428 if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
151 ReportLoadError(error_info); 429 coordinator->llc_subprocess_,
152 PnaclNonPpapiError(); 430 "RunWithDefaultCommandLine",
153 return NULL; 431 "hh",
154 } 432 &params,
155 ld_subprocess_ = plugin_->nacl_subprocess(ld_id); 433 coordinator->pexe_wrapper_->desc(),
156 return (ld_subprocess_ != NULL); 434 llc_out_file->desc())) {
435 coordinator->PnaclFailed("compile failed.");
436 }
437 // 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.
438 int is_shared_library = (params.outs()[0]->u.ival != 0);
439 nacl::string soname = params.outs()[1]->arrays.str;
440 nacl::string lib_dependencies = params.outs()[2]->arrays.str;
441 PLUGIN_PRINTF(("PnaclCoordinator: compile (coordinator=%p) succeeded"
442 " is_shared_library=%d, soname='%s', lib_dependencies='%s')\n",
443 arg, is_shared_library, soname.c_str(),
444 lib_dependencies.c_str()));
445 if (coordinator->SubprocessesShouldDie()) {
446 NaClThreadExit(1);
447 }
448 // Set up the lookup service for filename to handle resolution.
449 NaClSrpcService* service =
450 reinterpret_cast<NaClSrpcService*>(calloc(1, sizeof(*service)));
451 if (NULL == service) {
452 coordinator->PnaclFailed("lookup service alloc failed.");
453 }
454 if (!NaClSrpcServiceHandlerCtor(service, lookup_methods)) {
455 free(service);
456 coordinator->PnaclFailed("lookup service constructor failed.");
457 }
458 char* service_string = const_cast<char*>(service->service_string);
459 NaClSubprocess* ld_subprocess = coordinator->ld_subprocess_;
460 ld_subprocess->srpc_client()->AttachService(service, coordinator);
461 nacl::DescWrapper* ld_out_file = coordinator->nexe_file_->write_wrapper();
462 if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
463 ld_subprocess,
464 "RunWithDefaultCommandLine",
465 "ChiCC",
466 &params,
467 service_string,
468 ld_out_file->desc(),
469 is_shared_library,
470 soname.c_str(),
471 lib_dependencies.c_str())) {
472 coordinator->PnaclFailed("link failed.");
473 }
474 PLUGIN_PRINTF(("PnaclCoordinator: link (coordinator=%p) succeeded\n", arg));
475 if (coordinator->SubprocessesShouldDie()) {
476 NaClThreadExit(1);
477 }
478 pp::Core* core = pp::Module::Get()->core();
479 core->CallOnMainThread(0, coordinator->translate_done_cb_, PP_OK);
480 NaClThreadExit(0);
157 } 481 }
158 482
159 bool PnaclCoordinator::SubprocessesShouldDie() { 483 bool PnaclCoordinator::SubprocessesShouldDie() {
160 nacl::MutexLocker ml(&subprocess_mu_); 484 nacl::MutexLocker ml(&subprocess_mu_);
161 return subprocesses_should_die_; 485 return subprocesses_should_die_;
162 } 486 }
163 487
164 void PnaclCoordinator::SetSubprocessesShouldDie(bool subprocesses_should_die) { 488 void PnaclCoordinator::SetSubprocessesShouldDie(bool subprocesses_should_die) {
165 nacl::MutexLocker ml(&subprocess_mu_); 489 nacl::MutexLocker ml(&subprocess_mu_);
166 subprocesses_should_die_ = subprocesses_should_die; 490 subprocesses_should_die_ = subprocesses_should_die;
167 } 491 }
168 492
169 ////////////////////////////////////////////////////////////////////// 493 void PnaclCoordinator::LoadOneFile(int32_t pp_error,
170 // First few callbacks. 494 const nacl::string& url,
171 495 nacl::DescWrapper** wrapper,
172 ////////////////////////////////////////////////////////////////////// 496 pp::CompletionCallback& done_cb) {
173 497 PLUGIN_PRINTF(("PnaclCoordinator::LoadOneFile (pp_error=%"
174 namespace { 498 NACL_PRId32", url=%s)\n", pp_error, url.c_str()));
175 void AbortTranslateThread(PnaclTranslationUnit* translation_unit, 499 const nacl::string& full_url = resource_base_url_ + url;
176 const nacl::string& error_string) { 500 pp::CompletionCallback callback =
501 callback_factory_.NewCallback(&PnaclCoordinator::DidLoadFile,
502 full_url,
503 wrapper,
504 done_cb);
505 if (!plugin_->StreamAsFile(full_url, callback.pp_completion_callback())) {
506 ReportNonPpapiError(nacl::string("failed to load ") + url + "\n");
507 }
508 }
509
510 void PnaclCoordinator::DidLoadFile(int32_t pp_error,
511 const nacl::string& full_url,
512 nacl::DescWrapper** wrapper,
513 pp::CompletionCallback& done_cb) {
514 PLUGIN_PRINTF(("PnaclCoordinator::DidLoadFile (pp_error=%"
515 NACL_PRId32", url=%s)\n", pp_error, full_url.c_str()));
516 int32_t fd = GetLoadedFileDesc(pp_error, full_url, "resource");
517 if (fd < 0) {
518 return;
519 }
520 *wrapper = plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY);
521 done_cb.Run(PP_OK);
522 }
523
524 void PnaclCoordinator::ResumeLookup(int32_t pp_error) {
525 PLUGIN_PRINTF(("PnaclCoordinator::ResumeLookup (pp_error=%"
526 NACL_PRId32", url=%s)\n", pp_error));
527 UNREFERENCED_PARAMETER(pp_error);
528 nacl::MutexLocker ml(&mu_);
529 lookup_is_complete_ = true;
530 NaClXCondVarBroadcast(&cv_);
531 }
532
533 struct NaClDesc* PnaclCoordinator::LookupDesc(const nacl::string& url) {
534 PLUGIN_PRINTF(("PnaclCoordinator::LookupDesc (url=%s)\n", url.c_str()));
535 // This filename is part of the contract with the linker.
536 // TODO(sehr): Pass the FD in, and move lookup for this file to the linker.
537 const nacl::string kGeneratedObjectFileName = "___PNACL_GENERATED";
538 if (url == kGeneratedObjectFileName) {
539 return obj_file_->read_wrapper()->desc();
540 }
541 nacl::DescWrapper* wrapper;
542 // Create the callback used to report when lookup is done.
543 pp::CompletionCallback resume_cb =
544 callback_factory_.NewCallback(&PnaclCoordinator::ResumeLookup);
545 // Run the lookup request on the main thread.
546 lookup_is_complete_ = false;
547 pp::CompletionCallback load_cb =
548 callback_factory_.NewCallback(&PnaclCoordinator::LoadOneFile,
549 url, &wrapper, resume_cb);
177 pp::Core* core = pp::Module::Get()->core(); 550 pp::Core* core = pp::Module::Get()->core();
178 translation_unit->error_info.SetReport(ERROR_UNKNOWN, error_string); 551 core->CallOnMainThread(0, load_cb, PP_OK);
179 core->CallOnMainThread(0, translation_unit->translate_done_cb, 552 // Wait for completion (timeout every 10ms to check for process end).
180 PP_ERROR_FAILED); 553 const int32_t kTenMilliseconds = 10 * 1000 * 1000;
181 NaClThreadExit(1); 554 NACL_TIMESPEC_T reltime;
182 } 555 reltime.tv_sec = 0;
183 556 reltime.tv_nsec = kTenMilliseconds;
184 void WINAPI DoTranslateThread(void* arg) { 557 NaClXMutexLock(&mu_);
185 PnaclTranslationUnit* p = reinterpret_cast<PnaclTranslationUnit*>(arg); 558 while (!lookup_is_complete_) {
186 PnaclCoordinator* coordinator = p->coordinator; 559 // Check for termination.
187 NaClSubprocess* llc_subprocess = coordinator->llc_subprocess(); 560 if (SubprocessesShouldDie()) {
188 Plugin* plugin = coordinator->plugin(); 561 NaClXMutexUnlock(&mu_);
189 BrowserInterface* browser = plugin->browser_interface(); 562 NaClThreadExit(0);
190
191 // Set up LLC flags first.
192 // TODO(jvoung): Bake these into the llc nexe?
193 // May also want to improve scriptability, but the only thing we need
194 // probably is PIC vs non-PIC and micro-arch specification.
195 const char* llc_args_x8632[] = { "-march=x86",
196 "-mcpu=pentium4",
197 "-mtriple=i686-none-nacl-gnu",
198 "-asm-verbose=false",
199 "-filetype=obj" };
200 const char* llc_args_x8664[] = { "-march=x86-64",
201 "-mcpu=core2",
202 "-mtriple=x86_64-none-nacl-gnu",
203 "-asm-verbose=false",
204 "-filetype=obj" };
205 const char* llc_args_arm[] = { "-march=arm",
206 "-mcpu=cortex-a8",
207 "-mtriple=armv7a-none-nacl-gnueabi",
208 "-asm-verbose=false",
209 "-filetype=obj",
210 "-arm-reserve-r9",
211 "-sfi-disable-cp",
212 "-arm_static_tls",
213 "-sfi-store",
214 "-sfi-load",
215 "-sfi-stack",
216 "-sfi-branch",
217 "-sfi-data",
218 "-no-inline-jumptables" };
219
220 nacl::string sandbox_isa = GetSandboxISA();
221 const char** llc_args;
222 size_t num_args;
223
224 if (sandbox_isa.compare("x86-32") == 0) {
225 llc_args = llc_args_x8632;
226 num_args = NACL_ARRAY_SIZE(llc_args_x8632);
227 } else if (sandbox_isa.compare("x86-64") == 0) {
228 llc_args = llc_args_x8664;
229 num_args = NACL_ARRAY_SIZE(llc_args_x8664);
230 } else if (sandbox_isa.compare("arm") == 0) {
231 llc_args = llc_args_arm;
232 num_args = NACL_ARRAY_SIZE(llc_args_arm);
233 } else {
234 AbortTranslateThread(p,
235 "PnaclCoordinator compiler unhandled ISA " +
236 sandbox_isa + ".");
237 return;
238 }
239
240 for (uint32_t i = 0; i < num_args; i++) {
241 if (coordinator->SubprocessesShouldDie()) {
242 NaClThreadExit(1);
243 } 563 }
244 SrpcParams dummy_params; 564 NaClXCondVarTimedWaitRelative(&cv_, &mu_, &reltime);
245 if (!PnaclSrpcLib::InvokeSrpcMethod(browser, 565 }
246 llc_subprocess, 566 NaClXMutexUnlock(&mu_);
247 "AddArg", 567 return wrapper->desc();
248 "C",
249 &dummy_params,
250 llc_args[i])) {
251 AbortTranslateThread(p,
252 "PnaclCoordinator compiler AddArg(" +
253 nacl::string(llc_args[i]) + ") failed.");
254 }
255 }
256
257 if (coordinator->SubprocessesShouldDie()) {
258 NaClThreadExit(1);
259 }
260 SrpcParams params;
261 if (!PnaclSrpcLib::InvokeSrpcMethod(browser,
262 llc_subprocess,
263 "Translate",
264 "h",
265 &params,
266 p->pexe_wrapper->desc())) {
267 AbortTranslateThread(p,
268 "PnaclCoordinator compile failed.");
269 } else {
270 // Grab the outparams.
271 p->obj_wrapper.reset(
272 plugin->wrapper_factory()->MakeGeneric(params.outs()[0]->u.hval));
273 p->obj_len = params.outs()[1]->u.ival;
274 p->is_shared_library = params.outs()[2]->u.ival != 0;
275 p->soname = params.outs()[3]->arrays.str;
276 p->lib_dependencies = params.outs()[4]->arrays.str;
277 PLUGIN_PRINTF(("PnaclCoordinator::Translate SRPC succeeded (bytes=%"
278 NACL_PRId32", is_shared_library=%d, soname='%s', "
279 "lib_dependencies='%s')\n", p->obj_len,
280 p->is_shared_library, p->soname.c_str(),
281 p->lib_dependencies.c_str()));
282 }
283 if (coordinator->SubprocessesShouldDie()) {
284 NaClThreadExit(1);
285 }
286 pp::Core* core = pp::Module::Get()->core();
287 core->CallOnMainThread(0, p->translate_done_cb, PP_OK);
288 NaClThreadExit(0);
289 }
290
291 } // namespace
292
293 void PnaclCoordinator::RunTranslate(int32_t pp_error,
294 const nacl::string& pexe_url,
295 PnaclTranslationUnit* translation_unit) {
296 PLUGIN_PRINTF(("PnaclCoordinator::RunTranslate (pp_error=%"
297 NACL_PRId32")\n", pp_error));
298 // pp_error is checked by GetLoadedFileDesc.
299 int32_t fd = GetLoadedFileDesc(pp_error, pexe_url, "pexe");
300 if (fd < 0) {
301 PnaclPpapiError(pp_error);
302 return;
303 }
304 translation_unit->pexe_wrapper.reset(
305 plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY));
306 if (!StartLlcSubProcess()) {
307 ErrorInfo error_info;
308 error_info.SetReport(ERROR_UNKNOWN,
309 "Could not start compiler subprocess\n");
310 ReportLoadError(error_info);
311 PnaclNonPpapiError();
312 return;
313 }
314 // Invoke llvm asynchronously.
315 // RunLink runs on the main thread when llvm is done.
316 translation_unit->translate_done_cb =
317 callback_factory_.NewCallback(&PnaclCoordinator::RunLink,
318 translation_unit);
319 translate_thread_.reset(new NaClThread);
320 if (translate_thread_ == NULL) {
321 ErrorInfo error_info;
322 error_info.SetReport(ERROR_UNKNOWN,
323 "Could not allocate DoTranslateThread()\n");
324 ReportLoadError(error_info);
325 PnaclNonPpapiError();
326 return;
327 }
328 if (!NaClThreadCreateJoinable(translate_thread_.get(),
329 DoTranslateThread,
330 translation_unit,
331 kArbitraryStackSize)) {
332 ErrorInfo error_info;
333 error_info.SetReport(ERROR_UNKNOWN,
334 "Could not create a translator thread.\n");
335 ReportLoadError(error_info);
336 PnaclNonPpapiError();
337 }
338 }
339
340 //////////////////////////////////////////////////////////////////////
341 // Helper functions for loading native libs.
342 // Done here to avoid hacking on the manifest parser further...
343
344 namespace {
345
346 // Fake filename for the object file generated by llvm.
347 nacl::string GeneratedObjectFileName() {
348 return nacl::string("___PNACL_GENERATED");
349 }
350
351 nacl::string ResourceBaseUrl() {
352 nacl::string sandbox_isa = GetSandboxISA();
353 nacl::string base_url = "pnacl_support/" + sandbox_isa + "/";
354 return base_url;
355 }
356
357 string_vector LinkResources(const nacl::string& sandbox_isa,
358 bool withGenerated) {
359 string_vector results;
360 // NOTE: order of items == link order.
361 if (sandbox_isa.compare("x86-64") == 0) {
362 results.push_back("libpnacl_irt_shim.a");
363 }
364 results.push_back("crtbegin.o");
365 if (withGenerated) {
366 results.push_back(GeneratedObjectFileName());
367 }
368 results.push_back("libcrt_platform.a");
369 results.push_back("libgcc.a");
370 results.push_back("libgcc_eh.a");
371 results.push_back("crtend.o");
372 return results;
373 }
374
375 } // namespace
376
377 //////////////////////////////////////////////////////////////////////
378 // Final link callbacks.
379
380 namespace {
381
382 void AbortLinkThread(PnaclTranslationUnit* translation_unit,
383 const nacl::string& error_string) {
384 ErrorInfo error_info;
385 pp::Core* core = pp::Module::Get()->core();
386 translation_unit->error_info.SetReport(ERROR_UNKNOWN, error_string);
387 core->CallOnMainThread(0, translation_unit->link_done_cb, PP_ERROR_FAILED);
388 NaClThreadExit(1);
389 }
390
391 void WINAPI DoLinkThread(void* arg) {
392 PnaclTranslationUnit* p = reinterpret_cast<PnaclTranslationUnit*>(arg);
393 PnaclCoordinator* coordinator = p->coordinator;
394 NaClSubprocess* ld_subprocess = coordinator->ld_subprocess();
395 Plugin* plugin = coordinator->plugin();
396 BrowserInterface* browser_interface = plugin->browser_interface();
397
398 // Set up command line arguments (flags then files).
399
400 //// Flags.
401 // TODO(jvoung): Be able to handle the dynamic linking flags too,
402 // and don't hardcode so much here.
403 string_vector flags;
404 nacl::string sandbox_isa = GetSandboxISA();
405 flags.push_back("-nostdlib");
406 flags.push_back("-m");
407 if (sandbox_isa.compare("x86-32") == 0) {
408 flags.push_back("elf_nacl");
409 } else if (sandbox_isa.compare("x86-64") == 0) {
410 flags.push_back("elf64_nacl");
411 flags.push_back("-entry=_pnacl_wrapper_start");
412 } else if (sandbox_isa.compare("arm") == 0) {
413 flags.push_back("armelf_nacl");
414 } else {
415 AbortLinkThread(p,
416 "PnaclCoordinator linker unhandled ISA " +
417 sandbox_isa + ".");
418 }
419
420 for (string_vector::iterator i = flags.begin(), e = flags.end();
421 i != e; ++i) {
422 const nacl::string& flag = *i;
423 if (coordinator->SubprocessesShouldDie()) {
424 NaClThreadExit(1);
425 }
426 SrpcParams dummy_params;
427 if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
428 ld_subprocess,
429 "AddArg",
430 "C",
431 &dummy_params,
432 flag.c_str())) {
433 AbortLinkThread(p,
434 "PnaclCoordinator linker AddArg(" + flag +
435 ") failed.");
436 }
437 }
438
439 //// Files.
440 string_vector files = LinkResources(sandbox_isa, true);
441 PnaclResources* resources = coordinator->resources();
442 for (string_vector::iterator i = files.begin(), e = files.end();
443 i != e; ++i) {
444 const nacl::string& link_file = *i;
445 if (coordinator->SubprocessesShouldDie()) {
446 NaClThreadExit(1);
447 }
448 // Add as argument.
449 SrpcParams dummy_params;
450 if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
451 ld_subprocess,
452 "AddArg",
453 "C",
454 &dummy_params,
455 link_file.c_str())) {
456 AbortLinkThread(p,
457 "PnaclCoordinator linker AddArg(" +
458 link_file + ") failed.");
459 }
460 // Also map the file name to descriptor.
461 if (i->compare(GeneratedObjectFileName()) == 0) {
462 SrpcParams dummy_params2;
463 if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
464 ld_subprocess,
465 "AddFileWithSize",
466 "Chi",
467 &dummy_params2,
468 link_file.c_str(),
469 p->obj_wrapper->desc(),
470 p->obj_len)) {
471 AbortLinkThread(p,
472 "PnaclCoordinator linker AddFileWithSize"
473 "(" + link_file + ") failed.");
474 }
475 } else {
476 SrpcParams dummy_params2;
477 NaClDesc* link_file_desc = resources->WrapperForUrl(link_file)->desc();
478 if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
479 ld_subprocess,
480 "AddFile",
481 "Ch",
482 &dummy_params2,
483 link_file.c_str(),
484 link_file_desc)) {
485 AbortLinkThread(p,
486 "PnaclCoordinator linker AddFile(" + link_file +
487 ") failed.");
488 }
489 }
490 }
491
492 if (coordinator->SubprocessesShouldDie()) {
493 NaClThreadExit(1);
494 }
495
496 // Finally, do the Link!
497 SrpcParams params;
498 if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
499 ld_subprocess,
500 "Link",
501 "",
502 &params)) {
503 AbortLinkThread(p, "PnaclCoordinator link failed.");
504 } else {
505 // Grab the outparams.
506 p->nexe_wrapper.reset(
507 plugin->wrapper_factory()->MakeGeneric(params.outs()[0]->u.hval));
508 int32_t nexe_size = params.outs()[1]->u.ival; // only for debug.
509 PLUGIN_PRINTF(("PnaclCoordinator::InvokeLink succeeded (bytes=%"
510 NACL_PRId32")\n", nexe_size));
511 }
512 if (coordinator->SubprocessesShouldDie()) {
513 NaClThreadExit(1);
514 }
515 pp::Core* core = pp::Module::Get()->core();
516 core->CallOnMainThread(0, p->link_done_cb, PP_OK);
517 NaClThreadExit(0);
518 }
519
520 } // namespace
521
522 void PnaclCoordinator::RunLink(int32_t pp_error,
523 PnaclTranslationUnit* translation_unit) {
524 PLUGIN_PRINTF(("PnaclCoordinator::RunLink (pp_error=%"
525 NACL_PRId32")\n", pp_error));
526 if (pp_error != PP_OK) {
527 ReportLoadError(translation_unit->error_info);
528 PnaclPpapiError(pp_error);
529 return;
530 }
531 plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress);
532 if (!StartLdSubProcess()) {
533 ErrorInfo error_info;
534 error_info.SetReport(ERROR_UNKNOWN,
535 "Could not start linker subprocess\n");
536 ReportLoadError(error_info);
537 PnaclNonPpapiError();
538 return;
539 }
540
541 // Invoke ld asynchronously.
542 // When ld has completed, PnaclDidFinish is run on the main thread.
543 translation_unit->link_done_cb =
544 callback_factory_.NewCallback(&PnaclCoordinator::PnaclDidFinish,
545 translation_unit);
546 link_thread_.reset(new NaClThread);
547 if (link_thread_ == NULL) {
548 ErrorInfo error_info;
549 error_info.SetReport(ERROR_UNKNOWN,
550 "Could not allocate DoLinkThread()\n");
551 ReportLoadError(error_info);
552 PnaclNonPpapiError();
553 return;
554 }
555 if (!NaClThreadCreateJoinable(link_thread_.get(),
556 DoLinkThread,
557 translation_unit,
558 kArbitraryStackSize)) {
559 ErrorInfo error_info;
560 error_info.SetReport(ERROR_UNKNOWN,
561 "Could not create a linker thread.\n");
562 ReportLoadError(error_info);
563 PnaclNonPpapiError();
564 }
565 }
566
567 //////////////////////////////////////////////////////////////////////
568
569 void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error,
570 const nacl::string& pexe_url,
571 PnaclTranslationUnit* translation) {
572 PLUGIN_PRINTF(("PnaclCoordinator::ResourcesDidLoad (pp_error=%"
573 NACL_PRId32")\n", pp_error));
574 if (pp_error != PP_OK) {
575 ReportLoadError(translation->error_info);
576 PnaclPpapiError(pp_error);
577 return;
578 }
579 pp::CompletionCallback cb =
580 callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate,
581 pexe_url,
582 translation);
583
584 if (!plugin_->StreamAsFile(pexe_url, cb.pp_completion_callback())) {
585 ErrorInfo error_info;
586 error_info.SetReport(ERROR_UNKNOWN,
587 "PnaclCoordinator: Failed to download file: " +
588 pexe_url + "\n");
589 ReportLoadError(error_info);
590 PnaclNonPpapiError();
591 }
592 }
593
594 void PnaclCoordinator::BitcodeToNative(
595 const nacl::string& pexe_url,
596 const pp::CompletionCallback& finish_callback) {
597 PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (pexe=%s)\n",
598 pexe_url.c_str()));
599 // The base URL for finding all the resources will be obtained from the
600 // PNaCl manifest file.
601 // Also, the llc and ld pathnames should be read from the manifest.
602 // TODO(sehr): change to use the manifest file when ready.
603 resource_base_url_ = ResourceBaseUrl();
604 llc_url_ = "llc";
605 ld_url_ = "ld";
606 translate_notify_callback_ = finish_callback;
607
608 // Steps:
609 // (1) Schedule downloads for llc, ld nexes, and native libraries (resources).
610 // (2) When resources have been downloaded, download pexe.
611 // (3) When pexe download has completed, start translation.
612 // (4) When llc translation has finished do the link.
613 // (5) When the link is done, we are done, call the finish_callback.
614 // Hand off the SHM file descriptor returned by link.
615
616 // Set up async callbacks for these steps in reverse order.
617
618 translation_unit_.reset(new PnaclTranslationUnit(this));
619
620 // When resources loading completes, this causes the pexe download.
621 pp::CompletionCallback resources_cb =
622 callback_factory_.NewCallback(&PnaclCoordinator::ResourcesDidLoad,
623 pexe_url,
624 translation_unit_.get());
625 resources_->AddResourceUrl(llc_url_);
626 resources_->AddResourceUrl(ld_url_);
627 string_vector link_resources = LinkResources(GetSandboxISA(), false);
628 for (string_vector::iterator
629 i = link_resources.begin(), e = link_resources.end();
630 i != e;
631 ++i) {
632 resources_->AddResourceUrl(*i);
633 }
634 resources_->RunWhenAllLoaded(resources_cb);
635 resources_->StartDownloads();
636 } 568 }
637 569
638 } // namespace plugin 570 } // namespace plugin
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698