Modify loader management 26/291626/11
authorHwankyu Jhun <h.jhun@samsung.com>
Wed, 19 Apr 2023 09:54:36 +0000 (09:54 +0000)
committerHwankyu Jhun <h.jhun@samsung.com>
Thu, 20 Apr 2023 04:38:38 +0000 (04:38 +0000)
The management policy for the loader process will be changed.
Loader processes will be created without checking the CPU threshold.
When an execution request is received, if a loader process is in
the ready state, the execution request will be held until the loader process is
ready and then forwarded to the loader process.

This patch was created with reference to the patch below:
 - https://review.tizen.org/gerrit/#/c/platform/core/appfw/launchpad/+/288190/

Change-Id: I1b9dbed0824e7b72d6a743d8c8a2b4b266fa741c
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
18 files changed:
CMakeLists.txt
packaging/launchpad.spec
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
src/launchpad-process-pool/loader_executor.cc
src/launchpad-process-pool/loader_executor.hh
src/launchpad-process-pool/loader_manager.cc
src/launchpad-process-pool/loader_manager.hh
src/launchpad-process-pool/sequencer.cc
src/launchpad-process-pool/sequencer.hh
src/lib/launchpad-common/CMakeLists.txt
src/lib/launchpad-common/cpu_boost_controller.cc [new file with mode: 0644]
src/lib/launchpad-common/cpu_boost_controller.hh [new file with mode: 0644]

index ac8c783..d301623 100644 (file)
@@ -52,6 +52,7 @@ INCLUDE(ApplyPkgConfig)
 PKG_CHECK_MODULES(AUL_DEPS REQUIRED aul)
 PKG_CHECK_MODULES(BUNDLE_DEPS REQUIRED bundle)
 PKG_CHECK_MODULES(BUXTON2_DEPS REQUIRED buxton2)
+PKG_CHECK_MODULES(CAPI_SYSTEM_RESOURCE_DEPS REQUIRED capi-system-resource)
 PKG_CHECK_MODULES(DBUS_DEPS REQUIRED dbus-1)
 PKG_CHECK_MODULES(DLOG_DEPS REQUIRED dlog)
 PKG_CHECK_MODULES(DLOG_REDIRECT_STDOUT_DEPS REQUIRED dlog-redirect-stdout)
@@ -66,13 +67,13 @@ PKG_CHECK_MODULES(LIBSMACK_DEPS REQUIRED libsmack)
 PKG_CHECK_MODULES(LIBSYSTEMD_DEPS REQUIRED libsystemd)
 PKG_CHECK_MODULES(LIBTZPLATFORM_CONFIG_DEPS REQUIRED libtzplatform-config)
 PKG_CHECK_MODULES(LIBXML_DEPS REQUIRED libxml-2.0)
+PKG_CHECK_MODULES(PARCEL_DEPS REQUIRED parcel)
 PKG_CHECK_MODULES(PKGMGR_INSTALLER_DEPS REQUIRED pkgmgr-installer)
 PKG_CHECK_MODULES(SECURITY_MANAGER_DEPS REQUIRED security-manager)
 PKG_CHECK_MODULES(TANCHOR_DEPS REQUIRED tanchor)
 PKG_CHECK_MODULES(TIZEN_SHARED_QUEUE_DEPS REQUIRED tizen-shared-queue)
 PKG_CHECK_MODULES(TTRACE_DEPS REQUIRED ttrace)
 PKG_CHECK_MODULES(VCONF_DEPS REQUIRED vconf)
-PKG_CHECK_MODULES(PARCEL_DEPS REQUIRED parcel)
 
 ENABLE_TESTING()
 ADD_TEST(NAME ${TARGET_LAUNCHPAD_PROCESS_POOL_UNITTEST}
index bb01a7d..ab146ed 100644 (file)
@@ -16,6 +16,7 @@ BuildRequires:  cmake
 BuildRequires:  pkgconfig(aul)
 BuildRequires:  pkgconfig(bundle)
 BuildRequires:  pkgconfig(buxton2)
+BuildRequires:  pkgconfig(capi-system-resource)
 BuildRequires:  pkgconfig(dbus-1)
 BuildRequires:  pkgconfig(dlog)
 BuildRequires:  pkgconfig(dlog-redirect-stdout)
@@ -29,13 +30,13 @@ BuildRequires:  pkgconfig(libsmack)
 BuildRequires:  pkgconfig(libsystemd)
 BuildRequires:  pkgconfig(libtzplatform-config)
 BuildRequires:  pkgconfig(libxml-2.0)
+BuildRequires:  pkgconfig(parcel)
 BuildRequires:  pkgconfig(pkgmgr-installer)
 BuildRequires:  pkgconfig(security-manager)
 BuildRequires:  pkgconfig(tanchor)
 BuildRequires:  pkgconfig(tizen-shared-queue)
 BuildRequires:  pkgconfig(ttrace)
 BuildRequires:  pkgconfig(vconf)
-BuildRequires:  pkgconfig(parcel)
 
 Requires(post): /sbin/ldconfig
 Requires(post): /usr/bin/systemctl
index 1d5b2a0..7f99de4 100644 (file)
@@ -37,6 +37,7 @@ constexpr const char kKeyMemoryMonitorInterval[] = "Interval";
 
 constexpr const char kTagCpuChecker[] = "CpuChecker";
 constexpr const char kKeyCpuCheckerMaxCount[] = "MaxCount";
+constexpr const char kKeyCpuCheckerEnable[] = "Enable";
 
 constexpr const char kTagLogger[] = "Logger";
 constexpr const char kKeyLoggerPath[] = "Path";
@@ -111,7 +112,16 @@ Config::CPUChecker::CPUChecker(const IniParser& parser) {
   if (!max_count.empty() && std::isdigit(max_count[0]))
     max_count_ = std::stoi(max_count);
 
-  _W("[CPUChecker] max_count: %d", max_count_);
+  auto enable = parser.Get(kTagCpuChecker, kKeyCpuCheckerEnable);
+  if (enable == "0" || enable == "false")
+    enable_ = false;
+
+  _W("[CPUChecker] max_count: %d, enable: %s",
+      max_count_, enable_ ? "true" : "false");
+}
+
+const bool Config::CPUChecker::IsEnabled() const {
+  return enable_;
 }
 
 const std::string& Config::Logger::GetPath() const {
index 4a5f1f6..6355d9a 100644 (file)
@@ -60,9 +60,11 @@ class Config {
     explicit CPUChecker(const IniParser& parser);
 
     const int GetMaxCount() const;
+    const bool IsEnabled() const;
 
    private:
     int max_count_ = 10;
+    bool enable_ = false;
   };
 
   class Logger {
index 8718e9a..df0eb45 100644 (file)
@@ -20,6 +20,7 @@
 #include <string>
 #include <utility>
 
+#include <cpu_boost_controller.hh>
 #include <exception.hh>
 
 #include "launchpad-process-pool/log_private.hh"
@@ -165,8 +166,13 @@ void HydraLoaderContext::HandleHydraLoaderClientEvent(int condition) {
       _E("Receive() is failed. error(%d)", ret);
     } else {
       _W("Candidate process: %d", pid);
-      if (pid > 0)
+      if (pid > 0) {
         SetPid(pid);
+        if (IsPending()) {
+          CPUBoostController::DoBoost(pid, CPUBoostController::Level::Strong,
+              10000);
+        }
+      }
     }
   }
 }
index ac8aa35..26437a1 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <app_info.hh>
 #include <aul_keys.hh>
+#include <cpu_boost_controller.hh>
 #include <exception.hh>
 #include <executor.hh>
 #include <procfs.hh>
@@ -44,6 +45,7 @@
 #include "launchpad-process-pool/language_config.hh"
 #include "launchpad-process-pool/launcher_info.hh"
 #include "launchpad-process-pool/loader_manager.hh"
+#include "launchpad-process-pool/loader_executor.hh"
 #include "launchpad-process-pool/log.hh"
 #include "launchpad-process-pool/memory_monitor.hh"
 #include "launchpad-process-pool/region_format_config.hh"
@@ -153,6 +155,22 @@ int GetLoaderIdFromBundle(const tizen_base::Bundle& b) {
   return std::stoi(loader_id);
 }
 
+inline bool CanUseLoaderContext(const std::shared_ptr<LoaderContext>& context) {
+  return ((LoaderExecutor::GetInst().HasCandidateProcess() ||
+      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();
+  else
+    context->Prepare();
+}
+
 }  // namespace
 
 Launchpad::Launchpad(int argc, char** argv)
@@ -236,6 +254,7 @@ bool Launchpad::OnCreate() {
   }
 
   LoaderManager::GetInst().AddDefaultLoaderContexts();
+  LoaderManager::GetInst().SetEventListener(this);
   launchpad::Debug::GetInst().Init();
 
   _send_cmd_to_amd(LAUNCHPAD_LAUNCH_SIGNAL);
@@ -378,7 +397,7 @@ int Launchpad::LaunchRequestPrepare(std::shared_ptr<Request> request) {
     if (request->GetLoaderId() > PAD_LOADER_ID_DYNAMIC_BASE) {
       auto context = loader_manager.FindLoaderContext(LoaderType::Dynamic,
           request->GetLoaderId());
-      if (context != nullptr && context->IsPrepared())
+      if (context != nullptr && CanUseLoaderContext(context))
         request->SetAvailableLoaderContext(std::move(context));
     } else {
       request->SetLoaderId(PAD_LOADER_ID_DIRECT);
@@ -393,18 +412,19 @@ int Launchpad::LaunchRequestPrepare(std::shared_ptr<Request> request) {
           app_info->GetLoaderName());
       if (context != nullptr) {
         request->SetLoaderContext(context);
-        if (context->IsPrepared()) {
+        if (CanUseLoaderContext(context)) {
           request->SetAvailableLoaderContext(std::move(context));
         } else {
-          request->SetAvailableLoaderContext(
-              loader_manager.FindAlternativeLoaderContext(
-                static_cast<LoaderType>(context->GetType())));
+          auto alt_context = loader_manager.FindAlternativeLoaderContext(
+              static_cast<LoaderType>(context->GetType()));
+          if (alt_context != nullptr && CanUseLoaderContext(alt_context))
+            request->SetAvailableLoaderContext(std::move(alt_context));
         }
       }
     } else {
       auto context = loader_manager.FindLoaderContext(LoaderType::Dynamic,
           request->GetLoaderId());
-      if (context != nullptr && context->IsPrepared())
+      if (context != nullptr && CanUseLoaderContext(context))
         request->SetAvailableLoaderContext(std::move(context));
     }
   }
@@ -440,6 +460,16 @@ int Launchpad::LaunchRequestDo(std::shared_ptr<Request> request) {
     return 0;
   }
 
+  if (!loader_context->IsPrepared()) {
+    _W("Loader context is not prepared");
+    loader_context->SetPending(true);
+    CheckAndPrepareLoaderContext(loader_context.get());
+    CPUBoostController::DoBoost(loader_context->GetPid(),
+        CPUBoostController::Level::Strong, 10000);
+    pending_requests_.push_back(std::move(request));
+    return 1;
+  }
+
   auto* app_info = request->GetAppInfo();
   _W("Launch %d type process. appid: %s",
       static_cast<int>(loader_context->GetType()),
@@ -471,8 +501,8 @@ void Launchpad::HandleLaunchRequest(std::shared_ptr<Request> request) {
   }
 
   ret = LaunchRequestDo(request);
-  if (ret < 0)
-    request->SetPid(ret);
+  if (ret == 1)
+    return;
 
   LaunchRequestComplete(request);
   _D("PAD_CMD_LAUNCH] appid: %s, result: %d",
@@ -530,6 +560,26 @@ void Launchpad::OnSigchldReceived(pid_t pid) {
   LoaderManager::GetInst().HandleSigchld(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);
+
+  auto iter = pending_requests_.begin();
+  while (iter != pending_requests_.end()) {
+    auto request = *iter;
+    auto context = request->GetAvailableLoaderContext();
+    if (context != nullptr && context.get() == loader_context) {
+      pending_requests_.erase(iter);
+      LaunchRequestDo(request);
+      LaunchRequestComplete(request);
+      return;
+    }
+
+    iter++;
+  }
+}
+
 }  // namespace launchpad
 
 int main(int argc, char** argv) {
index 877ee9d..91036c1 100644 (file)
@@ -23,6 +23,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <vector>
 
 #include <io_channel.hh>
 #include <server_socket.hh>
 #include "launchpad-process-pool/region_format_config.hh"
 #include "launchpad-process-pool/request.hh"
 #include "launchpad-process-pool/signal_manager.hh"
+#include "launchpad-process-pool/loader_manager.hh"
 
 namespace launchpad {
 
 class Launchpad : public IOChannel::IEvent,
-                  public SignalManager::IEvent {
+                  public SignalManager::IEvent,
+                  public LoaderManager::IEvent {
  public:
   Launchpad(int argc, char** argv);
   ~Launchpad();
@@ -73,6 +76,7 @@ class Launchpad : public IOChannel::IEvent,
 
   void OnIOEventReceived(int fd, int condition) override;
   void OnSigchldReceived(pid_t pid) override;
+  void OnLoaderPrepared(LoaderContext* loader_context);
 
  private:
   int argc_;
@@ -87,6 +91,7 @@ class Launchpad : public IOChannel::IEvent,
   std::unique_ptr<LanguageConfig> lang_config_;
   std::unique_ptr<RegionFormatConfig> region_format_config_;
   std::unique_ptr<Worker> cleaner_;
+  std::vector<std::shared_ptr<Request>> pending_requests_;
 };
 
 }  // namespace launchpad
index c69b853..750a422 100644 (file)
@@ -534,6 +534,38 @@ void LoaderContext::UpdateState(LoaderMethod method, bool force) {
   }
 }
 
+bool LoaderContext::IsLaunchable() {
+  if (ShouldCheckAppInstallation() && !IsAppInstalled()) {
+    _W("The application is not installed. type(%d)", GetType());
+    return false;
+  }
+
+  if (ShouldWaitForFileCreation()) {
+    _W("The load should wait for file creation. type(%d)", GetType());
+    return false;
+  }
+
+  if (!IsActivated()) {
+    _W("The loader is deactivated. type(%d)", GetType());
+    return false;
+  }
+
+  if (GetPid() > 0) {
+    _W("The loader is already running. type(%d), pid(%d)", GetType(), GetPid());
+    return false;
+  }
+
+  return true;
+}
+
+void LoaderContext::SetPending(bool pending) {
+  pending_ = pending;
+}
+
+bool LoaderContext::IsPending() const {
+  return pending_;
+}
+
 void LoaderContext::SetLiveTimer() {
   _W("type(%d), loader_name(%s), deactivation_method(%d)",
       GetType(), GetLoaderName().c_str(),
@@ -582,6 +614,9 @@ void LoaderContext::HandleLoaderEvent() {
         pid_ = peer_cred->GetPid();
 
       prepared_ = true;
+      if (listener_!= nullptr)
+        listener_->OnLoaderPrepared(this);
+
       SECURE_LOGI("Type %d loader was connected. pid: %d", GetType(), pid_);
       UserTracer::Print("Type " + std::to_string(GetType()) +
           " loader was connected. pid: " + std::to_string(pid_));
index e5ee1cf..154d764 100644 (file)
@@ -62,6 +62,7 @@ class LoaderContext : public std::enable_shared_from_this<LoaderContext>,
    public:
     virtual ~IEvent() = default;
     virtual void OnTimeoutEvent(LoaderContext* context) = 0;
+    virtual void OnLoaderPrepared(LoaderContext* context) = 0;
   };
 
   LoaderContext(std::shared_ptr<LoaderInfo> loader_info, int loader_id,
@@ -104,6 +105,9 @@ class LoaderContext : public std::enable_shared_from_this<LoaderContext>,
   unsigned int GetScore() const;
   bool CanActivate(LoaderMethod method) const;
   void UpdateState(LoaderMethod method, bool force);
+  bool IsLaunchable();
+  void SetPending(bool pending);
+  bool IsPending() const;
 
  protected:
   void SetPrepared(bool prepared);
@@ -125,6 +129,7 @@ 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_;
index 601a61d..1be888e 100644 (file)
@@ -69,6 +69,10 @@ pid_t LoaderExecutor::Execute(const LoaderContext* loader_context,
   return Executor::Execute(priority);
 }
 
+bool LoaderExecutor::HasCandidateProcess() const {
+  return process_pool_->IsPrepared();
+}
+
 void LoaderExecutor::OnExecution() {
   std::vector<char*> loader_argv(loader_argv_.size() + 1);
   int loader_argc = loader_argv_.size();
index b703249..a55ca30 100644 (file)
@@ -39,6 +39,7 @@ class LoaderExecutor : public Executor::Delegator,
   static LoaderExecutor& GetInst();
 
   pid_t Execute(const LoaderContext* loader_context, int priority);
+  bool HasCandidateProcess() const;
 
  private:
   LoaderExecutor();
index 37c6c33..333574a 100644 (file)
@@ -70,6 +70,10 @@ void LoaderManager::Init() {
   disposed_ = false;
 }
 
+void LoaderManager::SetEventListener(LoaderManager::IEvent* event_listener) {
+  event_listener_ = event_listener;
+}
+
 void LoaderManager::HandleSigchld(pid_t pid) {
   auto context = FindLoaderContextFromPid(pid);
   if (context != nullptr) {
@@ -210,9 +214,8 @@ std::shared_ptr<LoaderContext> LoaderManager::FindLoaderContextFromPid(
 std::shared_ptr<HydraLoaderContext>
 LoaderManager::FindHydraLoaderContextFromPid(pid_t pid) {
   for (auto& context : loader_contexts_) {
-    if (context->IsHydraMode()) {
-      auto* hydra_context = dynamic_cast<HydraLoaderContext*>(context.get());
-      if (hydra_context != nullptr && hydra_context->GetHydraPid() == pid)
+    auto* hydra_context = dynamic_cast<HydraLoaderContext*>(context.get());
+    if (hydra_context != nullptr && hydra_context->GetHydraPid() == pid) {
         return std::dynamic_pointer_cast<HydraLoaderContext>(
             hydra_context->shared_from_this());
     }
@@ -304,8 +307,7 @@ std::shared_ptr<LoaderContext> LoaderManager::FindAlternativeLoaderContext(
     if (context == nullptr)
       continue;
 
-    if (context->IsPrepared())
-      return context;
+    return context;
   }
 
   return nullptr;
@@ -489,25 +491,8 @@ bool LoaderManager::OnIdleCheck(LoaderContext* context) {
   _W("Loader(%s), type(%d), pid(%d)",
       context->GetLoaderName().c_str(), context->GetType(), context->GetPid());
 
-  if (context->ShouldCheckAppInstallation() && !context->IsAppInstalled()) {
-    _W("The application is not installed");
-    return false;
-  }
-
-  if (context->ShouldWaitForFileCreation()) {
-    _W("The loader should wait for file creation");
-    return false;
-  }
-
-  if (!context->IsActivated()) {
-    _W("The loader is deactivated");
-    return false;
-  }
-
-  if (context->GetPid() > 0) {
-    _W("The loader is already running");
+  if (!context->IsLaunchable())
     return false;
-  }
 
   if (context->GetCPUChecker()->IsIdle()) {
     context->Prepare();
@@ -523,4 +508,19 @@ bool LoaderManager::OnIdleCheck(LoaderContext* context) {
   return true;
 }
 
+void LoaderManager::OnLoaderLaunch(LoaderContext* context) {
+  _W("Loader(%s), type(%d), pid(%d)",
+      context->GetLoaderName().c_str(), context->GetType(), context->GetPid());
+
+  if (!context->IsLaunchable())
+    return;
+
+  context->Prepare();
+}
+
+void LoaderManager::OnLoaderPrepared(LoaderContext* context) {
+  if (event_listener_ != nullptr)
+    event_listener_->OnLoaderPrepared(context);
+}
+
 }  // namespace launchpad
index e715f5a..cf8aa4a 100644 (file)
@@ -43,6 +43,12 @@ class LoaderManager : public AppDefinedLoaderInfoManager::IEvent,
                       public Sequencer::IEvent,
                       public LoaderContext::IEvent {
  public:
+  class IEvent {
+   public:
+    virtual ~IEvent() = default;
+    virtual void OnLoaderPrepared(LoaderContext* context) = 0;
+  };
+
   LoaderManager(const LoaderManager&) = delete;
   LoaderManager& operator=(const LoaderManager&) = delete;
   LoaderManager(LoaderManager&&) = delete;
@@ -51,6 +57,7 @@ class LoaderManager : public AppDefinedLoaderInfoManager::IEvent,
   static LoaderManager& GetInst();
   void Dispose();
 
+  void SetEventListener(IEvent* event_listener);
   void HandleSigchld(pid_t pid);
   void AddDefaultLoaderContexts();
   void ActivateLoaderContexts(LoaderMethod method);
@@ -96,9 +103,12 @@ class LoaderManager : public AppDefinedLoaderInfoManager::IEvent,
   void OnLoaderInfoRemoved(const std::string_view name) override;
   void OnTimeoutEvent(LoaderContext* context) override;
   bool OnIdleCheck(LoaderContext* context) override;
+  void OnLoaderLaunch(LoaderContext* context) override;
+  void OnLoaderPrepared(LoaderContext* context) override;
 
  private:
   bool disposed_ = true;
+  IEvent* event_listener_ = nullptr;
   std::unique_ptr<Sequencer> sequencer_;
   std::unique_ptr<LoaderInfoManager> loader_info_manager_;
   std::unique_ptr<AppDefinedLoaderInfoManager> app_defined_loader_info_manager_;
index 7ea3ed6..2232dea 100644 (file)
@@ -27,8 +27,8 @@ namespace launchpad {
 Sequencer::Sequencer(Sequencer::IEvent* listener) : listener_(listener) {}
 
 Sequencer::~Sequencer() {
-  if (idle_checker_ > 0)
-    g_source_remove(idle_checker_);
+  if (source_ > 0)
+    g_source_remove(source_);
 
   if (timer_ > 0)
     g_source_remove(timer_);
@@ -60,7 +60,8 @@ void Sequencer::Run() {
   if (timer_)
     return;
 
-  timer_ = g_timeout_add(500, RunCb, this);
+  guint interval = Config::GetInst().GetCPUChecker().IsEnabled() ? 500 : 100;
+  timer_ = g_timeout_add(interval, RunCb, this);
   if (timer_ == 0)
     _E("Failed to add sequencer timer");
 }
@@ -85,7 +86,7 @@ bool Sequencer::Exist(const std::shared_ptr<LoaderContext>& context) {
 
 gboolean Sequencer::RunCb(gpointer user_data) {
   auto* sequencer = static_cast<Sequencer*>(user_data);
-  if (sequencer->idle_checker_ > 0)
+  if (sequencer->source_ > 0)
       return G_SOURCE_CONTINUE;
 
   if (sequencer->queue_.empty()) {
@@ -105,7 +106,11 @@ gboolean Sequencer::RunCb(gpointer user_data) {
 
   _W("[SEQUENCER] Add idle checker. Type(%d)", context->GetType());
   sequencer->running_context_ = std::move(context);
-  sequencer->idle_checker_ = g_timeout_add(1000, IdleCheckCb, user_data);
+  if (Config::GetInst().GetCPUChecker().IsEnabled())
+    sequencer->source_ = g_timeout_add(1000, IdleCheckCb, user_data);
+  else
+    sequencer->source_ = g_idle_add(LaunchCb, user_data);
+
   return G_SOURCE_CONTINUE;
 }
 
@@ -115,11 +120,26 @@ gboolean Sequencer::IdleCheckCb(gpointer user_data) {
   if (listener == nullptr ||
       !listener->OnIdleCheck(sequencer->running_context_.get())) {
     sequencer->running_context_ = nullptr;
-    sequencer->idle_checker_ = 0;
+    sequencer->source_ = 0;
     return G_SOURCE_REMOVE;
   }
 
   return G_SOURCE_CONTINUE;
 }
 
+gboolean Sequencer::LaunchCb(gpointer user_data) {
+  auto* sequencer = static_cast<Sequencer*>(user_data);
+  sequencer->source_ = 0;
+
+  auto* listener = sequencer->listener_;
+  if (listener == nullptr) {
+    sequencer->running_context_ = nullptr;
+    return G_SOURCE_REMOVE;
+  }
+
+  listener->OnLoaderLaunch(sequencer->running_context_.get());
+  sequencer->running_context_ = nullptr;
+  return G_SOURCE_REMOVE;
+}
+
 }  // namespace launchpad
index d5d0230..9f594e1 100644 (file)
@@ -32,6 +32,7 @@ class Sequencer {
    public:
     virtual ~IEvent() = default;
     virtual bool OnIdleCheck(LoaderContext* context) = 0;
+    virtual void OnLoaderLaunch(LoaderContext* context) = 0;
   };
 
   explicit Sequencer(IEvent* listener);
@@ -46,11 +47,12 @@ class Sequencer {
  private:
   static gboolean RunCb(gpointer user_data);
   static gboolean IdleCheckCb(gpointer user_data);
+  static gboolean LaunchCb(gpointer user_data);
 
  private:
   IEvent* listener_;
   guint timer_ = 0;
-  guint idle_checker_ = 0;
+  guint source_ = 0;
   std::shared_ptr<LoaderContext> running_context_;
   std::list<std::shared_ptr<LoaderContext>> queue_;
 };
index e655544..a6a6ef1 100644 (file)
@@ -14,6 +14,7 @@ TARGET_INCLUDE_DIRECTORIES(${TARGET_LAUNCHPAD_COMMON} PUBLIC
 
 APPLY_PKG_CONFIG(${TARGET_LAUNCHPAD_COMMON} PUBLIC
   BUNDLE_DEPS
+  CAPI_SYSTEM_RESOURCE_DEPS
   DLOG_DEPS
   GIO_DEPS
   INIPARSER_DEPS
diff --git a/src/lib/launchpad-common/cpu_boost_controller.cc b/src/lib/launchpad-common/cpu_boost_controller.cc
new file mode 100644 (file)
index 0000000..cdc1814
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "launchpad-common/cpu_boost_controller.hh"
+
+#include <cpu-boosting.h>
+
+#include "launchpad-common/log_private.hh"
+
+namespace launchpad {
+
+void CPUBoostController::DoBoost(pid_t pid, Level level, int timeout_msec) {
+  if (pid < 1)
+    return;
+
+  resource_pid_t res_pid = {
+    .pid = 0,
+    .tid = &pid,
+    .tid_count = 1,
+  };
+
+  int ret = resource_set_cpu_boosting(res_pid,
+      static_cast<cpu_boosting_level_e>(level), CPU_BOOSTING_RESET_ON_FORK,
+      timeout_msec);
+  if (ret != 0)
+    _E("resource_set_cpu_boosting() is failed. error: %d", ret);
+  else
+    _D("resource_set_cpu_boosting() is successful");
+}
+
+}  // namespace launchpad
diff --git a/src/lib/launchpad-common/cpu_boost_controller.hh b/src/lib/launchpad-common/cpu_boost_controller.hh
new file mode 100644 (file)
index 0000000..1547c8c
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LIB_LAUNCHPAD_COMMON_CPU_BOOST_CONTROLLER_HH_
+#define LIB_LAUNCHPAD_COMMON_CPU_BOOST_CONTROLLER_HH_
+
+#include <sys/types.h>
+
+#undef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+
+namespace launchpad {
+
+class EXPORT_API CPUBoostController {
+ public:
+  enum class Level {
+    None,
+    Strong,
+    Medium,
+    Weak,
+  };
+
+  static void DoBoost(pid_t pid, Level level, int timeout_msec);
+};
+
+}  // namespace launchpad
+
+#endif  // LIB_LAUNCHPAD_COMMON_CPU_BOOST_CONTROLLER_HH_