Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bb297e9c authored by Suren Baghdasaryan's avatar Suren Baghdasaryan Committed by Android (Google) Code Review
Browse files

Merge changes from topic "re-enable fd caching and update VNDK" into qt-dev

* changes:
  libprocessgroup: limit libprocessgroup's VNDK API surface
  Re-enable file descriptor caching and add option to skip caching
parents 347f1ccf 41616d88
Loading
Loading
Loading
Loading
+10 −4
Original line number Diff line number Diff line
@@ -24,16 +24,20 @@
__BEGIN_DECLS

static constexpr const char* CGROUPV2_CONTROLLER_NAME = "cgroup2";
static constexpr const char* CGROUPS_RC_PATH = "/dev/cgroup_info/cgroup.rc";

bool CgroupGetControllerPath(const std::string& cgroup_name, std::string* path);
bool CgroupGetAttributePath(const std::string& attr_name, std::string* path);
bool CgroupGetAttributePathForTask(const std::string& attr_name, int tid, std::string* path);

bool UsePerAppMemcg();
bool SetTaskProfiles(int tid, const std::vector<std::string>& profiles, bool use_fd_cache = false);
bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles,
                        bool use_fd_cache = false);

bool SetTaskProfiles(int tid, const std::vector<std::string>& profiles);
bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles);
#ifndef __ANDROID_VNDK__

static constexpr const char* CGROUPS_RC_PATH = "/dev/cgroup_info/cgroup.rc";

bool UsePerAppMemcg();

// Return 0 and removes the cgroup if there are no longer any processes in it.
// Returns -1 in the case of an error occurring or if there are processes still running
@@ -54,4 +58,6 @@ bool setProcessGroupLimit(uid_t uid, int initialPid, int64_t limitInBytes);

void removeAllProcessGroups(void);

#endif // __ANDROID_VNDK__

__END_DECLS
+11 −4
Original line number Diff line number Diff line
@@ -112,12 +112,16 @@ static bool isMemoryCgroupSupported() {
    return memcg_supported;
}

bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles) {
bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles,
                        bool use_fd_cache) {
    const TaskProfiles& tp = TaskProfiles::GetInstance();

    for (const auto& name : profiles) {
        const TaskProfile* profile = tp.GetProfile(name);
        TaskProfile* profile = tp.GetProfile(name);
        if (profile != nullptr) {
            if (use_fd_cache) {
                profile->EnableResourceCaching();
            }
            if (!profile->ExecuteForProcess(uid, pid)) {
                PLOG(WARNING) << "Failed to apply " << name << " process profile";
            }
@@ -129,12 +133,15 @@ bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& pr
    return true;
}

bool SetTaskProfiles(int tid, const std::vector<std::string>& profiles) {
bool SetTaskProfiles(int tid, const std::vector<std::string>& profiles, bool use_fd_cache) {
    const TaskProfiles& tp = TaskProfiles::GetInstance();

    for (const auto& name : profiles) {
        const TaskProfile* profile = tp.GetProfile(name);
        TaskProfile* profile = tp.GetProfile(name);
        if (profile != nullptr) {
            if (use_fd_cache) {
                profile->EnableResourceCaching();
            }
            if (!profile->ExecuteForTask(tid)) {
                PLOG(WARNING) << "Failed to apply " << name << " task profile";
            }
+21 −13
Original line number Diff line number Diff line
@@ -46,26 +46,34 @@ int set_cpuset_policy(int tid, SchedPolicy policy) {

    switch (policy) {
        case SP_BACKGROUND:
            return SetTaskProfiles(tid, {"HighEnergySaving", "ProcessCapacityLow", "LowIoPriority",
                                         "TimerSlackHigh"})
            return SetTaskProfiles(tid,
                                   {"HighEnergySaving", "ProcessCapacityLow", "LowIoPriority",
                                    "TimerSlackHigh"},
                                   true)
                           ? 0
                           : -1;
        case SP_FOREGROUND:
        case SP_AUDIO_APP:
        case SP_AUDIO_SYS:
            return SetTaskProfiles(tid, {"HighPerformance", "ProcessCapacityHigh", "HighIoPriority",
                                         "TimerSlackNormal"})
            return SetTaskProfiles(tid,
                                   {"HighPerformance", "ProcessCapacityHigh", "HighIoPriority",
                                    "TimerSlackNormal"},
                                   true)
                           ? 0
                           : -1;
        case SP_TOP_APP:
            return SetTaskProfiles(tid, {"MaxPerformance", "ProcessCapacityMax", "MaxIoPriority",
                                         "TimerSlackNormal"})
            return SetTaskProfiles(tid,
                                   {"MaxPerformance", "ProcessCapacityMax", "MaxIoPriority",
                                    "TimerSlackNormal"},
                                   true)
                           ? 0
                           : -1;
        case SP_SYSTEM:
            return SetTaskProfiles(tid, {"ServiceCapacityLow", "TimerSlackNormal"}) ? 0 : -1;
            return SetTaskProfiles(tid, {"ServiceCapacityLow", "TimerSlackNormal"}, true) ? 0 : -1;
        case SP_RESTRICTED:
            return SetTaskProfiles(tid, {"ServiceCapacityRestricted", "TimerSlackNormal"}) ? 0 : -1;
            return SetTaskProfiles(tid, {"ServiceCapacityRestricted", "TimerSlackNormal"}, true)
                           ? 0
                           : -1;
        default:
            break;
    }
@@ -126,17 +134,17 @@ int set_sched_policy(int tid, SchedPolicy policy) {

    switch (policy) {
        case SP_BACKGROUND:
            return SetTaskProfiles(tid, {"HighEnergySaving", "TimerSlackHigh"}) ? 0 : -1;
            return SetTaskProfiles(tid, {"HighEnergySaving", "TimerSlackHigh"}, true) ? 0 : -1;
        case SP_FOREGROUND:
        case SP_AUDIO_APP:
        case SP_AUDIO_SYS:
            return SetTaskProfiles(tid, {"HighPerformance", "TimerSlackNormal"}) ? 0 : -1;
            return SetTaskProfiles(tid, {"HighPerformance", "TimerSlackNormal"}, true) ? 0 : -1;
        case SP_TOP_APP:
            return SetTaskProfiles(tid, {"MaxPerformance", "TimerSlackNormal"}) ? 0 : -1;
            return SetTaskProfiles(tid, {"MaxPerformance", "TimerSlackNormal"}, true) ? 0 : -1;
        case SP_RT_APP:
            return SetTaskProfiles(tid, {"RealtimePerformance", "TimerSlackNormal"}) ? 0 : -1;
            return SetTaskProfiles(tid, {"RealtimePerformance", "TimerSlackNormal"}, true) ? 0 : -1;
        default:
            return SetTaskProfiles(tid, {"TimerSlackNormal"}) ? 0 : -1;
            return SetTaskProfiles(tid, {"TimerSlackNormal"}, true) ? 0 : -1;
    }

    return 0;
+41 −36
Original line number Diff line number Diff line
@@ -138,31 +138,38 @@ bool SetCgroupAction::IsAppDependentPath(const std::string& path) {

SetCgroupAction::SetCgroupAction(const CgroupController& c, const std::string& p)
    : controller_(c), path_(p) {
#ifdef CACHE_FILE_DESCRIPTORS
    // cache file descriptor only if path is app independent
    // file descriptors for app-dependent paths can't be cached
    if (IsAppDependentPath(path_)) {
        // file descriptor is not cached
        fd_.reset(-2);
        fd_.reset(FDS_APP_DEPENDENT);
        return;
    }

    std::string tasks_path = c.GetTasksFilePath(p);
    // file descriptor can be cached later on request
    fd_.reset(FDS_NOT_CACHED);
}

void SetCgroupAction::EnableResourceCaching() {
    if (fd_ != FDS_NOT_CACHED) {
        return;
    }

    std::string tasks_path = controller_.GetTasksFilePath(path_);

    if (access(tasks_path.c_str(), W_OK) != 0) {
        // file is not accessible
        fd_.reset(-1);
        fd_.reset(FDS_INACCESSIBLE);
        return;
    }

    unique_fd fd(TEMP_FAILURE_RETRY(open(tasks_path.c_str(), O_WRONLY | O_CLOEXEC)));
    if (fd < 0) {
        PLOG(ERROR) << "Failed to cache fd '" << tasks_path << "'";
        fd_.reset(-1);
        fd_.reset(FDS_INACCESSIBLE);
        return;
    }

    fd_ = std::move(fd);
#endif
}

bool SetCgroupAction::AddTidToCgroup(int tid, int fd) {
@@ -184,8 +191,7 @@ bool SetCgroupAction::AddTidToCgroup(int tid, int fd) {
}

bool SetCgroupAction::ExecuteForProcess(uid_t uid, pid_t pid) const {
#ifdef CACHE_FILE_DESCRIPTORS
    if (fd_ >= 0) {
    if (IsFdValid()) {
        // fd is cached, reuse it
        if (!AddTidToCgroup(pid, fd_)) {
            LOG(ERROR) << "Failed to add task into cgroup";
@@ -194,12 +200,12 @@ bool SetCgroupAction::ExecuteForProcess(uid_t uid, pid_t pid) const {
        return true;
    }

    if (fd_ == -1) {
    if (fd_ == FDS_INACCESSIBLE) {
        // no permissions to access the file, ignore
        return true;
    }

    // this is app-dependent path, file descriptor is not cached
    // this is app-dependent path and fd is not cached or cached fd can't be used
    std::string procs_path = controller()->GetProcsFilePath(path_, uid, pid);
    unique_fd tmp_fd(TEMP_FAILURE_RETRY(open(procs_path.c_str(), O_WRONLY | O_CLOEXEC)));
    if (tmp_fd < 0) {
@@ -212,25 +218,10 @@ bool SetCgroupAction::ExecuteForProcess(uid_t uid, pid_t pid) const {
    }

    return true;
#else
    std::string procs_path = controller()->GetProcsFilePath(path_, uid, pid);
    unique_fd tmp_fd(TEMP_FAILURE_RETRY(open(procs_path.c_str(), O_WRONLY | O_CLOEXEC)));
    if (tmp_fd < 0) {
        // no permissions to access the file, ignore
        return true;
    }
    if (!AddTidToCgroup(pid, tmp_fd)) {
        LOG(ERROR) << "Failed to add task into cgroup";
        return false;
    }

    return true;
#endif
}

bool SetCgroupAction::ExecuteForTask(int tid) const {
#ifdef CACHE_FILE_DESCRIPTORS
    if (fd_ >= 0) {
    if (IsFdValid()) {
        // fd is cached, reuse it
        if (!AddTidToCgroup(tid, fd_)) {
            LOG(ERROR) << "Failed to add task into cgroup";
@@ -239,20 +230,23 @@ bool SetCgroupAction::ExecuteForTask(int tid) const {
        return true;
    }

    if (fd_ == -1) {
    if (fd_ == FDS_INACCESSIBLE) {
        // no permissions to access the file, ignore
        return true;
    }

    if (fd_ == FDS_APP_DEPENDENT) {
        // application-dependent path can't be used with tid
    LOG(ERROR) << "Application profile can't be applied to a thread";
        PLOG(ERROR) << "Application profile can't be applied to a thread";
        return false;
#else
    }

    // fd was not cached because cached fd can't be used
    std::string tasks_path = controller()->GetTasksFilePath(path_);
    unique_fd tmp_fd(TEMP_FAILURE_RETRY(open(tasks_path.c_str(), O_WRONLY | O_CLOEXEC)));
    if (tmp_fd < 0) {
        // no permissions to access the file, ignore
        return true;
        PLOG(WARNING) << "Failed to open " << tasks_path << ": " << strerror(errno);
        return false;
    }
    if (!AddTidToCgroup(tid, tmp_fd)) {
        LOG(ERROR) << "Failed to add task into cgroup";
@@ -260,7 +254,6 @@ bool SetCgroupAction::ExecuteForTask(int tid) const {
    }

    return true;
#endif
}

bool TaskProfile::ExecuteForProcess(uid_t uid, pid_t pid) const {
@@ -284,6 +277,18 @@ bool TaskProfile::ExecuteForTask(int tid) const {
    return true;
}

void TaskProfile::EnableResourceCaching() {
    if (res_cached_) {
        return;
    }

    for (auto& element : elements_) {
        element->EnableResourceCaching();
    }

    res_cached_ = true;
}

TaskProfiles& TaskProfiles::GetInstance() {
    // Deliberately leak this object to avoid a race between destruction on
    // process exit and concurrent access from another thread.
@@ -411,7 +416,7 @@ bool TaskProfiles::Load(const CgroupMap& cg_map, const std::string& file_name) {
    return true;
}

const TaskProfile* TaskProfiles::GetProfile(const std::string& name) const {
TaskProfile* TaskProfiles::GetProfile(const std::string& name) const {
    auto iter = profiles_.find(name);

    if (iter != profiles_.end()) {
+15 −4
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@ class ProfileAction {
    // Default implementations will fail
    virtual bool ExecuteForProcess(uid_t, pid_t) const { return false; };
    virtual bool ExecuteForTask(int) const { return false; };

    virtual void EnableResourceCaching() {}
};

// Profile actions
@@ -110,31 +112,40 @@ class SetCgroupAction : public ProfileAction {

    virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const;
    virtual bool ExecuteForTask(int tid) const;
    virtual void EnableResourceCaching();

    const CgroupController* controller() const { return &controller_; }
    std::string path() const { return path_; }

  private:
    enum FdState {
        FDS_INACCESSIBLE = -1,
        FDS_APP_DEPENDENT = -2,
        FDS_NOT_CACHED = -3,
    };

    CgroupController controller_;
    std::string path_;
#ifdef CACHE_FILE_DESCRIPTORS
    android::base::unique_fd fd_;
#endif

    static bool IsAppDependentPath(const std::string& path);
    static bool AddTidToCgroup(int tid, int fd);

    bool IsFdValid() const { return fd_ > FDS_INACCESSIBLE; }
};

class TaskProfile {
  public:
    TaskProfile() {}
    TaskProfile() : res_cached_(false) {}

    void Add(std::unique_ptr<ProfileAction> e) { elements_.push_back(std::move(e)); }

    bool ExecuteForProcess(uid_t uid, pid_t pid) const;
    bool ExecuteForTask(int tid) const;
    void EnableResourceCaching();

  private:
    bool res_cached_;
    std::vector<std::unique_ptr<ProfileAction>> elements_;
};

@@ -143,7 +154,7 @@ class TaskProfiles {
    // Should be used by all users
    static TaskProfiles& GetInstance();

    const TaskProfile* GetProfile(const std::string& name) const;
    TaskProfile* GetProfile(const std::string& name) const;
    const ProfileAttribute* GetAttribute(const std::string& name) const;

  private: