Support Launch Mode 69/294469/8
authorHwankyu Jhun <h.jhun@samsung.com>
Tue, 20 Jun 2023 01:24:45 +0000 (01:24 +0000)
committerHwankyu Jhun <h.jhun@samsung.com>
Tue, 20 Jun 2023 06:22:34 +0000 (06:22 +0000)
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 <h.jhun@samsung.com>
src/launchpad-process-pool/conf/launchpad.conf.in
src/launchpad-process-pool/config.cc
src/launchpad-process-pool/config.hh
src/launchpad-process-pool/hydra_loader_context.cc
src/launchpad-process-pool/launchpad.cc
src/launchpad-process-pool/launchpad.hh
src/launchpad-process-pool/loader_context.cc
src/launchpad-process-pool/loader_context.hh

index f85ba2fedcbc40e3df64faa34f7871af48b245cc..cc29900e9cd1dd8ccdb9eabdad63b25b8380f88e 100644 (file)
@@ -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
index 65a1e9f1421910414d9aff1986f3466431954b0e..fa82d4802268f41b15d0aa511e2a7d27d2554c8a 100644 (file)
@@ -19,6 +19,7 @@
 #include <utility>
 
 #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<int>(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
index 22a82418349a16837919a0c2fa1022e62baad36f..7d77e47c04852214b9bcb73e45a96c191e790603 100644 (file)
@@ -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
index cbcb6a841c403218f7b6b1a6fb1d5086f84dfad7..a2d29db175de48d2eb0555a4a44470de5f2c9135 100644 (file)
@@ -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);
         }
index 8ff9fe7e8621b5be80827582850dc1554665cd77..ad334491095d13cc266f11a2621125998a4ea731 100644 (file)
@@ -152,20 +152,6 @@ int GetLoaderIdFromBundle(const tizen_base::Bundle& b) {
   return std::stoi(loader_id);
 }
 
-inline bool CanUseLoaderContext(const std::shared_ptr<LoaderContext>& context) {
-  return (context->IsHydraMode() || context->GetPid() > 0) &&
-      !context->IsPending();
-}
-
-inline void CheckAndPrepareLoaderContext(LoaderContext* context) {
-  if (!context->IsLaunchable())
-    return;
-
-  auto* hydra_loader_context = dynamic_cast<HydraLoaderContext*>(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> request) {
   _D("[PAD_CMD_CONNECT] client fd: %d", client_socket_->GetFd());
 }
 
+bool Launchpad::CanUseLoaderContext(
+    const std::shared_ptr<LoaderContext>& 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> 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> 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> 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<int>(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_) {
index 690af31abf1dd116c5645056154b3766ff357afc..5300f311029ddb37d4fe236e365af6a63d423901 100644 (file)
 #include <server_socket.hh>
 
 #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> request);
   void HandleLaunchRequest(std::shared_ptr<Request> request);
 
+  bool CanUseLoaderContext(const std::shared_ptr<LoaderContext>& context);
   LaunchResult ForkProcessing(std::shared_ptr<Request> request);
   LaunchResult LaunchRequestPrepare(std::shared_ptr<Request> request);
   LaunchResult LaunchRequestDo(std::shared_ptr<Request> request);
+  LaunchResult LaunchRequestPend(std::shared_ptr<Request> request);
   void LaunchRequestComplete(std::shared_ptr<Request> request);
 
   void OnIOEventReceived(int fd, int condition) override;
@@ -99,6 +103,7 @@ class Launchpad : public IOChannel::IEvent,
   std::unique_ptr<RegionFormatConfig> region_format_config_;
   std::unique_ptr<Worker> cleaner_;
   std::vector<std::shared_ptr<Request>> pending_requests_;
+  Config::LaunchMode::Mode mode_;
 };
 
 }  // namespace launchpad
index cb30f517436ed0b637e0f9480769d6f4d50ab3d2..84fa007da41c4151a82cefbaf8c4f0b191952e6e 100644 (file)
@@ -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() {
index 882a6efad3118c66f1043ca38381e9d9c9d5ef0f..4561198d63238b5219950759104a79da7d02e2fe 100644 (file)
@@ -105,9 +105,10 @@ class LoaderContext : public std::enable_shared_from_this<LoaderContext>,
   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<LoaderContext>,
 
  private:
   bool prepared_ = false;
-  bool pending_ = false;
   std::shared_ptr<LoaderInfo> loader_info_;
   int loader_id_;
   pid_t caller_pid_;
@@ -151,6 +151,7 @@ class LoaderContext : public std::enable_shared_from_this<LoaderContext>,
   guint on_boot_timer_ = 0;
   std::vector<std::string> condition_path_exists_;
   IEvent* listener_ = nullptr;
+  uint32_t ref_count_ = 0;
 };
 
 }  // namespace launchpad