cpu-sched: move all threads, not just the main one 63/249463/8 accepted/tizen/unified/20201216.215925 submit/tizen/20201216.004818
authorMichal Bloch <m.bloch@partner.samsung.com>
Fri, 11 Dec 2020 19:11:06 +0000 (20:11 +0100)
committerMichal Bloch <m.bloch@partner.samsung.com>
Tue, 15 Dec 2020 12:52:14 +0000 (12:52 +0000)
Change-Id: If8947e4127d49554ca492571c9d08d755d02902a
Signed-off-by: Michal Bloch <m.bloch@partner.samsung.com>
src/cpu/cpu-sched.c

index 16332c4..e753d3b 100644 (file)
@@ -405,6 +405,64 @@ static int cpu_sched_cpu_off(void *data)
        return RESOURCED_ERROR_NONE;
 }
 
+static int proc_pid_tasks_filter(const struct dirent *de)
+{
+       // the only entries should be dot, dotdot, and TIDs
+       return de->d_name[0] != '.';
+}
+
+static bool add_one_tid_to_node(const char *node_path, const struct dirent *de)
+{
+       int const r = fwrite_str(node_path, de->d_name);
+
+       if (r == 0) {
+               /* We're not even logging this because
+                * Tizen already has too many logs and
+                * there is no need to clutter dlog. */
+
+               // _D("tid %s moved successfully", de->d_name);
+       } else if (r == -ESRCH) {
+               /* Threads can finish while we work.
+                * This is fine (if a bit of a race
+                * condition) so we don't mind if we
+                * try to move such a goner.
+                *
+                * Note that zombies don't get added
+                * to the task list, but nevertheless
+                * they return success, not ESRCH. */
+
+               _D("tid %s: already dead (not an error)", de->d_name);
+       } else {
+               errno = -r;
+               _W("failed to move tid %s: %m\n", de->d_name);
+               return false;
+       }
+
+       return true;
+}
+
+static int cpu_sched_add_all_tids_to_cpuset_node(const char *node_path, pid_t pid)
+{
+       char proc_pid_tasks_path[sizeof "/proc/" + MAX_DEC_SIZE(pid_t) + sizeof "/task" - 1];
+       int r = snprintf(proc_pid_tasks_path, sizeof proc_pid_tasks_path, "/proc/%d/task", pid);
+       ret_value_msg_if(r < 0, RESOURCED_ERROR_FAIL, "Failed to create proc path string for pid %d: %m", pid);
+
+       struct dirent **entries;
+       int entry_count = scandir(proc_pid_tasks_path, &entries, proc_pid_tasks_filter, alphasort);
+       ret_value_msg_if(entry_count < 0, RESOURCED_ERROR_FAIL, "Couldn't read tid list for pid %d: %m", pid);
+
+       bool ok = true;
+       for (int i = 0; i < entry_count; ++i) {
+               struct dirent *const de = entries[i];
+               ok &= add_one_tid_to_node(node_path, de);
+               free(de);
+       }
+
+       free(entries);
+
+       return ok ? RESOURCED_ERROR_NONE : RESOURCED_ERROR_FAIL;
+}
+
 static int cpu_sched_add_pid_to_cpuset(struct coreset *set, pid_t pid)
 {
        assert(set);
@@ -412,14 +470,11 @@ static int cpu_sched_add_pid_to_cpuset(struct coreset *set, pid_t pid)
        _D("cpu-sched: add pid %d to cpuset %s", pid, set->name);
 
        char path[PATH_MAX];
-       int r = snprintf(path, sizeof path, "%s/%s", CPUSET_CGROUP, set->name);
-       if (r < 0) {
-               _E("cpu-sched: failed to setup path for cpuset (%s)", set->name);
-               return r;
-       }
+       int r = snprintf(path, sizeof path, CPUSET_CGROUP "/%s/tasks", set->name);
+       ret_value_msg_if(r < 0, RESOURCED_ERROR_FAIL, "cpu-sched: failed to setup path for cpuset (%s)", set->name);
 
-       r = cgroup_write_node_int32(path, "tasks", pid);
-       ret_value_msg_if(r < 0, RESOURCED_ERROR_FAIL, "Failed to attach pid %d to cgroup %s: %m", pid, path);
+       r = cpu_sched_add_all_tids_to_cpuset_node(path, pid);
+       ret_value_msg_if(r != RESOURCED_ERROR_NONE, r, "Failed to attach pid %d and all its threads to cpuset %s", pid, set->name);
 
        return RESOURCED_ERROR_NONE;
 }
@@ -430,8 +485,8 @@ static int cpu_sched_remove_pid_from_cpuset(struct coreset *set, pid_t pid)
 
        _D("cpu-sched: moving pid %d to toplevel cpuset (from %s cpuset)", pid, set->name);
 
-       int r = cgroup_write_node_int32(CPUSET_CGROUP, "tasks", pid);
-       ret_value_msg_if(r < 0, RESOURCED_ERROR_FAIL, "Failed to attach pid %d to cgroup " CPUSET_CGROUP ": %m", pid);
+       int r = cpu_sched_add_all_tids_to_cpuset_node(CPUSET_CGROUP "/tasks", pid);
+       ret_value_msg_if(r != RESOURCED_ERROR_NONE, r, "Failed to attach pid %d and all its threads to top-level cpuset", pid);
 
        return RESOURCED_ERROR_NONE;
 }