extern unsigned int sysctl_sched_rt_period;
extern int sysctl_sched_rt_runtime;
+#ifdef CONFIG_UCLAMP_TASK
+extern unsigned int sysctl_sched_uclamp_util_min;
+extern unsigned int sysctl_sched_uclamp_util_max;
+#endif
+
#ifdef CONFIG_CFS_BANDWIDTH
extern unsigned int sysctl_sched_cfs_bandwidth_slice;
#endif
void __user *buffer, size_t *lenp,
loff_t *ppos);
+#ifdef CONFIG_UCLAMP_TASK
+extern int sched_uclamp_handler(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp,
+ loff_t *ppos);
+#endif
+
extern int sysctl_numa_balancing(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp,
loff_t *ppos);
*/
static DEFINE_MUTEX(uclamp_mutex);
+/*
+ * Minimum utilization for tasks in the root cgroup
+ * default: 0
+ */
+unsigned int sysctl_sched_uclamp_util_min;
+
+/*
+ * Maximum utilization for tasks in the root cgroup
+ * default: 1024
+ */
+unsigned int sysctl_sched_uclamp_util_max = 1024;
+
+static struct uclamp_se uclamp_default[UCLAMP_CNT];
+
/**
* uclamp_map: reference counts a utilization "clamp value"
* @value: the utilization "clamp value" required
group_id = uc_se->group_id;
#ifdef CONFIG_UCLAMP_TASK_GROUP
+ /*
+ * Tasks in the root group, which do not have a task specific clamp
+ * value, get the system default calmp value.
+ */
+ if (group_id == UCLAMP_NOT_VALID &&
+ task_group(p) == &root_task_group) {
+ return uclamp_default[clamp_id].group_id;
+ }
+
/* Use TG's clamp value to limit task specific values */
uc_se = &task_group(p)->uclamp[clamp_id];
if (group_id == UCLAMP_NOT_VALID ||
clamp_value > uc_se->effective.value) {
group_id = uc_se->effective.group_id;
}
+#else
+ /* By default, all tasks get the system default clamp value */
+ if (group_id == UCLAMP_NOT_VALID)
+ return uclamp_default[clamp_id].group_id;
#endif
return group_id;
uclamp_group_put(clamp_id, prev_group_id);
}
+int sched_uclamp_handler(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp,
+ loff_t *ppos)
+{
+ int group_id[UCLAMP_CNT] = { UCLAMP_NOT_VALID };
+ struct uclamp_se *uc_se;
+ int old_min, old_max;
+ int result;
+
+ mutex_lock(&uclamp_mutex);
+
+ old_min = sysctl_sched_uclamp_util_min;
+ old_max = sysctl_sched_uclamp_util_max;
+
+ result = proc_dointvec(table, write, buffer, lenp, ppos);
+ if (result)
+ goto undo;
+ if (!write)
+ goto done;
+
+ if (sysctl_sched_uclamp_util_min > sysctl_sched_uclamp_util_max)
+ goto undo;
+ if (sysctl_sched_uclamp_util_max > 1024)
+ goto undo;
+
+ /* Find a valid group_id for each required clamp value */
+ if (old_min != sysctl_sched_uclamp_util_min) {
+ result = uclamp_group_find(UCLAMP_MIN, sysctl_sched_uclamp_util_min);
+ if (result == -ENOSPC) {
+ pr_err("Cannot allocate more than %d UTIL_MIN clamp groups\n",
+ CONFIG_UCLAMP_GROUPS_COUNT);
+ goto undo;
+ }
+ group_id[UCLAMP_MIN] = result;
+ }
+ if (old_max != sysctl_sched_uclamp_util_max) {
+ result = uclamp_group_find(UCLAMP_MAX, sysctl_sched_uclamp_util_max);
+ if (result == -ENOSPC) {
+ pr_err("Cannot allocate more than %d UTIL_MAX clamp groups\n",
+ CONFIG_UCLAMP_GROUPS_COUNT);
+ goto undo;
+ }
+ group_id[UCLAMP_MAX] = result;
+ }
+
+ /* Update each required clamp group */
+ if (old_min != sysctl_sched_uclamp_util_min) {
+ uc_se = &uclamp_default[UCLAMP_MIN];
+ uclamp_group_get(NULL, UCLAMP_MIN, group_id[UCLAMP_MIN],
+ uc_se, sysctl_sched_uclamp_util_min);
+ }
+ if (old_max != sysctl_sched_uclamp_util_max) {
+ uc_se = &uclamp_default[UCLAMP_MAX];
+ uclamp_group_get(NULL, UCLAMP_MAX, group_id[UCLAMP_MAX],
+ uc_se, sysctl_sched_uclamp_util_max);
+ }
+
+ if (result) {
+undo:
+ sysctl_sched_uclamp_util_min = old_min;
+ sysctl_sched_uclamp_util_max = old_max;
+ }
+
+done:
+ mutex_unlock(&uclamp_mutex);
+
+ return result;
+}
+
#ifdef CONFIG_UCLAMP_TASK_GROUP
/**
* init_uclamp_sched_group: initialize data structures required for TG's
/* Map root TG's clamp value */
uclamp_group_init(clamp_id, group_id, uclamp_none(clamp_id));
- /* Init root TG's clamp group */
+ /* Init root TG's clamp group: max values always enabled */
uc_se = &root_task_group.uclamp[clamp_id];
- uc_se->value = uclamp_none(clamp_id);
+ uc_se->value = uclamp_none(UCLAMP_MAX);
uc_se->group_id = group_id;
- uc_se->effective.value = uclamp_none(clamp_id);
+ uc_se->effective.value = uclamp_none(UCLAMP_MAX);
uc_se->effective.group_id = group_id;
/* Attach root TG's clamp group */