Separate the functions and structure related to CPU sched-attr from the util.c/.h files
and create independent files called sched-attr.c/.h.
The reason is that the existing util file contained mixed functions with various purposes.
Change-Id: Iadf592b6e15789f721e49d2945a463156b4a38e2
Signed-off-by: Unsung Lee <unsung.lee@samsung.com>
--- /dev/null
+/*
+ * resourced
+ *
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+/*
+ * @file sched-attr.c
+ * @desc CPU sched attr handling function
+ */
+
+#include <stdint.h>
+#include <sched.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <ctype.h>
+#include <sys/types.h>
+
+#include "sched-attr.h"
+#include "resourced.h"
+#include "trace.h"
+#include "cpu-common.h"
+
+#if !defined(SYS_sched_setattr)
+#if defined(__NR_sched_setattr)
+#define SYS_sched_setattr __NR_sched_setattr
+#else
+#define SYS_sched_setattr -1
+#endif /* defined(__NR_sched_setattr) */
+#endif /* !defined(SYS_sched_setattr) */
+
+#if !defined(SYS_sched_getattr)
+#if defined(__NR_sched_getattr)
+#define SYS_sched_getattr __NR_sched_getattr
+#else
+#define SYS_sched_getattr -1
+#endif /* defined(__NR_sched_getattr) */
+#endif /* !defined(SYS_sched_getattr) */
+
+static bool is_sched_setattr_supported(void)
+{
+ if (SYS_sched_setattr >= 0)
+ return true;
+ else
+ return false;
+}
+
+static bool is_sched_getattr_supported(void)
+{
+ if (SYS_sched_getattr >= 0)
+ return true;
+ else
+ return false;
+}
+
+static int sched_attr_set_scheduling_of_thread(pid_t pid, struct sched_attr sched_attr,
+ unsigned int flags)
+{
+ int ret;
+ struct sched_attr thread_sched_attr = sched_attr;
+ uint32_t sched_policy = thread_sched_attr.sched_policy & ~SCHED_RESET_ON_FORK;
+
+ switch (sched_policy) {
+ case SCHED_IDLE:
+ if (thread_sched_attr.sched_priority != 0) {
+ _E("priority of SCHED_IDLE should be 0");
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ break;
+ case SCHED_BATCH:
+ case SCHED_OTHER:
+ if (thread_sched_attr.sched_priority != 0) {
+ _E("priority of %s should be 0",
+ sched_policy == SCHED_BATCH ? "SCHED_BATCH" : "SCHED_OTHER");
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ if (thread_sched_attr.sched_nice == CPU_INIT_NICE) {
+ _E("Nice value should be located (%d ~ %d)",
+ CPU_MIN_NICE, CPU_MAX_NICE);
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ if (!is_sched_setattr_supported())
+ setpriority(PRIO_PROCESS, pid, thread_sched_attr.sched_nice);
+
+ break;
+ case SCHED_FIFO:
+ case SCHED_RR:
+ if (thread_sched_attr.sched_priority == CPU_INIT_PRIO) {
+ _E("priority of %s should be located between %d and %d",
+ sched_policy == SCHED_FIFO ? "SCHED_FIFO" : "SCHED_RR",
+ CPU_MIN_PRIO, CPU_MAX_PRIO);
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ break;
+ case SCHED_DEADLINE:
+ _W("SCHED_DEADLINE is not supported yet");
+
+ return RESOURCED_ERROR_NONE;
+ default:
+ _E("Unknown sched type (%d)", sched_policy);
+
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ if (is_sched_setattr_supported()) {
+ ret = syscall(SYS_sched_setattr, pid, &thread_sched_attr, flags);
+ } else {
+ struct sched_param sp = { .sched_priority = thread_sched_attr.sched_priority};
+ ret = sched_setscheduler(pid, thread_sched_attr.sched_policy, &sp);
+ }
+
+ if (ret != 0) {
+ switch (errno) {
+ case EINVAL:
+ _E("Failed to set policy and priority by invalid input");
+ break;
+ case EPERM:
+ _E("Failed to set policy and priority by permission");
+ break;
+ default:
+ _E("Failed to set policy and priority by no pid (%d)", pid);
+ break;
+ }
+
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ return RESOURCED_ERROR_NONE;
+}
+
+int sched_attr_set_scheduling(pid_t pid, bool is_process,
+ struct sched_attr sched_attr, unsigned int flags)
+{
+ int ret = 0;
+ int fail_cnt = 0;
+ pid_t tid;
+ _cleanup_free_ char *buf = NULL;
+ DIR *dir;
+ struct dirent *dirent;
+
+ if (!is_process)
+ return sched_attr_set_scheduling_of_thread(pid, sched_attr, flags);
+
+ ret = asprintf(&buf, "/proc/%d/task", pid);
+ if (ret < 0)
+ return RESOURCED_ERROR_OUT_OF_MEMORY;
+
+ dir = opendir(buf);
+ if (!dir)
+ return RESOURCED_ERROR_FAIL;
+
+ _D("CPU scheduling policy (%s)",
+ sched_attr.sched_policy == SCHED_IDLE ? "SCHED_IDLE" :
+ sched_attr.sched_policy == SCHED_BATCH ? "SCHED_BATCH" :
+ sched_attr.sched_policy == SCHED_OTHER ? "SCHED_OTHER" :
+ sched_attr.sched_policy == SCHED_FIFO ? "SCHED_FIFO" :
+ sched_attr.sched_policy == SCHED_RR ? "SCHED_RR" :
+ sched_attr.sched_policy == SCHED_DEADLINE ? "SCHED_DEADLINE" : "UNKNOWN");
+
+ while ((dirent = readdir(dir))) {
+ const char *id = dirent->d_name;
+ if(!isdigit(*id))
+ continue;
+
+ tid = atoi(id);
+ if (tid > 0) {
+ ret = sched_attr_set_scheduling_of_thread(tid, sched_attr, flags);
+ if (ret < 0) {
+ _E("Failed to change scheduler of tid (%d)", tid);
+ fail_cnt++;
+ }
+ } else {
+ _E("Thread id (%d) should be larger than 0", tid);
+ fail_cnt++;
+ }
+ }
+
+ closedir(dir);
+
+ if (fail_cnt > 0)
+ return RESOURCED_ERROR_FAIL;
+
+ return RESOURCED_ERROR_NONE;
+}
+
+int sched_attr_get_scheduling(pid_t pid, struct sched_attr *sched_attr,
+ unsigned int flags)
+{
+ int ret = 0;
+ struct sched_param sp;
+ int sched_policy;
+
+ if (is_sched_getattr_supported())
+ return syscall(SYS_sched_getattr, pid, sched_attr, sizeof(struct sched_attr), flags);
+
+ sched_policy = sched_getscheduler(pid);
+ if (ret < 0) {
+ _E("Failed to call sched_getscheduler by %m");
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ sched_attr->sched_policy = sched_policy;
+ sched_attr->sched_nice = getpriority(PRIO_PROCESS, pid);
+
+ ret = sched_getparam(pid, &sp);
+ if (ret < 0) {
+ _E("Failed to call sched_sched_getparam by %m");
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ sched_attr->sched_priority = sp.sched_priority;
+
+ return RESOURCED_ERROR_NONE;
+}
--- /dev/null
+/*
+ * resourced
+ *
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+/*
+ * @file sched-attr.h
+ * @desc CPU sched attr handling function
+ */
+
+#ifndef _RESOURCED_SCHED_ATTR_H_
+#define _RESOURCED_SCHED_ATTR_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+struct sched_attr {
+ uint32_t size; /* Size of this structure */
+ uint32_t sched_policy; /* Policy (SCHED_*) */
+ uint64_t sched_flags; /* Flags */
+ int32_t sched_nice; /* Nice value (SCHED_OTHER, SCHED_BATCH) */
+ uint32_t sched_priority; /* Static priority (SCHED_FIFO, SCHED_RR) */
+
+ /* Remaining fields are for SCHED_DEADLINE */
+ uint64_t sched_runtime;
+ uint64_t sched_deadline;
+ uint64_t sched_period;
+};
+
+int sched_attr_set_scheduling(pid_t pid, bool is_process,
+ struct sched_attr sched_attr, unsigned int flags);
+int sched_attr_get_scheduling(pid_t pid, struct sched_attr *sched_attr,
+ unsigned int flags);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /*_RESOURCED_SCHED_ATTR_H_*/
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
-#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <fcntl.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
-#include <sched.h>
#include <ctype.h>
#include "util.h"
#define MEGA_SHIFT 20
#define KILO_SHIFT 10
-#if !defined(SYS_sched_setattr) && defined(__NR_sched_setattr)
-# define SYS_sched_setattr _NR_sched_setattr
-#endif
-
-#if !defined(SYS_sched_getattr) && defined(__NR_sched_getattr)
-# define SYS_sched_getattr _NR_sched_getattr
-#endif
-
-int sched_setattr(pid_t pid, struct sched_attr *attr, unsigned int flags)
-{
- int error;
- uint32_t sched_policy = attr->sched_policy & ~SCHED_RESET_ON_FORK;
-
- switch (sched_policy) {
- case SCHED_IDLE:
- if (attr->sched_priority != 0) {
- _E("[CPU-SCHED] priority of SCHED_IDLE should be 0");
- return RESOURCED_ERROR_FAIL;
- }
- break;
- case SCHED_BATCH:
- case SCHED_OTHER:
- if (attr->sched_priority != 0) {
- _E("[CPU-SCHED] priority of %s should be 0", sched_policy == SCHED_BATCH ? "SCHED_BATCH" : "SCHED_OTHER");
- return RESOURCED_ERROR_FAIL;
- }
-
- if (attr->sched_nice == CPU_INIT_NICE) {
- _W("[CPU-SCHED] nice value should be located between %d and %d",
- CPU_MIN_NICE, CPU_MAX_NICE);
- return RESOURCED_ERROR_FAIL;
- }
-
-#ifndef SYS_sched_setattr
- setpriority(PRIO_PROCESS, pid, attr->sched_nice);
-#endif
- break;
- case SCHED_FIFO:
- case SCHED_RR:
- if (attr->sched_priority == CPU_INIT_PRIO) {
- _E("[CPU-SCHED] priority of %s should be located between %d and %d",
- sched_policy == SCHED_FIFO ? "SCHED_FIFO" : "SCHED_RR",
- CPU_MIN_PRIO, CPU_MAX_PRIO);
- return RESOURCED_ERROR_FAIL;
- }
- break;
- case SCHED_DEADLINE:
- _W("[CPU-SCHED] we do not support deadline scheulder yet");
- return RESOURCED_ERROR_NONE;
- default:
- _E("[CPU-SCHED] Unknown sched type (%d)", sched_policy);
- return RESOURCED_ERROR_FAIL;
- }
-
-#ifdef SYS_sched_setattr
- error = syscall(SYS_sched_setattr, pid, attr, flags);
-#else
- {
- struct sched_param sp = { .sched_priority = attr->sched_priority};
- error = sched_setscheduler(pid, attr->sched_policy, &sp);
- }
-#endif
- if (error) {
- switch (errno) {
- case EINVAL:
- _E("[CPU-SCHED] Failed to set policy and priority by invalid input");
- break;
- case EPERM:
- _E("[CPU-SCHED] Failed to set policy and priority by permission");
- break;
- default:
- _E("[CPU-SCHED] Failed to set policy and priority by no pid (%d)", pid);
- break;
- }
-
- return RESOURCED_ERROR_FAIL;
- }
-
- return RESOURCED_ERROR_NONE;
-}
-
-int sched_setattr_of_all_tasks(pid_t pid, struct sched_attr *attr, unsigned int flag)
-{
- int r;
- int fail_cnt = 0;
- pid_t tid;
- _cleanup_free_ char *buf = NULL;
- DIR *dir;
- struct dirent *dirent;
-
- r = asprintf(&buf, "/proc/%d/task", pid);
- if (r < 0)
- return -ENOMEM;
-
- dir = opendir(buf);
- if (!dir)
- return -ENOTDIR;
-
- _D("[CPU-SCHED] policy = %s", attr->sched_policy == SCHED_IDLE ? "SCHED_IDLE" :
- attr->sched_policy == SCHED_BATCH ? "SCHED_BATCH" :
- attr->sched_policy == SCHED_OTHER ? "SCHED_OTHER" :
- attr->sched_policy == SCHED_FIFO ? "SCHED_FIFO" :
- attr->sched_policy == SCHED_RR ? "SCHED_RR" :
- attr->sched_policy == SCHED_DEADLINE ? "SCHED_DEADLINE" : "UNKNOWN");
-
- while ((dirent = readdir(dir))) {
- const char *id = dirent->d_name;
- if(!isdigit(*id))
- continue;
-
- tid = atoi(id);
- if (tid > 0) {
- r = sched_setattr(tid, attr, flag);
- if (r < 0) {
- _E("Failed to change scheduler of tid (%d)", tid);
- fail_cnt++;
- }
- }
- else {
- _E("Thread id (%d) should be larger than 0", tid);
- fail_cnt++;
- }
- }
-
- closedir(dir);
-
- if (fail_cnt > 0)
- return fail_cnt;
- else
- return 0;
-}
-
-int sched_getattr(pid_t pid, struct sched_attr *attr, unsigned int flags)
-{
-#ifdef SYS_sched_getattr
- return syscall(SYS_sched_getattr, pid, attr, sizeof(struct sched_attr), flags);
-#else
- int ret;
- struct sched_param sp;
-
- ret = sched_getscheduler(pid);
- if (ret < 0) {
- _E("Failed to call sched_getscheduler by %m");
- return RESOURCED_ERROR_FAIL;
- }
- else
- attr->sched_policy = ret;
-
- attr->sched_nice = getpriority(PRIO_PROCESS, pid);
-
- ret = sched_getparam(pid, &sp);
- if (ret < 0) {
- _E("Failed to call sched_sched_getparam by %m");
- return RESOURCED_ERROR_FAIL;
- }
- else {
- attr->sched_priority = sp.sched_priority;
- return RESOURCED_ERROR_NONE;
- }
-#endif
-}
-
static int parent(pid_t pid)
{
int status;
#define _pure_ __attribute__ ((pure))
#define _cleanup_(x) __attribute__((cleanup(x)))
-struct sched_attr {
- uint32_t size; /* Size of this structure */
- uint32_t sched_policy; /* Policy (SCHED_*) */
- unsigned long long sched_flags; /* Flags */
- int32_t sched_nice; /* Nice value (SCHED_OTHER, SCHED_BATCH) */
- uint32_t sched_priority; /* Static priority (SCHED_FIFO, SCHED_RR) */
- /* Remaining fields are for SCHED_DEADLINE */
- unsigned long long sched_runtime;
- unsigned long long sched_deadline;
- unsigned long long sched_period;
-};
-
static inline void freep(void *p)
{
free(*(void**) p);
int resourced_restarted(void);
-int sched_setattr(pid_t pid, struct sched_attr *attr, unsigned int flag);
-int sched_setattr_of_all_tasks(pid_t pid, struct sched_attr *attr, unsigned int flag);
-int sched_getattr(pid_t pid, struct sched_attr *attr, unsigned int flags);
-
int str_name_cpy(char *dst, const char *src, int dst_size, int src_length);
int str_name_cat(char *dst, const char *src, int dst_size, int dst_length, int src_length);
#include "macro.h"
#include "procfs.h"
#include "appinfo-list.h"
-#include "util.h"
+#include "sched-attr.h"
#include "file-helper.h"
#include "freezer-common.h"
#include "fd-handler.h"
default:
_E("[PROCESS] Unknown CPU sched type");
}
- error = sched_setattr_of_all_tasks(pid, &attr, 0);
+ error = sched_attr_set_scheduling(pid, true, attr, 0);
if (error)
_E("[PROCESS] Failed to set sched attributes");
#include "resourced.h"
#include "trace.h"
#include "vconf.h"
-#include "util.h"
+#include "sched-attr.h"
#include "cgroup.h"
#include "config-parser.h"
#include "const.h"
if (pai->app_cpu_nice_update_exclude)
goto cpu_cgroup_move;
- sched_setattr_of_all_tasks(pai->main_pid, &throttling_attr, 0);
+ sched_attr_set_scheduling(pai->main_pid, true, throttling_attr, 0);
if (pai->childs) {
gslist_for_each_item(iter, pai->childs) {
child_pid = GPOINTER_TO_PID(iter->data);
- sched_setattr_of_all_tasks(child_pid, &throttling_attr, 0);
+ sched_attr_set_scheduling(child_pid, true, throttling_attr, 0);
}
}
}
else {
- sched_setattr_of_all_tasks(pid, &throttling_attr, 0);
+ sched_attr_set_scheduling(pid, true, throttling_attr, 0);
}
cpu_cgroup_move:
if (pai->app_cpu_nice_update_exclude)
goto cpu_cgroup_move;
- sched_setattr_of_all_tasks(pai->main_pid, &normal_attr, 0);
+ sched_attr_set_scheduling(pai->main_pid, true, normal_attr, 0);
if (pai->childs) {
gslist_for_each_item(iter, pai->childs) {
child_pid = GPOINTER_TO_PID(iter->data);
- sched_setattr_of_all_tasks(child_pid, &normal_attr, 0);
+ sched_attr_set_scheduling(child_pid, true, normal_attr, 0);
}
}
}
else {
- sched_setattr_of_all_tasks(pid, &normal_attr, 0);
+ sched_attr_set_scheduling(pid, true, normal_attr, 0);
}
cpu_cgroup_move:
#include "module.h"
#include "macro.h"
-#include "util.h"
+#include "sched-attr.h"
#include "trace.h"
#include "notifier.h"
#include "resourced.h"
g_hash_table_remove(g_cpu_boosting_info_table[cpu_boosting_info->level],
&tid_list[i]);
- if (sched_setattr(tid_list[i],
- &cpu_boosting_attr[CPU_BOOSTING_LEVEL_NONE], 0) < 0) {
+ if (sched_attr_set_scheduling(tid_list[i], false,
+ cpu_boosting_attr[CPU_BOOSTING_LEVEL_NONE], 0) < 0) {
fail_cnt++;
continue;
}
continue;
}
- if (sched_setattr(tid_list[i], &attr, 0) < 0) {
+ if (sched_attr_set_scheduling(tid_list[i], false, attr, 0) < 0) {
tid_list[i] = 0;
fail_cnt++;
continue;
remove_cpu_boosting_info_in_tables(&tid_list[i]);
- ret = sched_setattr(tid_list[i],
- &cpu_boosting_attr[CPU_BOOSTING_LEVEL_NONE], 0);
+ ret = sched_attr_set_scheduling(tid_list[i], false,
+ cpu_boosting_attr[CPU_BOOSTING_LEVEL_NONE], 0);
if (ret != RESOURCED_ERROR_NONE) {
fail_cnt++;
continue;
find_cpu_boosting_info_in_tables(&cpu_boosting_info, &tid_list[i]);
if (cpu_boosting_info == NULL) {
- if (sched_getattr(tid_list[i], &attr, 0) < 0) {
+ if (sched_attr_get_scheduling(tid_list[i], &attr, 0) < 0) {
fail_cnt++;
continue;
}
* Therefore, resourced needs to figure out cpu priority or nice value through the kernel.
*/
if (cpu_boosting_info == NULL) {
- if (sched_getattr(source_tid, &attr, 0) < 0) {
+ if (sched_attr_get_scheduling(source_tid, &attr, 0) < 0) {
_E("[CPU-BOOSTING] Failed to get boost cpu of (tid = %d)", source_tid);
goto destroy_input;
}
*
**/
-#include "util.h"
+#include "sched-attr.h"
#include "const.h"
#include "dbus-handler.h"
#include "cgroup.h"
default:
_E("[CPU-SCHED] Unknown CPU sched type");
}
- error = sched_setattr_of_all_tasks(pid, &attr, 0);
+ error = sched_attr_set_scheduling(pid, true, attr, 0);
if (error)
_E("[CPU-SCHED] Failed to set sched attributes");