Loading kernel-rwolf/PKGBUILD +1 −1 Original line number Diff line number Diff line # Maintainer: Sebastien Luttringer <seblu@seblu.net> pkgname=kernel-rwolf pkgver=2.6.37_rc2 pkgver=2.6.37_rc3 pkgrel=1 makedepends=('gcc') arch=('x86_64') Loading kernel-rwolf/config +7 −5 Original line number Diff line number Diff line # # Automatically generated make config: don't edit # Linux/x86_64 2.6.37-rc1 Kernel Configuration # Tue Nov 2 00:00:11 2010 # Linux/x86_64 2.6.37-rc3 Kernel Configuration # Mon Nov 22 14:30:42 2010 # CONFIG_64BIT=y # CONFIG_X86_32 is not set Loading Loading @@ -143,6 +143,7 @@ CONFIG_IPC_NS=y CONFIG_USER_NS=y CONFIG_PID_NS=y CONFIG_NET_NS=y CONFIG_SCHED_AUTOGROUP=y CONFIG_MM_OWNER=y # CONFIG_SYSFS_DEPRECATED is not set CONFIG_RELAY=y Loading Loading @@ -435,7 +436,6 @@ CONFIG_HIBERNATION=y CONFIG_PM_STD_PARTITION="" CONFIG_PM_RUNTIME=y CONFIG_PM_OPS=y # CONFIG_PM_OPP is not set CONFIG_ACPI=y CONFIG_ACPI_SLEEP=y CONFIG_ACPI_PROCFS=y Loading Loading @@ -3427,7 +3427,7 @@ CONFIG_MSPRO_BLOCK=m CONFIG_MEMSTICK_TIFM_MS=m CONFIG_MEMSTICK_JMICRON_38X=m CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=m CONFIG_LEDS_CLASS=y # # LED drivers Loading @@ -3438,6 +3438,8 @@ CONFIG_LEDS_PCA9532=m CONFIG_LEDS_GPIO=m CONFIG_LEDS_GPIO_PLATFORM=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set # CONFIG_LEDS_CLEVO_MAIL is not set CONFIG_LEDS_PCA955X=m CONFIG_LEDS_DAC124S085=m Loading Loading @@ -3580,7 +3582,6 @@ CONFIG_UIO_SERCOS3=m CONFIG_UIO_PCI_GENERIC=m CONFIG_UIO_NETX=m # CONFIG_STAGING is not set # CONFIG_MACH_NO_WESTBRIDGE is not set CONFIG_X86_PLATFORM_DEVICES=y # CONFIG_ACER_WMI is not set # CONFIG_ACERHDF is not set Loading Loading @@ -4025,6 +4026,7 @@ CONFIG_DEFAULT_IO_DELAY_TYPE=0 # CONFIG_KEYS=y # CONFIG_KEYS_DEBUG_PROC_KEYS is not set # CONFIG_SECURITY_DMESG_RESTRICT is not set # CONFIG_SECURITY is not set CONFIG_SECURITYFS=y # CONFIG_INTEL_TXT is not set Loading kernel-rwolf/patch.d/3-1-automated_per_tty_task_groups.patch 0 → 100644 +359 −0 Original line number Diff line number Diff line 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. kernel-rwolf/patch.d/3-2-automated_per_tty_task_groups.patch 0 → 100644 +43 −0 Original line number Diff line number Diff line --- linux-2.6.orig/kernel/sched.c +++ linux-2.6/kernel/sched.c @@ -606,27 +606,33 @@ 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)); - tg = container_of(css, struct task_group, css); + return container_of(css, struct task_group, css); +} - return autogroup_task_group(p, tg); +static inline struct task_group *effective_task_group(struct task_struct *p) +{ + return autogroup_task_group(p, task_group(p)); } /* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */ static inline void set_task_rq(struct task_struct *p, unsigned int cpu) { +#if (defined(CONFIG_FAIR_GROUP_SCHED) || defined(CONFIG_RT_GROUP_SCHED)) + struct task_group *tg = effective_task_group(p); +#endif + #ifdef CONFIG_FAIR_GROUP_SCHED - p->se.cfs_rq = task_group(p)->cfs_rq[cpu]; - p->se.parent = task_group(p)->se[cpu]; + p->se.cfs_rq = tg->cfs_rq[cpu]; + p->se.parent = tg->se[cpu]; #endif #ifdef CONFIG_RT_GROUP_SCHED - p->rt.rt_rq = task_group(p)->rt_rq[cpu]; - p->rt.parent = task_group(p)->rt_se[cpu]; + p->rt.rt_rq = tg->rt_rq[cpu]; + p->rt.parent = tg->rt_se[cpu]; #endif } Loading
kernel-rwolf/PKGBUILD +1 −1 Original line number Diff line number Diff line # Maintainer: Sebastien Luttringer <seblu@seblu.net> pkgname=kernel-rwolf pkgver=2.6.37_rc2 pkgver=2.6.37_rc3 pkgrel=1 makedepends=('gcc') arch=('x86_64') Loading
kernel-rwolf/config +7 −5 Original line number Diff line number Diff line # # Automatically generated make config: don't edit # Linux/x86_64 2.6.37-rc1 Kernel Configuration # Tue Nov 2 00:00:11 2010 # Linux/x86_64 2.6.37-rc3 Kernel Configuration # Mon Nov 22 14:30:42 2010 # CONFIG_64BIT=y # CONFIG_X86_32 is not set Loading Loading @@ -143,6 +143,7 @@ CONFIG_IPC_NS=y CONFIG_USER_NS=y CONFIG_PID_NS=y CONFIG_NET_NS=y CONFIG_SCHED_AUTOGROUP=y CONFIG_MM_OWNER=y # CONFIG_SYSFS_DEPRECATED is not set CONFIG_RELAY=y Loading Loading @@ -435,7 +436,6 @@ CONFIG_HIBERNATION=y CONFIG_PM_STD_PARTITION="" CONFIG_PM_RUNTIME=y CONFIG_PM_OPS=y # CONFIG_PM_OPP is not set CONFIG_ACPI=y CONFIG_ACPI_SLEEP=y CONFIG_ACPI_PROCFS=y Loading Loading @@ -3427,7 +3427,7 @@ CONFIG_MSPRO_BLOCK=m CONFIG_MEMSTICK_TIFM_MS=m CONFIG_MEMSTICK_JMICRON_38X=m CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=m CONFIG_LEDS_CLASS=y # # LED drivers Loading @@ -3438,6 +3438,8 @@ CONFIG_LEDS_PCA9532=m CONFIG_LEDS_GPIO=m CONFIG_LEDS_GPIO_PLATFORM=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set # CONFIG_LEDS_CLEVO_MAIL is not set CONFIG_LEDS_PCA955X=m CONFIG_LEDS_DAC124S085=m Loading Loading @@ -3580,7 +3582,6 @@ CONFIG_UIO_SERCOS3=m CONFIG_UIO_PCI_GENERIC=m CONFIG_UIO_NETX=m # CONFIG_STAGING is not set # CONFIG_MACH_NO_WESTBRIDGE is not set CONFIG_X86_PLATFORM_DEVICES=y # CONFIG_ACER_WMI is not set # CONFIG_ACERHDF is not set Loading Loading @@ -4025,6 +4026,7 @@ CONFIG_DEFAULT_IO_DELAY_TYPE=0 # CONFIG_KEYS=y # CONFIG_KEYS_DEBUG_PROC_KEYS is not set # CONFIG_SECURITY_DMESG_RESTRICT is not set # CONFIG_SECURITY is not set CONFIG_SECURITYFS=y # CONFIG_INTEL_TXT is not set Loading
kernel-rwolf/patch.d/3-1-automated_per_tty_task_groups.patch 0 → 100644 +359 −0 Original line number Diff line number Diff line 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.
kernel-rwolf/patch.d/3-2-automated_per_tty_task_groups.patch 0 → 100644 +43 −0 Original line number Diff line number Diff line --- linux-2.6.orig/kernel/sched.c +++ linux-2.6/kernel/sched.c @@ -606,27 +606,33 @@ 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)); - tg = container_of(css, struct task_group, css); + return container_of(css, struct task_group, css); +} - return autogroup_task_group(p, tg); +static inline struct task_group *effective_task_group(struct task_struct *p) +{ + return autogroup_task_group(p, task_group(p)); } /* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */ static inline void set_task_rq(struct task_struct *p, unsigned int cpu) { +#if (defined(CONFIG_FAIR_GROUP_SCHED) || defined(CONFIG_RT_GROUP_SCHED)) + struct task_group *tg = effective_task_group(p); +#endif + #ifdef CONFIG_FAIR_GROUP_SCHED - p->se.cfs_rq = task_group(p)->cfs_rq[cpu]; - p->se.parent = task_group(p)->se[cpu]; + p->se.cfs_rq = tg->cfs_rq[cpu]; + p->se.parent = tg->se[cpu]; #endif #ifdef CONFIG_RT_GROUP_SCHED - p->rt.rt_rq = task_group(p)->rt_rq[cpu]; - p->rt.parent = task_group(p)->rt_se[cpu]; + p->rt.rt_rq = tg->rt_rq[cpu]; + p->rt.parent = tg->rt_se[cpu]; #endif }