Loading libcutils/Android.bp +5 −1 Original line number Diff line number Diff line Loading @@ -235,6 +235,7 @@ test_libraries = [ "libbase", "libjsoncpp", "libprocessgroup", "libcgrouprc", ] cc_test { Loading @@ -249,7 +250,10 @@ cc_test { name: "libcutils_test_static", test_suites: ["device-tests"], defaults: ["libcutils_test_default"], static_libs: ["libc"] + test_libraries, static_libs: [ "libc", "libcgrouprc_format", ] + test_libraries, stl: "libc++_static", target: { Loading libprocessgroup/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ cc_library { }, shared_libs: [ "libbase", "libcgrouprc", "libjsoncpp", ], // for cutils/android_filesystem_config.h Loading libprocessgroup/cgroup_map.cpp +49 −86 Original line number Diff line number Diff line Loading @@ -48,28 +48,38 @@ static constexpr const char* CGROUP_PROCS_FILE = "/cgroup.procs"; static constexpr const char* CGROUP_TASKS_FILE = "/tasks"; static constexpr const char* CGROUP_TASKS_FILE_V2 = "/cgroup.tasks"; CgroupController::CgroupController(uint32_t version, const std::string& name, const std::string& path) { version_ = version; strncpy(name_, name.c_str(), sizeof(name_) - 1); name_[sizeof(name_) - 1] = '\0'; strncpy(path_, path.c_str(), sizeof(path_) - 1); path_[sizeof(path_) - 1] = '\0'; uint32_t CgroupController::version() const { CHECK(HasValue()); return ACgroupController_getVersion(controller_); } std::string CgroupController::GetTasksFilePath(const std::string& path) const { std::string tasks_path = path_; const char* CgroupController::name() const { CHECK(HasValue()); return ACgroupController_getName(controller_); } if (!path.empty()) { tasks_path += "/" + path; const char* CgroupController::path() const { CHECK(HasValue()); return ACgroupController_getPath(controller_); } return (version_ == 1) ? tasks_path + CGROUP_TASKS_FILE : tasks_path + CGROUP_TASKS_FILE_V2; bool CgroupController::HasValue() const { return controller_ != nullptr; } std::string CgroupController::GetProcsFilePath(const std::string& path, uid_t uid, std::string CgroupController::GetTasksFilePath(const std::string& rel_path) const { std::string tasks_path = path(); if (!rel_path.empty()) { tasks_path += "/" + rel_path; } return (version() == 1) ? tasks_path + CGROUP_TASKS_FILE : tasks_path + CGROUP_TASKS_FILE_V2; } std::string CgroupController::GetProcsFilePath(const std::string& rel_path, uid_t uid, pid_t pid) const { std::string proc_path(path_); proc_path.append("/").append(path); std::string proc_path(path()); proc_path.append("/").append(rel_path); proc_path = regex_replace(proc_path, std::regex("<uid>"), std::to_string(uid)); proc_path = regex_replace(proc_path, std::regex("<pid>"), std::to_string(pid)); Loading @@ -90,7 +100,7 @@ bool CgroupController::GetTaskGroup(int tid, std::string* group) const { return true; } std::string cg_tag = StringPrintf(":%s:", name_); std::string cg_tag = StringPrintf(":%s:", name()); size_t start_pos = content.find(cg_tag); if (start_pos == std::string::npos) { return false; Loading @@ -107,20 +117,12 @@ bool CgroupController::GetTaskGroup(int tid, std::string* group) const { return true; } CgroupMap::CgroupMap() : cg_file_data_(nullptr), cg_file_size_(0) { CgroupMap::CgroupMap() { if (!LoadRcFile()) { LOG(ERROR) << "CgroupMap::LoadRcFile called for [" << getpid() << "] failed"; } } CgroupMap::~CgroupMap() { if (cg_file_data_) { munmap(cg_file_data_, cg_file_size_); cg_file_data_ = nullptr; cg_file_size_ = 0; } } CgroupMap& CgroupMap::GetInstance() { // Deliberately leak this object to avoid a race between destruction on // process exit and concurrent access from another thread. Loading @@ -129,85 +131,46 @@ CgroupMap& CgroupMap::GetInstance() { } bool CgroupMap::LoadRcFile() { struct stat sb; if (cg_file_data_) { // Data already initialized return true; } unique_fd fd(TEMP_FAILURE_RETRY(open(CGROUPS_RC_PATH, O_RDONLY | O_CLOEXEC))); if (fd < 0) { PLOG(ERROR) << "open() failed for " << CGROUPS_RC_PATH; return false; if (!loaded_) { loaded_ = (ACgroupFile_getVersion() != 0); } if (fstat(fd, &sb) < 0) { PLOG(ERROR) << "fstat() failed for " << CGROUPS_RC_PATH; return false; } size_t file_size = sb.st_size; if (file_size < sizeof(CgroupFile)) { LOG(ERROR) << "Invalid file format " << CGROUPS_RC_PATH; return false; } CgroupFile* file_data = (CgroupFile*)mmap(nullptr, file_size, PROT_READ, MAP_SHARED, fd, 0); if (file_data == MAP_FAILED) { PLOG(ERROR) << "Failed to mmap " << CGROUPS_RC_PATH; return false; } if (file_data->version_ != CgroupFile::FILE_CURR_VERSION) { LOG(ERROR) << CGROUPS_RC_PATH << " file version mismatch"; munmap(file_data, file_size); return false; } if (file_size != sizeof(CgroupFile) + file_data->controller_count_ * sizeof(CgroupController)) { LOG(ERROR) << CGROUPS_RC_PATH << " file has invalid size"; munmap(file_data, file_size); return false; } cg_file_data_ = file_data; cg_file_size_ = file_size; return true; return loaded_; } void CgroupMap::Print() const { if (!cg_file_data_) { if (!loaded_) { LOG(ERROR) << "CgroupMap::Print called for [" << getpid() << "] failed, RC file was not initialized properly"; return; } LOG(INFO) << "File version = " << cg_file_data_->version_; LOG(INFO) << "File controller count = " << cg_file_data_->controller_count_; LOG(INFO) << "File version = " << ACgroupFile_getVersion(); LOG(INFO) << "File controller count = " << ACgroupFile_getControllerCount(); LOG(INFO) << "Mounted cgroups:"; CgroupController* controller = (CgroupController*)(cg_file_data_ + 1); for (int i = 0; i < cg_file_data_->controller_count_; i++, controller++) { LOG(INFO) << "\t" << controller->name() << " ver " << controller->version() << " path " << controller->path(); auto controller_count = ACgroupFile_getControllerCount(); for (uint32_t i = 0; i < controller_count; ++i) { const ACgroupController* controller = ACgroupFile_getController(i); LOG(INFO) << "\t" << ACgroupController_getName(controller) << " ver " << ACgroupController_getVersion(controller) << " path " << ACgroupController_getPath(controller); } } const CgroupController* CgroupMap::FindController(const std::string& name) const { if (!cg_file_data_) { CgroupController CgroupMap::FindController(const std::string& name) const { if (!loaded_) { LOG(ERROR) << "CgroupMap::FindController called for [" << getpid() << "] failed, RC file was not initialized properly"; return nullptr; return CgroupController(nullptr); } // skip the file header to get to the first controller CgroupController* controller = (CgroupController*)(cg_file_data_ + 1); for (int i = 0; i < cg_file_data_->controller_count_; i++, controller++) { if (name == controller->name()) { return controller; auto controller_count = ACgroupFile_getControllerCount(); for (uint32_t i = 0; i < controller_count; ++i) { const ACgroupController* controller = ACgroupFile_getController(i); if (name == ACgroupController_getName(controller)) { return CgroupController(controller); } } return nullptr; return CgroupController(nullptr); } libprocessgroup/cgroup_map.h +15 −29 Original line number Diff line number Diff line Loading @@ -20,39 +20,30 @@ #include <sys/types.h> #include <map> #include <memory> #include <mutex> #include <string> #include <vector> // Minimal controller description to be mmapped into process address space #include <android/cgrouprc.h> // Convenient wrapper of an ACgroupController pointer. class CgroupController { public: CgroupController() {} CgroupController(uint32_t version, const std::string& name, const std::string& path); // Does not own controller explicit CgroupController(const ACgroupController* controller) : controller_(controller) {} uint32_t version() const; const char* name() const; const char* path() const; uint32_t version() const { return version_; } const char* name() const { return name_; } const char* path() const { return path_; } bool HasValue() const; std::string GetTasksFilePath(const std::string& path) const; std::string GetProcsFilePath(const std::string& path, uid_t uid, pid_t pid) const; bool GetTaskGroup(int tid, std::string* group) const; private: static constexpr size_t CGROUP_NAME_BUF_SZ = 16; static constexpr size_t CGROUP_PATH_BUF_SZ = 32; uint32_t version_; char name_[CGROUP_NAME_BUF_SZ]; char path_[CGROUP_PATH_BUF_SZ]; }; struct CgroupFile { static constexpr uint32_t FILE_VERSION_1 = 1; static constexpr uint32_t FILE_CURR_VERSION = FILE_VERSION_1; uint32_t version_; uint32_t controller_count_; CgroupController controllers_[]; const ACgroupController* controller_ = nullptr; }; class CgroupMap { Loading @@ -61,16 +52,11 @@ class CgroupMap { static bool SetupCgroups(); static CgroupMap& GetInstance(); const CgroupController* FindController(const std::string& name) const; CgroupController FindController(const std::string& name) const; private: struct CgroupFile* cg_file_data_; size_t cg_file_size_; bool loaded_ = false; CgroupMap(); ~CgroupMap(); bool LoadRcFile(); void Print() const; }; libprocessgroup/cgrouprc/Android.bp +6 −1 Original line number Diff line number Diff line Loading @@ -12,10 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. cc_library_shared { cc_library { name: "libcgrouprc", host_supported: true, recovery_available: true, // Do not ever mark this as vendor_available; otherwise, vendor modules // that links to the static library will behave unexpectedly. All on-device // modules should use libprocessgroup which links to the LL-NDK library // defined below. The static library is built for tests. vendor_available: false, srcs: [ "cgroup_controller.cpp", "cgroup_file.cpp", Loading Loading
libcutils/Android.bp +5 −1 Original line number Diff line number Diff line Loading @@ -235,6 +235,7 @@ test_libraries = [ "libbase", "libjsoncpp", "libprocessgroup", "libcgrouprc", ] cc_test { Loading @@ -249,7 +250,10 @@ cc_test { name: "libcutils_test_static", test_suites: ["device-tests"], defaults: ["libcutils_test_default"], static_libs: ["libc"] + test_libraries, static_libs: [ "libc", "libcgrouprc_format", ] + test_libraries, stl: "libc++_static", target: { Loading
libprocessgroup/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ cc_library { }, shared_libs: [ "libbase", "libcgrouprc", "libjsoncpp", ], // for cutils/android_filesystem_config.h Loading
libprocessgroup/cgroup_map.cpp +49 −86 Original line number Diff line number Diff line Loading @@ -48,28 +48,38 @@ static constexpr const char* CGROUP_PROCS_FILE = "/cgroup.procs"; static constexpr const char* CGROUP_TASKS_FILE = "/tasks"; static constexpr const char* CGROUP_TASKS_FILE_V2 = "/cgroup.tasks"; CgroupController::CgroupController(uint32_t version, const std::string& name, const std::string& path) { version_ = version; strncpy(name_, name.c_str(), sizeof(name_) - 1); name_[sizeof(name_) - 1] = '\0'; strncpy(path_, path.c_str(), sizeof(path_) - 1); path_[sizeof(path_) - 1] = '\0'; uint32_t CgroupController::version() const { CHECK(HasValue()); return ACgroupController_getVersion(controller_); } std::string CgroupController::GetTasksFilePath(const std::string& path) const { std::string tasks_path = path_; const char* CgroupController::name() const { CHECK(HasValue()); return ACgroupController_getName(controller_); } if (!path.empty()) { tasks_path += "/" + path; const char* CgroupController::path() const { CHECK(HasValue()); return ACgroupController_getPath(controller_); } return (version_ == 1) ? tasks_path + CGROUP_TASKS_FILE : tasks_path + CGROUP_TASKS_FILE_V2; bool CgroupController::HasValue() const { return controller_ != nullptr; } std::string CgroupController::GetProcsFilePath(const std::string& path, uid_t uid, std::string CgroupController::GetTasksFilePath(const std::string& rel_path) const { std::string tasks_path = path(); if (!rel_path.empty()) { tasks_path += "/" + rel_path; } return (version() == 1) ? tasks_path + CGROUP_TASKS_FILE : tasks_path + CGROUP_TASKS_FILE_V2; } std::string CgroupController::GetProcsFilePath(const std::string& rel_path, uid_t uid, pid_t pid) const { std::string proc_path(path_); proc_path.append("/").append(path); std::string proc_path(path()); proc_path.append("/").append(rel_path); proc_path = regex_replace(proc_path, std::regex("<uid>"), std::to_string(uid)); proc_path = regex_replace(proc_path, std::regex("<pid>"), std::to_string(pid)); Loading @@ -90,7 +100,7 @@ bool CgroupController::GetTaskGroup(int tid, std::string* group) const { return true; } std::string cg_tag = StringPrintf(":%s:", name_); std::string cg_tag = StringPrintf(":%s:", name()); size_t start_pos = content.find(cg_tag); if (start_pos == std::string::npos) { return false; Loading @@ -107,20 +117,12 @@ bool CgroupController::GetTaskGroup(int tid, std::string* group) const { return true; } CgroupMap::CgroupMap() : cg_file_data_(nullptr), cg_file_size_(0) { CgroupMap::CgroupMap() { if (!LoadRcFile()) { LOG(ERROR) << "CgroupMap::LoadRcFile called for [" << getpid() << "] failed"; } } CgroupMap::~CgroupMap() { if (cg_file_data_) { munmap(cg_file_data_, cg_file_size_); cg_file_data_ = nullptr; cg_file_size_ = 0; } } CgroupMap& CgroupMap::GetInstance() { // Deliberately leak this object to avoid a race between destruction on // process exit and concurrent access from another thread. Loading @@ -129,85 +131,46 @@ CgroupMap& CgroupMap::GetInstance() { } bool CgroupMap::LoadRcFile() { struct stat sb; if (cg_file_data_) { // Data already initialized return true; } unique_fd fd(TEMP_FAILURE_RETRY(open(CGROUPS_RC_PATH, O_RDONLY | O_CLOEXEC))); if (fd < 0) { PLOG(ERROR) << "open() failed for " << CGROUPS_RC_PATH; return false; if (!loaded_) { loaded_ = (ACgroupFile_getVersion() != 0); } if (fstat(fd, &sb) < 0) { PLOG(ERROR) << "fstat() failed for " << CGROUPS_RC_PATH; return false; } size_t file_size = sb.st_size; if (file_size < sizeof(CgroupFile)) { LOG(ERROR) << "Invalid file format " << CGROUPS_RC_PATH; return false; } CgroupFile* file_data = (CgroupFile*)mmap(nullptr, file_size, PROT_READ, MAP_SHARED, fd, 0); if (file_data == MAP_FAILED) { PLOG(ERROR) << "Failed to mmap " << CGROUPS_RC_PATH; return false; } if (file_data->version_ != CgroupFile::FILE_CURR_VERSION) { LOG(ERROR) << CGROUPS_RC_PATH << " file version mismatch"; munmap(file_data, file_size); return false; } if (file_size != sizeof(CgroupFile) + file_data->controller_count_ * sizeof(CgroupController)) { LOG(ERROR) << CGROUPS_RC_PATH << " file has invalid size"; munmap(file_data, file_size); return false; } cg_file_data_ = file_data; cg_file_size_ = file_size; return true; return loaded_; } void CgroupMap::Print() const { if (!cg_file_data_) { if (!loaded_) { LOG(ERROR) << "CgroupMap::Print called for [" << getpid() << "] failed, RC file was not initialized properly"; return; } LOG(INFO) << "File version = " << cg_file_data_->version_; LOG(INFO) << "File controller count = " << cg_file_data_->controller_count_; LOG(INFO) << "File version = " << ACgroupFile_getVersion(); LOG(INFO) << "File controller count = " << ACgroupFile_getControllerCount(); LOG(INFO) << "Mounted cgroups:"; CgroupController* controller = (CgroupController*)(cg_file_data_ + 1); for (int i = 0; i < cg_file_data_->controller_count_; i++, controller++) { LOG(INFO) << "\t" << controller->name() << " ver " << controller->version() << " path " << controller->path(); auto controller_count = ACgroupFile_getControllerCount(); for (uint32_t i = 0; i < controller_count; ++i) { const ACgroupController* controller = ACgroupFile_getController(i); LOG(INFO) << "\t" << ACgroupController_getName(controller) << " ver " << ACgroupController_getVersion(controller) << " path " << ACgroupController_getPath(controller); } } const CgroupController* CgroupMap::FindController(const std::string& name) const { if (!cg_file_data_) { CgroupController CgroupMap::FindController(const std::string& name) const { if (!loaded_) { LOG(ERROR) << "CgroupMap::FindController called for [" << getpid() << "] failed, RC file was not initialized properly"; return nullptr; return CgroupController(nullptr); } // skip the file header to get to the first controller CgroupController* controller = (CgroupController*)(cg_file_data_ + 1); for (int i = 0; i < cg_file_data_->controller_count_; i++, controller++) { if (name == controller->name()) { return controller; auto controller_count = ACgroupFile_getControllerCount(); for (uint32_t i = 0; i < controller_count; ++i) { const ACgroupController* controller = ACgroupFile_getController(i); if (name == ACgroupController_getName(controller)) { return CgroupController(controller); } } return nullptr; return CgroupController(nullptr); }
libprocessgroup/cgroup_map.h +15 −29 Original line number Diff line number Diff line Loading @@ -20,39 +20,30 @@ #include <sys/types.h> #include <map> #include <memory> #include <mutex> #include <string> #include <vector> // Minimal controller description to be mmapped into process address space #include <android/cgrouprc.h> // Convenient wrapper of an ACgroupController pointer. class CgroupController { public: CgroupController() {} CgroupController(uint32_t version, const std::string& name, const std::string& path); // Does not own controller explicit CgroupController(const ACgroupController* controller) : controller_(controller) {} uint32_t version() const; const char* name() const; const char* path() const; uint32_t version() const { return version_; } const char* name() const { return name_; } const char* path() const { return path_; } bool HasValue() const; std::string GetTasksFilePath(const std::string& path) const; std::string GetProcsFilePath(const std::string& path, uid_t uid, pid_t pid) const; bool GetTaskGroup(int tid, std::string* group) const; private: static constexpr size_t CGROUP_NAME_BUF_SZ = 16; static constexpr size_t CGROUP_PATH_BUF_SZ = 32; uint32_t version_; char name_[CGROUP_NAME_BUF_SZ]; char path_[CGROUP_PATH_BUF_SZ]; }; struct CgroupFile { static constexpr uint32_t FILE_VERSION_1 = 1; static constexpr uint32_t FILE_CURR_VERSION = FILE_VERSION_1; uint32_t version_; uint32_t controller_count_; CgroupController controllers_[]; const ACgroupController* controller_ = nullptr; }; class CgroupMap { Loading @@ -61,16 +52,11 @@ class CgroupMap { static bool SetupCgroups(); static CgroupMap& GetInstance(); const CgroupController* FindController(const std::string& name) const; CgroupController FindController(const std::string& name) const; private: struct CgroupFile* cg_file_data_; size_t cg_file_size_; bool loaded_ = false; CgroupMap(); ~CgroupMap(); bool LoadRcFile(); void Print() const; };
libprocessgroup/cgrouprc/Android.bp +6 −1 Original line number Diff line number Diff line Loading @@ -12,10 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. cc_library_shared { cc_library { name: "libcgrouprc", host_supported: true, recovery_available: true, // Do not ever mark this as vendor_available; otherwise, vendor modules // that links to the static library will behave unexpectedly. All on-device // modules should use libprocessgroup which links to the LL-NDK library // defined below. The static library is built for tests. vendor_available: false, srcs: [ "cgroup_controller.cpp", "cgroup_file.cpp", Loading