diff --git a/meta-oniro-staging/recipes-devtools/ninja/ninja/0001-feat-support-cpu-limit-by-cgroups-on-linux.patch b/meta-oniro-staging/recipes-devtools/ninja/ninja/0001-feat-support-cpu-limit-by-cgroups-on-linux.patch new file mode 100644 index 0000000000000000000000000000000000000000..56a99c7d03d7e39a0910089925b216f5079c3c43 --- /dev/null +++ b/meta-oniro-staging/recipes-devtools/ninja/ninja/0001-feat-support-cpu-limit-by-cgroups-on-linux.patch @@ -0,0 +1,212 @@ +From 250747d4c422c893aaf516ce19fabb77a7926968 Mon Sep 17 00:00:00 2001 +From: Mateusz Guzik <mjguzik@gmail.com> +Date: Sat, 28 Nov 2020 23:54:09 +0000 +Subject: [PATCH] feat: support cpu limit by cgroups on linux + +Signed-off-by: Andrei Gherzan <andrei.gherzan@huawei.com> +Upstream-Status: Backport [540be336f5639ee6a89e959e6f9f434c01900ecf] +--- + src/util.cc | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 166 insertions(+), 3 deletions(-) + +diff --git a/src/util.cc b/src/util.cc +index c76f730..d609e49 100644 +--- a/src/util.cc ++++ b/src/util.cc +@@ -49,6 +49,13 @@ + #include <libperfstat.h> + #elif defined(linux) || defined(__GLIBC__) + #include <sys/sysinfo.h> ++#include <fstream> ++#include <map> ++#include "string_piece_util.h" ++#endif ++ ++#if defined(__FreeBSD__) ++#include <sys/cpuset.h> + #endif + + #include "edit_distance.h" +@@ -481,20 +488,176 @@ string StripAnsiEscapeCodes(const string& in) { + return stripped; + } + ++#if defined(linux) || defined(__GLIBC__) ++std::pair<int64_t, bool> readCount(const std::string& path) { ++ std::ifstream file(path.c_str()); ++ if (!file.is_open()) ++ return std::make_pair(0, false); ++ int64_t n = 0; ++ file >> n; ++ if (file.good()) ++ return std::make_pair(n, true); ++ return std::make_pair(0, false); ++} ++ ++struct MountPoint { ++ int mountId; ++ int parentId; ++ StringPiece deviceId; ++ StringPiece root; ++ StringPiece mountPoint; ++ vector<StringPiece> options; ++ vector<StringPiece> optionalFields; ++ StringPiece fsType; ++ StringPiece mountSource; ++ vector<StringPiece> superOptions; ++ bool parse(const string& line) { ++ vector<StringPiece> pieces = SplitStringPiece(line, ' '); ++ if (pieces.size() < 10) ++ return false; ++ size_t optionalStart = 0; ++ for (size_t i = 6; i < pieces.size(); i++) { ++ if (pieces[i] == "-") { ++ optionalStart = i + 1; ++ break; ++ } ++ } ++ if (optionalStart == 0) ++ return false; ++ if (optionalStart + 3 != pieces.size()) ++ return false; ++ mountId = atoi(pieces[0].AsString().c_str()); ++ parentId = atoi(pieces[1].AsString().c_str()); ++ deviceId = pieces[2]; ++ root = pieces[3]; ++ mountPoint = pieces[4]; ++ options = SplitStringPiece(pieces[5], ','); ++ optionalFields = ++ vector<StringPiece>(&pieces[6], &pieces[optionalStart - 1]); ++ fsType = pieces[optionalStart]; ++ mountSource = pieces[optionalStart + 1]; ++ superOptions = SplitStringPiece(pieces[optionalStart + 2], ','); ++ return true; ++ } ++ string translate(string& path) const { ++ // path must be sub dir of root ++ if (path.compare(0, root.len_, root.str_, root.len_) != 0) { ++ return string(); ++ } ++ path.erase(0, root.len_); ++ if (path == ".." || (path.length() > 2 && path.compare(0, 3, "../") == 0)) { ++ return string(); ++ } ++ return mountPoint.AsString() + "/" + path; ++ } ++}; ++ ++struct CGroupSubSys { ++ int id; ++ string name; ++ vector<string> subsystems; ++ bool parse(string& line) { ++ size_t first = line.find(':'); ++ if (first == string::npos) ++ return false; ++ line[first] = '\0'; ++ size_t second = line.find(':', first + 1); ++ if (second == string::npos) ++ return false; ++ line[second] = '\0'; ++ id = atoi(line.c_str()); ++ name = line.substr(second + 1); ++ vector<StringPiece> pieces = ++ SplitStringPiece(StringPiece(line.c_str() + first + 1), ','); ++ for (size_t i = 0; i < pieces.size(); i++) { ++ subsystems.push_back(pieces[i].AsString()); ++ } ++ return true; ++ } ++}; ++ ++map<string, string> ParseMountInfo(map<string, CGroupSubSys>& subsystems) { ++ map<string, string> cgroups; ++ ifstream mountinfo("/proc/self/mountinfo"); ++ if (!mountinfo.is_open()) ++ return cgroups; ++ while (!mountinfo.eof()) { ++ string line; ++ getline(mountinfo, line); ++ MountPoint mp; ++ if (!mp.parse(line)) ++ continue; ++ if (mp.fsType != "cgroup") ++ continue; ++ for (size_t i = 0; i < mp.superOptions.size(); i++) { ++ string opt = mp.superOptions[i].AsString(); ++ map<string, CGroupSubSys>::iterator subsys = subsystems.find(opt); ++ if (subsys == subsystems.end()) ++ continue; ++ string newPath = mp.translate(subsys->second.name); ++ if (!newPath.empty()) ++ cgroups.insert(make_pair(opt, newPath)); ++ } ++ } ++ return cgroups; ++} ++ ++map<string, CGroupSubSys> ParseSelfCGroup() { ++ map<string, CGroupSubSys> cgroups; ++ ifstream cgroup("/proc/self/cgroup"); ++ if (!cgroup.is_open()) ++ return cgroups; ++ string line; ++ while (!cgroup.eof()) { ++ getline(cgroup, line); ++ CGroupSubSys subsys; ++ if (!subsys.parse(line)) ++ continue; ++ for (size_t i = 0; i < subsys.subsystems.size(); i++) { ++ cgroups.insert(make_pair(subsys.subsystems[i], subsys)); ++ } ++ } ++ return cgroups; ++} ++ ++int ParseCPUFromCGroup() { ++ map<string, CGroupSubSys> subsystems = ParseSelfCGroup(); ++ map<string, string> cgroups = ParseMountInfo(subsystems); ++ map<string, string>::iterator cpu = cgroups.find("cpu"); ++ if (cpu == cgroups.end()) ++ return -1; ++ std::pair<int64_t, bool> quota = readCount(cpu->second + "/cpu.cfs_quota_us"); ++ if (!quota.second || quota.first == -1) ++ return -1; ++ std::pair<int64_t, bool> period = ++ readCount(cpu->second + "/cpu.cfs_period_us"); ++ if (!period.second) ++ return -1; ++ return quota.first / period.first; ++} ++#endif ++ + int GetProcessorCount() { + #ifdef _WIN32 + return GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); + #else +-#ifdef CPU_COUNT ++ int cgroupCount = -1; ++ int schedCount = -1; ++#if defined(linux) || defined(__GLIBC__) ++ cgroupCount = ParseCPUFromCGroup(); ++#endif + // The number of exposed processors might not represent the actual number of + // processors threads can run on. This happens when a CPU set limitation is + // active, see https://github.com/ninja-build/ninja/issues/1278 ++#ifdef CPU_COUNT + cpu_set_t set; + if (sched_getaffinity(getpid(), sizeof(set), &set) == 0) { +- return CPU_COUNT(&set); ++ schedCount = CPU_COUNT(&set); + } + #endif +- return sysconf(_SC_NPROCESSORS_ONLN); ++ if (cgroupCount >= 0 && schedCount >= 0) return std::min(cgroupCount, schedCount); ++ if (cgroupCount < 0 && schedCount < 0) return sysconf(_SC_NPROCESSORS_ONLN); ++ return std::max(cgroupCount, schedCount); + #endif + } + +-- +2.25.1 + diff --git a/meta-oniro-staging/recipes-devtools/ninja/ninja_1.10.2.bbappend b/meta-oniro-staging/recipes-devtools/ninja/ninja_1.10.2.bbappend new file mode 100644 index 0000000000000000000000000000000000000000..0478ededfec7ce14ec0c4d5f5c34d241b202fb23 --- /dev/null +++ b/meta-oniro-staging/recipes-devtools/ninja/ninja_1.10.2.bbappend @@ -0,0 +1,8 @@ +# SPDX-FileCopyrightText: Huawei Inc. +# +# SPDX-License-Identifier: Apache-2.0 + +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" +SRC_URI += "\ + file://0001-feat-support-cpu-limit-by-cgroups-on-linux.patch \ +"