mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-28 13:16:41 +00:00
linux: add 'RFC-RFT-v3-sched-automated-per-tty-task-groups' patch
Signed-off-by: Stephan Raue <stephan@openelec.tv>
This commit is contained in:
parent
cc3f8eb7bf
commit
30542200df
@ -0,0 +1,359 @@
|
|||||||
|
Index: linux-2.6/include/linux/sched.h
|
||||||
|
===================================================================
|
||||||
|
--- linux-2.6.orig/include/linux/sched.h
|
||||||
|
+++ linux-2.6/include/linux/sched.h
|
||||||
|
@@ -509,6 +509,8 @@ struct thread_group_cputimer {
|
||||||
|
spinlock_t lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
+struct autogroup;
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* NOTE! "signal_struct" does not have it's own
|
||||||
|
* locking, because a shared signal_struct always
|
||||||
|
@@ -576,6 +578,9 @@ struct signal_struct {
|
||||||
|
|
||||||
|
struct tty_struct *tty; /* NULL if no tty */
|
||||||
|
|
||||||
|
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||||
|
+ struct autogroup *autogroup;
|
||||||
|
+#endif
|
||||||
|
/*
|
||||||
|
* Cumulative resource counters for dead threads in the group,
|
||||||
|
* and for reaped dead child processes forked by this group.
|
||||||
|
@@ -1931,6 +1936,20 @@ int sched_rt_handler(struct ctl_table *t
|
||||||
|
|
||||||
|
extern unsigned int sysctl_sched_compat_yield;
|
||||||
|
|
||||||
|
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||||
|
+extern unsigned int sysctl_sched_autogroup_enabled;
|
||||||
|
+
|
||||||
|
+extern void sched_autogroup_create_attach(struct task_struct *p);
|
||||||
|
+extern void sched_autogroup_detach(struct task_struct *p);
|
||||||
|
+extern void sched_autogroup_fork(struct signal_struct *sig);
|
||||||
|
+extern void sched_autogroup_exit(struct signal_struct *sig);
|
||||||
|
+#else
|
||||||
|
+static inline void sched_autogroup_create_attach(struct task_struct *p) { }
|
||||||
|
+static inline void sched_autogroup_detach(struct task_struct *p) { }
|
||||||
|
+static inline void sched_autogroup_fork(struct signal_struct *sig) { }
|
||||||
|
+static inline void sched_autogroup_exit(struct signal_struct *sig) { }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
#ifdef CONFIG_RT_MUTEXES
|
||||||
|
extern int rt_mutex_getprio(struct task_struct *p);
|
||||||
|
extern void rt_mutex_setprio(struct task_struct *p, int prio);
|
||||||
|
Index: linux-2.6/kernel/sched.c
|
||||||
|
===================================================================
|
||||||
|
--- linux-2.6.orig/kernel/sched.c
|
||||||
|
+++ linux-2.6/kernel/sched.c
|
||||||
|
@@ -78,6 +78,7 @@
|
||||||
|
|
||||||
|
#include "sched_cpupri.h"
|
||||||
|
#include "workqueue_sched.h"
|
||||||
|
+#include "sched_autogroup.h"
|
||||||
|
|
||||||
|
#define CREATE_TRACE_POINTS
|
||||||
|
#include <trace/events/sched.h>
|
||||||
|
@@ -605,11 +606,14 @@ static inline int cpu_of(struct rq *rq)
|
||||||
|
*/
|
||||||
|
static inline struct task_group *task_group(struct task_struct *p)
|
||||||
|
{
|
||||||
|
+ struct task_group *tg;
|
||||||
|
struct cgroup_subsys_state *css;
|
||||||
|
|
||||||
|
css = task_subsys_state_check(p, cpu_cgroup_subsys_id,
|
||||||
|
lockdep_is_held(&task_rq(p)->lock));
|
||||||
|
- return container_of(css, struct task_group, css);
|
||||||
|
+ tg = container_of(css, struct task_group, css);
|
||||||
|
+
|
||||||
|
+ return autogroup_task_group(p, tg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
|
||||||
|
@@ -2006,6 +2010,7 @@ static void sched_irq_time_avg_update(st
|
||||||
|
#include "sched_idletask.c"
|
||||||
|
#include "sched_fair.c"
|
||||||
|
#include "sched_rt.c"
|
||||||
|
+#include "sched_autogroup.c"
|
||||||
|
#include "sched_stoptask.c"
|
||||||
|
#ifdef CONFIG_SCHED_DEBUG
|
||||||
|
# include "sched_debug.c"
|
||||||
|
@@ -7979,7 +7984,7 @@ void __init sched_init(void)
|
||||||
|
#ifdef CONFIG_CGROUP_SCHED
|
||||||
|
list_add(&init_task_group.list, &task_groups);
|
||||||
|
INIT_LIST_HEAD(&init_task_group.children);
|
||||||
|
-
|
||||||
|
+ autogroup_init(&init_task);
|
||||||
|
#endif /* CONFIG_CGROUP_SCHED */
|
||||||
|
|
||||||
|
#if defined CONFIG_FAIR_GROUP_SCHED && defined CONFIG_SMP
|
||||||
|
Index: linux-2.6/kernel/fork.c
|
||||||
|
===================================================================
|
||||||
|
--- linux-2.6.orig/kernel/fork.c
|
||||||
|
+++ linux-2.6/kernel/fork.c
|
||||||
|
@@ -174,8 +174,10 @@ static inline void free_signal_struct(st
|
||||||
|
|
||||||
|
static inline void put_signal_struct(struct signal_struct *sig)
|
||||||
|
{
|
||||||
|
- if (atomic_dec_and_test(&sig->sigcnt))
|
||||||
|
+ if (atomic_dec_and_test(&sig->sigcnt)) {
|
||||||
|
+ sched_autogroup_exit(sig);
|
||||||
|
free_signal_struct(sig);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
void __put_task_struct(struct task_struct *tsk)
|
||||||
|
@@ -904,6 +906,7 @@ static int copy_signal(unsigned long clo
|
||||||
|
posix_cpu_timers_init_group(sig);
|
||||||
|
|
||||||
|
tty_audit_fork(sig);
|
||||||
|
+ sched_autogroup_fork(sig);
|
||||||
|
|
||||||
|
sig->oom_adj = current->signal->oom_adj;
|
||||||
|
sig->oom_score_adj = current->signal->oom_score_adj;
|
||||||
|
Index: linux-2.6/drivers/tty/tty_io.c
|
||||||
|
===================================================================
|
||||||
|
--- linux-2.6.orig/drivers/tty/tty_io.c
|
||||||
|
+++ linux-2.6/drivers/tty/tty_io.c
|
||||||
|
@@ -3160,6 +3160,7 @@ static void __proc_set_tty(struct task_s
|
||||||
|
put_pid(tsk->signal->tty_old_pgrp);
|
||||||
|
tsk->signal->tty = tty_kref_get(tty);
|
||||||
|
tsk->signal->tty_old_pgrp = NULL;
|
||||||
|
+ sched_autogroup_create_attach(tsk);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
|
||||||
|
Index: linux-2.6/kernel/sched_autogroup.h
|
||||||
|
===================================================================
|
||||||
|
--- /dev/null
|
||||||
|
+++ linux-2.6/kernel/sched_autogroup.h
|
||||||
|
@@ -0,0 +1,16 @@
|
||||||
|
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||||
|
+
|
||||||
|
+static inline struct task_group *
|
||||||
|
+autogroup_task_group(struct task_struct *p, struct task_group *tg);
|
||||||
|
+
|
||||||
|
+#else /* !CONFIG_SCHED_AUTOGROUP */
|
||||||
|
+
|
||||||
|
+static inline void autogroup_init(struct task_struct *init_task) { }
|
||||||
|
+
|
||||||
|
+static inline struct task_group *
|
||||||
|
+autogroup_task_group(struct task_struct *p, struct task_group *tg)
|
||||||
|
+{
|
||||||
|
+ return tg;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#endif /* CONFIG_SCHED_AUTOGROUP */
|
||||||
|
Index: linux-2.6/kernel/sched_autogroup.c
|
||||||
|
===================================================================
|
||||||
|
--- /dev/null
|
||||||
|
+++ linux-2.6/kernel/sched_autogroup.c
|
||||||
|
@@ -0,0 +1,150 @@
|
||||||
|
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||||
|
+
|
||||||
|
+unsigned int __read_mostly sysctl_sched_autogroup_enabled = 1;
|
||||||
|
+
|
||||||
|
+struct autogroup {
|
||||||
|
+ struct kref kref;
|
||||||
|
+ struct task_group *tg;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct autogroup autogroup_default;
|
||||||
|
+
|
||||||
|
+static void autogroup_init(struct task_struct *init_task)
|
||||||
|
+{
|
||||||
|
+ autogroup_default.tg = &init_task_group;
|
||||||
|
+ kref_init(&autogroup_default.kref);
|
||||||
|
+ init_task->signal->autogroup = &autogroup_default;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline void autogroup_destroy(struct kref *kref)
|
||||||
|
+{
|
||||||
|
+ struct autogroup *ag = container_of(kref, struct autogroup, kref);
|
||||||
|
+ struct task_group *tg = ag->tg;
|
||||||
|
+
|
||||||
|
+ kfree(ag);
|
||||||
|
+ sched_destroy_group(tg);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline void autogroup_kref_put(struct autogroup *ag)
|
||||||
|
+{
|
||||||
|
+ kref_put(&ag->kref, autogroup_destroy);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline struct autogroup *autogroup_kref_get(struct autogroup *ag)
|
||||||
|
+{
|
||||||
|
+ kref_get(&ag->kref);
|
||||||
|
+ return ag;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline struct autogroup *autogroup_create(void)
|
||||||
|
+{
|
||||||
|
+ struct autogroup *ag = kmalloc(sizeof(*ag), GFP_KERNEL);
|
||||||
|
+
|
||||||
|
+ if (!ag)
|
||||||
|
+ goto out_fail;
|
||||||
|
+
|
||||||
|
+ ag->tg = sched_create_group(&init_task_group);
|
||||||
|
+ kref_init(&ag->kref);
|
||||||
|
+
|
||||||
|
+ if (!(IS_ERR(ag->tg)))
|
||||||
|
+ return ag;
|
||||||
|
+
|
||||||
|
+out_fail:
|
||||||
|
+ if (ag) {
|
||||||
|
+ kfree(ag);
|
||||||
|
+ WARN_ON(1);
|
||||||
|
+ } else
|
||||||
|
+ WARN_ON(1);
|
||||||
|
+
|
||||||
|
+ return autogroup_kref_get(&autogroup_default);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline bool
|
||||||
|
+task_wants_autogroup(struct task_struct *p, struct task_group *tg)
|
||||||
|
+{
|
||||||
|
+ if (tg != &root_task_group)
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ if (p->sched_class != &fair_sched_class)
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ if (p->flags & PF_EXITING)
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline struct task_group *
|
||||||
|
+autogroup_task_group(struct task_struct *p, struct task_group *tg)
|
||||||
|
+{
|
||||||
|
+ int enabled = ACCESS_ONCE(sysctl_sched_autogroup_enabled);
|
||||||
|
+
|
||||||
|
+ if (enabled && task_wants_autogroup(p, tg))
|
||||||
|
+ return p->signal->autogroup->tg;
|
||||||
|
+
|
||||||
|
+ return tg;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+autogroup_move_group(struct task_struct *p, struct autogroup *ag)
|
||||||
|
+{
|
||||||
|
+ struct autogroup *prev;
|
||||||
|
+ struct task_struct *t;
|
||||||
|
+
|
||||||
|
+ prev = p->signal->autogroup;
|
||||||
|
+ if (prev == ag)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ p->signal->autogroup = autogroup_kref_get(ag);
|
||||||
|
+ sched_move_task(p);
|
||||||
|
+
|
||||||
|
+ rcu_read_lock();
|
||||||
|
+ list_for_each_entry_rcu(t, &p->thread_group, thread_group) {
|
||||||
|
+ sched_move_task(t);
|
||||||
|
+ }
|
||||||
|
+ rcu_read_unlock();
|
||||||
|
+
|
||||||
|
+ autogroup_kref_put(prev);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Must be called with siglock held */
|
||||||
|
+void sched_autogroup_create_attach(struct task_struct *p)
|
||||||
|
+{
|
||||||
|
+ struct autogroup *ag = autogroup_create();
|
||||||
|
+
|
||||||
|
+ autogroup_move_group(p, ag);
|
||||||
|
+ /* drop extra refrence added by autogroup_create() */
|
||||||
|
+ autogroup_kref_put(ag);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(sched_autogroup_create_attach);
|
||||||
|
+
|
||||||
|
+/* Must be called with siglock held. Currently has no users */
|
||||||
|
+void sched_autogroup_detach(struct task_struct *p)
|
||||||
|
+{
|
||||||
|
+ autogroup_move_group(p, &autogroup_default);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL(sched_autogroup_detach);
|
||||||
|
+
|
||||||
|
+void sched_autogroup_fork(struct signal_struct *sig)
|
||||||
|
+{
|
||||||
|
+ struct sighand_struct *sighand = current->sighand;
|
||||||
|
+
|
||||||
|
+ spin_lock(&sighand->siglock);
|
||||||
|
+ sig->autogroup = autogroup_kref_get(current->signal->autogroup);
|
||||||
|
+ spin_unlock(&sighand->siglock);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void sched_autogroup_exit(struct signal_struct *sig)
|
||||||
|
+{
|
||||||
|
+ autogroup_kref_put(sig->autogroup);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __init setup_autogroup(char *str)
|
||||||
|
+{
|
||||||
|
+ sysctl_sched_autogroup_enabled = 0;
|
||||||
|
+
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+__setup("noautogroup", setup_autogroup);
|
||||||
|
+#endif
|
||||||
|
Index: linux-2.6/kernel/sysctl.c
|
||||||
|
===================================================================
|
||||||
|
--- linux-2.6.orig/kernel/sysctl.c
|
||||||
|
+++ linux-2.6/kernel/sysctl.c
|
||||||
|
@@ -382,6 +382,17 @@ static struct ctl_table kern_table[] = {
|
||||||
|
.mode = 0644,
|
||||||
|
.proc_handler = proc_dointvec,
|
||||||
|
},
|
||||||
|
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||||
|
+ {
|
||||||
|
+ .procname = "sched_autogroup_enabled",
|
||||||
|
+ .data = &sysctl_sched_autogroup_enabled,
|
||||||
|
+ .maxlen = sizeof(unsigned int),
|
||||||
|
+ .mode = 0644,
|
||||||
|
+ .proc_handler = proc_dointvec,
|
||||||
|
+ .extra1 = &zero,
|
||||||
|
+ .extra2 = &one,
|
||||||
|
+ },
|
||||||
|
+#endif
|
||||||
|
#ifdef CONFIG_PROVE_LOCKING
|
||||||
|
{
|
||||||
|
.procname = "prove_locking",
|
||||||
|
Index: linux-2.6/init/Kconfig
|
||||||
|
===================================================================
|
||||||
|
--- linux-2.6.orig/init/Kconfig
|
||||||
|
+++ linux-2.6/init/Kconfig
|
||||||
|
@@ -728,6 +728,18 @@ config NET_NS
|
||||||
|
|
||||||
|
endif # NAMESPACES
|
||||||
|
|
||||||
|
+config SCHED_AUTOGROUP
|
||||||
|
+ bool "Automatic process group scheduling"
|
||||||
|
+ select CGROUPS
|
||||||
|
+ select CGROUP_SCHED
|
||||||
|
+ select FAIR_GROUP_SCHED
|
||||||
|
+ help
|
||||||
|
+ This option optimizes the scheduler for common desktop workloads by
|
||||||
|
+ automatically creating and populating task groups. This separation
|
||||||
|
+ of workloads isolates aggressive CPU burners (like build jobs) from
|
||||||
|
+ desktop applications. Task group autogeneration is currently based
|
||||||
|
+ upon task tty association.
|
||||||
|
+
|
||||||
|
config MM_OWNER
|
||||||
|
bool
|
||||||
|
|
||||||
|
Index: linux-2.6/Documentation/kernel-parameters.txt
|
||||||
|
===================================================================
|
||||||
|
--- linux-2.6.orig/Documentation/kernel-parameters.txt
|
||||||
|
+++ linux-2.6/Documentation/kernel-parameters.txt
|
||||||
|
@@ -1622,6 +1622,8 @@ and is between 256 and 4096 characters.
|
||||||
|
noapic [SMP,APIC] Tells the kernel to not make use of any
|
||||||
|
IOAPICs that may be present in the system.
|
||||||
|
|
||||||
|
+ noautogroup Disable scheduler automatic task group creation.
|
||||||
|
+
|
||||||
|
nobats [PPC] Do not use BATs for mapping kernel lowmem
|
||||||
|
on "Classic" PPC cores.
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user