Unverified Commit 61a1dd4f authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!4093 introduce smart_grid zone

Merge Pull Request from: @zouyipeng 
 
The patch sets include two parts:

1. patch 1~3: Rebase smart_grid from OLK-5.10 to OLK-6.6
2. patch 4~8: introduce smart_grid zone qos and cpufreq

Since V6:

rebase to OLK-6.6 head

Since V5:

Only modified mm/mempolicy.c review comments
Since V4:

rebase to OLK-6.6 head
Since V3:

fix some review comments
Since V2:

move new sysctl form sysctl.c to fair.c
add smart_grid cmdline
Since V1:

Don't init smart_grid cpufreq with dynamic_affinity disable.
Forbid smart_grid cgroup interface with dynamic_affinity disable.
Hui Tang (1):
sched: Introduce smart grid scheduling strategy for cfs

Wang ShaoBo (2):
sched: smart grid: init sched_grid_qos structure on QOS purpose
config: enable CONFIG_QOS_SCHED_SMART_GRID by default

Yipeng Zou (5):
sched: introduce smart grid qos zone
smart_grid: introduce /proc/pid/smart_grid_level
smart_grid: introduce smart_grid_strategy_ctrl sysctl
smart_grid: cpufreq: introduce smart_grid cpufreq control
smart_grid: introduce smart_grid cmdline

--
2.34.1

#I8WMOG:【OLK-6.6】【功耗】支持功耗感知调度 
 
Link:https://gitee.com/openeuler/kernel/pulls/4093

 

Reviewed-by: default avatarZhang Jianhua <chris.zjh@huawei.com>
Reviewed-by: default avatarWeilong Chen <chenweilong@huawei.com>
Reviewed-by: default avatarKefeng Wang <wangkefeng.wang@huawei.com>
Reviewed-by: default avatarLiu Chao <liuchao173@huawei.com>
Reviewed-by: default avatarZucheng Zheng <zhengzucheng@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
Acked-by: default avatarXie XiuQi <xiexiuqi@huawei.com>
parents 867ff6cc e76dedf2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -179,6 +179,7 @@ CONFIG_CFS_BANDWIDTH=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_SCHED_MM_CID=y
CONFIG_QOS_SCHED_DYNAMIC_AFFINITY=y
CONFIG_QOS_SCHED_SMART_GRID=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_RDMA=y
CONFIG_CGROUP_FREEZER=y
+1 −0
Original line number Diff line number Diff line
@@ -200,6 +200,7 @@ CONFIG_CFS_BANDWIDTH=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_SCHED_MM_CID=y
CONFIG_QOS_SCHED_DYNAMIC_AFFINITY=y
# CONFIG_QOS_SCHED_SMART_GRID is not set
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_RDMA=y
CONFIG_CGROUP_FREEZER=y
+244 −0
Original line number Diff line number Diff line
@@ -2823,6 +2823,247 @@ int cpufreq_boost_enabled(void)
}
EXPORT_SYMBOL_GPL(cpufreq_boost_enabled);

#ifdef CONFIG_QOS_SCHED_SMART_GRID

struct smart_grid_zone {
	char governor_name[SMART_GRID_ZONE_NR][CPUFREQ_NAME_LEN];
	unsigned int enable;
	struct irq_work irq_work;
	struct work_struct work;
	unsigned int is_init;
};

static struct smart_grid_zone sg_zone;
static DEFINE_MUTEX(sg_zone_lock);

#define SG_WRITE_BUFF_LEN	30

void cpufreq_smart_grid_start_sync(void)
{
	/* No need sync when smart grid disabled */
	if (!smart_grid_enabled())
		return;

	if (likely(sg_zone.is_init))
		irq_work_queue(&sg_zone.irq_work);
}

static ssize_t show_smart_grid_governor(struct kobject *kobj,
					struct kobj_attribute *attr, char *buf)
{
	int len = 0;
	int gov_index;

	mutex_lock(&sg_zone_lock);
	if (!sg_zone.enable) {
		mutex_unlock(&sg_zone_lock);
		return sprintf(buf, "smart_grid governor disable\n");
	}

	for (gov_index = 0; gov_index < SMART_GRID_ZONE_NR; gov_index++)
		len += sprintf(buf + len, "smart_grid-%d: %s\n", gov_index,
								 sg_zone.governor_name[gov_index]);

	mutex_unlock(&sg_zone_lock);
	return len;
}

static ssize_t store_smart_grid_governor(struct kobject *kobj, struct kobj_attribute *attr,
					 const char *buf, size_t count)
{
	struct cpufreq_governor *target_gov = NULL;
	unsigned int current_level;
	char *level_string = NULL;
	char buf_string[SG_WRITE_BUFF_LEN];
	char *gov_string = buf_string;
	char save_string[CPUFREQ_NAME_LEN];
	int ret;

	mutex_lock(&sg_zone_lock);
	if (!sg_zone.enable) {
		ret = -EINVAL;
		goto fail;
	}

	if (strscpy(buf_string, buf, SG_WRITE_BUFF_LEN) <= 0) {
		ret = -EINVAL;
		goto fail;
	}

	level_string = strsep(&gov_string, "-");
	if (level_string == NULL) {
		ret = -EINVAL;
		goto fail;
	}

	if (kstrtouint(level_string, 10, &current_level)) {
		ret = -EINVAL;
		goto fail;
	}

	if (current_level >= SMART_GRID_ZONE_NR) {
		ret = -EINVAL;
		goto fail;
	}

	if (sscanf(gov_string, "%15s", save_string) != 1) {
		ret = -EINVAL;
		goto fail;
	}

	target_gov = cpufreq_parse_governor(save_string);
	if (target_gov == NULL) {
		ret = -EINVAL;
		goto fail;
	}
	module_put(target_gov->owner);

	strscpy(sg_zone.governor_name[current_level], save_string, CPUFREQ_NAME_LEN);
	cpufreq_smart_grid_start_sync();
	mutex_unlock(&sg_zone_lock);
	return count;

fail:
	mutex_unlock(&sg_zone_lock);
	return ret;
}
define_one_global_rw(smart_grid_governor);

static ssize_t show_smart_grid_governor_enable(struct kobject *kobj,
					       struct kobj_attribute *attr, char *buf)
{
	return sprintf(buf, "%u\n", sg_zone.enable);
}

static void smart_grid_irq_work(struct irq_work *irq_work)
{
	struct smart_grid_zone *zone;

	zone = container_of(irq_work, struct smart_grid_zone, irq_work);
	schedule_work_on(smp_processor_id(), &zone->work);
}

static void smart_grid_work_handler(struct work_struct *work)
{
	struct smart_grid_zone *zone;
	struct cpufreq_governor *target_gov = NULL;
	struct cpufreq_policy *policy = NULL;
	unsigned int cpu;
	int gov_index;

	zone = container_of(work, struct smart_grid_zone, work);

	mutex_lock(&sg_zone_lock);
	if (!sg_zone.enable) {
		mutex_unlock(&sg_zone_lock);
		return;
	}

	/*
	 * Because of the policy may be shared between hot and warm zone.
	 * We need to make sure hot zone have the highest priority.
	 */
	for (gov_index = SMART_GRID_ZONE_NR - 1; gov_index >= 0; gov_index--) {
		target_gov = cpufreq_parse_governor(sg_zone.governor_name[gov_index]);
		if (target_gov == NULL)
			continue;

		for_each_cpu(cpu, sched_grid_zone_cpumask(gov_index)) {
			if (cpu_is_offline(cpu))
				continue;

			policy = cpufreq_cpu_acquire(cpu);
			if (policy == NULL)
				continue;

			if (policy->governor == target_gov) {
				cpufreq_cpu_release(policy);
				continue;
			}
			/*Try to switch governor */
			store_scaling_governor(policy, sg_zone.governor_name[gov_index],
					       CPUFREQ_NAME_LEN);
			cpufreq_cpu_release(policy);
		}
		module_put(target_gov->owner);
	}
	mutex_unlock(&sg_zone_lock);
}

static void sg_zone_set_enable(void)
{
	int gov_index;

	/* Set default smart_grid governor */
	for (gov_index = 0; gov_index < SMART_GRID_ZONE_NR; gov_index++) {
		if (!gov_index)
			strscpy(sg_zone.governor_name[gov_index], "performance", CPUFREQ_NAME_LEN);
		else
			strscpy(sg_zone.governor_name[gov_index], "powersave", CPUFREQ_NAME_LEN);
	}

	sg_zone.enable = 1;
	cpufreq_smart_grid_start_sync();
}

static void sg_zone_set_disable(void)
{
	sg_zone.enable = 0;
}

static ssize_t store_smart_grid_governor_enable(struct kobject *kobj, struct kobj_attribute *attr,
						const char *buf, size_t count)
{
	unsigned int enable;

	if (kstrtouint(buf, 10, &enable))
		return -EINVAL;

	if (enable > 1)
		return -EINVAL;

	mutex_lock(&sg_zone_lock);
	if (sg_zone.enable == enable) {
		mutex_unlock(&sg_zone_lock);
		return -EINVAL;
	}

	if (enable)
		sg_zone_set_enable();
	else
		sg_zone_set_disable();

	mutex_unlock(&sg_zone_lock);
	return count;
}
define_one_global_rw(smart_grid_governor_enable);

static int create_smart_grid_sysfs_file(void)
{
	int ret;

	/* No need init when smart grid disabled */
	if (!smart_grid_enabled())
		return 0;

	ret = sysfs_create_file(cpufreq_global_kobject, &smart_grid_governor.attr);
	if (ret)
		pr_err("%s: cannot register global smart_grid_governor sysfs file\n",
		       __func__);

	ret = sysfs_create_file(cpufreq_global_kobject, &smart_grid_governor_enable.attr);
	if (ret)
		pr_err("%s: cannot register global smart_grid_governor_enable sysfs file\n",
		       __func__);

	init_irq_work(&sg_zone.irq_work, smart_grid_irq_work);
	INIT_WORK(&sg_zone.work, smart_grid_work_handler);
	sg_zone.enable = 0;
	sg_zone.is_init = 1;
	return ret;
}
#endif

/*********************************************************************
 *               REGISTER / UNREGISTER CPUFREQ DRIVER                *
 *********************************************************************/
@@ -2998,6 +3239,9 @@ static int __init cpufreq_core_init(void)
	if (!strlen(default_governor))
		strncpy(default_governor, gov->name, CPUFREQ_NAME_LEN);

#ifdef CONFIG_QOS_SCHED_SMART_GRID
	create_smart_grid_sysfs_file();
#endif
	return 0;
}
module_param(off, int, 0444);
+16 −0
Original line number Diff line number Diff line
@@ -436,6 +436,19 @@ __weak void arch_proc_pid_thread_features(struct seq_file *m,
{
}

#ifdef CONFIG_QOS_SCHED_DYNAMIC_AFFINITY
static void task_cpus_preferred(struct seq_file *m, struct task_struct *task)
{
	if (!dynamic_affinity_enabled())
		return;

	seq_printf(m, "Cpus_preferred:\t%*pb\n",
		   cpumask_pr_args(task->prefer_cpus));
	seq_printf(m, "Cpus_preferred_list:\t%*pbl\n",
		   cpumask_pr_args(task->prefer_cpus));
}
#endif

int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
			struct pid *pid, struct task_struct *task)
{
@@ -461,6 +474,9 @@ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
	cpuset_task_status_allowed(m, task);
	task_context_switch_counts(m, task);
	arch_proc_pid_thread_features(m, task);
#ifdef CONFIG_QOS_SCHED_DYNAMIC_AFFINITY
	task_cpus_preferred(m, task);
#endif
	return 0;
}

+84 −0
Original line number Diff line number Diff line
@@ -92,6 +92,10 @@
#include <linux/sched/coredump.h>
#include <linux/sched/debug.h>
#include <linux/sched/stat.h>
#ifdef CONFIG_QOS_SCHED_SMART_GRID
#include <linux/sched/grid_qos.h>
#include <linux/sched.h>
#endif
#include <linux/posix-timers.h>
#include <linux/time_namespace.h>
#include <linux/resctrl.h>
@@ -3313,6 +3317,83 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,
}
#endif /* CONFIG_STACKLEAK_METRICS */

#ifdef CONFIG_QOS_SCHED_SMART_GRID
static int smart_grid_level_show(struct seq_file *m, void *v)
{
	struct inode *inode = m->private;
	struct task_struct *p;

	if (!smart_grid_enabled())
		return -EPERM;

	p = get_proc_task(inode);
	if (!p)
		return -ESRCH;

	if (p->grid_qos != NULL)
		seq_printf(m, "%d\n", p->grid_qos->stat.class_lvl);

	put_task_struct(p);

	return 0;
}

static int smart_grid_level_open(struct inode *inode, struct file *filp)
{
	return single_open(filp, smart_grid_level_show, inode);
}

static ssize_t smart_grid_level_write(struct file *file, const char __user *buf,
				      size_t count, loff_t *offset)
{
	struct inode *inode = file_inode(file);
	struct task_struct *p;
	char buffer[TASK_COMM_LEN];
	const size_t maxlen = sizeof(buffer) - 1;
	unsigned int level = SCHED_GRID_QOS_TASK_LEVEL_MAX;
	int ret = 0;

	if (!smart_grid_enabled())
		return -EPERM;

	memset(buffer, 0, sizeof(buffer));
	if (copy_from_user(buffer, buf, count > maxlen ? maxlen : count))
		return -EFAULT;

	p = get_proc_task(inode);
	if (!p)
		return -ESRCH;

	if (kstrtouint(buffer, 10, &level)) {
		put_task_struct(p);
		return -EINVAL;
	}

	if (level >= SCHED_GRID_QOS_TASK_LEVEL_MAX) {
		put_task_struct(p);
		return -EINVAL;
	}

	if (p->grid_qos != NULL &&
	    p->grid_qos->stat.set_class_lvl != NULL)
		ret = p->grid_qos->stat.set_class_lvl(&p->grid_qos->stat, level);

	put_task_struct(p);

	if (ret)
		return ret;
	return count;
}

static const struct file_operations proc_pid_sg_level_operations = {
	.open		= smart_grid_level_open,
	.read		= seq_read,
	.write		= smart_grid_level_write,
	.llseek		= seq_lseek,
	.release	= single_release,
};
#endif

/*
 * Thread groups
 */
@@ -3336,6 +3417,9 @@ static const struct pid_entry tgid_base_stuff[] = {
#ifdef CONFIG_SCHED_DEBUG
	REG("sched",      S_IRUGO|S_IWUSR, proc_pid_sched_operations),
#endif
#ifdef CONFIG_QOS_SCHED_SMART_GRID
	REG("smart_grid_level", 0644, proc_pid_sg_level_operations),
#endif
#ifdef CONFIG_SCHED_AUTOGROUP
	REG("autogroup",  S_IRUGO|S_IWUSR, proc_pid_sched_autogroup_operations),
#endif
Loading