more rt group sched updates
Subsystems (4)
cover more rt group sched updates
includes the two patches from yesterday,
series against sched-devel
PATCH 1/7 sched: rt throttling vs no_hz
We need to teach no_hz about the rt throttling because its tick driven.
--- include/linux/sched.h | 2 ++ kernel/sched.c | 23 ++++++++++++++++++++++- kernel/sched_rt.c | 30 ++++++++++++++++-------------- kernel/time/tick-sched.c | 5 +++++ 4 files changed, 45 insertions(+), 15 deletions(-)
include/linux/sched.h +2 -0
@@ -230,6 +230,8 @@ static inline int select_nohz_load_balan }#endif +extern unsigned long rt_needs_cpu (int cpu); +/* * Only dump TASK_* tasks. (0 for all tasks) */
kernel/sched.c +22 -1
@@ -442,6 +442,7 @@ struct rq {struct cfs_rq cfs;struct rt_rq rt;u64 rt_period_expire; +int rt_throttled;#ifdef CONFIG_FAIR_GROUP_SCHED /* list of leaf cfs_rq on this cpu: */
@@ -594,6 +595,23 @@ static void update_rq_clock(struct rq *r#define task_rq (p) cpu_rq(task_cpu(p))#define cpu_curr (cpu) (cpu_rq(cpu)->curr) +unsigned long rt_needs_cpu (int cpu) +{ +struct rq *rq =cpu_rq (cpu); +u64 delta; + +if (!rq->rt_throttled) +return 0 ; + +if (rq->clock > rq->rt_period_expire) +return 1 ; + + delta = rq->rt_period_expire - rq->clock; +do_div (delta,NSEC_PER_SEC /HZ ); + +return (unsigned long )delta; +} +/* * Tunables that become constants when CONFIG_SCHED_DEBUG is off: */
@@ -7099,9 +7117,11 @@ static void init_rt_rq(struct rt_rq *rt_/* delimiter for bitsearch: */ __set_bit (MAX_RT_PRIO , array->bitmap); +#if definedCONFIG_SMP || definedCONFIG_FAIR_GROUP_SCHED + rt_rq->highest_prio =MAX_RT_PRIO ; +#endif #ifdef CONFIG_SMP rt_rq->rt_nr_migratory =0 ; - rt_rq->highest_prio =MAX_RT_PRIO ; rt_rq->overloaded =0 ;#endif
@@ -7186,6 +7206,7 @@ void __init sched_init(void)list_add (&init_task_group.list, &task_groups);#endif rq->rt_period_expire =0 ; + rq->rt_throttled =0 ;for (j =0 ; j <CPU_LOAD_IDX_MAX ; j++) rq->cpu_load[j] =0 ;
kernel/sched_rt.c +16 -14
@@ -175,7 +175,11 @@ static int sched_rt_ratio_exceeded(struc ratio = (period * rt_ratio) >>SCHED_RT_FRAC_SHIFT ;if (rt_rq->rt_time > ratio) { +struct rq *rq =rq_of_rt_rq (rt_rq); + + rq->rt_throttled =1 ; rt_rq->rt_throttled =1 ; +sched_rt_ratio_dequeue (rt_rq);return 1 ; }
@@ -183,18 +187,6 @@ static int sched_rt_ratio_exceeded(strucreturn 0 ; } -static void __update_sched_rt_period (struct rt_rq *rt_rq,u64 period) -{ -unsigned long rt_ratio =sched_rt_ratio (rt_rq); -u64 ratio = (period * rt_ratio) >>SCHED_RT_FRAC_SHIFT ; - - rt_rq->rt_time -=min (rt_rq->rt_time, ratio); -if (rt_rq->rt_throttled) { - rt_rq->rt_throttled =0 ; -sched_rt_ratio_enqueue (rt_rq); - } -} -static void update_sched_rt_period (struct rq *rq) {struct rt_rq *rt_rq;
@@ -204,8 +196,18 @@ static void update_sched_rt_period(struc period = (u64 )sysctl_sched_rt_period *NSEC_PER_MSEC ; rq->rt_period_expire += period; -for_each_leaf_rt_rq (rt_rq, rq) -__update_sched_rt_period (rt_rq, period); +for_each_leaf_rt_rq (rt_rq, rq) { +unsigned long rt_ratio =sched_rt_ratio (rt_rq); +u64 ratio = (period * rt_ratio) >>SCHED_RT_FRAC_SHIFT ; + + rt_rq->rt_time -=min (rt_rq->rt_time, ratio); +if (rt_rq->rt_throttled) { + rt_rq->rt_throttled =0 ; +sched_rt_ratio_enqueue (rt_rq); + } + } + + rq->rt_throttled =0 ; } }
kernel/time/tick-sched.c +5 -0
@@ -153,6 +153,7 @@ void tick_nohz_update_jiffies(void)void tick_nohz_stop_sched_tick (void ) {unsigned long seq, last_jiffies, next_jiffies, delta_jiffies, flags; +unsigned long rt_jiffies;struct tick_sched *ts;ktime_t last_update, expires, now, delta;struct clock_event_device *dev =__get_cpu_var (tick_cpu_device).evtdev;
@@ -216,6 +217,10 @@ void tick_nohz_stop_sched_tick(void) next_jiffies =get_next_timer_interrupt (last_jiffies); delta_jiffies = next_jiffies - last_jiffies; + rt_jiffies =rt_needs_cpu (cpu); +if (rt_jiffies && rt_jiffies < delta_jiffies) + delta_jiffies = rt_jiffies; +if (rcu_needs_cpu (cpu)) delta_jiffies =1 ;/*
--
PATCH 2/7 sched: load_balance_monitor rename
In reply to Peter Zijlstradon't start the load_balance_monitor when there is only a single cpu. rename the kthread because its currently longer than TASK_COMM_LEN
--- kernel/sched.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
kernel/sched.c +4 -1
@@ -7070,8 +7070,11 @@ void __init sched_init_smp(void)sched_init_granularity ();#ifdef CONFIG_FAIR_GROUP_SCHED +if (nr_cpu_ids ==1 ) +return ; + lb_monitor_task =kthread_create (load_balance_monitor,NULL , -"load_balance_monitor" ); +"group_balance" );if (!IS_ERR (lb_monitor_task)) { lb_monitor_task->flags |=PF_NOFREEZE ;wake_up_process (lb_monitor_task);
--
PATCH 3/7 hrtimer: clean up cpu->base locking tricks
In reply to Peter ZijlstraIn order to more easily allow for the scheduler to use timers, clean up the locking a bit.
--- kernel/hrtimer.c | 109 +++++++++++++++++++++++++++++++++++++++++++---- kernel/time/tick-sched.c | 8 --- 2 files changed, 102 insertions(+), 15 deletions(-)
kernel/hrtimer.c +22 -2
@@ -1063,7 +1063,9 @@ void hrtimer_interrupt(struct clock_even basenow =ktime_add (now, base->offset);while ((node = base->first)) { +enum hrtimer_restart (*fn)(struct hrtimer *);struct hrtimer *timer; +int restart; timer = rb_entry(node, struct hrtimer, node);
@@ -1091,13 +1093,29 @@ void hrtimer_interrupt(struct clock_even HRTIMER_STATE_CALLBACK, 0);timer_stats_account_hrtimer (timer); + fn = timer->function; +if (timer->cb_mode ==HRTIMER_CB_IRQSAFE_NO_SOFTIRQ ) { +/* +* Used for scheduler timers, avoid lock +* inversion with rq->lock and tasklist_lock. +* +* These timers are required to deal with +* enqueue expiry themselves and are not +* allowed to migrate. +*/ +spin_unlock (&cpu_base->lock); + restart =fn (timer); +spin_lock (&cpu_base->lock); + }else + restart =fn (timer); +/* * Note: We clear the CALLBACK bit after * enqueue_hrtimer to avoid reprogramming of * the event hardware. This happens at the end * of this function anyway. */ -if (timer->function (timer) !=HRTIMER_NORESTART ) { +if (restart !=HRTIMER_NORESTART ) {BUG_ON (timer->state !=HRTIMER_STATE_CALLBACK );enqueue_hrtimer (timer, base,0 ); }
@@ -1268,7 +1361,7 @@ void hrtimer_init_sleeper(struct hrtimer sl->timer.function = hrtimer_wakeup; sl->task = task;#ifdef CONFIG_HIGH_RES_TIMERS - sl->timer.cb_mode =HRTIMER_CB_IRQSAFE_NO_RESTART ; + sl->timer.cb_mode =HRTIMER_CB_IRQSAFE_NO_SOFTIRQ ;#endif }
@@ -1279,6 +1372,8 @@ static int __sched do_nanosleep(struct h do { set_current_state(TASK_INTERRUPTIBLE); hrtimer_start(&t->timer, t->timer.expires, mode); + if (!hrtimer_active(&t->timer)) + t->task = NULL; if (likely(t->task)) schedule();
kernel/time/tick-sched.c +0 -8
@@ -514,7 +514,6 @@ static enum hrtimer_restart tick_sched_t {struct tick_sched *ts = container_of(timer, struct tick_sched, sched_timer); -struct hrtimer_cpu_base *base = timer->base->cpu_base;struct pt_regs *regs =get_irq_regs ();ktime_t now =ktime_get ();int cpu =smp_processor_id ();
@@ -552,15 +551,8 @@ static enum hrtimer_restart tick_sched_ttouch_softlockup_watchdog (); ts->idle_jiffies++; } -/* -* update_process_times() might take tasklist_lock, hence -* drop the base lock. sched-tick hrtimers are per-CPU and -* never accessible by userspace APIs, so this is safe to do. -*/ -spin_unlock (&base->lock);update_process_times (user_mode (regs));profile_tick (CPU_PROFILING ); -spin_lock (&base->lock); }/* Do not restart, when we are in the idle loop */
--
PATCH 4/7 hrtimer: fixup the HRTIMER_CB_IRQSAFE_NO_SOFTIRQ fallback
In reply to Peter ZijlstraCurrently all highres=off timers are run from softirq context, but HRTIMER_CB_IRQSAFE_NO_SOFTIRQ timers expect to run from irq context.
Fix this up by splitting it similar to the highres=on case.
--- include/linux/hrtimer.h | 1 kernel/hrtimer.c | 223 ++++++++++++++++++++++++------------------------ kernel/timer.c | 3 3 files changed, 117 insertions(+), 110 deletions(-)
kernel/hrtimer.c +114 -109
@@ -1030,6 +1030,85 @@ int hrtimer_get_res(const clockid_t whic }EXPORT_SYMBOL_GPL (hrtimer_get_res); +static void run_hrtimer_pending (struct hrtimer_cpu_base *cpu_base) +{ +spin_lock_irq (&cpu_base->lock); + +while (!list_empty (&cpu_base->cb_pending)) { +enum hrtimer_restart (*fn)(struct hrtimer *); +struct hrtimer *timer; +int restart; + + timer =list_entry (cpu_base->cb_pending.next, + struct hrtimer, cb_entry); + +timer_stats_account_hrtimer (timer); + + fn = timer->function; +__remove_hrtimer (timer, timer->base,HRTIMER_STATE_CALLBACK ,0 ); +spin_unlock_irq (&cpu_base->lock); + + restart =fn (timer); + +spin_lock_irq (&cpu_base->lock); + + timer->state &= ~HRTIMER_STATE_CALLBACK ; +if (restart ==HRTIMER_RESTART ) { +BUG_ON (hrtimer_active (timer)); +/* +* Enqueue the timer, allow reprogramming of the event +* device +*/ +enqueue_hrtimer (timer, timer->base,1 ); + }else if (hrtimer_active (timer)) { +/* +* If the timer was rearmed on another CPU, reprogram +* the event device. +*/ +if (timer->base->first == &timer->node) +hrtimer_reprogram (timer, timer->base); + } + } +spin_unlock_irq (&cpu_base->lock); +} + +static void __run_hrtimer (struct hrtimer *timer) +{ +struct hrtimer_clock_base *base = timer->base; +struct hrtimer_cpu_base *cpu_base = base->cpu_base; +enum hrtimer_restart (*fn)(struct hrtimer *); +int restart; + +__remove_hrtimer (timer, base,HRTIMER_STATE_CALLBACK ,0 ); +timer_stats_account_hrtimer (timer); + + fn = timer->function; +if (timer->cb_mode ==HRTIMER_CB_IRQSAFE_NO_SOFTIRQ ) { +/* +* Used for scheduler timers, avoid lock inversion with +* rq->lock and tasklist_lock. +* +* These timers are required to deal with enqueue expiry +* themselves and are not allowed to migrate. +*/ +spin_unlock (&cpu_base->lock); + restart =fn (timer); +spin_lock (&cpu_base->lock); + }else + restart =fn (timer); + +/* +* Note: We clear the CALLBACK bit after enqueue_hrtimer to avoid +* reprogramming of the event hardware. This happens at the end of this +* function anyway. +*/ +if (restart !=HRTIMER_NORESTART ) { +BUG_ON (timer->state !=HRTIMER_STATE_CALLBACK ); +enqueue_hrtimer (timer, base,0 ); + } + timer->state &= ~HRTIMER_STATE_CALLBACK ; +} +#ifdef CONFIG_HIGH_RES_TIMERS /*
@@ -1063,9 +1142,7 @@ void hrtimer_interrupt(struct clock_even basenow =ktime_add (now, base->offset);while ((node = base->first)) { -enum hrtimer_restart (*fn)(struct hrtimer *);struct hrtimer *timer; -int restart; timer = rb_entry(node, struct hrtimer, node);
@@ -1089,37 +1166,7 @@ void hrtimer_interrupt(struct clock_evencontinue ; } -__remove_hrtimer (timer, base, -HRTIMER_STATE_CALLBACK ,0 ); -timer_stats_account_hrtimer (timer); - - fn = timer->function; -if (timer->cb_mode ==HRTIMER_CB_IRQSAFE_NO_SOFTIRQ ) { -/* -* Used for scheduler timers, avoid lock -* inversion with rq->lock and tasklist_lock. -* -* These timers are required to deal with -* enqueue expiry themselves and are not -* allowed to migrate. -*/ -spin_unlock (&cpu_base->lock); - restart =fn (timer); -spin_lock (&cpu_base->lock); - }else - restart =fn (timer); - -/* -* Note: We clear the CALLBACK bit after -* enqueue_hrtimer to avoid reprogramming of -* the event hardware. This happens at the end -* of this function anyway. -*/ -if (restart !=HRTIMER_NORESTART ) { -BUG_ON (timer->state !=HRTIMER_STATE_CALLBACK ); -enqueue_hrtimer (timer, base,0 ); - } - timer->state &= ~HRTIMER_STATE_CALLBACK ; +__run_hrtimer (timer); }spin_unlock (&cpu_base->lock); base++;
@@ -1140,52 +1187,41 @@ void hrtimer_interrupt(struct clock_evenstatic void run_hrtimer_softirq (struct softirq_action *h) { -struct hrtimer_cpu_base *cpu_base = &__get_cpu_var (hrtimer_bases); - -spin_lock_irq (&cpu_base->lock); - -while (!list_empty (&cpu_base->cb_pending)) { -enum hrtimer_restart (*fn)(struct hrtimer *); -struct hrtimer *timer; -int restart; - - timer =list_entry (cpu_base->cb_pending.next, - struct hrtimer, cb_entry); +run_hrtimer_pending (&__get_cpu_var (hrtimer_bases)); +} -timer_stats_account_hrtimer (timer); +#endif /* CONFIG_HIGH_RES_TIMERS */ - fn = timer->function; -__remove_hrtimer (timer, timer->base,HRTIMER_STATE_CALLBACK ,0 ); -spin_unlock_irq (&cpu_base->lock); +/* +* Called from timer softirq every jiffy, expire hrtimers: +* +* For HRT its the fall back code to run the softirq in the timer +* softirq context in case the hrtimer initialization failed or has +* not been done yet. +*/ +void hrtimer_run_pending (void ) +{ +struct hrtimer_cpu_base *cpu_base = &__get_cpu_var (hrtimer_bases); - restart =fn (timer); +if (hrtimer_hres_active ()) +return ; -spin_lock_irq (&cpu_base->lock); +/* +* This _is_ ugly: We have to check in the softirq context, +* whether we can switch to highres and / or nohz mode. The +* clocksource switch happens in the timer interrupt with +* xtime_lock held. Notification from there only sets the +* check bit in the tick_oneshot code, otherwise we might +* deadlock vs. xtime_lock. +*/ +if (tick_check_oneshot_change (!hrtimer_is_hres_enabled ())) +hrtimer_switch_to_hres (); - timer->state &= ~HRTIMER_STATE_CALLBACK ; -if (restart ==HRTIMER_RESTART ) { -BUG_ON (hrtimer_active (timer)); -/* -* Enqueue the timer, allow reprogramming of the event -* device -*/ -enqueue_hrtimer (timer, timer->base,1 ); - }else if (hrtimer_active (timer)) { -/* -* If the timer was rearmed on another CPU, reprogram -* the event device. -*/ -if (timer->base->first == &timer->node) -hrtimer_reprogram (timer, timer->base); - } - } -spin_unlock_irq (&cpu_base->lock); +run_hrtimer_pending (cpu_base); } -#endif /* CONFIG_HIGH_RES_TIMERS */ -/* -* Expire the per base hrtimer-queue: +* Called from hardirq context every jiffy */ static inline void run_hrtimer_queue (struct hrtimer_cpu_base *cpu_base,int index)
@@ -1203,42 +1239,23 @@ static inline void run_hrtimer_queue(strwhile ((node = base->first)) {struct hrtimer *timer; -enum hrtimer_restart (*fn)(struct hrtimer *); -int restart; timer = rb_entry(node, struct hrtimer, node);if (base->softirq_time.tv64 <= timer->expires.tv64)break ; -#ifdef CONFIG_HIGH_RES_TIMERS -WARN_ON_ONCE (timer->cb_mode ==HRTIMER_CB_IRQSAFE_NO_SOFTIRQ ); -#endif -timer_stats_account_hrtimer (timer); - - fn = timer->function; -__remove_hrtimer (timer, base,HRTIMER_STATE_CALLBACK ,0 ); -spin_unlock_irq (&cpu_base->lock); - - restart =fn (timer); - -spin_lock_irq (&cpu_base->lock); - - timer->state &= ~HRTIMER_STATE_CALLBACK ; -if (restart !=HRTIMER_NORESTART ) { -BUG_ON (hrtimer_active (timer)); -enqueue_hrtimer (timer, base,0 ); +if (timer->cb_mode ==HRTIMER_CB_SOFTIRQ ) { +__remove_hrtimer (timer, base,HRTIMER_STATE_PENDING ,0 ); +list_add_tail (&timer->cb_entry, + &base->cpu_base->cb_pending); +continue ; } + +__run_hrtimer (timer); }spin_unlock_irq (&cpu_base->lock); } -/* -* Called from timer softirq every jiffy, expire hrtimers: -* -* For HRT its the fall back code to run the softirq in the timer -* softirq context in case the hrtimer initialization failed or has -* not been done yet. -*/ void hrtimer_run_queues (void ) {struct hrtimer_cpu_base *cpu_base = &__get_cpu_var (hrtimer_bases);
@@ -1247,18 +1264,6 @@ void hrtimer_run_queues(void)if (hrtimer_hres_active ())return ; -/* -* This _is_ ugly: We have to check in the softirq context, -* whether we can switch to highres and / or nohz mode. The -* clocksource switch happens in the timer interrupt with -* xtime_lock held. Notification from there only sets the -* check bit in the tick_oneshot code, otherwise we might -* deadlock vs. xtime_lock. -*/ -if (tick_check_oneshot_change (!hrtimer_is_hres_enabled ())) -if (hrtimer_switch_to_hres ()) -return ; -hrtimer_get_softirq_time (cpu_base);for (i =0 ; i <HRTIMER_MAX_CLOCK_BASES ; i++)
kernel/timer.c +2 -1
@@ -896,7 +896,7 @@ static void run_timer_softirq(struct sof {tvec_base_t *base =__get_cpu_var (tvec_bases); -hrtimer_run_queues (); +hrtimer_run_pending ();if (time_after_eq (jiffies, base->timer_jiffies))__run_timers (base);
@@ -907,6 +907,7 @@ static void run_timer_softirq(struct sof*/ void run_local_timers (void ) { +hrtimer_run_queues ();raise_softirq (TIMER_SOFTIRQ );softlockup_tick (); }
include/linux/hrtimer.h +1 -0
@@ -319,6 +319,7 @@ extern void hrtimer_init_sleeper(struct/* Soft interrupt function to run the hrtimer queues: */ extern void hrtimer_run_queues (void ); +extern void hrtimer_run_pending (void );/* Bootup initialization: */ extern void __init hrtimers_init (void );
--
PATCH 5/7 sched: rt-group: reduce rescheduling
In reply to Peter ZijlstraOnly reschedule if the new group has a higher prio task.
--- kernel/sched_rt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
kernel/sched_rt.c +4 -1
@@ -94,8 +94,11 @@ static void sched_rt_ratio_enqueue(strucstruct sched_rt_entity *rt_se = rt_rq->rt_se;if (rt_se && !on_rt_rq (rt_se) && rt_rq->rt_nr_running) { +struct task_struct *curr =rq_of_rt_rq (rt_rq)->curr; +enqueue_rt_entity (rt_se); -resched_task (rq_of_rt_rq (rt_rq)->curr); +if (rt_rq->highest_prio < curr->prio) +resched_task (curr); } }
--
PATCH 6/7 sched: rt-group: per group period
In reply to Peter ZijlstraSteven asked for per group periods in order to get closer to RMA or EDF scheduling.
Use the fancy new hrtimers to provide a per group period
--- include/linux/sched.h | 2 kernel/sched.c | 225 +++++++++++++++++++++++++++++++++++++++++------ kernel/sched_rt.c | 61 ++++++------ kernel/sysctl.c | 2 kernel/time/tick-sched.c | 5 - 5 files changed, 232 insertions(+), 63 deletions(-)
include/linux/sched.h +0 -2
@@ -230,8 +230,6 @@ static inline int select_nohz_load_balan }#endif -extern unsigned long rt_needs_cpu (int cpu); -/* * Only dump TASK_* tasks. (0 for all tasks) */
kernel/sched.c +200 -25
347 lines not on this page · raw message
kernel/sched_rt.c +31 -30
96 lines not on this page · raw message
kernel/sysctl.c +1 -1
@@ -311,7 +311,7 @@ static struct ctl_table kern_table[] = { }, { .ctl_name = CTL_UNNUMBERED, - .procname = "sched_rt_period_ms", + .procname = "sched_rt_period_us", .data = &sysctl_sched_rt_period, .maxlen = sizeof(unsigned int), .mode = 0644,
kernel/time/tick-sched.c +0 -5
@@ -153,7 +153,6 @@ void tick_nohz_update_jiffies(void)void tick_nohz_stop_sched_tick (void ) {unsigned long seq, last_jiffies, next_jiffies, delta_jiffies, flags; -unsigned long rt_jiffies;struct tick_sched *ts;ktime_t last_update, expires, now, delta;struct clock_event_device *dev =__get_cpu_var (tick_cpu_device).evtdev;
@@ -217,10 +216,6 @@ void tick_nohz_stop_sched_tick(void) next_jiffies =get_next_timer_interrupt (last_jiffies); delta_jiffies = next_jiffies - last_jiffies; - rt_jiffies =rt_needs_cpu (cpu); -if (rt_jiffies && rt_jiffies < delta_jiffies) - delta_jiffies = rt_jiffies; -if (rcu_needs_cpu (cpu)) delta_jiffies =1 ;/*
--
Re: [PATCH 6/7] sched: rt-group: per group period
Could you please fold this into the 6/7 patch.
It reverts a wandering chunk (the 32768 thing), but more importantly it fixes !FAIR_GROUP_SCHED compilation.
--- kernel/sched.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
kernel/sched.c +7 -3
@@ -647,7 +647,7 @@ const_debug unsigned int sysctl_sched_rt* ratio of time -rt tasks may consume. * default: 95% */ -const_debug unsigned int sysctl_sched_rt_ratio = 32768; //62259; +const_debug unsigned int sysctl_sched_rt_ratio = 62259;/* * For kernel-internal use: high-speed (but slightly incorrect) per-cpu
@@ -5379,6 +5379,7 @@ static void __init sched_rt_period_init(hotcpu_notifier (sched_rt_period_hotplug,0 ); } +#ifdef CONFIG_FAIR_GROUP_SCHED static void __sched_rt_period_init_tg (void *arg) {struct task_group *tg = arg;
@@ -5404,12 +5405,14 @@ static void sched_rt_period_destroy_tg(s {on_each_cpu (__sched_rt_period_destroy_tg, tg,0 ,1 ); } -#else +#endif /* CONFIG_FAIR_GROUP_SCHED */ +#else /* CONFIG_SMP */ static void __init sched_rt_period_init (void ) {sched_rt_period_start_cpu (0 ); } +#ifdef CONFIG_FAIR_GROUP_SCHED static void sched_rt_period_init_tg (struct task_group *tg) {sched_rt_period_start (tg->rt_rq[0 ]);
@@ -5419,7 +5422,8 @@ static void sched_rt_period_destroy_tg(s {sched_rt_period_stop (tg->rt_rq[0 ]); } -#endif +#endif /* CONFIG_FAIR_GROUP_SCHED */ +#endif /* CONFIG_SMP */ #ifdef CONFIG_SMP /*
Re: [PATCH 6/7] sched: rt-group: per group period
Quoted 4 lines · Peter Zijlstra
Could you please fold this into the 6/7 patch.
It reverts a wandering chunk (the 32768 thing), but more importantly it fixes !FAIR_GROUP_SCHED compilation.
done. Btw., there's a new warning:
kernel/sched_rt.c:197: warning: 'rt_se_boosted' defined but not used
Ingo
PATCH 7/7 sched: rt-group: deal with PI
In reply to Peter ZijlstraSteven mentioned the fun case where a lock holding task will be throttled.
Simple fix: allow groups that have boosted tasks to run anyway. This is ofcourse not quite correct. Needs more tricks.
--- kernel/sched.c | 3 +++ kernel/sched_rt.c | 50 ++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 45 insertions(+), 8 deletions(-)
kernel/sched.c +3 -0
@@ -376,6 +376,8 @@ struct rt_rq {struct hrtimer rt_period_timer;#ifdef CONFIG_FAIR_GROUP_SCHED +unsigned long rt_nr_boosted; +struct rq *rq;struct list_head leaf_rt_rq_list;struct task_group *tg;
@@ -7273,6 +7275,7 @@ static void init_rt_rq(struct rt_rq *rt_ rt_rq->rt_period_timer.cb_mode =HRTIMER_CB_IRQSAFE_NO_SOFTIRQ ;#ifdef CONFIG_FAIR_GROUP_SCHED + rt_rq->rt_nr_boosted =0 ; rt_rq->rq = rq;#endif }
kernel/sched_rt.c +42 -8
114 lines not on this page · raw message
--
Ingo Molnar
AppliedQuoted 3 lines · Peter Zijlstra
includes the two patches from yesterday,
series against sched-devel
thanks, applied.
Ingo