15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/trusted/desc/nacl_desc_wrapper.h" 8ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/plugin.h" 9ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/plugin_error.h" 10ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/pnacl_resources.h" 11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/srpc_params.h" 12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/temporary_file.h" 13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/utility.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace plugin { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PnaclTranslateThread::PnaclTranslateThread() : llc_subprocess_active_(false), 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ld_subprocess_active_(false), 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done_(false), 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) time_stats_(), 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manifest_(NULL), 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) obj_file_(NULL), 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nexe_file_(NULL), 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) coordinator_error_info_(NULL), 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resources_(NULL), 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) coordinator_(NULL), 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) plugin_(NULL) { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXMutexCtor(&subprocess_mu_); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXMutexCtor(&cond_mu_); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXCondVarCtor(&buffer_cond_); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PnaclTranslateThread::RunTranslate( 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const pp::CompletionCallback& finish_callback, 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Manifest* manifest, 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TempFile* obj_file, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TempFile* nexe_file, 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ErrorInfo* error_info, 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PnaclResources* resources, 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PnaclOptions* pnacl_options, 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PnaclCoordinator* coordinator, 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Plugin* plugin) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("PnaclStreamingTranslateThread::RunTranslate)\n")); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manifest_ = manifest; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) obj_file_ = obj_file; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nexe_file_ = nexe_file; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) coordinator_error_info_ = error_info; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resources_ = resources; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pnacl_options_ = pnacl_options; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) coordinator_ = coordinator; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) plugin_ = plugin; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invoke llc followed by ld off the main thread. This allows use of 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // blocking RPCs that would otherwise block the JavaScript main thread. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report_translate_finished_ = finish_callback; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) translate_thread_.reset(new NaClThread); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (translate_thread_ == NULL) { 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TranslateFailed(ERROR_PNACL_THREAD_CREATE, 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "could not allocate thread struct."); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int32_t kArbitraryStackSize = 128 * 1024; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!NaClThreadCreateJoinable(translate_thread_.get(), 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoTranslateThread, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kArbitraryStackSize)) { 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TranslateFailed(ERROR_PNACL_THREAD_CREATE, 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "could not create thread."); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) translate_thread_.reset(NULL); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Called from main thread to send bytes to the translator. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PnaclTranslateThread::PutBytes(std::vector<char>* bytes, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count) { 76bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch PLUGIN_PRINTF(("PutBytes (this=%p, bytes=%p, size=%" NACL_PRIuS 77bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch ", count=%d)\n", 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, bytes, bytes ? bytes->size() : 0, count)); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t buffer_size = 0; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we are done (error or not), Signal the translation thread to stop. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (count <= PP_OK) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXMutexLock(&cond_mu_); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done_ = true; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXCondVarSignal(&buffer_cond_); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXMutexUnlock(&cond_mu_); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(bytes != NULL); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure that the buffer we send to the translation thread is the right size 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (count can be < the buffer size). This can be done without the lock. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_size = bytes->size(); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes->resize(count); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXMutexLock(&cond_mu_); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_buffers_.push_back(std::vector<char>()); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes->swap(data_buffers_.back()); // Avoid copying the buffer data. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXCondVarSignal(&buffer_cond_); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXMutexUnlock(&cond_mu_); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure the buffer we send back to the coordinator is the expected size 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes->resize(buffer_size); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NaClSubprocess* PnaclTranslateThread::StartSubprocess( 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const nacl::string& url_for_nexe, 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Manifest* manifest, 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ErrorInfo* error_info) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("PnaclTranslateThread::StartSubprocess (url_for_nexe=%s)\n", 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_for_nexe.c_str())); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::DescWrapper* wrapper = resources_->WrapperForUrl(url_for_nexe); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::scoped_ptr<NaClSubprocess> subprocess( 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) plugin_->LoadHelperNaClModule(wrapper, manifest, error_info)); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (subprocess.get() == NULL) { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(( 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "PnaclTranslateThread::StartSubprocess: subprocess creation failed\n")); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return subprocess.release(); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WINAPI PnaclTranslateThread::DoTranslateThread(void* arg) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PnaclTranslateThread* translator = 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<PnaclTranslateThread*>(arg); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) translator->DoTranslate(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PnaclTranslateThread::DoTranslate() { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ErrorInfo error_info; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SrpcParams params; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::DescWrapper* llc_out_file = obj_file_->write_wrapper(); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::MutexLocker ml(&subprocess_mu_); 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64_t llc_start_time = NaClGetTimeOfDayMicroseconds(); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) llc_subprocess_.reset( 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) StartSubprocess(resources_->GetLlcUrl(), manifest_, &error_info)); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (llc_subprocess_ == NULL) { 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TranslateFailed(ERROR_PNACL_LLC_SETUP, 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Compile process could not be created: " + 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_info.message()); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) llc_subprocess_active_ = true; 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) time_stats_.pnacl_llc_load_time = 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (NaClGetTimeOfDayMicroseconds() - llc_start_time); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run LLC. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PluginReverseInterface* llc_reverse = 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) llc_subprocess_->service_runtime()->rev_interface(); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) llc_reverse->AddTempQuotaManagedFile(obj_file_->identifier()); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64_t compile_start_time = NaClGetTimeOfDayMicroseconds(); 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool init_success; 157ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch std::vector<char> options = pnacl_options_->GetOptCommandline(); 158ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch init_success = llc_subprocess_->InvokeSrpcMethod( 159ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch "StreamInitWithOverrides", 160ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch "hC", 161ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ¶ms, 162ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch llc_out_file->desc(), 163ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch &options[0], 164ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch options.size()); 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!init_success) { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (llc_subprocess_->srpc_client()->GetLastError() == 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NACL_SRPC_RESULT_APP_ERROR) { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The error message is only present if the error was returned from llc 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TranslateFailed(ERROR_PNACL_LLC_INTERNAL, 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nacl::string("Stream init failed: ") + 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string(params.outs()[0]->arrays.str)); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TranslateFailed(ERROR_PNACL_LLC_INTERNAL, 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Stream init internal error"); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("PnaclCoordinator: StreamInit successful\n")); 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pp::Core* core = pp::Module::Get()->core(); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // llc process is started. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while(!done_ || data_buffers_.size() > 0) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXMutexLock(&cond_mu_); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while(!done_ && data_buffers_.size() == 0) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXCondVarWait(&buffer_cond_, &cond_mu_); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 189bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch PLUGIN_PRINTF(("PnaclTranslateThread awake (done=%d, size=%" NACL_PRIuS 190bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch ")\n", 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done_, data_buffers_.size())); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data_buffers_.size() > 0) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<char> data; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.swap(data_buffers_.front()); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_buffers_.pop_front(); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXMutexUnlock(&cond_mu_); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("StreamChunk\n")); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!llc_subprocess_->InvokeSrpcMethod("StreamChunk", 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "C", 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ¶ms, 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &data[0], 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.size())) { 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TranslateFailed(ERROR_PNACL_LLC_INTERNAL, 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Compile stream chunk failed."); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("StreamChunk Successful\n")); 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) core->CallOnMainThread( 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0, 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) coordinator_->GetCompileProgressCallback(data.size()), 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PP_OK); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXMutexUnlock(&cond_mu_); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("PnaclTranslateThread done with chunks\n")); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Finish llc. 218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!llc_subprocess_->InvokeSrpcMethod("StreamEnd", std::string(), ¶ms)) { 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("PnaclTranslateThread StreamEnd failed\n")); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (llc_subprocess_->srpc_client()->GetLastError() == 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NACL_SRPC_RESULT_APP_ERROR) { 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The error string is only present if the error was sent back from llc. 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TranslateFailed(ERROR_PNACL_LLC_INTERNAL, 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) params.outs()[3]->arrays.str); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TranslateFailed(ERROR_PNACL_LLC_INTERNAL, 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Compile StreamEnd internal error"); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) time_stats_.pnacl_compile_time = 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (NaClGetTimeOfDayMicroseconds() - compile_start_time); 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // LLC returns values that are used to determine how linking is done. 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int is_shared_library = (params.outs()[0]->u.ival != 0); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string soname = params.outs()[1]->arrays.str; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string lib_dependencies = params.outs()[2]->arrays.str; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("PnaclCoordinator: compile (translator=%p) succeeded" 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " is_shared_library=%d, soname='%s', lib_dependencies='%s')\n", 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, is_shared_library, soname.c_str(), 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lib_dependencies.c_str())); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shut down the llc subprocess. 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXMutexLock(&subprocess_mu_); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) llc_subprocess_active_ = false; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) llc_subprocess_.reset(NULL); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXMutexUnlock(&subprocess_mu_); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if(!RunLdSubprocess(is_shared_library, soname, lib_dependencies)) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core->CallOnMainThread(0, report_translate_finished_, PP_OK); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PnaclTranslateThread::RunLdSubprocess(int is_shared_library, 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const nacl::string& soname, 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const nacl::string& lib_dependencies 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ErrorInfo error_info; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SrpcParams params; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset object file for reading first. 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!obj_file_->Reset()) { 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TranslateFailed(ERROR_PNACL_LD_SETUP, 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Link process could not reset object file"); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::DescWrapper* ld_in_file = obj_file_->read_wrapper(); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper(); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create LD process 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::MutexLocker ml(&subprocess_mu_); 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64_t ld_start_time = NaClGetTimeOfDayMicroseconds(); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ld_subprocess_.reset( 27590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) StartSubprocess(resources_->GetLdUrl(), manifest_, &error_info)); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ld_subprocess_ == NULL) { 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TranslateFailed(ERROR_PNACL_LD_SETUP, 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Link process could not be created: " + 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_info.message()); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ld_subprocess_active_ = true; 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) time_stats_.pnacl_ld_load_time = 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (NaClGetTimeOfDayMicroseconds() - ld_start_time); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PluginReverseInterface* ld_reverse = 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ld_subprocess_->service_runtime()->rev_interface(); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ld_reverse->AddTempQuotaManagedFile(nexe_file_->identifier()); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64_t link_start_time = NaClGetTimeOfDayMicroseconds(); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run LD. 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ld_subprocess_->InvokeSrpcMethod("RunWithDefaultCommandLine", 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "hhiss", 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ¶ms, 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ld_in_file->desc(), 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ld_out_file->desc(), 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_shared_library, 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) soname.c_str(), 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lib_dependencies.c_str())) { 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TranslateFailed(ERROR_PNACL_LD_INTERNAL, 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "link failed."); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) time_stats_.pnacl_link_time = 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NaClGetTimeOfDayMicroseconds() - link_start_time; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("PnaclCoordinator: link (translator=%p) succeeded\n", 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shut down the ld subprocess. 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXMutexLock(&subprocess_mu_); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ld_subprocess_active_ = false; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ld_subprocess_.reset(NULL); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXMutexUnlock(&subprocess_mu_); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PnaclTranslateThread::TranslateFailed( 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enum PluginErrorCode err_code, 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const nacl::string& error_string) { 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("PnaclTranslateThread::TranslateFailed (error_string='%s')\n", 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_string.c_str())); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp::Core* core = pp::Module::Get()->core(); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (coordinator_error_info_->message().empty()) { 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only use our message if one hasn't already been set by the coordinator 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (e.g. pexe load failed). 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) coordinator_error_info_->SetReport(err_code, 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string("PnaclCoordinator: ") + 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_string); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core->CallOnMainThread(0, report_translate_finished_, PP_ERROR_FAILED); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PnaclTranslateThread::AbortSubprocesses() { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("PnaclTranslateThread::AbortSubprocesses\n")); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXMutexLock(&subprocess_mu_); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (llc_subprocess_ != NULL && llc_subprocess_active_) { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) llc_subprocess_->service_runtime()->Shutdown(); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) llc_subprocess_active_ = false; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ld_subprocess_ != NULL && ld_subprocess_active_) { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ld_subprocess_->service_runtime()->Shutdown(); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ld_subprocess_active_ = false; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXMutexUnlock(&subprocess_mu_); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::MutexLocker ml(&cond_mu_); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done_ = true; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Free all buffered bitcode chunks 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_buffers_.clear(); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClXCondVarSignal(&buffer_cond_); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PnaclTranslateThread::~PnaclTranslateThread() { 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("~PnaclTranslateThread (translate_thread=%p)\n", this)); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AbortSubprocesses(); 354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (translate_thread_ != NULL) 355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NaClThreadJoin(translate_thread_.get()); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("~PnaclTranslateThread joined\n")); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClCondVarDtor(&buffer_cond_); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClMutexDtor(&cond_mu_); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClMutexDtor(&subprocess_mu_); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace plugin 363