diff --git a/services/include/updater/updater.h b/services/include/updater/updater.h index ab6f212c75ab011c3ef1571893890d7aeedc0dd1..0e8f4f669da236da139c88b271aea9efb9d453cc 100644 --- a/services/include/updater/updater.h +++ b/services/include/updater/updater.h @@ -56,6 +56,7 @@ enum NotifyAction { struct UpdaterParams { bool forceUpdate = false; bool forceReboot = false; + bool isLoadReduction = false; std::string sdExtMode {}; std::string factoryResetMode {}; PackageUpdateMode updateMode = HOTA_UPDATE; @@ -144,5 +145,11 @@ void RegisterMode(const BootMode &mode); std::vector &GetBootModes(void); std::optional SelectMode(const UpdateMessage &boot); + +std::vector GetAllTids(pid_t pid); + +bool SetCpuAffinityByPid(pid_t binaryPid, unsigned int reservedCores); + +void ReduceLoad(const UpdaterParams &upParams); } // Updater #endif /* UPDATER_UPDATER_H */ diff --git a/services/include/updater/updater_const.h b/services/include/updater/updater_const.h index 9ef5acba96919ccb15b39e58e4fd17a574f5ad83..0d327718ac114e364a45fc693aa674345de65411 100644 --- a/services/include/updater/updater_const.h +++ b/services/include/updater/updater_const.h @@ -113,6 +113,7 @@ constexpr int32_t DEFAULT_PIPE_NUM = 2; constexpr int32_t BINARY_MAX_ARGS = 3; constexpr int32_t BINARY_SECOND_ARG = 2; constexpr int32_t WRITE_SECOND_CMD = 2; +constexpr uint32_t LITTLE_CPU_CORES = 4; constexpr int REBOOT = 0; constexpr int WIPE_DATA = 1; constexpr int WIPE_CACHE = 2; diff --git a/services/updater.cpp b/services/updater.cpp index 78ed1177355bc69f4cbd648cf4874527ffd0c0c9..11f710178c046746a029dd4ef22c90e829c41668 100644 --- a/services/updater.cpp +++ b/services/updater.cpp @@ -680,32 +680,38 @@ static std::string GetBinaryPath(PkgManager::PkgManagerPtr pkgManager, UpdaterPa return fullPath; } +static std::string GetFullPath(PkgManager::PkgManagerPtr pkgManager, UpdaterParams &upParams) +{ + std::string fullPath = ""; + if (upParams.updateBin.size() > 0) { + fullPath = GetBinaryPathFromBin(pkgManager, upParams); + } else if (upParams.updatePackage.size() > 0) { + fullPath = GetBinaryPath(pkgManager, upParams); + } + if (chmod(fullPath.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) { + LOG(ERROR) << "Failed to change mode"; + } + return fullPath; +} + UpdaterStatus StartUpdaterProc(PkgManager::PkgManagerPtr pkgManager, UpdaterParams &upParams) { UPDATER_INIT_RECORD; + if (pkgManager == nullptr) { + LOG(ERROR) << "pkgManager is nullptr"; + UPDATER_LAST_WORD(UPDATE_CORRUPT, "pkgManager is nullptr"); + return UPDATE_CORRUPT; + } int pfd[DEFAULT_PIPE_NUM]; /* communication between parent and child */ if (pipe(pfd) < 0) { LOG(ERROR) << "Create pipe failed: "; UPDATER_LAST_WORD(UPDATE_ERROR, "Create pipe failed"); return UPDATE_ERROR; } - if (pkgManager == nullptr) { - LOG(ERROR) << "pkgManager is nullptr"; - UPDATER_LAST_WORD(UPDATE_CORRUPT, "pkgManager is nullptr"); - return UPDATE_CORRUPT; - } int pipeRead = pfd[0]; int pipeWrite = pfd[1]; - std::string fullPath = ""; - if (upParams.updateBin.size() > 0) { - fullPath = GetBinaryPathFromBin(pkgManager, upParams); - } else if (upParams.updatePackage.size() > 0) { - fullPath = GetBinaryPath(pkgManager, upParams); - } - if (chmod(fullPath.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) { - LOG(ERROR) << "Failed to change mode"; - } + std::string fullPath = GetFullPath(pkgManager, upParams); #ifdef WITH_SELINUX Restorecon(fullPath.c_str()); @@ -716,6 +722,8 @@ UpdaterStatus StartUpdaterProc(PkgManager::PkgManagerPtr pkgManager, UpdaterPara ERROR_CODE(CODE_FORK_FAIL); upParams.binaryPid = -1; UPDATER_LAST_WORD(UPDATE_ERROR, "fork failed"); + close(pipeRead); + close(pipeWrite); return UPDATE_ERROR; } @@ -728,6 +736,7 @@ UpdaterStatus StartUpdaterProc(PkgManager::PkgManagerPtr pkgManager, UpdaterPara } upParams.binaryPid = pid; + ReduceLoad(upParams); close(pipeWrite); // close write endpoint bool retryUpdate = false; if (HandlePipeMsg(upParams, pipeRead, retryUpdate) != UPDATE_SUCCESS) { diff --git a/services/updater_utils.cpp b/services/updater_utils.cpp index b1af159fb9c3bf8478c4b7a2ccb8d73788f3d898..ec17c43d352a711e0af0a924395bf587cc0c0a61 100755 --- a/services/updater_utils.cpp +++ b/services/updater_utils.cpp @@ -13,12 +13,17 @@ * limitations under the License. */ #include +#include +#include +#include +#include #include #include +#include #include #include #include -#include +#include #include "applypatch/partition_record.h" #include "flashd/flashd.h" @@ -287,4 +292,80 @@ std::optional SelectMode(const UpdateMessage &boot) LOG(INFO) << "enter " << it->modeName << " mode"; return *it; } + +std::vector GetAllTids(pid_t pid) +{ + std::vector tids; + std::string pathName = std::string("/proc/").append(std::to_string(pid)).append("/task"); + char tmpPath[PATH_MAX + 1] = {0}; + if (realpath(pathName.c_str(), tmpPath) == nullptr || tmpPath[0] == '\0') { + LOG(ERROR) << "realpath fail pathName:" << pathName; + return tids; + } + DIR *dir = opendir(tmpPath); + if (dir == nullptr) { + LOG(ERROR) << "opendir fail pathName:" << pathName; + return tids; + } + struct dirent *de = nullptr; + while ((de = readdir(dir)) != nullptr) { + if (!(de->d_type & DT_DIR) || !isdigit(de->d_name[0])) { + continue; + } + int32_t temp = -1; + if (!Utils::ConvertToLong(de->d_name, temp)) { + LOG(ERROR) << "ConvertToLong failed"; + continue; + } + pid_t tid = static_cast(temp); + if (tid > 0) { + tids.push_back(tid); + } + } + closedir(dir); + return tids; +} + +bool SetCpuAffinityByPid(pid_t binaryPid, unsigned int reservedCores) +{ + LOG(INFO) << "SetCpuAffinityByPid binaryPid:" << binaryPid; + if (binaryPid == -1) { + LOG(WARNING) << "invalid binaryPid:" << binaryPid; + return false; + } + unsigned int coreCount = std::thread::hardware_concurrency(); + LOG(INFO) << "coreCount:" << coreCount << ", reservedCores:" << reservedCores; + if (coreCount <= reservedCores) { + LOG(WARNING) << "coreCount:" << coreCount << " <= " << reservedCores; + return false; + } + cpu_set_t mask; + CPU_ZERO(&mask); + for (unsigned int i = 0; i < coreCount - reservedCores; i++) { + CPU_SET(i, &mask); + } + std::vector tids = GetAllTids(binaryPid); + if (tids.empty()) { + LOG(WARNING) << "set affinity faild, tids is null"; + return false; + } + int syscallRes; + for (auto& tid : tids) { + syscallRes = syscall(__NR_sched_setaffinity, tid, sizeof(mask), &mask); + LOG(INFO) << "setaffinity tid:" << tid; + if (syscallRes != 0) { + LOG(ERROR) << "set affinity faild:" << syscallRes; + } + } + return true; +} + +void ReduceLoad(const UpdaterParams &upParams) +{ + if (upParams.isLoadReduction) { + unsigned int coreCount = std::thread::hardware_concurrency(); + unsigned int reservedCores = coreCount - LITTLE_CPU_CORES; + SetCpuAffinityByPid(upParams.binaryPid, reservedCores); + } +} } // namespace Updater diff --git a/test/fuzztest/UpdaterStartUpdaterProc_fuzzer/UpdaterStartUpdaterProc_fuzzer.cpp b/test/fuzztest/UpdaterStartUpdaterProc_fuzzer/UpdaterStartUpdaterProc_fuzzer.cpp index 2d7ecaa56ee4180e351d36e97e4299613d7b9ca9..d8f2337d7c74ed527109e2f05f1e41efb50a520c 100644 --- a/test/fuzztest/UpdaterStartUpdaterProc_fuzzer/UpdaterStartUpdaterProc_fuzzer.cpp +++ b/test/fuzztest/UpdaterStartUpdaterProc_fuzzer/UpdaterStartUpdaterProc_fuzzer.cpp @@ -165,6 +165,7 @@ static int StartUpdaterProcFun(const std::string &patch) UpdaterParams upParams; upParams.updatePackage.push_back(patch); upParams.retryCount = 0; + upParams.isLoadReduction = true; status = StartUpdaterProc(pkgManager, upParams); LOG(INFO) << "[fuzz] status " << status; PkgManager::ReleasePackageInstance(pkgManager); diff --git a/test/unittest/service_test/updater_service_unittest.cpp b/test/unittest/service_test/updater_service_unittest.cpp index d4aadd6963f054394ce406bdb4e0fad2465f3ae6..c260639bc185a50e580cbbffbf4078786be0b754 100644 --- a/test/unittest/service_test/updater_service_unittest.cpp +++ b/test/unittest/service_test/updater_service_unittest.cpp @@ -316,6 +316,7 @@ HWTEST_F(UpdaterUtilUnitTest, StartUpdaterProcTest, TestSize.Level1) { Hpackage::PkgManager::PkgManagerPtr pkgManager = Hpackage::PkgManager::CreatePackageInstance(); UpdaterParams upParams; + upParams.isLoadReduction = true; EXPECT_EQ(StartUpdaterProc(nullptr, upParams), UPDATE_CORRUPT); EXPECT_EQ(StartUpdaterProc(pkgManager, upParams), UPDATE_ERROR); }