|
楼主 |
发表于 17-11-2010 14:04:24
|
显示全部楼层
完成这一killer feature的代码补丁:- 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
- @@ -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
- @@ -8509,15 +8514,11 @@ void sched_destroy_group(struct task_gro
- /* change task's runqueue when it moves between groups.
- * The caller of this function should have put the task in its new group
- * by now. This function just updates tsk->se.cfs_rq and tsk->se.parent to
- - * reflect its new group.
- + * reflect its new group. Called with the runqueue lock held.
- */
- -void sched_move_task(struct task_struct *tsk)
- +void __sched_move_task(struct task_struct *tsk, struct rq *rq)
- {
- int on_rq, running;
- - unsigned long flags;
- - struct rq *rq;
- -
- - rq = task_rq_lock(tsk, &flags);
-
- running = task_current(rq, tsk);
- on_rq = tsk->se.on_rq;
- @@ -8538,7 +8539,15 @@ void sched_move_task(struct task_struct
- tsk->sched_class->set_curr_task(rq);
- if (on_rq)
- enqueue_task(rq, tsk, 0);
- +}
-
- +void sched_move_task(struct task_struct *tsk)
- +{
- + struct rq *rq;
- + unsigned long flags;
- +
- + rq = task_rq_lock(tsk, &flags);
- + __sched_move_task(tsk, rq);
- task_rq_unlock(rq, &flags);
- }
- #endif /* CONFIG_CGROUP_SCHED */
- 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,18 @@
- +#ifdef CONFIG_SCHED_AUTOGROUP
- +
- +static void __sched_move_task(struct task_struct *tsk, struct rq *rq);
- +
- +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,140 @@
- +#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 struct task_group *
- +autogroup_task_group(struct task_struct *p, struct task_group *tg)
- +{
- + int enabled = ACCESS_ONCE(sysctl_sched_autogroup_enabled);
- +
- + enabled &= (tg == &root_task_group);
- + enabled &= (p->sched_class == &fair_sched_class);
- + enabled &= (!(p->flags & PF_EXITING));
- +
- + if (enabled)
- + 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;
- + struct rq *rq;
- + unsigned long flags;
- +
- + rq = task_rq_lock(p, &flags);
- + prev = p->signal->autogroup;
- + if (prev == ag) {
- + task_rq_unlock(rq, &flags);
- + return;
- + }
- +
- + p->signal->autogroup = autogroup_kref_get(ag);
- + __sched_move_task(p, rq);
- + task_rq_unlock(rq, &flags);
- +
- + 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);
- +}
- +
- +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);
- +
- +/* 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)
- +{
- + sig->autogroup = autogroup_kref_get(current->signal->autogroup);
- +}
- +
- +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.
-
复制代码 |
|