scheduler changes for v2.6.39
Subsystems (3)
Linus,
Please pull the latest sched-core-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git sched-core-for-linus
Thanks,
Ingo
------------------>
Darren Hart (2):
sched: Allow SCHED_BATCH to preempt SCHED_IDLE tasks
sched: Allow users with sufficient RLIMIT_NICE to change from SCHED_IDLE policy
Heiko Carstens (1):
sched: Add #ifdef around irq time accounting functions
Mike Galbraith (2):
sched: Add yield_to(task, preempt) functionality sched, autogroup: Stop claiming ownership of the root task group
Paul Turner (2):
sched: Simplify update_cfs_shares parameters
sched: Avoid expensive initial update_cfs_load()
Peter Zijlstra (6):
sched: Simplify the idle scheduling class
sched: Fix switch_from_fair()
sched: Avoid expensive initial update_cfs_load(), on UP too
sched: Clean up remnants of sd_idle
sched: Clean up some f_b_g() comments
sched: Fix the group_imb logic
Rik van Riel (3):
sched: Check the right ->nr_running in yield_task_fair()
sched: Limit the scope of clear_buddies
sched: Use a buddy to implement yield_task_fair()
Venkatesh Pallipadi (8):
softirqs: Free up pf flag PF_KSOFTIRQD
time: Add nsecs_to_cputime64 interface for asm-generic
sched: Refactor account_system_time separating id-update
sched: Export ns irqtimes through /proc/stat
softirqs: Account ksoftirqd time as cpustat softirq
sched: Wholesale removal of sd_idle logic
sched: Clean up the IRQ_TIME_ACCOUNTING code
sched: Resched proper CPU on yield_to()
Yong Zhang (2):
sched, autogroup, sysctl: Use proc_dointvec_minmax() instead sched, autogroup: Stop going ahead if autogroup is disabled
include/asm-generic/cputime.h | 3 + include/linux/interrupt.h | 7 + include/linux/jiffies.h | 1 + include/linux/sched.h | 13 +- kernel/sched.c | 296 +++++++++++++++++++++++++++---- kernel/sched_autogroup.c | 15 +- kernel/sched_autogroup.h | 5 + kernel/sched_debug.c | 2 +- kernel/sched_fair.c | 397 ++++++++++++++++++++++++----------------- kernel/sched_idletask.c | 26 +--- kernel/sched_rt.c | 19 +- kernel/sched_stoptask.c | 7 +- kernel/softirq.c | 3 +- kernel/sysctl.c | 9 +- kernel/time.c | 23 +++- 15 files changed, 565 insertions(+), 261 deletions(-)
include/asm-generic/cputime.h +3 -0
@@ -30,6 +30,9 @@ typedef u64 cputime64_t;#define cputime64_to_jiffies64 (__ct) (__ct)#define jiffies64_to_cputime64 (__jif) (__jif)#define cputime_to_cputime64 (__ct) ((u64) __ct) +#define cputime64_gt (__a, __b) ((__a) > (__b)) + +#define nsecs_to_cputime64 (__ct) nsecs_to_jiffies64(__ct)/*
include/linux/interrupt.h +7 -0
@@ -426,6 +426,13 @@ extern void raise_softirq(unsigned int nr);*/ DECLARE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list); +DECLARE_PER_CPU(struct task_struct *, ksoftirqd); + +static inline struct task_struct *this_cpu_ksoftirqd (void ) +{ +return this_cpu_read (ksoftirqd); +} +/* Try to send a softirq to a remote cpu. If this cannot be done, the * work will be queued to the local cpu. */
include/linux/jiffies.h +1 -0
@@ -307,6 +307,7 @@ extern clock_t jiffies_to_clock_t(long x);extern unsigned long clock_t_to_jiffies (unsigned long x);extern u64 jiffies_64_to_clock_t (u64 x);extern u64 nsec_to_clock_t (u64 x); +extern u64 nsecs_to_jiffies64 (u64 n);extern unsigned long nsecs_to_jiffies (u64 n);#define TIMESTAMP_SIZE 30
include/linux/sched.h +5 -8
@@ -1058,6 +1058,7 @@ struct sched_class {void (*enqueue_task) (struct rq *rq,struct task_struct *p,int flags);void (*dequeue_task) (struct rq *rq,struct task_struct *p,int flags);void (*yield_task) (struct rq *rq); +bool (*yield_to_task) (struct rq *rq,struct task_struct *p,bool preempt);void (*check_preempt_curr) (struct rq *rq,struct task_struct *p,int flags);
@@ -1084,12 +1085,10 @@ struct sched_class {void (*task_tick) (struct rq *rq,struct task_struct *p,int queued);void (*task_fork) (struct task_struct *p); -void (*switched_from) (struct rq *this_rq,struct task_struct *task, -int running); -void (*switched_to) (struct rq *this_rq,struct task_struct *task, -int running); +void (*switched_from) (struct rq *this_rq,struct task_struct *task); +void (*switched_to) (struct rq *this_rq,struct task_struct *task);void (*prio_changed) (struct rq *this_rq,struct task_struct *task, -int oldprio,int running); +int oldprio);unsigned int (*get_rr_interval) (struct rq *rq,struct task_struct *task);
@@ -1715,7 +1714,6 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t */* * Per process flags */ -#define PF_KSOFTIRQD 0x00000001/* I am ksoftirqd */ #define PF_STARTING 0x00000002/* being created */ #define PF_EXITING 0x00000004/* getting shut down */ #define PF_EXITPIDONE 0x00000008/* pi exit done on shut down */
@@ -1945,8 +1943,6 @@ int sched_rt_handler(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos); -extern unsigned int sysctl_sched_compat_yield; -#ifdef CONFIG_SCHED_AUTOGROUP extern unsigned int sysctl_sched_autogroup_enabled;
@@ -1977,6 +1973,7 @@ static inline int rt_mutex_getprio(struct task_struct *p)# define rt_mutex_adjust_pi (p) do { } while (0)#endif +extern bool yield_to (struct task_struct *p,bool preempt);extern void set_user_nice (struct task_struct *p,long nice);extern int task_prio (const struct task_struct *p);extern int task_nice (const struct task_struct *p);
kernel/sched.c +262 -34
435 lines not on this page · raw message
kernel/sched_autogroup.c +10 -5
@@ -12,7 +12,6 @@ static atomic_t autogroup_seq_nr;static void __init autogroup_init (struct task_struct *init_task) { autogroup_default.tg = &root_task_group; - root_task_group.autogroup = &autogroup_default;kref_init (&autogroup_default.kref);init_rwsem (&autogroup_default.lock); init_task->signal->autogroup = &autogroup_default;
@@ -130,7 +129,7 @@ task_wants_autogroup(struct task_struct *p, struct task_group *tg)static inline bool task_group_is_autogroup (struct task_group *tg) { -return tg != &root_task_group && tg->autogroup; +return !!tg->autogroup; } static inline struct task_group *
@@ -161,11 +160,15 @@ autogroup_move_group(struct task_struct *p, struct autogroup *ag) p->signal->autogroup =autogroup_kref_get (ag); +if (!ACCESS_ONCE (sysctl_sched_autogroup_enabled)) + goto out; + t = p; do { sched_move_task(t); } while_each_thread(p, t); +out: unlock_task_sighand(p, &flags); autogroup_kref_put(prev); }
@@ -247,10 +250,14 @@ void proc_sched_autogroup_show_task(struct task_struct *p, struct seq_file *m) {struct autogroup *ag =autogroup_task_get (p); +if (!task_group_is_autogroup (ag->tg)) + goto out; +down_read (&ag->lock);seq_printf (m,"/autogroup-%ld nice %d\n" , ag->id, ag->nice);up_read (&ag->lock); +out:autogroup_kref_put (ag); }#endif /* CONFIG_PROC_FS */
@@ -258,9 +265,7 @@ void proc_sched_autogroup_show_task(struct task_struct *p, struct seq_file *m)#ifdef CONFIG_SCHED_DEBUG static inline int autogroup_path (struct task_group *tg,char *buf,int buflen) { -int enabled =ACCESS_ONCE (sysctl_sched_autogroup_enabled); - -if (!enabled || !tg->autogroup) +if (!task_group_is_autogroup (tg))return 0 ;return snprintf (buf, buflen,"%s-%ld" ,"/autogroup" , tg->autogroup->id);
kernel/sched_autogroup.h +5 -0
@@ -1,6 +1,11 @@ #ifdef CONFIG_SCHED_AUTOGROUP struct autogroup { + /* + * reference doesn't mean how many thread attach to this + * autogroup now. It just stands for the number of task + * could use this autogroup. + */ struct kref kref; struct task_group *tg; struct rw_semaphore lock;
kernel/sched_debug.c +1 -1
@@ -179,7 +179,7 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)raw_spin_lock_irqsave (&rq->lock, flags);if (cfs_rq->rb_leftmost) - MIN_vruntime = (__pick_next_entity (cfs_rq))->vruntime; + MIN_vruntime = (__pick_first_entity (cfs_rq))->vruntime; last =__pick_last_entity (cfs_rq);if (last) max_vruntime = last->vruntime;
kernel/sched_fair.c +230 -167
751 lines not on this page · raw message
kernel/sched_idletask.c +5 -21
@@ -52,31 +52,15 @@ static void set_curr_task_idle(struct rq *rq) { } -static void switched_to_idle (struct rq *rq,struct task_struct *p, -int running) +static void switched_to_idle (struct rq *rq,struct task_struct *p) { -/* Can this actually happen?? */ -if (running) -resched_task (rq->curr); -else -check_preempt_curr (rq, p,0 ); +BUG (); } -static void prio_changed_idle (struct rq *rq,struct task_struct *p, -int oldprio,int running) +static void +prio_changed_idle (struct rq *rq,struct task_struct *p,int oldprio) { -/* This can happen for hot plug CPUS */ - -/* -* Reschedule if we are currently running on this runqueue and -* our priority decreased, or if we are not currently running on -* this runqueue and our priority is higher than the current's -*/ -if (running) { -if (p->prio > oldprio) -resched_task (rq->curr); - }else -check_preempt_curr (rq, p,0 ); +BUG (); }static unsigned int get_rr_interval_idle (struct rq *rq,struct task_struct *task)
kernel/sched_rt.c +10 -9
@@ -1599,8 +1599,7 @@ static void rq_offline_rt(struct rq *rq)* When switch from the rt queue, we bring ourselves to a position * that we might want to pull RT tasks from other runqueues. */ -static void switched_from_rt (struct rq *rq,struct task_struct *p, -int running) +static void switched_from_rt (struct rq *rq,struct task_struct *p) {/* * If there are other RT tasks then we will reschedule
@@ -1609,7 +1608,7 @@ static void switched_from_rt(struct rq *rq, struct task_struct *p,* we may need to handle the pulling of RT tasks * now. */ -if (!rq->rt.rt_nr_running) +if (p->se.on_rq && !rq->rt.rt_nr_running)pull_rt_task (rq); }
@@ -1628,8 +1627,7 @@ static inline void init_sched_rt_class(void)* with RT tasks. In this case we try to push them off to * other runqueues. */ -static void switched_to_rt (struct rq *rq,struct task_struct *p, -int running) +static void switched_to_rt (struct rq *rq,struct task_struct *p) {int check_resched =1 ;
@@ -1640,7 +1638,7 @@ static void switched_to_rt(struct rq *rq, struct task_struct *p,* If that current running task is also an RT task * then see if we can move to another run queue. */ -if (!running) { +if (p->se.on_rq && rq->curr != p) {#ifdef CONFIG_SMP if (rq->rt.overloaded && push_rt_task(rq) &&/* Don't resched if we changed runqueues */
@@ -1656,10 +1654,13 @@ static void switched_to_rt(struct rq *rq, struct task_struct *p,* Priority of the task has changed. This may cause * us to initiate a push or pull. */ -static void prio_changed_rt (struct rq *rq,struct task_struct *p, -int oldprio,int running) +static void +prio_changed_rt (struct rq *rq,struct task_struct *p,int oldprio) { -if (running) { +if (!p->se.on_rq) +return ; + +if (rq->curr == p) {#ifdef CONFIG_SMP /* * If our priority decreases while running, we
kernel/sched_stoptask.c +3 -4
@@ -59,14 +59,13 @@ static void set_curr_task_stop(struct rq *rq) { } -static void switched_to_stop (struct rq *rq,struct task_struct *p, -int running) +static void switched_to_stop (struct rq *rq,struct task_struct *p) {BUG ();/* its impossible to change to this class */ } -static void prio_changed_stop (struct rq *rq,struct task_struct *p, -int oldprio,int running) +static void +prio_changed_stop (struct rq *rq,struct task_struct *p,int oldprio) {BUG ();/* how!?, what priority? */ }
kernel/softirq.c +1 -2
@@ -54,7 +54,7 @@ EXPORT_SYMBOL(irq_stat); static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp; -static DEFINE_PER_CPU(struct task_struct *, ksoftirqd); +DEFINE_PER_CPU(struct task_struct *, ksoftirqd);char *softirq_to_name[NR_SOFTIRQS ] = {"HI" ,"TIMER" ,"NET_TX" ,"NET_RX" ,"BLOCK" ,"BLOCK_IOPOLL" ,
@@ -721,7 +721,6 @@ static int run_ksoftirqd(void * __bind_cpu) {set_current_state (TASK_INTERRUPTIBLE ); - current->flags |=PF_KSOFTIRQD ;while (!kthread_should_stop ()) {preempt_disable ();if (!local_softirq_pending ()) {
kernel/sysctl.c +1 -8
@@ -361,20 +361,13 @@ static struct ctl_table kern_table[] = { .mode = 0644, .proc_handler = sched_rt_handler, }, - { - .procname = "sched_compat_yield", - .data = &sysctl_sched_compat_yield, - .maxlen = sizeof(unsigned int), - .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, + .proc_handler = proc_dointvec_minmax, .extra1 = &zero, .extra2 = &one, },
kernel/time.c +21 -2
@@ -645,7 +645,7 @@ u64 nsec_to_clock_t(u64 x) }/** -* nsecs_to_jiffies - Convert nsecs in u64 to jiffies +* nsecs_to_jiffies64 - Convert nsecs in u64 to jiffies64 * * @n: nsecs in u64 *
@@ -657,7 +657,7 @@ u64 nsec_to_clock_t(u64 x)* NSEC_PER_SEC = 10^9 = (5^9 * 2^9) = (1953125 * 512) * ULLONG_MAX ns = 18446744073.709551615 secs = about 584 years */ -unsigned long nsecs_to_jiffies (u64 n) +u64 nsecs_to_jiffies64 (u64 n) {#if (NSEC_PER_SEC %HZ ) ==0 /* Common case, HZ = 100, 128, 200, 250, 256, 500, 512, 1000 etc. */
@@ -674,6 +674,25 @@ unsigned long nsecs_to_jiffies(u64 n)#endif } + +/** +* nsecs_to_jiffies - Convert nsecs in u64 to jiffies +* +* @n: nsecs in u64 +* +* Unlike {m,u}secs_to_jiffies, type of input is not unsigned int but u64. +* And this doesn't return MAX_JIFFY_OFFSET since this function is designed +* for scheduler, not for use in device drivers to calculate timeout value. +* +* note: +* NSEC_PER_SEC = 10^9 = (5^9 * 2^9) = (1953125 * 512) +* ULLONG_MAX ns = 18446744073.709551615 secs = about 584 years +*/ +unsigned long nsecs_to_jiffies (u64 n) +{ +return (unsigned long )nsecs_to_jiffies64 (n); +} +#if (BITS_PER_LONG <64 )u64 get_jiffies_64 (void ) {