From bb2f14404524ad512ebcab41e277f4375117af2f Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 20 Jun 2023 01:24:45 +0000 Subject: [PATCH] Support Launch Mode The platform developer can set the launch mode of the app execution about the loader using the configuration file. There are 4 modes as below: 1. Mode=Previous_Operation: - This mode is the original behavior. If the loader is not preapred, the application will be executed using fork() & execv(). 2. Mode=Default_Operation: - This mode is the default behavior from Tizen 8.0. - If the loader is not prepared and the loader is running, the launchpad waits until the loader is prepared. And then, the launch request will be delivered to the loader process. 3. Mode=Always_Loader: - This mode is that the application will be always executed using the loader process. - Even if the loader process is not executed, the launch request will be delivered to the loader process. - If the loader process is not executed, the launchpad executes the loader process when getting the launch request. - After processing the launch request, the launchpad executes the loader process when the pending request exists. 4. Mode=Always_Loader_Without_CPUChecker: - This mode is the modified version of the "Mode=Always_Loader". - The loader process will be executed after processing the launch request. Change-Id: I95c7be50f4e8e79b7c490b03ecf1733c1a3f1aed Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/conf/launchpad.conf.in | 17 ++++- src/launchpad-process-pool/config.cc | 37 +++++++++- src/launchpad-process-pool/config.hh | 19 +++++ src/launchpad-process-pool/hydra_loader_context.cc | 2 +- src/launchpad-process-pool/launchpad.cc | 82 ++++++++++++++-------- src/launchpad-process-pool/launchpad.hh | 7 +- src/launchpad-process-pool/loader_context.cc | 16 +++-- src/launchpad-process-pool/loader_context.hh | 7 +- 8 files changed, 146 insertions(+), 41 deletions(-) diff --git a/src/launchpad-process-pool/conf/launchpad.conf.in b/src/launchpad-process-pool/conf/launchpad.conf.in index f85ba2f..cc29900 100644 --- a/src/launchpad-process-pool/conf/launchpad.conf.in +++ b/src/launchpad-process-pool/conf/launchpad.conf.in @@ -17,4 +17,19 @@ Enable=1 [ProcessPool] NumberOfProcesses=1 -NumberOfLoaderProcesses=1 \ No newline at end of file +NumberOfLoaderProcesses=1 + +## Mode=Previous_Operation +## - If the loader proces is not prepared, the application will be executed using fork() & execv(). +## Mode=Default_Operation +## - If the loader process is not prepared and is running, the application will be executed using the loader process. +## - If the loader process is not running, the application will be executed using fork() & execv(). +## Mode=Always_Loader +## - If the loader process is not executed, the launchpad executes a new loader process when getting the launch request. +## - And then, the launch request will be delivered after the loader process is prepared. +## - After processing the launch request, the launchpad executes the loader process when the pending request exists. +## Mode=Always_Loader_Without_CPUChecker +## - This mode is the modified version of "Mode=Always_Loader". +## - After processing the launch request, the launchpad executes a new loader process without CPU Checker. +[LaunchMode] +Mode=Default_Operation diff --git a/src/launchpad-process-pool/config.cc b/src/launchpad-process-pool/config.cc index 65a1e9f..fa82d48 100644 --- a/src/launchpad-process-pool/config.cc +++ b/src/launchpad-process-pool/config.cc @@ -19,6 +19,7 @@ #include #include "launchpad-process-pool/log_private.hh" +#include "launchpad-process-pool/util.hh" namespace launchpad { namespace { @@ -48,6 +49,14 @@ constexpr const char kKeyProcessPoolNumberOfProcesses[] = "NumberOfProcesses"; constexpr const char kKeyProcessPoolNumberOfLoaderProcesses[] = "NumberOfLoaderProcesses"; +constexpr const char kTagLaunchMode[] = "LaunchMode"; +constexpr const char kKeyMode[] = "Mode"; +constexpr const char kValueModePreviousOperation[] = "PREVIOUS_OPERATION"; +constexpr const char kValueModeDefaultOperation[] = "DEFAULT_OPERATION"; +constexpr const char kValueModeAlwaysLoader[] = "ALWAYS_LOADER"; +constexpr const char kValueModeAlwaysLoaderWithoutCPUChecker[] = + "ALWAYS_LOADER_WITHOUT_CPUCHECKER"; + } // namespace const std::string& Config::MemoryStatus::GetLowKey() const { @@ -176,6 +185,27 @@ const int Config::ProcessPool::GetNumberOfLoaderProcesses() const { return number_of_loader_processes_; } +Config::LaunchMode::LaunchMode(const IniParser& parser) { + auto mode = parser.Get(kTagLaunchMode, kKeyMode); + if (!mode.empty()) { + mode = ToUpper(mode); + if (mode == kValueModePreviousOperation) + mode_ = LaunchMode::Mode::PreviousOperation; + else if (mode == kValueModeDefaultOperation) + mode_ = LaunchMode::Mode::DefaultOperation; + else if (mode == kValueModeAlwaysLoader) + mode_ = LaunchMode::Mode::AlwaysLoader; + else if (mode == kValueModeAlwaysLoaderWithoutCPUChecker) + mode_ = LaunchMode::Mode::AlwaysLoaderWithoutCPUChecker; + } + + _W("[LaunchMode] mode: %d(%s)", static_cast(mode_), mode.c_str()); +} + +const Config::LaunchMode::Mode Config::LaunchMode::GetMode() const { + return mode_; +} + Config& Config::GetInst() { static Config inst; return inst; @@ -187,7 +217,8 @@ Config::Config() memory_monitor_(Config::MemoryMonitor(parser_)), cpu_checker_(Config::CPUChecker(parser_)), logger_(Config::Logger(parser_)), - process_pool_(Config::ProcessPool(parser_)) { + process_pool_(Config::ProcessPool(parser_)), + launch_mode_(Config::LaunchMode(parser_)) { } const Config::MemoryStatus& Config::GetMemoryStatus() const { @@ -210,4 +241,8 @@ const Config::ProcessPool& Config::GetProcessPool() const { return process_pool_; } +const Config::LaunchMode& Config::GetLaunchMode() const { + return launch_mode_; +} + } // namespace launchpad diff --git a/src/launchpad-process-pool/config.hh b/src/launchpad-process-pool/config.hh index 22a8241..7d77e47 100644 --- a/src/launchpad-process-pool/config.hh +++ b/src/launchpad-process-pool/config.hh @@ -91,6 +91,23 @@ class Config { int number_of_loader_processes_ = 1; }; + class LaunchMode { + public: + enum class Mode : int { + PreviousOperation = 0, + DefaultOperation = 1, + AlwaysLoader = 2, + AlwaysLoaderWithoutCPUChecker = 3, + }; + + explicit LaunchMode(const IniParser& parser); + + const Mode GetMode() const; + + private: + Mode mode_ = Mode::DefaultOperation; + }; + Config(const Config&) = delete; Config& operator = (const Config&) = delete; Config(Config&&) = delete; @@ -103,6 +120,7 @@ class Config { const CPUChecker& GetCPUChecker() const; const Logger& GetLogger() const; const ProcessPool& GetProcessPool() const; + const LaunchMode& GetLaunchMode() const; private: Config(); @@ -115,6 +133,7 @@ class Config { CPUChecker cpu_checker_; Logger logger_; ProcessPool process_pool_; + LaunchMode launch_mode_; }; } // namespace launchpad diff --git a/src/launchpad-process-pool/hydra_loader_context.cc b/src/launchpad-process-pool/hydra_loader_context.cc index cbcb6a8..a2d29db 100644 --- a/src/launchpad-process-pool/hydra_loader_context.cc +++ b/src/launchpad-process-pool/hydra_loader_context.cc @@ -180,7 +180,7 @@ void HydraLoaderContext::HandleHydraLoaderClientEvent(int condition) { _W("Candidate process: %d", pid); if (pid > 0) { SetPid(pid); - if (IsPending()) { + if (RefCount() > 0) { CPUBoostController::DoBoost(pid, CPUBoostController::Level::Strong, 10000); } diff --git a/src/launchpad-process-pool/launchpad.cc b/src/launchpad-process-pool/launchpad.cc index 8ff9fe7..ad33449 100644 --- a/src/launchpad-process-pool/launchpad.cc +++ b/src/launchpad-process-pool/launchpad.cc @@ -152,20 +152,6 @@ int GetLoaderIdFromBundle(const tizen_base::Bundle& b) { return std::stoi(loader_id); } -inline bool CanUseLoaderContext(const std::shared_ptr& context) { - return (context->IsHydraMode() || context->GetPid() > 0) && - !context->IsPending(); -} - -inline void CheckAndPrepareLoaderContext(LoaderContext* context) { - if (!context->IsLaunchable()) - return; - - auto* hydra_loader_context = dynamic_cast(context); - if (hydra_loader_context != nullptr) - hydra_loader_context->Prepare(); -} - } // namespace Launchpad::Launchpad(int argc, char** argv) @@ -212,6 +198,7 @@ Launchpad::Launchpad(int argc, char** argv) CPUBoostController::Clear(getpid()); return G_SOURCE_REMOVE; }, this); + mode_ = Config::GetInst().GetLaunchMode().GetMode(); } Launchpad::~Launchpad() { @@ -381,6 +368,29 @@ void Launchpad::HandleConnectRequest(std::shared_ptr request) { _D("[PAD_CMD_CONNECT] client fd: %d", client_socket_->GetFd()); } +bool Launchpad::CanUseLoaderContext( + const std::shared_ptr& context) { + if (context->IsPrepared()) + return true; + + if (mode_ == Config::LaunchMode::Mode::PreviousOperation) + return false; + + if (mode_ == Config::LaunchMode::Mode::DefaultOperation) { + if (context->IsHydraMode()) + return true; + + return context->GetPid() > 0 && context->RefCount() == 0; + } + + // Config::LaunchMode::Mode::AlwaysLoader + // Config::LaunchMode::Mode::AlwaysLoaderWithoutCPUChecker + if (context->GetPid() > 0) + return true; + + return context->IsLaunchable(); +} + Launchpad::LaunchResult Launchpad::LaunchRequestPrepare( std::shared_ptr request) { auto* app_info = AppInfo::Create(request->GetBundle()); @@ -464,6 +474,27 @@ Launchpad::LaunchResult Launchpad::ForkProcessing( return LaunchResult::Success; } +Launchpad::LaunchResult Launchpad::LaunchRequestPend( + std::shared_ptr request) { + auto loader_context = request->GetAvailableLoaderContext(); + if (loader_context->IsPrepared()) + return LaunchResult::Continue; + + _W("Loader context is not prepared"); + loader_context->Ref(); + if (loader_context->GetPid() <= 0) + loader_context->Prepare(); + + if (loader_context->GetPid() > 0) { + CPUBoostController::DoBoost(loader_context->GetPid(), + CPUBoostController::Level::Strong, 10000); + request->SendResult(loader_context->GetPid()); + } + + pending_requests_.push_back(std::move(request)); + return LaunchResult::Pending; +} + Launchpad::LaunchResult Launchpad::LaunchRequestDo( std::shared_ptr request) { auto loader_context = request->GetAvailableLoaderContext(); @@ -474,25 +505,20 @@ Launchpad::LaunchResult Launchpad::LaunchRequestDo( return ForkProcessing(request); } - if (!loader_context->IsPrepared()) { - _W("Loader context is not prepared"); - loader_context->SetPending(true); - CheckAndPrepareLoaderContext(loader_context.get()); - if (loader_context->GetPid() > 0) { - CPUBoostController::DoBoost(loader_context->GetPid(), - CPUBoostController::Level::Strong, 10000); - request->SendResult(loader_context->GetPid()); - } - - pending_requests_.push_back(std::move(request)); + if (LaunchRequestPend(request) == LaunchResult::Pending) return LaunchResult::Pending; - } auto* app_info = request->GetAppInfo(); _W("Launch %d type process. appid: %s", static_cast(loader_context->GetType()), app_info->GetAppId().c_str()); request->SetPid(loader_context->Deploy(app_info)); + + if ((mode_ == Config::LaunchMode::Mode::AlwaysLoaderWithoutCPUChecker) || + (mode_ == Config::LaunchMode::Mode::AlwaysLoader && + loader_context->RefCount() > 0)) + loader_context->Prepare(); + return LaunchResult::Success; } @@ -572,7 +598,7 @@ void Launchpad::OnSigchldReceived(pid_t pid) { void Launchpad::OnLoaderPrepared(LoaderContext* loader_context) { _W("Loader is prepared. name(%s), pid(%d)", loader_context->GetLoaderName().c_str(), loader_context->GetPid()); - loader_context->SetPending(false); + loader_context->Unref(); auto iter = pending_requests_.begin(); while (iter != pending_requests_.end()) { @@ -592,7 +618,7 @@ void Launchpad::OnLoaderPrepared(LoaderContext* loader_context) { void Launchpad::OnLoaderLaunched(LoaderContext* loader_context) { _W("Loader is launched. name(%s), pid(%d)", loader_context->GetLoaderName().c_str(), loader_context->GetPid()); - if (!loader_context->IsPending()) + if (loader_context->RefCount() == 0) return; for (auto& request : pending_requests_) { diff --git a/src/launchpad-process-pool/launchpad.hh b/src/launchpad-process-pool/launchpad.hh index 690af31..5300f31 100644 --- a/src/launchpad-process-pool/launchpad.hh +++ b/src/launchpad-process-pool/launchpad.hh @@ -31,9 +31,10 @@ #include #include "launchpad-process-pool/app_executor.hh" +#include "launchpad-process-pool/config.hh" +#include "launchpad-process-pool/loader_manager.hh" #include "launchpad-process-pool/request.hh" #include "launchpad-process-pool/signal_manager.hh" -#include "launchpad-process-pool/loader_manager.hh" namespace launchpad { @@ -45,6 +46,7 @@ class Launchpad : public IOChannel::IEvent, Fail = -1, Success = 0, Pending = 1, + Continue = 2, }; Launchpad(int argc, char** argv); @@ -75,9 +77,11 @@ class Launchpad : public IOChannel::IEvent, void HandleConnectRequest(std::shared_ptr request); void HandleLaunchRequest(std::shared_ptr request); + bool CanUseLoaderContext(const std::shared_ptr& context); LaunchResult ForkProcessing(std::shared_ptr request); LaunchResult LaunchRequestPrepare(std::shared_ptr request); LaunchResult LaunchRequestDo(std::shared_ptr request); + LaunchResult LaunchRequestPend(std::shared_ptr request); void LaunchRequestComplete(std::shared_ptr request); void OnIOEventReceived(int fd, int condition) override; @@ -99,6 +103,7 @@ class Launchpad : public IOChannel::IEvent, std::unique_ptr region_format_config_; std::unique_ptr cleaner_; std::vector> pending_requests_; + Config::LaunchMode::Mode mode_; }; } // namespace launchpad diff --git a/src/launchpad-process-pool/loader_context.cc b/src/launchpad-process-pool/loader_context.cc index cb30f51..84fa007 100644 --- a/src/launchpad-process-pool/loader_context.cc +++ b/src/launchpad-process-pool/loader_context.cc @@ -559,16 +559,20 @@ bool LoaderContext::IsLaunchable() { return true; } -void LoaderContext::SetPending(bool pending) { - pending_ = pending; +void LoaderContext::SetEventListener(IEvent* listener) { + listener_ = listener; } -bool LoaderContext::IsPending() const { - return pending_; +void LoaderContext::Ref() { + ref_count_++; } -void LoaderContext::SetEventListener(IEvent* listener) { - listener_ = listener; +void LoaderContext::Unref() { + ref_count_--; +} + +uint32_t LoaderContext::RefCount() const { + return ref_count_; } void LoaderContext::SetLiveTimer() { diff --git a/src/launchpad-process-pool/loader_context.hh b/src/launchpad-process-pool/loader_context.hh index 882a6ef..4561198 100644 --- a/src/launchpad-process-pool/loader_context.hh +++ b/src/launchpad-process-pool/loader_context.hh @@ -105,9 +105,10 @@ class LoaderContext : public std::enable_shared_from_this, bool CanActivate(LoaderMethod method) const; void UpdateState(LoaderMethod method, bool force); bool IsLaunchable(); - void SetPending(bool pending); - bool IsPending() const; void SetEventListener(IEvent* listener); + void Ref(); + void Unref(); + uint32_t RefCount() const; protected: void SetPrepared(bool prepared); @@ -129,7 +130,6 @@ class LoaderContext : public std::enable_shared_from_this, private: bool prepared_ = false; - bool pending_ = false; std::shared_ptr loader_info_; int loader_id_; pid_t caller_pid_; @@ -151,6 +151,7 @@ class LoaderContext : public std::enable_shared_from_this, guint on_boot_timer_ = 0; std::vector condition_path_exists_; IEvent* listener_ = nullptr; + uint32_t ref_count_ = 0; }; } // namespace launchpad -- 2.7.4