]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
sched/rt: Move RT related code from sched/core.c to sched/rt.c
authorNicolas Pitre <nicolas.pitre@linaro.org>
Wed, 21 Jun 2017 18:22:02 +0000 (14:22 -0400)
committerIngo Molnar <mingo@kernel.org>
Fri, 23 Jun 2017 08:46:45 +0000 (10:46 +0200)
This helps making sched/core.c smaller and hopefully easier to understand and maintain.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20170621182203.30626-3-nicolas.pitre@linaro.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
kernel/sched/core.c
kernel/sched/rt.c
kernel/sched/sched.h

index 54e1b0700af3d2a47d0eaa708858e7bc94e23798..5186797908dc261eb4132271b2ced312708a12c9 100644 (file)
@@ -6224,321 +6224,6 @@ void sched_move_task(struct task_struct *tsk)
 
        task_rq_unlock(rq, tsk, &rf);
 }
-#endif /* CONFIG_CGROUP_SCHED */
-
-#ifdef CONFIG_RT_GROUP_SCHED
-/*
- * Ensure that the real time constraints are schedulable.
- */
-static DEFINE_MUTEX(rt_constraints_mutex);
-
-/* Must be called with tasklist_lock held */
-static inline int tg_has_rt_tasks(struct task_group *tg)
-{
-       struct task_struct *g, *p;
-
-       /*
-        * Autogroups do not have RT tasks; see autogroup_create().
-        */
-       if (task_group_is_autogroup(tg))
-               return 0;
-
-       for_each_process_thread(g, p) {
-               if (rt_task(p) && task_group(p) == tg)
-                       return 1;
-       }
-
-       return 0;
-}
-
-struct rt_schedulable_data {
-       struct task_group *tg;
-       u64 rt_period;
-       u64 rt_runtime;
-};
-
-static int tg_rt_schedulable(struct task_group *tg, void *data)
-{
-       struct rt_schedulable_data *d = data;
-       struct task_group *child;
-       unsigned long total, sum = 0;
-       u64 period, runtime;
-
-       period = ktime_to_ns(tg->rt_bandwidth.rt_period);
-       runtime = tg->rt_bandwidth.rt_runtime;
-
-       if (tg == d->tg) {
-               period = d->rt_period;
-               runtime = d->rt_runtime;
-       }
-
-       /*
-        * Cannot have more runtime than the period.
-        */
-       if (runtime > period && runtime != RUNTIME_INF)
-               return -EINVAL;
-
-       /*
-        * Ensure we don't starve existing RT tasks.
-        */
-       if (rt_bandwidth_enabled() && !runtime && tg_has_rt_tasks(tg))
-               return -EBUSY;
-
-       total = to_ratio(period, runtime);
-
-       /*
-        * Nobody can have more than the global setting allows.
-        */
-       if (total > to_ratio(global_rt_period(), global_rt_runtime()))
-               return -EINVAL;
-
-       /*
-        * The sum of our children's runtime should not exceed our own.
-        */
-       list_for_each_entry_rcu(child, &tg->children, siblings) {
-               period = ktime_to_ns(child->rt_bandwidth.rt_period);
-               runtime = child->rt_bandwidth.rt_runtime;
-
-               if (child == d->tg) {
-                       period = d->rt_period;
-                       runtime = d->rt_runtime;
-               }
-
-               sum += to_ratio(period, runtime);
-       }
-
-       if (sum > total)
-               return -EINVAL;
-
-       return 0;
-}
-
-static int __rt_schedulable(struct task_group *tg, u64 period, u64 runtime)
-{
-       int ret;
-
-       struct rt_schedulable_data data = {
-               .tg = tg,
-               .rt_period = period,
-               .rt_runtime = runtime,
-       };
-
-       rcu_read_lock();
-       ret = walk_tg_tree(tg_rt_schedulable, tg_nop, &data);
-       rcu_read_unlock();
-
-       return ret;
-}
-
-static int tg_set_rt_bandwidth(struct task_group *tg,
-               u64 rt_period, u64 rt_runtime)
-{
-       int i, err = 0;
-
-       /*
-        * Disallowing the root group RT runtime is BAD, it would disallow the
-        * kernel creating (and or operating) RT threads.
-        */
-       if (tg == &root_task_group && rt_runtime == 0)
-               return -EINVAL;
-
-       /* No period doesn't make any sense. */
-       if (rt_period == 0)
-               return -EINVAL;
-
-       mutex_lock(&rt_constraints_mutex);
-       read_lock(&tasklist_lock);
-       err = __rt_schedulable(tg, rt_period, rt_runtime);
-       if (err)
-               goto unlock;
-
-       raw_spin_lock_irq(&tg->rt_bandwidth.rt_runtime_lock);
-       tg->rt_bandwidth.rt_period = ns_to_ktime(rt_period);
-       tg->rt_bandwidth.rt_runtime = rt_runtime;
-
-       for_each_possible_cpu(i) {
-               struct rt_rq *rt_rq = tg->rt_rq[i];
-
-               raw_spin_lock(&rt_rq->rt_runtime_lock);
-               rt_rq->rt_runtime = rt_runtime;
-               raw_spin_unlock(&rt_rq->rt_runtime_lock);
-       }
-       raw_spin_unlock_irq(&tg->rt_bandwidth.rt_runtime_lock);
-unlock:
-       read_unlock(&tasklist_lock);
-       mutex_unlock(&rt_constraints_mutex);
-
-       return err;
-}
-
-static int sched_group_set_rt_runtime(struct task_group *tg, long rt_runtime_us)
-{
-       u64 rt_runtime, rt_period;
-
-       rt_period = ktime_to_ns(tg->rt_bandwidth.rt_period);
-       rt_runtime = (u64)rt_runtime_us * NSEC_PER_USEC;
-       if (rt_runtime_us < 0)
-               rt_runtime = RUNTIME_INF;
-
-       return tg_set_rt_bandwidth(tg, rt_period, rt_runtime);
-}
-
-static long sched_group_rt_runtime(struct task_group *tg)
-{
-       u64 rt_runtime_us;
-
-       if (tg->rt_bandwidth.rt_runtime == RUNTIME_INF)
-               return -1;
-
-       rt_runtime_us = tg->rt_bandwidth.rt_runtime;
-       do_div(rt_runtime_us, NSEC_PER_USEC);
-       return rt_runtime_us;
-}
-
-static int sched_group_set_rt_period(struct task_group *tg, u64 rt_period_us)
-{
-       u64 rt_runtime, rt_period;
-
-       rt_period = rt_period_us * NSEC_PER_USEC;
-       rt_runtime = tg->rt_bandwidth.rt_runtime;
-
-       return tg_set_rt_bandwidth(tg, rt_period, rt_runtime);
-}
-
-static long sched_group_rt_period(struct task_group *tg)
-{
-       u64 rt_period_us;
-
-       rt_period_us = ktime_to_ns(tg->rt_bandwidth.rt_period);
-       do_div(rt_period_us, NSEC_PER_USEC);
-       return rt_period_us;
-}
-#endif /* CONFIG_RT_GROUP_SCHED */
-
-#ifdef CONFIG_RT_GROUP_SCHED
-static int sched_rt_global_constraints(void)
-{
-       int ret = 0;
-
-       mutex_lock(&rt_constraints_mutex);
-       read_lock(&tasklist_lock);
-       ret = __rt_schedulable(NULL, 0, 0);
-       read_unlock(&tasklist_lock);
-       mutex_unlock(&rt_constraints_mutex);
-
-       return ret;
-}
-
-static int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk)
-{
-       /* Don't accept realtime tasks when there is no way for them to run */
-       if (rt_task(tsk) && tg->rt_bandwidth.rt_runtime == 0)
-               return 0;
-
-       return 1;
-}
-
-#else /* !CONFIG_RT_GROUP_SCHED */
-static int sched_rt_global_constraints(void)
-{
-       unsigned long flags;
-       int i;
-
-       raw_spin_lock_irqsave(&def_rt_bandwidth.rt_runtime_lock, flags);
-       for_each_possible_cpu(i) {
-               struct rt_rq *rt_rq = &cpu_rq(i)->rt;
-
-               raw_spin_lock(&rt_rq->rt_runtime_lock);
-               rt_rq->rt_runtime = global_rt_runtime();
-               raw_spin_unlock(&rt_rq->rt_runtime_lock);
-       }
-       raw_spin_unlock_irqrestore(&def_rt_bandwidth.rt_runtime_lock, flags);
-
-       return 0;
-}
-#endif /* CONFIG_RT_GROUP_SCHED */
-
-static int sched_rt_global_validate(void)
-{
-       if (sysctl_sched_rt_period <= 0)
-               return -EINVAL;
-
-       if ((sysctl_sched_rt_runtime != RUNTIME_INF) &&
-               (sysctl_sched_rt_runtime > sysctl_sched_rt_period))
-               return -EINVAL;
-
-       return 0;
-}
-
-static void sched_rt_do_global(void)
-{
-       def_rt_bandwidth.rt_runtime = global_rt_runtime();
-       def_rt_bandwidth.rt_period = ns_to_ktime(global_rt_period());
-}
-
-int sched_rt_handler(struct ctl_table *table, int write,
-               void __user *buffer, size_t *lenp,
-               loff_t *ppos)
-{
-       int old_period, old_runtime;
-       static DEFINE_MUTEX(mutex);
-       int ret;
-
-       mutex_lock(&mutex);
-       old_period = sysctl_sched_rt_period;
-       old_runtime = sysctl_sched_rt_runtime;
-
-       ret = proc_dointvec(table, write, buffer, lenp, ppos);
-
-       if (!ret && write) {
-               ret = sched_rt_global_validate();
-               if (ret)
-                       goto undo;
-
-               ret = sched_dl_global_validate();
-               if (ret)
-                       goto undo;
-
-               ret = sched_rt_global_constraints();
-               if (ret)
-                       goto undo;
-
-               sched_rt_do_global();
-               sched_dl_do_global();
-       }
-       if (0) {
-undo:
-               sysctl_sched_rt_period = old_period;
-               sysctl_sched_rt_runtime = old_runtime;
-       }
-       mutex_unlock(&mutex);
-
-       return ret;
-}
-
-int sched_rr_handler(struct ctl_table *table, int write,
-               void __user *buffer, size_t *lenp,
-               loff_t *ppos)
-{
-       int ret;
-       static DEFINE_MUTEX(mutex);
-
-       mutex_lock(&mutex);
-       ret = proc_dointvec(table, write, buffer, lenp, ppos);
-       /*
-        * Make sure that internally we keep jiffies.
-        * Also, writing zero resets the timeslice to default:
-        */
-       if (!ret && write) {
-               sched_rr_timeslice =
-                       sysctl_sched_rr_timeslice <= 0 ? RR_TIMESLICE :
-                       msecs_to_jiffies(sysctl_sched_rr_timeslice);
-       }
-       mutex_unlock(&mutex);
-       return ret;
-}
-
-#ifdef CONFIG_CGROUP_SCHED
 
 static inline struct task_group *css_tg(struct cgroup_subsys_state *css)
 {
index 581d5c7a52645c4fdedd53c310247fc8fad6421d..45caf937ef90ead71864d4fbb12e7281e4b8ff9b 100644 (file)
@@ -2449,6 +2449,316 @@ const struct sched_class rt_sched_class = {
        .update_curr            = update_curr_rt,
 };
 
+#ifdef CONFIG_RT_GROUP_SCHED
+/*
+ * Ensure that the real time constraints are schedulable.
+ */
+static DEFINE_MUTEX(rt_constraints_mutex);
+
+/* Must be called with tasklist_lock held */
+static inline int tg_has_rt_tasks(struct task_group *tg)
+{
+       struct task_struct *g, *p;
+
+       /*
+        * Autogroups do not have RT tasks; see autogroup_create().
+        */
+       if (task_group_is_autogroup(tg))
+               return 0;
+
+       for_each_process_thread(g, p) {
+               if (rt_task(p) && task_group(p) == tg)
+                       return 1;
+       }
+
+       return 0;
+}
+
+struct rt_schedulable_data {
+       struct task_group *tg;
+       u64 rt_period;
+       u64 rt_runtime;
+};
+
+static int tg_rt_schedulable(struct task_group *tg, void *data)
+{
+       struct rt_schedulable_data *d = data;
+       struct task_group *child;
+       unsigned long total, sum = 0;
+       u64 period, runtime;
+
+       period = ktime_to_ns(tg->rt_bandwidth.rt_period);
+       runtime = tg->rt_bandwidth.rt_runtime;
+
+       if (tg == d->tg) {
+               period = d->rt_period;
+               runtime = d->rt_runtime;
+       }
+
+       /*
+        * Cannot have more runtime than the period.
+        */
+       if (runtime > period && runtime != RUNTIME_INF)
+               return -EINVAL;
+
+       /*
+        * Ensure we don't starve existing RT tasks.
+        */
+       if (rt_bandwidth_enabled() && !runtime && tg_has_rt_tasks(tg))
+               return -EBUSY;
+
+       total = to_ratio(period, runtime);
+
+       /*
+        * Nobody can have more than the global setting allows.
+        */
+       if (total > to_ratio(global_rt_period(), global_rt_runtime()))
+               return -EINVAL;
+
+       /*
+        * The sum of our children's runtime should not exceed our own.
+        */
+       list_for_each_entry_rcu(child, &tg->children, siblings) {
+               period = ktime_to_ns(child->rt_bandwidth.rt_period);
+               runtime = child->rt_bandwidth.rt_runtime;
+
+               if (child == d->tg) {
+                       period = d->rt_period;
+                       runtime = d->rt_runtime;
+               }
+
+               sum += to_ratio(period, runtime);
+       }
+
+       if (sum > total)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int __rt_schedulable(struct task_group *tg, u64 period, u64 runtime)
+{
+       int ret;
+
+       struct rt_schedulable_data data = {
+               .tg = tg,
+               .rt_period = period,
+               .rt_runtime = runtime,
+       };
+
+       rcu_read_lock();
+       ret = walk_tg_tree(tg_rt_schedulable, tg_nop, &data);
+       rcu_read_unlock();
+
+       return ret;
+}
+
+static int tg_set_rt_bandwidth(struct task_group *tg,
+               u64 rt_period, u64 rt_runtime)
+{
+       int i, err = 0;
+
+       /*
+        * Disallowing the root group RT runtime is BAD, it would disallow the
+        * kernel creating (and or operating) RT threads.
+        */
+       if (tg == &root_task_group && rt_runtime == 0)
+               return -EINVAL;
+
+       /* No period doesn't make any sense. */
+       if (rt_period == 0)
+               return -EINVAL;
+
+       mutex_lock(&rt_constraints_mutex);
+       read_lock(&tasklist_lock);
+       err = __rt_schedulable(tg, rt_period, rt_runtime);
+       if (err)
+               goto unlock;
+
+       raw_spin_lock_irq(&tg->rt_bandwidth.rt_runtime_lock);
+       tg->rt_bandwidth.rt_period = ns_to_ktime(rt_period);
+       tg->rt_bandwidth.rt_runtime = rt_runtime;
+
+       for_each_possible_cpu(i) {
+               struct rt_rq *rt_rq = tg->rt_rq[i];
+
+               raw_spin_lock(&rt_rq->rt_runtime_lock);
+               rt_rq->rt_runtime = rt_runtime;
+               raw_spin_unlock(&rt_rq->rt_runtime_lock);
+       }
+       raw_spin_unlock_irq(&tg->rt_bandwidth.rt_runtime_lock);
+unlock:
+       read_unlock(&tasklist_lock);
+       mutex_unlock(&rt_constraints_mutex);
+
+       return err;
+}
+
+int sched_group_set_rt_runtime(struct task_group *tg, long rt_runtime_us)
+{
+       u64 rt_runtime, rt_period;
+
+       rt_period = ktime_to_ns(tg->rt_bandwidth.rt_period);
+       rt_runtime = (u64)rt_runtime_us * NSEC_PER_USEC;
+       if (rt_runtime_us < 0)
+               rt_runtime = RUNTIME_INF;
+
+       return tg_set_rt_bandwidth(tg, rt_period, rt_runtime);
+}
+
+long sched_group_rt_runtime(struct task_group *tg)
+{
+       u64 rt_runtime_us;
+
+       if (tg->rt_bandwidth.rt_runtime == RUNTIME_INF)
+               return -1;
+
+       rt_runtime_us = tg->rt_bandwidth.rt_runtime;
+       do_div(rt_runtime_us, NSEC_PER_USEC);
+       return rt_runtime_us;
+}
+
+int sched_group_set_rt_period(struct task_group *tg, u64 rt_period_us)
+{
+       u64 rt_runtime, rt_period;
+
+       rt_period = rt_period_us * NSEC_PER_USEC;
+       rt_runtime = tg->rt_bandwidth.rt_runtime;
+
+       return tg_set_rt_bandwidth(tg, rt_period, rt_runtime);
+}
+
+long sched_group_rt_period(struct task_group *tg)
+{
+       u64 rt_period_us;
+
+       rt_period_us = ktime_to_ns(tg->rt_bandwidth.rt_period);
+       do_div(rt_period_us, NSEC_PER_USEC);
+       return rt_period_us;
+}
+
+static int sched_rt_global_constraints(void)
+{
+       int ret = 0;
+
+       mutex_lock(&rt_constraints_mutex);
+       read_lock(&tasklist_lock);
+       ret = __rt_schedulable(NULL, 0, 0);
+       read_unlock(&tasklist_lock);
+       mutex_unlock(&rt_constraints_mutex);
+
+       return ret;
+}
+
+int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk)
+{
+       /* Don't accept realtime tasks when there is no way for them to run */
+       if (rt_task(tsk) && tg->rt_bandwidth.rt_runtime == 0)
+               return 0;
+
+       return 1;
+}
+
+#else /* !CONFIG_RT_GROUP_SCHED */
+static int sched_rt_global_constraints(void)
+{
+       unsigned long flags;
+       int i;
+
+       raw_spin_lock_irqsave(&def_rt_bandwidth.rt_runtime_lock, flags);
+       for_each_possible_cpu(i) {
+               struct rt_rq *rt_rq = &cpu_rq(i)->rt;
+
+               raw_spin_lock(&rt_rq->rt_runtime_lock);
+               rt_rq->rt_runtime = global_rt_runtime();
+               raw_spin_unlock(&rt_rq->rt_runtime_lock);
+       }
+       raw_spin_unlock_irqrestore(&def_rt_bandwidth.rt_runtime_lock, flags);
+
+       return 0;
+}
+#endif /* CONFIG_RT_GROUP_SCHED */
+
+static int sched_rt_global_validate(void)
+{
+       if (sysctl_sched_rt_period <= 0)
+               return -EINVAL;
+
+       if ((sysctl_sched_rt_runtime != RUNTIME_INF) &&
+               (sysctl_sched_rt_runtime > sysctl_sched_rt_period))
+               return -EINVAL;
+
+       return 0;
+}
+
+static void sched_rt_do_global(void)
+{
+       def_rt_bandwidth.rt_runtime = global_rt_runtime();
+       def_rt_bandwidth.rt_period = ns_to_ktime(global_rt_period());
+}
+
+int sched_rt_handler(struct ctl_table *table, int write,
+               void __user *buffer, size_t *lenp,
+               loff_t *ppos)
+{
+       int old_period, old_runtime;
+       static DEFINE_MUTEX(mutex);
+       int ret;
+
+       mutex_lock(&mutex);
+       old_period = sysctl_sched_rt_period;
+       old_runtime = sysctl_sched_rt_runtime;
+
+       ret = proc_dointvec(table, write, buffer, lenp, ppos);
+
+       if (!ret && write) {
+               ret = sched_rt_global_validate();
+               if (ret)
+                       goto undo;
+
+               ret = sched_dl_global_validate();
+               if (ret)
+                       goto undo;
+
+               ret = sched_rt_global_constraints();
+               if (ret)
+                       goto undo;
+
+               sched_rt_do_global();
+               sched_dl_do_global();
+       }
+       if (0) {
+undo:
+               sysctl_sched_rt_period = old_period;
+               sysctl_sched_rt_runtime = old_runtime;
+       }
+       mutex_unlock(&mutex);
+
+       return ret;
+}
+
+int sched_rr_handler(struct ctl_table *table, int write,
+               void __user *buffer, size_t *lenp,
+               loff_t *ppos)
+{
+       int ret;
+       static DEFINE_MUTEX(mutex);
+
+       mutex_lock(&mutex);
+       ret = proc_dointvec(table, write, buffer, lenp, ppos);
+       /*
+        * Make sure that internally we keep jiffies.
+        * Also, writing zero resets the timeslice to default:
+        */
+       if (!ret && write) {
+               sched_rr_timeslice =
+                       sysctl_sched_rr_timeslice <= 0 ? RR_TIMESLICE :
+                       msecs_to_jiffies(sysctl_sched_rr_timeslice);
+       }
+       mutex_unlock(&mutex);
+       return ret;
+}
+
 #ifdef CONFIG_SCHED_DEBUG
 extern void print_rt_rq(struct seq_file *m, int cpu, struct rt_rq *rt_rq);
 
index d4eb3f67529d1ff17d17457da954173a32026def..eeef1a3086d1e74af034782cd780bbf7e44333b2 100644 (file)
@@ -383,6 +383,11 @@ extern int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent
 extern void init_tg_rt_entry(struct task_group *tg, struct rt_rq *rt_rq,
                struct sched_rt_entity *rt_se, int cpu,
                struct sched_rt_entity *parent);
+extern int sched_group_set_rt_runtime(struct task_group *tg, long rt_runtime_us);
+extern int sched_group_set_rt_period(struct task_group *tg, u64 rt_period_us);
+extern long sched_group_rt_runtime(struct task_group *tg);
+extern long sched_group_rt_period(struct task_group *tg);
+extern int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk);
 
 extern struct task_group *sched_create_group(struct task_group *parent);
 extern void sched_online_group(struct task_group *tg,